mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-25 20:23:19 +00:00
Convert AppUpdatesSettingsFragment to compose.
This commit is contained in:
committed by
Jeffrey Starke
parent
d92286297f
commit
92d31ee6ff
@@ -6,60 +6,136 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.updates
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.Rows
|
||||
import org.signal.core.ui.compose.Scaffolds
|
||||
import org.signal.core.ui.compose.SignalPreview
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.compose.ComposeFragment
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobs.ApkUpdateJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
/**
|
||||
* Settings around app updates. Only shown for builds that manage their own app updates.
|
||||
*/
|
||||
class AppUpdatesSettingsFragment : DSLSettingsFragment(R.string.preferences_app_updates__title) {
|
||||
class AppUpdatesSettingsFragment : ComposeFragment() {
|
||||
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
adapter.submitList(getConfiguration().toMappingModelList())
|
||||
private val viewModel: AppUpdatesSettingsViewModel by viewModels()
|
||||
|
||||
@Composable
|
||||
override fun FragmentContent() {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
AppUpdatesSettingsScreen(
|
||||
state = state,
|
||||
callbacks = remember { Callbacks() }
|
||||
)
|
||||
}
|
||||
|
||||
private fun getConfiguration(): DSLConfiguration {
|
||||
return configure {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
private inner class Callbacks : AppUpdatesSettingsCallbacks {
|
||||
override fun onNavigationClick() {
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onAutoUpdateChanged(enabled: Boolean) {
|
||||
SignalStore.apkUpdate.autoUpdate = enabled
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
override fun onCheckForUpdatesClick() {
|
||||
AppDependencies.jobManager.add(ApkUpdateJob())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface AppUpdatesSettingsCallbacks {
|
||||
fun onNavigationClick() = Unit
|
||||
fun onAutoUpdateChanged(enabled: Boolean) = Unit
|
||||
fun onCheckForUpdatesClick() = Unit
|
||||
|
||||
object Empty : AppUpdatesSettingsCallbacks
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AppUpdatesSettingsScreen(
|
||||
state: AppUpdatesSettingsState,
|
||||
callbacks: AppUpdatesSettingsCallbacks
|
||||
) {
|
||||
Scaffolds.Settings(
|
||||
title = stringResource(R.string.preferences_app_updates__title),
|
||||
onNavigationClick = callbacks::onNavigationClick,
|
||||
navigationIcon = ImageVector.vectorResource(R.drawable.symbol_arrow_start_24)
|
||||
) { paddingValues ->
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(paddingValues)
|
||||
) {
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
switchPref(
|
||||
title = DSLSettingsText.from("Automatic updates"),
|
||||
summary = DSLSettingsText.from("Automatically download and install app updates"),
|
||||
isChecked = SignalStore.apkUpdate.autoUpdate,
|
||||
onClick = {
|
||||
SignalStore.apkUpdate.autoUpdate = !SignalStore.apkUpdate.autoUpdate
|
||||
}
|
||||
item {
|
||||
Rows.ToggleRow(
|
||||
checked = state.autoUpdateEnabled,
|
||||
text = "Automatic updates",
|
||||
label = "Automatically download and install app updates",
|
||||
onCheckChanged = callbacks::onAutoUpdateChanged
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Rows.TextRow(
|
||||
text = "Check for updates",
|
||||
label = "Last checked on: ${rememberLastSuccessfulUpdateString(state.lastCheckedTime)}",
|
||||
onClick = callbacks::onCheckForUpdatesClick
|
||||
)
|
||||
}
|
||||
|
||||
clickPref(
|
||||
title = DSLSettingsText.from("Check for updates"),
|
||||
summary = DSLSettingsText.from("Last checked on: $lastSuccessfulUpdateString"),
|
||||
onClick = {
|
||||
AppDependencies.jobManager.add(ApkUpdateJob())
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val lastSuccessfulUpdateString: String
|
||||
get() {
|
||||
val lastUpdateTime = SignalStore.apkUpdate.lastSuccessfulCheck
|
||||
|
||||
return if (lastUpdateTime > 0) {
|
||||
val dateFormat = SimpleDateFormat("MMMM dd, yyyy 'at' h:mma", Locale.US)
|
||||
dateFormat.format(Date(lastUpdateTime))
|
||||
} else {
|
||||
"Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberLastSuccessfulUpdateString(lastUpdateTime: Duration): String {
|
||||
return remember(lastUpdateTime) {
|
||||
if (lastUpdateTime > Duration.ZERO) {
|
||||
val dateFormat = SimpleDateFormat("MMMM dd, yyyy 'at' h:mma", Locale.US)
|
||||
dateFormat.format(Date(lastUpdateTime.inWholeMilliseconds))
|
||||
} else {
|
||||
"Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
private fun AppUpdatesSettingsScreenPreview() {
|
||||
Previews.Preview {
|
||||
AppUpdatesSettingsScreen(
|
||||
state = AppUpdatesSettingsState(
|
||||
lastCheckedTime = System.currentTimeMillis().milliseconds,
|
||||
autoUpdateEnabled = true
|
||||
),
|
||||
callbacks = AppUpdatesSettingsCallbacks.Empty
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.updates
|
||||
|
||||
import kotlin.time.Duration
|
||||
|
||||
data class AppUpdatesSettingsState(
|
||||
val lastCheckedTime: Duration,
|
||||
val autoUpdateEnabled: Boolean
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.updates
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class AppUpdatesSettingsViewModel : ViewModel() {
|
||||
private val internalState = MutableStateFlow(getState())
|
||||
|
||||
val state: StateFlow<AppUpdatesSettingsState> = internalState
|
||||
|
||||
fun refresh() {
|
||||
internalState.update { getState() }
|
||||
}
|
||||
|
||||
private fun getState(): AppUpdatesSettingsState {
|
||||
return AppUpdatesSettingsState(
|
||||
lastCheckedTime = SignalStore.apkUpdate.lastSuccessfulCheck.milliseconds,
|
||||
autoUpdateEnabled = SignalStore.apkUpdate.autoUpdate
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user