mirror of https://github.com/tasks/tasks
Convert attribution activity to compose
parent
0dbd0551d1
commit
a8e83a03b1
@ -1,64 +1,36 @@
|
|||||||
package org.tasks.activities.attribution
|
package org.tasks.activities.attribution
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.activity.viewModels
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import butterknife.BindView
|
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
import com.google.common.collect.Multimaps
|
import com.google.android.material.composethemeadapter.MdcTheme
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.tasks.R
|
import org.tasks.R
|
||||||
import org.tasks.activities.attribution.AttributionViewModel.LibraryAttribution
|
import org.tasks.compose.AttributionList.AttributionList
|
||||||
|
import org.tasks.databinding.ActivityAttributionsBinding
|
||||||
import org.tasks.injection.ThemedInjectingAppCompatActivity
|
import org.tasks.injection.ThemedInjectingAppCompatActivity
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class AttributionActivity : ThemedInjectingAppCompatActivity() {
|
class AttributionActivity : ThemedInjectingAppCompatActivity() {
|
||||||
@BindView(R.id.toolbar)
|
val viewModel: AttributionViewModel by viewModels()
|
||||||
lateinit var toolbar: Toolbar
|
|
||||||
|
|
||||||
@BindView(R.id.list)
|
|
||||||
lateinit var recyclerView: RecyclerView
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_attributions)
|
val binding = ActivityAttributionsBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
ButterKnife.bind(this)
|
ButterKnife.bind(this)
|
||||||
toolbar.setTitle(R.string.third_party_licenses)
|
with(binding.toolbar.toolbar) {
|
||||||
toolbar.setNavigationIcon(R.drawable.ic_outline_arrow_back_24px)
|
setTitle(R.string.third_party_licenses)
|
||||||
toolbar.setNavigationOnClickListener { finish() }
|
setNavigationIcon(R.drawable.ic_outline_arrow_back_24px)
|
||||||
themeColor.apply(toolbar)
|
setNavigationOnClickListener { finish() }
|
||||||
recyclerView.layoutManager = LinearLayoutManager(this)
|
themeColor.apply(this)
|
||||||
}
|
}
|
||||||
|
viewModel.attributions.observe(this) {
|
||||||
override fun onResume() {
|
binding.compose.setContent {
|
||||||
super.onResume()
|
MdcTheme {
|
||||||
ViewModelProvider(this)
|
AttributionList(it)
|
||||||
.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, libraries.sorted().joinToString("\n"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,30 +0,0 @@
|
|||||||
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,22 +0,0 @@
|
|||||||
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,22 +0,0 @@
|
|||||||
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,25 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
package org.tasks.compose
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.Card
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.colorResource
|
||||||
|
import org.tasks.R
|
||||||
|
import org.tasks.activities.attribution.AttributionViewModel.LibraryAttribution
|
||||||
|
import org.tasks.compose.Constants.KEYLINE_FIRST
|
||||||
|
|
||||||
|
object AttributionList {
|
||||||
|
@Composable
|
||||||
|
fun AttributionList(licenses: Map<String, Map<String, List<LibraryAttribution>>>) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
licenses.forEach { (license, libraries) ->
|
||||||
|
Text(
|
||||||
|
license,
|
||||||
|
style = MaterialTheme.typography.h6,
|
||||||
|
color = MaterialTheme.colors.onBackground,
|
||||||
|
modifier = Modifier.padding(KEYLINE_FIRST)
|
||||||
|
)
|
||||||
|
libraries.forEach { (copyrightHolder, libraries) ->
|
||||||
|
LibraryCard(copyrightHolder, libraries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LibraryCard(copyrightHolder: String, libraries: List<LibraryAttribution>) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(Constants.HALF_KEYLINE),
|
||||||
|
backgroundColor = colorResource(R.color.content_background),
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(KEYLINE_FIRST)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
copyrightHolder,
|
||||||
|
style = MaterialTheme.typography.body1,
|
||||||
|
color = MaterialTheme.colors.secondary
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(Constants.HALF_KEYLINE))
|
||||||
|
libraries.forEach {
|
||||||
|
Text(
|
||||||
|
"\u2022 ${it.libraryName!!}",
|
||||||
|
style = MaterialTheme.typography.body2,
|
||||||
|
color = MaterialTheme.colors.onBackground
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
style="@style/CardViewStyle"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
app:cardMaxElevation="1dp"
|
|
||||||
app:cardElevation="1dp"
|
|
||||||
app:cardBackgroundColor="@color/content_background">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:paddingTop="@dimen/keyline_first"
|
|
||||||
android:paddingBottom="@dimen/keyline_first"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/copyright_holder"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingStart="@dimen/keyline_first"
|
|
||||||
android:paddingEnd="@dimen/keyline_first"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textSize="@dimen/sku_details_row_text_size"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/libraries"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingStart="@dimen/keyline_first"
|
|
||||||
android:paddingEnd="@dimen/keyline_first"
|
|
||||||
android:textColor="?android:textColorSecondary"
|
|
||||||
android:textSize="@dimen/sku_details_row_text_size"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<TextView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/license_name"
|
|
||||||
style="@style/TextAppearance"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/keyline_first"
|
|
||||||
android:layout_marginBottom="@dimen/keyline_first"
|
|
||||||
android:layout_marginStart="@dimen/card_view_margin"
|
|
||||||
android:layout_marginEnd="@dimen/card_view_margin"
|
|
||||||
android:paddingStart="@dimen/keyline_first"
|
|
||||||
android:paddingEnd="@dimen/keyline_first"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:textColor="?attr/colorAccent"
|
|
||||||
android:textSize="@dimen/sku_details_row_text_size"
|
|
||||||
app:fontFamily="sans-serif-medium"/>
|
|
||||||
Loading…
Reference in New Issue