mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-06 02:40:58 +01:00
Show toast & add option to fetch release notes when app updates (#1182)
## Description When Wholphin is updated, it will show a short toast message. This works for both app store and side loaded installs. You can now click on the "Installed version" in settings to fetch the release notes for the current version. ### Related issues Closes #1058 ### Testing Emulator ## Screenshots  ## AI or LLM usage None
This commit is contained in:
parent
46beee00bb
commit
feb8c31791
7 changed files with 207 additions and 85 deletions
|
|
@ -24,7 +24,6 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.collectAsState
|
||||
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
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
|
|
@ -55,20 +54,26 @@ import com.github.damontecres.wholphin.preferences.advancedPreferences
|
|||
import com.github.damontecres.wholphin.preferences.basicPreferences
|
||||
import com.github.damontecres.wholphin.preferences.screensaverPreferences
|
||||
import com.github.damontecres.wholphin.preferences.updatePlaybackPreferences
|
||||
import com.github.damontecres.wholphin.services.Release
|
||||
import com.github.damontecres.wholphin.services.SeerrConnectionStatus
|
||||
import com.github.damontecres.wholphin.services.UpdateChecker
|
||||
import com.github.damontecres.wholphin.ui.components.ConfirmDialog
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
||||
import com.github.damontecres.wholphin.ui.components.ScrollableDialog
|
||||
import com.github.damontecres.wholphin.ui.ifElse
|
||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.playOnClickSound
|
||||
import com.github.damontecres.wholphin.ui.playSoundOnFocus
|
||||
import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings
|
||||
import com.github.damontecres.wholphin.ui.setup.ReleaseNotes
|
||||
import com.github.damontecres.wholphin.ui.setup.UpdateViewModel
|
||||
import com.github.damontecres.wholphin.ui.setup.seerr.AddSeerServerDialog
|
||||
import com.github.damontecres.wholphin.ui.setup.seerr.SwitchSeerrViewModel
|
||||
import com.github.damontecres.wholphin.ui.showToast
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -93,6 +98,7 @@ fun PreferencesContent(
|
|||
val currentUser by viewModel.currentUser.observeAsState()
|
||||
val currentServer by seerrVm.currentSeerrServer.collectAsState(null)
|
||||
var showPinFlow by remember { mutableStateOf(false) }
|
||||
var showVersionDialog by remember { mutableStateOf(false) }
|
||||
|
||||
var cacheUsage by remember { mutableStateOf(CacheUsage(0, 0, 0)) }
|
||||
val seerrConnection by viewModel.seerrConnection.collectAsState()
|
||||
|
|
@ -252,15 +258,13 @@ fun PreferencesContent(
|
|||
}
|
||||
when (pref) {
|
||||
AppPreference.InstalledVersion -> {
|
||||
var clickCount by remember { mutableIntStateOf(0) }
|
||||
ClickPreference(
|
||||
title = stringResource(R.string.installed_version),
|
||||
onClick = {
|
||||
if (movementSounds) playOnClickSound(context)
|
||||
if (clickCount++ >= 2) {
|
||||
clickCount = 0
|
||||
viewModel.navigationManager.navigateTo(Destination.Debug)
|
||||
}
|
||||
showVersionDialog = true
|
||||
},
|
||||
onLongClick = {
|
||||
viewModel.navigationManager.navigateTo(Destination.Debug)
|
||||
},
|
||||
summary = installedVersion.toString(),
|
||||
interactionSource = interactionSource,
|
||||
|
|
@ -615,6 +619,33 @@ fun PreferencesContent(
|
|||
},
|
||||
)
|
||||
}
|
||||
if (showVersionDialog) {
|
||||
LaunchedEffect(Unit) {
|
||||
viewModel.fetchReleaseNotes()
|
||||
}
|
||||
val release by viewModel.releaseNotes.collectAsState()
|
||||
ScrollableDialog(
|
||||
onDismissRequest = { showVersionDialog = false },
|
||||
) {
|
||||
item {
|
||||
when (val r = release) {
|
||||
is DataLoadingState.Error -> {
|
||||
ErrorMessage(message = "Error", exception = r.exception)
|
||||
}
|
||||
|
||||
DataLoadingState.Pending,
|
||||
DataLoadingState.Loading,
|
||||
-> {
|
||||
LoadingPage()
|
||||
}
|
||||
|
||||
is DataLoadingState.Success<Release> -> {
|
||||
ReleaseNotes(r.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@ import com.github.damontecres.wholphin.preferences.resetSubtitles
|
|||
import com.github.damontecres.wholphin.preferences.updateSubtitlePreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.Release
|
||||
import com.github.damontecres.wholphin.services.ScreensaverService
|
||||
import com.github.damontecres.wholphin.services.SeerrServerRepository
|
||||
import com.github.damontecres.wholphin.services.UpdateChecker
|
||||
import com.github.damontecres.wholphin.ui.detail.DebugViewModel.Companion.sendAppLogs
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
import com.github.damontecres.wholphin.util.RememberTabManager
|
||||
|
|
@ -22,9 +25,11 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.model.ClientInfo
|
||||
import org.jellyfin.sdk.model.DeviceInfo
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
|
|
@ -42,6 +47,7 @@ class PreferencesViewModel
|
|||
private val seerrServerRepository: SeerrServerRepository,
|
||||
private val deviceInfo: DeviceInfo,
|
||||
private val clientInfo: ClientInfo,
|
||||
private val updateChecker: UpdateChecker,
|
||||
) : ViewModel(),
|
||||
RememberTabManager by rememberTabManager {
|
||||
val currentUser get() = serverRepository.currentUser
|
||||
|
|
@ -51,6 +57,8 @@ class PreferencesViewModel
|
|||
private val _quickConnectStatus = MutableStateFlow<LoadingState>(LoadingState.Pending)
|
||||
val quickConnectStatus: StateFlow<LoadingState> = _quickConnectStatus
|
||||
|
||||
val releaseNotes = MutableStateFlow<DataLoadingState<Release>>(DataLoadingState.Pending)
|
||||
|
||||
init {
|
||||
viewModelScope.launchIO {
|
||||
serverRepository.currentUser.value?.let { user ->
|
||||
|
|
@ -99,6 +107,23 @@ class PreferencesViewModel
|
|||
}
|
||||
}
|
||||
|
||||
fun fetchReleaseNotes() {
|
||||
viewModelScope.launchIO {
|
||||
releaseNotes.update { DataLoadingState.Loading }
|
||||
try {
|
||||
val release = updateChecker.getRelease(updateChecker.getInstalledVersion())
|
||||
if (release != null) {
|
||||
releaseNotes.update { DataLoadingState.Success(release) }
|
||||
} else {
|
||||
releaseNotes.update { DataLoadingState.Error("Release not found") }
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error fetching release")
|
||||
releaseNotes.update { DataLoadingState.Error(ex) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun resetSubtitleSettings(appPreferences: DataStore<AppPreferences>) {
|
||||
appPreferences.updateData {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ import com.github.damontecres.wholphin.services.Release
|
|||
import com.github.damontecres.wholphin.services.UpdateChecker
|
||||
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
||||
import com.github.damontecres.wholphin.ui.components.BasicDialog
|
||||
import com.github.damontecres.wholphin.ui.components.Button
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
||||
import com.github.damontecres.wholphin.ui.components.TextButton
|
||||
|
|
@ -66,6 +65,7 @@ import com.github.damontecres.wholphin.util.LoadingExceptionHandler
|
|||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
import com.github.damontecres.wholphin.util.Version
|
||||
import com.mikepenz.markdown.m3.Markdown
|
||||
import com.mikepenz.markdown.m3.markdownTypography
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
|
|
@ -272,15 +272,7 @@ fun InstallUpdatePageContent(
|
|||
},
|
||||
) {
|
||||
item {
|
||||
Markdown(
|
||||
(release.notes.joinToString("\n\n") + (release.body ?: ""))
|
||||
.replace(
|
||||
Regex("https://github.com/damontecres/\\w+/pull/(\\d+)"),
|
||||
"#$1",
|
||||
)
|
||||
// Remove the last line for full changelog since its just a link
|
||||
.replace(Regex("\\*\\*Full Changelog\\*\\*.*"), ""),
|
||||
)
|
||||
ReleaseNotes(release)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
|
|
@ -317,6 +309,25 @@ fun InstallUpdatePageContent(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ReleaseNotes(
|
||||
release: Release,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Markdown(
|
||||
content = release.content,
|
||||
typography =
|
||||
markdownTypography(
|
||||
h1 = MaterialTheme.typography.headlineLarge,
|
||||
h2 = MaterialTheme.typography.headlineMedium,
|
||||
h3 = MaterialTheme.typography.headlineSmall,
|
||||
text = MaterialTheme.typography.bodySmall,
|
||||
code = MaterialTheme.typography.bodySmall,
|
||||
),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DownloadDialog(
|
||||
contentLength: Long,
|
||||
|
|
@ -392,13 +403,15 @@ private fun InstallUpdatePageContentPreview() {
|
|||
downloadUrl = "https://url",
|
||||
publishedAt = null,
|
||||
body =
|
||||
"Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus " +
|
||||
"## Header 2\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.\n\n" +
|
||||
"### Header 3\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. " +
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue