Convert attribution classes to kotlin

pull/996/head
Alex Baker 4 years ago
parent 55911097cf
commit 82307a9d78

@ -1,87 +0,0 @@
package org.tasks.activities.attribution;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import android.os.Bundle;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Multimaps;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.tasks.R;
import org.tasks.activities.attribution.AttributionViewModel.LibraryAttribution;
import org.tasks.injection.ActivityComponent;
import org.tasks.injection.ThemedInjectingAppCompatActivity;
import timber.log.Timber;
public class AttributionActivity extends ThemedInjectingAppCompatActivity {
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.list)
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_attributions);
ButterKnife.bind(this);
toolbar.setTitle(R.string.third_party_licenses);
toolbar.setNavigationIcon(R.drawable.ic_outline_arrow_back_24px);
toolbar.setNavigationOnClickListener(v -> finish());
themeColor.apply(toolbar);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
@Override
protected void onResume() {
super.onResume();
new ViewModelProvider(this)
.get(AttributionViewModel.class)
.observe(this, this::updateAttributions);
}
private void updateAttributions(List<LibraryAttribution> libraryAttributions) {
List<AttributionRow> rows = new ArrayList<>();
ImmutableListMultimap<String, LibraryAttribution> index =
Multimaps.index(libraryAttributions, LibraryAttribution::getLicense);
ArrayList<String> licenses = new ArrayList<>(index.keySet());
Collections.sort(licenses);
for (String license : licenses) {
rows.add(new AttributionRow(license));
ImmutableList<LibraryAttribution> libraries = index.get(license);
ImmutableListMultimap<String, LibraryAttribution> idx =
Multimaps.index(libraries, LibraryAttribution::getCopyrightHolder);
List<String> copyrightHolders = newArrayList(idx.keySet());
Collections.sort(copyrightHolders);
for (String copyrightHolder : copyrightHolders) {
List<String> libs = newArrayList(transform(idx.get(copyrightHolder),
a -> "\u2022 " + a.getLibraryName()));
Collections.sort(libs);
rows.add(new AttributionRow(copyrightHolder, Joiner.on("\n").join(libs)));
}
}
recyclerView.setAdapter(new AttributionAdapter(rows));
Timber.d(libraryAttributions.toString());
}
@Override
public void inject(ActivityComponent component) {
component.inject(this);
}
}

@ -0,0 +1,66 @@
package org.tasks.activities.attribution
import android.os.Bundle
import androidx.appcompat.widget.Toolbar
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import butterknife.ButterKnife
import com.google.common.base.Joiner
import com.google.common.collect.Multimaps
import org.tasks.R
import org.tasks.activities.attribution.AttributionViewModel.LibraryAttribution
import org.tasks.injection.ActivityComponent
import org.tasks.injection.ThemedInjectingAppCompatActivity
import timber.log.Timber
import java.util.*
class AttributionActivity : ThemedInjectingAppCompatActivity() {
@BindView(R.id.toolbar)
lateinit var toolbar: Toolbar
@BindView(R.id.list)
lateinit var recyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_attributions)
ButterKnife.bind(this)
toolbar.setTitle(R.string.third_party_licenses)
toolbar.setNavigationIcon(R.drawable.ic_outline_arrow_back_24px)
toolbar.setNavigationOnClickListener { finish() }
themeColor.apply(toolbar)
recyclerView.layoutManager = LinearLayoutManager(this)
}
override fun onResume() {
super.onResume()
ViewModelProvider(this)
.get(AttributionViewModel::class.java)
.observe(this, androidx.lifecycle.Observer { libraryAttributions: List<LibraryAttribution>? ->
updateAttributions(libraryAttributions!!)
})
}
private fun updateAttributions(libraryAttributions: List<LibraryAttribution>) {
val rows = ArrayList<AttributionRow>()
val byLicense = Multimaps.index(libraryAttributions) { it!!.license }
byLicense.keySet().sorted().forEach { license ->
rows.add(AttributionRow(license))
rows.addAll(getRows(byLicense[license]))
}
recyclerView.adapter = AttributionAdapter(rows)
Timber.d(libraryAttributions.toString())
}
private fun getRows(attributions: List<LibraryAttribution>): Iterable<AttributionRow> {
val byCopyrightHolder = Multimaps.index(attributions) { lib -> lib!!.copyrightHolder }
return byCopyrightHolder.keySet().sorted().map {
val libraries = byCopyrightHolder[it].map { a -> "\u2022 " + a.libraryName }
AttributionRow(it, Joiner.on("\n").join(libraries.toList().sorted()))
}
}
override fun inject(component: ActivityComponent) = component.inject(this)
}

@ -1,47 +0,0 @@
package org.tasks.activities.attribution;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import java.util.List;
import org.tasks.R;
public class AttributionAdapter extends RecyclerView.Adapter<ViewHolder> {
private final List<AttributionRow> rows;
AttributionAdapter(List<AttributionRow> rows) {
this.rows = rows;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return viewType == 0
? new LicenseHeader(inflater.inflate(R.layout.row_attribution_header, parent, false))
: new LicenseRow(inflater.inflate(R.layout.row_attribution, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
AttributionRow row = rows.get(position);
if (getItemViewType(position) == 0) {
((LicenseHeader) holder).bind(row.getLicense());
} else {
((LicenseRow) holder).bind(row.getCopyrightHolder(), row.getLibraries());
}
}
@Override
public int getItemViewType(int position) {
return rows.get(position).isHeader() ? 0 : 1;
}
@Override
public int getItemCount() {
return rows.size();
}
}

@ -0,0 +1,30 @@
package org.tasks.activities.attribution
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import org.tasks.R
class AttributionAdapter internal constructor(private val rows: List<AttributionRow>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return if (viewType == 0) {
LicenseHeader(inflater.inflate(R.layout.row_attribution_header, parent, false))
} else {
LicenseRow(inflater.inflate(R.layout.row_attribution, parent, false))
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val row = rows[position]
if (getItemViewType(position) == 0) {
(holder as LicenseHeader).bind(row.license)
} else {
(holder as LicenseRow).bind(row.copyrightHolder, row.libraries)
}
}
override fun getItemViewType(position: Int) = if (rows[position].isHeader) 0 else 1
override fun getItemCount() = rows.size
}

@ -1,39 +0,0 @@
package org.tasks.activities.attribution;
public class AttributionRow {
private final boolean isHeader;
private final String license;
private final String copyrightHolder;
private final String libraries;
AttributionRow(String license) {
this.license = license;
isHeader = true;
copyrightHolder = null;
libraries = null;
}
AttributionRow(String copyrightHolder, String libraries) {
this.copyrightHolder = copyrightHolder;
this.libraries = libraries;
isHeader = false;
license = null;
}
boolean isHeader() {
return isHeader;
}
public String getLicense() {
return license;
}
String getCopyrightHolder() {
return copyrightHolder;
}
public String getLibraries() {
return libraries;
}
}

@ -0,0 +1,22 @@
package org.tasks.activities.attribution
class AttributionRow {
val isHeader: Boolean
val license: String?
val copyrightHolder: String?
val libraries: String?
internal constructor(license: String?) {
this.license = license
isHeader = true
copyrightHolder = null
libraries = null
}
internal constructor(copyrightHolder: String?, libraries: String?) {
this.copyrightHolder = copyrightHolder
this.libraries = libraries
isHeader = false
license = null
}
}

@ -1,77 +0,0 @@
package org.tasks.activities.attribution;
import android.content.Context;
import androidx.annotation.Keep;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import com.google.gson.GsonBuilder;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import timber.log.Timber;
@SuppressWarnings({"WeakerAccess", "RedundantSuppression"})
public class AttributionViewModel extends androidx.lifecycle.ViewModel {
private final MutableLiveData<List<LibraryAttribution>> attributions = new MutableLiveData<>();
private final CompositeDisposable disposables = new CompositeDisposable();
private boolean loaded;
void observe(AppCompatActivity activity, Observer<List<LibraryAttribution>> observer) {
attributions.observe(activity, observer);
load(activity);
}
private void load(Context context) {
if (loaded) {
return;
}
loaded = true;
disposables.add(
Single.fromCallable(
() -> {
InputStream licenses = context.getAssets().open("licenses.json");
InputStreamReader reader =
new InputStreamReader(licenses, StandardCharsets.UTF_8);
AttributionList list =
new GsonBuilder().create().fromJson(reader, AttributionList.class);
return list.libraries;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(attributions::setValue, Timber::e));
}
@Override
protected void onCleared() {
disposables.dispose();
}
static class AttributionList {
List<LibraryAttribution> libraries;
}
static class LibraryAttribution {
String copyrightHolder;
String license;
String libraryName;
String getCopyrightHolder() {
return copyrightHolder;
}
@Keep
String getLicense() {
return license;
}
String getLibraryName() {
return libraryName;
}
}
}

@ -0,0 +1,61 @@
package org.tasks.activities.attribution
import android.content.Context
import androidx.annotation.Keep
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import com.google.gson.GsonBuilder
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
class AttributionViewModel : ViewModel() {
private val attributions = MutableLiveData<List<LibraryAttribution>?>()
private val disposables = CompositeDisposable()
private var loaded = false
fun observe(activity: AppCompatActivity, observer: Observer<List<LibraryAttribution>?>) {
attributions.observe(activity, observer)
load(activity)
}
private fun load(context: Context) {
if (loaded) {
return
}
loaded = true
disposables.add(
Single.fromCallable {
val licenses = context.assets.open("licenses.json")
val reader = InputStreamReader(licenses, StandardCharsets.UTF_8)
val list = GsonBuilder().create().fromJson(reader, AttributionList::class.java)
list.libraries
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ value: List<LibraryAttribution>? -> attributions.setValue(value) }) { t: Throwable? -> Timber.e(t) })
}
override fun onCleared() {
disposables.dispose()
}
internal class AttributionList {
var libraries: List<LibraryAttribution>? = null
}
class LibraryAttribution {
var copyrightHolder: String? = null
@get:Keep
var license: String? = null
var libraryName: String? = null
}
}

@ -1,23 +0,0 @@
package org.tasks.activities.attribution;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import org.tasks.R;
class LicenseHeader extends RecyclerView.ViewHolder {
@BindView(R.id.license_name)
TextView licenseName;
LicenseHeader(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
void bind(String license) {
licenseName.setText(license);
}
}

@ -0,0 +1,22 @@
package org.tasks.activities.attribution
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import butterknife.ButterKnife
import org.tasks.R
internal class LicenseHeader(itemView: View) : RecyclerView.ViewHolder(itemView) {
@BindView(R.id.license_name)
lateinit var licenseName: TextView
init {
ButterKnife.bind(this, itemView)
}
fun bind(license: String?) {
licenseName.text = license
}
}

@ -1,28 +0,0 @@
package org.tasks.activities.attribution;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import org.tasks.R;
class LicenseRow extends RecyclerView.ViewHolder {
@BindView(R.id.copyright_holder)
TextView copyrightHolder;
@BindView(R.id.libraries)
TextView libraries;
LicenseRow(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
void bind(String copyrightHolder, String libraries) {
this.copyrightHolder.setText(copyrightHolder);
this.libraries.setText(libraries);
}
}

@ -0,0 +1,25 @@
package org.tasks.activities.attribution
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import butterknife.ButterKnife
import org.tasks.R
internal class LicenseRow(itemView: View) : RecyclerView.ViewHolder(itemView) {
@BindView(R.id.copyright_holder)
lateinit var copyrightHolder: TextView
@BindView(R.id.libraries)
lateinit var libraries: TextView
init {
ButterKnife.bind(this, itemView)
}
fun bind(copyrightHolder: String?, libraries: String?) {
this.copyrightHolder.text = copyrightHolder
this.libraries.text = libraries
}
}
Loading…
Cancel
Save