From 82307a9d7872a9a192c0635b84d287873092e87d Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Mon, 27 Apr 2020 11:05:34 -0500 Subject: [PATCH] Convert attribution classes to kotlin --- .../attribution/AttributionActivity.java | 87 ------------------- .../attribution/AttributionActivity.kt | 66 ++++++++++++++ .../attribution/AttributionAdapter.java | 47 ---------- .../attribution/AttributionAdapter.kt | 30 +++++++ .../attribution/AttributionRow.java | 39 --------- .../activities/attribution/AttributionRow.kt | 22 +++++ .../attribution/AttributionViewModel.java | 77 ---------------- .../attribution/AttributionViewModel.kt | 61 +++++++++++++ .../activities/attribution/LicenseHeader.java | 23 ----- .../activities/attribution/LicenseHeader.kt | 22 +++++ .../activities/attribution/LicenseRow.java | 28 ------ .../activities/attribution/LicenseRow.kt | 25 ++++++ 12 files changed, 226 insertions(+), 301 deletions(-) delete mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionActivity.java create mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionActivity.kt delete mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.java create mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.kt delete mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionRow.java create mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionRow.kt delete mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.java create mode 100644 app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.kt delete mode 100644 app/src/main/java/org/tasks/activities/attribution/LicenseHeader.java create mode 100644 app/src/main/java/org/tasks/activities/attribution/LicenseHeader.kt delete mode 100644 app/src/main/java/org/tasks/activities/attribution/LicenseRow.java create mode 100644 app/src/main/java/org/tasks/activities/attribution/LicenseRow.kt diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionActivity.java b/app/src/main/java/org/tasks/activities/attribution/AttributionActivity.java deleted file mode 100644 index 2e196248b..000000000 --- a/app/src/main/java/org/tasks/activities/attribution/AttributionActivity.java +++ /dev/null @@ -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 libraryAttributions) { - List rows = new ArrayList<>(); - ImmutableListMultimap index = - Multimaps.index(libraryAttributions, LibraryAttribution::getLicense); - ArrayList licenses = new ArrayList<>(index.keySet()); - Collections.sort(licenses); - for (String license : licenses) { - rows.add(new AttributionRow(license)); - ImmutableList libraries = index.get(license); - ImmutableListMultimap idx = - Multimaps.index(libraries, LibraryAttribution::getCopyrightHolder); - List copyrightHolders = newArrayList(idx.keySet()); - Collections.sort(copyrightHolders); - for (String copyrightHolder : copyrightHolders) { - List 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); - } -} diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionActivity.kt b/app/src/main/java/org/tasks/activities/attribution/AttributionActivity.kt new file mode 100644 index 000000000..54b14861d --- /dev/null +++ b/app/src/main/java/org/tasks/activities/attribution/AttributionActivity.kt @@ -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? -> + updateAttributions(libraryAttributions!!) + }) + } + + private fun updateAttributions(libraryAttributions: List) { + val rows = ArrayList() + 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): Iterable { + 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) +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.java b/app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.java deleted file mode 100644 index 3f7e7eb11..000000000 --- a/app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.java +++ /dev/null @@ -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 { - - private final List rows; - - AttributionAdapter(List 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(); - } -} diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.kt b/app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.kt new file mode 100644 index 000000000..3da3a788d --- /dev/null +++ b/app/src/main/java/org/tasks/activities/attribution/AttributionAdapter.kt @@ -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) : RecyclerView.Adapter() { + 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 +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionRow.java b/app/src/main/java/org/tasks/activities/attribution/AttributionRow.java deleted file mode 100644 index af319a31c..000000000 --- a/app/src/main/java/org/tasks/activities/attribution/AttributionRow.java +++ /dev/null @@ -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; - } -} diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionRow.kt b/app/src/main/java/org/tasks/activities/attribution/AttributionRow.kt new file mode 100644 index 000000000..c042c3d82 --- /dev/null +++ b/app/src/main/java/org/tasks/activities/attribution/AttributionRow.kt @@ -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 + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.java b/app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.java deleted file mode 100644 index 8950fab3b..000000000 --- a/app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.java +++ /dev/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> attributions = new MutableLiveData<>(); - private final CompositeDisposable disposables = new CompositeDisposable(); - private boolean loaded; - - void observe(AppCompatActivity activity, Observer> 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 libraries; - } - - static class LibraryAttribution { - String copyrightHolder; - String license; - String libraryName; - - String getCopyrightHolder() { - return copyrightHolder; - } - - @Keep - String getLicense() { - return license; - } - - String getLibraryName() { - return libraryName; - } - } -} diff --git a/app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.kt b/app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.kt new file mode 100644 index 000000000..70d1d2175 --- /dev/null +++ b/app/src/main/java/org/tasks/activities/attribution/AttributionViewModel.kt @@ -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?>() + private val disposables = CompositeDisposable() + private var loaded = false + + fun observe(activity: AppCompatActivity, observer: Observer?>) { + 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? -> attributions.setValue(value) }) { t: Throwable? -> Timber.e(t) }) + } + + override fun onCleared() { + disposables.dispose() + } + + internal class AttributionList { + var libraries: List? = null + } + + class LibraryAttribution { + var copyrightHolder: String? = null + + @get:Keep + var license: String? = null + var libraryName: String? = null + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/activities/attribution/LicenseHeader.java b/app/src/main/java/org/tasks/activities/attribution/LicenseHeader.java deleted file mode 100644 index 704b11f61..000000000 --- a/app/src/main/java/org/tasks/activities/attribution/LicenseHeader.java +++ /dev/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); - } -} diff --git a/app/src/main/java/org/tasks/activities/attribution/LicenseHeader.kt b/app/src/main/java/org/tasks/activities/attribution/LicenseHeader.kt new file mode 100644 index 000000000..8eba797f9 --- /dev/null +++ b/app/src/main/java/org/tasks/activities/attribution/LicenseHeader.kt @@ -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 + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/activities/attribution/LicenseRow.java b/app/src/main/java/org/tasks/activities/attribution/LicenseRow.java deleted file mode 100644 index 26a0cd12a..000000000 --- a/app/src/main/java/org/tasks/activities/attribution/LicenseRow.java +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/activities/attribution/LicenseRow.kt b/app/src/main/java/org/tasks/activities/attribution/LicenseRow.kt new file mode 100644 index 000000000..7d9aef9b7 --- /dev/null +++ b/app/src/main/java/org/tasks/activities/attribution/LicenseRow.kt @@ -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 + } +} \ No newline at end of file