Update: Migrate Installed to use Compose solely

This commit is contained in:
machiav3lli 2022-05-03 03:26:07 +02:00
parent e61572ed8c
commit 467ee02cde

View File

@ -30,12 +30,15 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@ -44,7 +47,6 @@ import com.looker.droidify.R
import com.looker.droidify.content.Preferences
import com.looker.droidify.database.entity.Product
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.databinding.FragmentComposeBinding
import com.looker.droidify.service.SyncService
import com.looker.droidify.ui.activities.PrefsActivityX
import com.looker.droidify.ui.compose.ProductsHorizontalRecycler
@ -57,8 +59,6 @@ import com.looker.droidify.utility.isDarkTheme
class InstalledFragment : MainNavFragmentX() {
private lateinit var binding: FragmentComposeBinding
override val primarySource = Source.INSTALLED
override val secondarySource = Source.UPDATES
@ -70,9 +70,9 @@ class InstalledFragment : MainNavFragmentX() {
savedInstanceState: Bundle?,
): View {
super.onCreate(savedInstanceState)
binding = FragmentComposeBinding.inflate(inflater, container, false)
binding.lifecycleOwner = this
return binding.root
return ComposeView(requireContext()).apply {
setContent { InstalledPage() }
}
}
override fun setupLayout() {
@ -83,161 +83,158 @@ class InstalledFragment : MainNavFragmentX() {
// Avoid the compiler using the same class as observer
Log.d(this::class.java.canonicalName, this.toString())
}
viewModel.primaryProducts.observe(viewLifecycleOwner) {
redrawPage(it, viewModel.secondaryProducts.value)
}
viewModel.secondaryProducts.observe(viewLifecycleOwner) {
redrawPage(viewModel.primaryProducts.value, it)
}
}
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
private fun redrawPage(primaryList: List<Product>?, secondaryList: List<Product>?) {
binding.composeView.setContent {
AppTheme(
darkTheme = when (Preferences[Preferences.Key.Theme]) {
is Preferences.Theme.System -> isSystemInDarkTheme()
is Preferences.Theme.AmoledSystem -> isSystemInDarkTheme()
else -> isDarkTheme
}
) {
Scaffold(
// TODO add the topBar to the activity instead of the fragments
topBar = {
TopBar(title = stringResource(id = R.string.application_name)) {
ExpandableSearchAction(
query = viewModel.searchQuery.value.orEmpty(),
onClose = {
viewModel.searchQuery.value = ""
},
onQueryChanged = { query ->
if (isResumed && query != viewModel.searchQuery.value)
viewModel.setSearchQuery(query)
}
)
TopBarAction(icon = Icons.Rounded.Sync) {
mainActivityX.syncConnection.binder?.sync(SyncService.SyncRequest.MANUAL)
}
TopBarAction(icon = Icons.Rounded.Settings) {
startActivity(Intent(context, PrefsActivityX::class.java))
}
}
}
) { padding ->
var updatesVisible by remember(secondaryList) { mutableStateOf(true) }
@Composable
private fun InstalledPage() {
val primaryList by viewModel.primaryProducts.observeAsState(null)
val secondaryList by viewModel.secondaryProducts.observeAsState(null)
val searchQuery by viewModel.searchQuery.observeAsState("")
Column(
Modifier
.padding(padding)
.background(MaterialTheme.colorScheme.background)
.fillMaxSize()
) {
AnimatedVisibility(visible = secondaryList.orEmpty().isNotEmpty()) {
Column {
Row(
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
ElevatedButton(
colors = ButtonDefaults.elevatedButtonColors(
contentColor = MaterialTheme.colorScheme.primary
),
onClick = { updatesVisible = !updatesVisible }
) {
Text(
modifier = Modifier.padding(start = 4.dp),
text = stringResource(id = R.string.updates),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleSmall
)
Spacer(modifier = Modifier.width(8.dp))
Icon(
modifier = Modifier.size(18.dp),
painter = painterResource(id = if (updatesVisible) R.drawable.ic_arrow_up else R.drawable.ic_arrow_down),
contentDescription = stringResource(id = R.string.updates)
)
}
Spacer(modifier = Modifier.weight(1f))
Chip(
shape = MaterialTheme.shapes.medium,
colors = ChipDefaults.chipColors(
backgroundColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
),
onClick = {
viewModel.secondaryProducts.value?.let {
mainActivityX.syncConnection.binder?.updateApps(
it.map(
Product::toItem
)
)
}
}
) {
Icon(
modifier = Modifier.size(18.dp),
painter = painterResource(id = R.drawable.ic_download),
contentDescription = stringResource(id = R.string.update_all)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(id = R.string.update_all))
}
}
AnimatedVisibility(visible = updatesVisible) {
ProductsHorizontalRecycler(
secondaryList,
repositories
) { item ->
AppSheetX(item.packageName)
.showNow(
parentFragmentManager,
"Product ${item.packageName}"
)
}
}
}
}
Row(
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(id = R.string.installed_applications),
modifier = Modifier.weight(1f),
)
Chip(
shape = MaterialTheme.shapes.medium,
colors = ChipDefaults.chipColors(
backgroundColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
),
onClick = { } // TODO add sort & filter
) {
Icon(
modifier = Modifier.size(18.dp),
painter = painterResource(id = R.drawable.ic_sort),
contentDescription = stringResource(id = R.string.sort_filter)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(id = R.string.sort_filter))
}
}
ProductsVerticalRecycler(primaryList?.sortedBy(Product::label),
repositories,
modifier = Modifier
.fillMaxWidth()
.weight(1f),
onUserClick = { item ->
AppSheetX(item.packageName)
.showNow(parentFragmentManager, "Product ${item.packageName}")
AppTheme(
darkTheme = when (Preferences[Preferences.Key.Theme]) {
is Preferences.Theme.System -> isSystemInDarkTheme()
is Preferences.Theme.AmoledSystem -> isSystemInDarkTheme()
else -> isDarkTheme
}
) {
Scaffold(
// TODO add the topBar to the activity instead of the fragments
topBar = {
TopBar(title = stringResource(id = R.string.application_name)) {
ExpandableSearchAction(
query = searchQuery.orEmpty(),
onClose = {
viewModel.setSearchQuery("")
},
onFavouriteClick = {},
onInstallClick = {
mainActivityX.syncConnection.binder?.installApps(listOf(it))
onQueryChanged = { query ->
if (isResumed && query != searchQuery)
viewModel.setSearchQuery(query)
}
)
TopBarAction(icon = Icons.Rounded.Sync) {
mainActivityX.syncConnection.binder?.sync(SyncService.SyncRequest.MANUAL)
}
TopBarAction(icon = Icons.Rounded.Settings) {
startActivity(Intent(context, PrefsActivityX::class.java))
}
}
}
) { padding ->
var updatesVisible by remember(secondaryList) { mutableStateOf(true) }
Column(
Modifier
.padding(padding)
.background(MaterialTheme.colorScheme.background)
.fillMaxSize()
) {
AnimatedVisibility(visible = secondaryList.orEmpty().isNotEmpty()) {
Column {
Row(
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
ElevatedButton(
colors = ButtonDefaults.elevatedButtonColors(
contentColor = MaterialTheme.colorScheme.primary
),
onClick = { updatesVisible = !updatesVisible }
) {
Text(
modifier = Modifier.padding(start = 4.dp),
text = stringResource(id = R.string.updates),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleSmall
)
Spacer(modifier = Modifier.width(8.dp))
Icon(
modifier = Modifier.size(18.dp),
painter = painterResource(id = if (updatesVisible) R.drawable.ic_arrow_up else R.drawable.ic_arrow_down),
contentDescription = stringResource(id = R.string.updates)
)
}
Spacer(modifier = Modifier.weight(1f))
Chip(
shape = MaterialTheme.shapes.medium,
colors = ChipDefaults.chipColors(
backgroundColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
),
onClick = {
secondaryList?.let {
mainActivityX.syncConnection.binder?.updateApps(
it.map(
Product::toItem
)
)
}
}
) {
Icon(
modifier = Modifier.size(18.dp),
painter = painterResource(id = R.drawable.ic_download),
contentDescription = stringResource(id = R.string.update_all)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(id = R.string.update_all))
}
}
AnimatedVisibility(visible = updatesVisible) {
ProductsHorizontalRecycler(
secondaryList,
repositories
) { item ->
AppSheetX(item.packageName)
.showNow(
parentFragmentManager,
"Product ${item.packageName}"
)
}
}
}
}
Row(
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(id = R.string.installed_applications),
modifier = Modifier.weight(1f),
)
Chip(
shape = MaterialTheme.shapes.medium,
colors = ChipDefaults.chipColors(
backgroundColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
),
onClick = { } // TODO add sort & filter
) {
Icon(
modifier = Modifier.size(18.dp),
painter = painterResource(id = R.drawable.ic_sort),
contentDescription = stringResource(id = R.string.sort_filter)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(id = R.string.sort_filter))
}
}
ProductsVerticalRecycler(primaryList?.sortedBy(Product::label),
repositories,
modifier = Modifier
.fillMaxWidth()
.weight(1f),
onUserClick = { item ->
AppSheetX(item.packageName)
.showNow(parentFragmentManager, "Product ${item.packageName}")
},
onFavouriteClick = {},
onInstallClick = {
mainActivityX.syncConnection.binder?.installApps(listOf(it))
}
)
}
}
}
}