mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Add prefs & page for app updates
This commit is contained in:
parent
14de2442bd
commit
cbc680da7d
9 changed files with 652 additions and 359 deletions
|
|
@ -332,29 +332,36 @@ sealed interface AppPreference<T> {
|
|||
getter = { },
|
||||
setter = { prefs, _ -> prefs },
|
||||
)
|
||||
// val AutoCheckForUpdates =
|
||||
// AppSwitchPreference(
|
||||
// title = R.string.check_for_updates,
|
||||
// prefKey = R.string.pref_key_auto_check_updates,
|
||||
// defaultValue = true,
|
||||
// getter = { it.updatePreferences.checkForUpdates },
|
||||
// setter = { prefs, value ->
|
||||
// prefs.updateUpdatePreferences { checkForUpdates = value }
|
||||
// },
|
||||
// summaryOn = R.string.enabled,
|
||||
// summaryOff = R.string.disabled,
|
||||
// )
|
||||
|
||||
// val UpdateUrl =
|
||||
// AppStringPreference(
|
||||
// title = R.string.update_url,
|
||||
// defaultValue = "",
|
||||
// getter = { it.updatePreferences.updateUrl },
|
||||
// setter = { prefs, value ->
|
||||
// prefs.updateUpdatePreferences { updateUrl = value }
|
||||
// },
|
||||
// summary = R.string.update_url_summary,
|
||||
// )
|
||||
val Update =
|
||||
AppClickablePreference(
|
||||
title = R.string.check_for_updates,
|
||||
getter = { },
|
||||
setter = { prefs, _ -> prefs },
|
||||
)
|
||||
|
||||
val AutoCheckForUpdates =
|
||||
AppSwitchPreference(
|
||||
title = R.string.auto_check_for_updates,
|
||||
defaultValue = true,
|
||||
getter = { it.autoCheckForUpdates },
|
||||
setter = { prefs, value ->
|
||||
prefs.update { autoCheckForUpdates = value }
|
||||
},
|
||||
summaryOn = R.string.enabled,
|
||||
summaryOff = R.string.disabled,
|
||||
)
|
||||
|
||||
val UpdateUrl =
|
||||
AppStringPreference(
|
||||
title = R.string.update_url,
|
||||
defaultValue = "", // TODO
|
||||
getter = { it.updateUrl },
|
||||
setter = { prefs, value ->
|
||||
prefs.update { updateUrl = value }
|
||||
},
|
||||
summary = R.string.update_url_summary,
|
||||
)
|
||||
|
||||
val OssLicenseInfo =
|
||||
AppDestinationPreference(
|
||||
|
|
@ -465,7 +472,7 @@ val basicPreferences =
|
|||
preferences =
|
||||
listOf(
|
||||
AppPreference.InstalledVersion,
|
||||
AppPreference.OssLicenseInfo,
|
||||
AppPreference.Update,
|
||||
),
|
||||
),
|
||||
PreferenceGroup(
|
||||
|
|
@ -494,6 +501,21 @@ val advancedPreferences =
|
|||
AppPreference.PlaybackDebugInfo,
|
||||
),
|
||||
),
|
||||
PreferenceGroup(
|
||||
title = R.string.updates,
|
||||
preferences =
|
||||
listOf(
|
||||
AppPreference.AutoCheckForUpdates,
|
||||
AppPreference.UpdateUrl,
|
||||
),
|
||||
),
|
||||
PreferenceGroup(
|
||||
title = R.string.more,
|
||||
preferences =
|
||||
listOf(
|
||||
AppPreference.OssLicenseInfo,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
data class AppSwitchPreference(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ class AppPreferencesSerializer
|
|||
AppPreferences
|
||||
.newBuilder()
|
||||
.apply {
|
||||
updateUrl = AppPreference.UpdateUrl.defaultValue
|
||||
autoCheckForUpdates = AppPreference.AutoCheckForUpdates.defaultValue
|
||||
|
||||
playbackPreferences =
|
||||
PlaybackPreferences
|
||||
.newBuilder()
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ sealed class Destination(
|
|||
constructor(item: BaseItem) : this(item.id, item.resumeMs ?: 0, item)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data object UpdateApp : Destination(true)
|
||||
|
||||
@Serializable
|
||||
data object License : Destination(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.github.damontecres.dolphin.ui.main.HomePage
|
|||
import com.github.damontecres.dolphin.ui.main.SearchPage
|
||||
import com.github.damontecres.dolphin.ui.playback.PlaybackPage
|
||||
import com.github.damontecres.dolphin.ui.preferences.PreferencesPage
|
||||
import com.github.damontecres.dolphin.ui.setup.InstallUpdatePage
|
||||
import com.github.damontecres.dolphin.ui.setup.SwitchServerContent
|
||||
import com.github.damontecres.dolphin.ui.setup.SwitchUserContent
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
|
|
@ -134,6 +135,8 @@ fun DestinationContent(
|
|||
}
|
||||
}
|
||||
|
||||
Destination.UpdateApp -> InstallUpdatePage(preferences, modifier)
|
||||
|
||||
Destination.License -> LicenseInfo(modifier)
|
||||
|
||||
Destination.Search ->
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -45,22 +46,21 @@ import com.github.damontecres.dolphin.preferences.advancedPreferences
|
|||
import com.github.damontecres.dolphin.preferences.basicPreferences
|
||||
import com.github.damontecres.dolphin.preferences.uiPreferences
|
||||
import com.github.damontecres.dolphin.ui.ifElse
|
||||
import com.github.damontecres.dolphin.ui.nav.Destination
|
||||
import com.github.damontecres.dolphin.ui.playOnClickSound
|
||||
import com.github.damontecres.dolphin.ui.playSoundOnFocus
|
||||
import com.github.damontecres.dolphin.ui.setup.UpdateViewModel
|
||||
import com.github.damontecres.dolphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.dolphin.util.ExceptionHandler
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
data class Release(
|
||||
val version: String,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun PreferencesContent(
|
||||
initialPreferences: AppPreferences,
|
||||
preferenceScreenOption: PreferenceScreenOption,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: PreferencesViewModel = hiltViewModel(),
|
||||
updateVM: UpdateViewModel = hiltViewModel(),
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
@ -74,19 +74,16 @@ fun PreferencesContent(
|
|||
}
|
||||
}
|
||||
|
||||
val movementSounds = true
|
||||
val installedVersion =
|
||||
remember { context.packageManager.getPackageInfo(context.packageName, 0).versionName }
|
||||
var updateVersion by remember { mutableStateOf<Release?>(null) }
|
||||
val updateAvailable = false
|
||||
// remember(updateVersion) { updateVersion?.version?.isGreaterThan(installedVersion) == true }
|
||||
val release by updateVM.release.observeAsState(null)
|
||||
LaunchedEffect(Unit) {
|
||||
if (preferences.autoCheckForUpdates) {
|
||||
updateVM.init(preferences.updateUrl)
|
||||
}
|
||||
}
|
||||
|
||||
// if (preferences.updatePreferences.checkForUpdates) {
|
||||
// LaunchedEffect(Unit) {
|
||||
// updateVersion =
|
||||
// UpdateChecker.getLatestRelease(context, preferences.updatePreferences.updateUrl)
|
||||
// }
|
||||
// }
|
||||
val movementSounds = true
|
||||
val installedVersion = updateVM.currentVersion
|
||||
val updateAvailable = release?.version?.isGreaterThan(installedVersion) ?: false
|
||||
|
||||
val prefList =
|
||||
when (preferenceScreenOption) {
|
||||
|
|
@ -135,22 +132,9 @@ fun PreferencesContent(
|
|||
.padding(vertical = 8.dp),
|
||||
)
|
||||
}
|
||||
prefList.forEachIndexed { groupIndex, group ->
|
||||
item {
|
||||
Text(
|
||||
text = stringResource(group.title),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
textAlign = TextAlign.Start,
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp, bottom = 4.dp),
|
||||
)
|
||||
}
|
||||
if (updateAvailable &&
|
||||
groupIndex == 0 &&
|
||||
preferenceScreenOption == PreferenceScreenOption.BASIC
|
||||
if (preferenceScreenOption == PreferenceScreenOption.BASIC &&
|
||||
preferences.autoCheckForUpdates &&
|
||||
updateAvailable
|
||||
) {
|
||||
item {
|
||||
val updateFocusRequester = remember { FocusRequester() }
|
||||
|
|
@ -164,11 +148,9 @@ fun PreferencesContent(
|
|||
title = stringResource(R.string.install_update),
|
||||
onClick = {
|
||||
if (movementSounds) playOnClickSound(context)
|
||||
updateVersion?.let {
|
||||
// navigationManager.navigateTo(Destination.UpdateApp(it))
|
||||
}
|
||||
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
||||
},
|
||||
summary = updateVersion?.version?.toString(),
|
||||
summary = release?.version?.toString(),
|
||||
modifier =
|
||||
Modifier
|
||||
.focusRequester(updateFocusRequester)
|
||||
|
|
@ -176,6 +158,19 @@ fun PreferencesContent(
|
|||
)
|
||||
}
|
||||
}
|
||||
prefList.forEachIndexed { groupIndex, group ->
|
||||
item {
|
||||
Text(
|
||||
text = stringResource(group.title),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
textAlign = TextAlign.Start,
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp, bottom = 4.dp),
|
||||
)
|
||||
}
|
||||
group.preferences.forEachIndexed { prefIndex, pref ->
|
||||
pref as AppPreference<Any>
|
||||
item {
|
||||
|
|
@ -210,57 +205,45 @@ fun PreferencesContent(
|
|||
)
|
||||
}
|
||||
|
||||
// AppPreference.Update -> {
|
||||
// ClickPreference(
|
||||
// title =
|
||||
// if (updateVersion != null && updateAvailable) {
|
||||
// stringResource(R.string.install_update)
|
||||
// } else if (!preferences.updatePreferences.checkForUpdates && updateVersion == null) {
|
||||
// stringResource(R.string.check_for_updates)
|
||||
// } else {
|
||||
// stringResource(R.string.no_update_available)
|
||||
// },
|
||||
// onClick = {
|
||||
// if (movementSounds) playOnClickSound(context)
|
||||
// if (updateVersion != null && updateAvailable) {
|
||||
// updateVersion?.let {
|
||||
// navigationManager.navigate(
|
||||
// Destination.UpdateApp(it),
|
||||
// )
|
||||
// }
|
||||
// } else {
|
||||
// scope.launch {
|
||||
// updateVersion =
|
||||
// UpdateChecker.getLatestRelease(
|
||||
// context,
|
||||
// preferences.updatePreferences.updateUrl,
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// onLongClick = {
|
||||
// if (movementSounds) playOnClickSound(context)
|
||||
// updateVersion?.let {
|
||||
// navigationManager.navigate(
|
||||
// Destination.UpdateApp(it),
|
||||
// )
|
||||
// }
|
||||
// },
|
||||
// summary =
|
||||
// if (updateAvailable) {
|
||||
// updateVersion?.version?.toString()
|
||||
// } else {
|
||||
// null
|
||||
// },
|
||||
// interactionSource = interactionSource,
|
||||
// modifier =
|
||||
// Modifier
|
||||
// .ifElse(
|
||||
// groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
||||
// Modifier.focusRequester(focusRequester),
|
||||
// ),
|
||||
// )
|
||||
// }
|
||||
AppPreference.Update -> {
|
||||
ClickPreference(
|
||||
title =
|
||||
if (release != null && updateAvailable) {
|
||||
stringResource(R.string.install_update)
|
||||
} else if (!preferences.autoCheckForUpdates && release == null) {
|
||||
stringResource(R.string.check_for_updates)
|
||||
} else {
|
||||
stringResource(R.string.no_update_available)
|
||||
},
|
||||
onClick = {
|
||||
if (movementSounds) playOnClickSound(context)
|
||||
if (release != null && updateAvailable) {
|
||||
release?.let {
|
||||
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
||||
}
|
||||
} else {
|
||||
updateVM.init(preferences.updateUrl)
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
if (movementSounds) playOnClickSound(context)
|
||||
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
||||
},
|
||||
summary =
|
||||
if (updateAvailable) {
|
||||
release?.version?.toString()
|
||||
} else {
|
||||
null
|
||||
},
|
||||
interactionSource = interactionSource,
|
||||
modifier =
|
||||
Modifier
|
||||
.ifElse(
|
||||
groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
||||
Modifier.focusRequester(focusRequester),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val value = pref.getter.invoke(preferences)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,263 @@
|
|||
package com.github.damontecres.dolphin.ui.setup
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.gestures.scrollBy
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.key.Key
|
||||
import androidx.compose.ui.input.key.KeyEventType
|
||||
import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.key.onKeyEvent
|
||||
import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.tv.material3.Button
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import androidx.tv.material3.surfaceColorAtElevation
|
||||
import com.github.damontecres.dolphin.preferences.UserPreferences
|
||||
import com.github.damontecres.dolphin.ui.PreviewTvSpec
|
||||
import com.github.damontecres.dolphin.ui.components.ErrorMessage
|
||||
import com.github.damontecres.dolphin.ui.components.LoadingPage
|
||||
import com.github.damontecres.dolphin.ui.nav.NavigationManager
|
||||
import com.github.damontecres.dolphin.ui.theme.DolphinTheme
|
||||
import com.github.damontecres.dolphin.util.ExceptionHandler
|
||||
import com.github.damontecres.dolphin.util.LoadingExceptionHandler
|
||||
import com.github.damontecres.dolphin.util.LoadingState
|
||||
import com.github.damontecres.dolphin.util.Release
|
||||
import com.github.damontecres.dolphin.util.UpdateChecker
|
||||
import com.github.damontecres.dolphin.util.Version
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class UpdateViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
val updater: UpdateChecker,
|
||||
val navigationManager: NavigationManager,
|
||||
) : ViewModel() {
|
||||
val loading = MutableLiveData<LoadingState>(LoadingState.Pending)
|
||||
val release = MutableLiveData<Release?>(null)
|
||||
|
||||
val currentVersion = updater.getInstalledVersion()
|
||||
|
||||
fun init(updateUrl: String) {
|
||||
loading.value = LoadingState.Loading
|
||||
viewModelScope.launch(Dispatchers.IO + LoadingExceptionHandler(loading, "Failed to check for update")) {
|
||||
val release = updater.getLatestRelease(updateUrl)
|
||||
withContext(Dispatchers.Main) {
|
||||
this@UpdateViewModel.release.value = release
|
||||
loading.value = LoadingState.Success
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun installRelease(release: Release) {
|
||||
viewModelScope.launch(Dispatchers.IO + LoadingExceptionHandler(loading, "Failed to install update")) {
|
||||
updater.installRelease(release)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun InstallUpdatePage(
|
||||
preferences: UserPreferences,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: UpdateViewModel = hiltViewModel(),
|
||||
) {
|
||||
val loading by viewModel.loading.observeAsState(LoadingState.Pending)
|
||||
val release by viewModel.release.observeAsState(null)
|
||||
LaunchedEffect(Unit) {
|
||||
viewModel.init(preferences.appPreferences.updateUrl)
|
||||
}
|
||||
when (val state = loading) {
|
||||
is LoadingState.Error -> ErrorMessage(state, modifier)
|
||||
LoadingState.Loading,
|
||||
LoadingState.Pending,
|
||||
-> LoadingPage(modifier)
|
||||
|
||||
LoadingState.Success ->
|
||||
release?.let {
|
||||
if (it.version.isGreaterThan(viewModel.currentVersion)) {
|
||||
InstallUpdatePageContent(
|
||||
currentVersion = viewModel.currentVersion,
|
||||
release = it,
|
||||
onInstallRelease = {
|
||||
viewModel.installRelease(it)
|
||||
},
|
||||
onCancel = {
|
||||
viewModel.navigationManager.goBack()
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = "No update available",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun InstallUpdatePageContent(
|
||||
currentVersion: Version,
|
||||
release: Release,
|
||||
onInstallRelease: () -> Unit,
|
||||
onCancel: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = modifier,
|
||||
) {
|
||||
val scrollAmount = 100f
|
||||
val columnState = rememberLazyListState()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
fun scroll(reverse: Boolean = false) {
|
||||
scope.launch(ExceptionHandler()) {
|
||||
columnState.scrollBy(if (reverse) -scrollAmount else scrollAmount)
|
||||
}
|
||||
}
|
||||
val columnInteractionSource = remember { MutableInteractionSource() }
|
||||
val columnFocused by columnInteractionSource.collectIsFocusedAsState()
|
||||
val columnColor =
|
||||
if (columnFocused) {
|
||||
MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)
|
||||
}
|
||||
LazyColumn(
|
||||
state = columnState,
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier =
|
||||
Modifier
|
||||
.focusable(interactionSource = columnInteractionSource)
|
||||
.fillMaxHeight()
|
||||
.fillMaxWidth(.6f)
|
||||
.background(
|
||||
columnColor,
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
).onKeyEvent {
|
||||
if (it.type == KeyEventType.KeyUp) {
|
||||
return@onKeyEvent false
|
||||
}
|
||||
if (it.key == Key.DirectionDown) {
|
||||
scroll(false)
|
||||
return@onKeyEvent true
|
||||
}
|
||||
if (it.key == Key.DirectionUp) {
|
||||
scroll(true)
|
||||
return@onKeyEvent true
|
||||
}
|
||||
return@onKeyEvent false
|
||||
},
|
||||
) {
|
||||
item {
|
||||
Text(
|
||||
// TODO render markdown
|
||||
text = release.notes.joinToString("\n\n") + (release.body ?: ""),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterVertically)
|
||||
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp), shape = RoundedCornerShape(16.dp))
|
||||
.padding(16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Update available",
|
||||
style = MaterialTheme.typography.displaySmall,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
Text(
|
||||
text = "$currentVersion => " + release.version.toString(),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
Button(
|
||||
onClick = onInstallRelease,
|
||||
) {
|
||||
Text(
|
||||
text = "Download & Update",
|
||||
)
|
||||
}
|
||||
Button(
|
||||
onClick = onCancel,
|
||||
) {
|
||||
Text(
|
||||
text = "Cancel",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewTvSpec
|
||||
@Composable
|
||||
private fun InstallUpdatePageContentPreview() {
|
||||
DolphinTheme {
|
||||
InstallUpdatePageContent(
|
||||
currentVersion = Version.fromString("v0.4.0"),
|
||||
release =
|
||||
Release(
|
||||
version = Version.fromString("v0.5.3"),
|
||||
downloadUrl = "https://url",
|
||||
publishedAt = null,
|
||||
body =
|
||||
"Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus " +
|
||||
"ex sapien vitae pellentesque sem placerat. In id cursus mi pretium " +
|
||||
"tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. " +
|
||||
"Pulvinar vivamus fringilla lacus nec metus bibendum egestas. " +
|
||||
"Iaculis massa nisl malesuada lacinia integer nunc posuere. " +
|
||||
"Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora " +
|
||||
"torquent per conubia nostra inceptos himenaeos.\n\n" +
|
||||
"Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus " +
|
||||
"ex sapien vitae pellentesque sem placerat. In id cursus mi pretium " +
|
||||
"tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. " +
|
||||
"Pulvinar vivamus fringilla lacus nec metus bibendum egestas. " +
|
||||
"Iaculis massa nisl malesuada lacinia integer nunc posuere. " +
|
||||
"Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora " +
|
||||
"torquent per conubia nostra inceptos himenaeos.",
|
||||
notes = listOf(),
|
||||
),
|
||||
onInstallRelease = {},
|
||||
onCancel = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,8 +16,10 @@ import androidx.core.content.FileProvider
|
|||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.github.damontecres.dolphin.R
|
||||
import com.github.damontecres.dolphin.hilt.StandardOkHttpClient
|
||||
import com.github.damontecres.dolphin.ui.findActivity
|
||||
import com.github.damontecres.dolphin.ui.isNotNullOrBlank
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -31,13 +33,18 @@ import okhttp3.Request
|
|||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.util.Date
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class UpdateChecker(
|
||||
private val context: Context,
|
||||
private val okHttpClient: OkHttpClient,
|
||||
) {
|
||||
@Singleton
|
||||
class UpdateChecker
|
||||
@Inject
|
||||
constructor(
|
||||
@param:ApplicationContext private val context: Context,
|
||||
@param:StandardOkHttpClient private val okHttpClient: OkHttpClient,
|
||||
) {
|
||||
companion object {
|
||||
// TODO apk names
|
||||
private const val ASSET_NAME = "Dolphin.apk"
|
||||
|
|
@ -303,7 +310,7 @@ class UpdateChecker(
|
|||
Timber.e(ex, "Exception during cleanup")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Release(
|
||||
|
|
|
|||
|
|
@ -63,4 +63,7 @@ message AppPreferences {
|
|||
PlaybackPreferences playback_preferences = 3;
|
||||
HomePagePreferences home_page_preferences = 4;
|
||||
InterfacePreferences interface_preferences = 5;
|
||||
|
||||
bool auto_check_for_updates = 6;
|
||||
string update_url = 7;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,5 +68,11 @@
|
|||
<string name="skip_comercials_behavior">Skip commercials behavior</string>
|
||||
<string name="skip_outro_behavior">Skip outro behavior</string>
|
||||
<string name="skip_intro_behavior">Skip intro behavior</string>
|
||||
<string name="check_for_updates">Check for updates</string>
|
||||
<string name="auto_check_for_updates">Automatically check for updates</string>
|
||||
<string name="update_url">Update URL</string>
|
||||
<string name="update_url_summary">URL used to check for app updates</string>
|
||||
<string name="updates">Updates</string>
|
||||
<string name="no_update_available">No update available</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue