forked from agzam/vyatsu-schedule
feat: autoupdater
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
package agzam.vyatsu.ui.settings
|
||||
|
||||
import agzam.vyatsu.BuildConfig
|
||||
import agzam.vyatsu.update.UpdateState
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun SettingsScreen(viewModel: UpdateViewModel) {
|
||||
val autoEnabled by viewModel.autoEnabled.collectAsState()
|
||||
val updateState by viewModel.updateState.collectAsState()
|
||||
|
||||
LazyColumn(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.windowInsetsPadding(WindowInsets.statusBars)
|
||||
) {
|
||||
item { SectionHeader("Обновления") }
|
||||
item {
|
||||
SettingsItem(
|
||||
title = "Автоматические обновления",
|
||||
subtitle = "Проверять и устанавливать новые версии при запуске",
|
||||
trailing = {
|
||||
Switch(
|
||||
checked = autoEnabled,
|
||||
onCheckedChange = { viewModel.setAutoEnabled(it) }
|
||||
)
|
||||
}
|
||||
)
|
||||
SettingsDivider()
|
||||
}
|
||||
item {
|
||||
SettingsItem(
|
||||
title = "Проверить наличие обновлений",
|
||||
subtitle = updateStatusText(updateState),
|
||||
onClick = { viewModel.checkNow() }
|
||||
)
|
||||
SettingsDivider()
|
||||
}
|
||||
if (updateState is UpdateState.Available || updateState is UpdateState.ReadyToInstall) {
|
||||
item {
|
||||
SettingsItem(
|
||||
title = "Установить обновление",
|
||||
subtitle = installHint(updateState, viewModel),
|
||||
onClick = {
|
||||
when (updateState) {
|
||||
is UpdateState.Available -> viewModel.downloadAndInstall()
|
||||
is UpdateState.ReadyToInstall -> viewModel.installDownloadedApk()
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
)
|
||||
SettingsDivider()
|
||||
}
|
||||
}
|
||||
|
||||
item { SectionHeader("О приложении") }
|
||||
item {
|
||||
SettingsItem(
|
||||
title = "Версия",
|
||||
trailing = {
|
||||
Text(
|
||||
BuildConfig.VERSION_NAME,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
)
|
||||
SettingsDivider()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateStatusText(state: UpdateState): String = when (state) {
|
||||
is UpdateState.Idle -> "Проверить сейчас"
|
||||
is UpdateState.Checking -> "Проверка…"
|
||||
is UpdateState.UpToDate -> "Установлена последняя версия"
|
||||
is UpdateState.Available -> "Доступна версия ${state.version}"
|
||||
is UpdateState.Downloading -> "Скачивание: ${state.progress?.let { "$it%" } ?: "…"}"
|
||||
is UpdateState.ReadyToInstall -> "Обновление скачано, нажмите для установки"
|
||||
is UpdateState.Failed -> "Ошибка: ${state.message}"
|
||||
}
|
||||
|
||||
private fun installHint(state: UpdateState, viewModel: UpdateViewModel): String = when {
|
||||
state is UpdateState.ReadyToInstall && !viewModel.canRequestInstalls() ->
|
||||
"Разрешите установку приложений из этого источника"
|
||||
else -> "Нажмите, чтобы продолжить"
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SectionHeader(title: String) {
|
||||
Text(
|
||||
title,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SettingsItem(
|
||||
title: String,
|
||||
subtitle: String? = null,
|
||||
trailing: (@Composable () -> Unit)? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
) {
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 48.dp)
|
||||
.then(if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(title, style = MaterialTheme.typography.bodyLarge)
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
subtitle,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
}
|
||||
trailing?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SettingsDivider() {
|
||||
HorizontalDivider(Modifier.padding(horizontal = 16.dp))
|
||||
}
|
||||
Reference in New Issue
Block a user