Skip to content

Commit

Permalink
<Merge> version-migrate-ui -> dev
Browse files Browse the repository at this point in the history
  • Loading branch information
chr56 committed Nov 25, 2024
2 parents 7238bf5 + 5c53318 commit 1fac722
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,33 @@ object MigrationManager {
return currentVersion != previousVersion
}

fun migrate(context: Context) {
fun migrate(context: Context): Int {

val from = PrerequisiteSetting.instance(context).previousVersion
val to = currentVersionCode(context)

var status = CODE_SUCCESSFUL

when (from) {
in 1 until 1040 -> { // v1.4.0
throw IllegalStateException("You are upgrading from a very old version (version $from)! Please Wipe app data!")
return CODE_FORBIDDEN
}

in 1040 until 1070 -> { // v1.7.0
reportError(
IllegalStateException(), TAG,
"You are upgrading from a very old version (version $from)! Try to wipe app data!"
)
status = CODE_WARNING
}
}

if (from != to) {
Log.i(TAG, "Start Migration: $from -> $to")
if (from == to) {
debug { Log.i(TAG, "No Need to Migrate") }
return CODE_NO_ACTION
}

// Actual migration

Log.i(TAG, "Start Migration: $from -> $to")

try {
MigrateOperator(context, from, to).apply {
migrate(CustomArtistImageStoreMigration())
migrate(ThemeStoreMigration())
Expand All @@ -69,14 +76,22 @@ object MigrationManager {

Log.i(TAG, "End Migration")

PrerequisiteSetting.instance(context).previousVersion = to
} else {
debug {
Log.i(TAG, "No Need to Migrate")
}
PrerequisiteSetting.instance(context).previousVersion = to // todo

} catch (e: Exception) {
reportError(e, TAG, "Failed to migrate")
return CODE_UNKNOWN_ERROR
}

return status
}

const val CODE_SUCCESSFUL = 0
const val CODE_NO_ACTION = 1
const val CODE_WARNING = 100
const val CODE_FORBIDDEN = -100
const val CODE_UNKNOWN_ERROR = -1

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import player.phonograph.ui.basis.ComposeActivity
import player.phonograph.ui.compose.PhonographTheme
import player.phonograph.ui.compose.components.StatusBarStub
import player.phonograph.ui.modules.main.MainActivity
import player.phonograph.util.permissions.navigateToAppDetailSetting
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
Expand All @@ -14,12 +15,16 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Done
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Warning
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
Expand All @@ -29,10 +34,13 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import android.content.res.Resources
import android.os.Bundle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
Expand All @@ -43,23 +51,31 @@ import kotlinx.coroutines.withContext

class MigrationActivity : ComposeActivity() {

private val isCompleteFlow = MutableStateFlow(false)
private val isCompletedFlow = MutableStateFlow(false)
private val migrationResultFlow = MutableStateFlow<Int?>(null)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val isComplete by isCompleteFlow.collectAsState()
val color = remember { derivedStateOf { if (isComplete) colorDone else colorProcess } }
val isCompleted by isCompletedFlow.collectAsState()
val color = remember { derivedStateOf { if (isCompleted) colorDone else colorProcess } }
PhonographTheme(color) {
StatusBarStub()
Scaffold(
Modifier.systemBarsPadding(),
topBar = {
TopAppBar(title = { Text(stringResource(R.string.version_migration)) })
TopAppBar(
title = { Text(stringResource(R.string.version_migration)) },
actions = { Options() }
)
}
) {
Column(Modifier.padding(it)) {
ProgressScreen(isComplete)
if (isCompleted) {
ResultScreen()
} else {
OngoingScreen()
}
}
SideEffect {
migrateImpl()
Expand All @@ -70,55 +86,115 @@ class MigrationActivity : ComposeActivity() {
}

@Composable
private fun ColumnScope.ProgressScreen(done: Boolean) {
if (done) {
Image(
Icons.Default.Done, stringResource(R.string.success),
Modifier
.padding(56.dp)
.align(Alignment.CenterHorizontally)
)
Text(
stringResource(R.string.success),
Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center
)
SideEffect {
jumpToMainActivity()
}
TextButton(
::gotoMainActivity,
Modifier.align(Alignment.CenterHorizontally),
) {
Text(
stringResource(android.R.string.ok),
Modifier.padding(4.dp)
)
}
} else {
CircularProgressIndicator(
Modifier
.padding(56.dp)
.align(Alignment.CenterHorizontally)
)
private fun ColumnScope.ResultScreen() {
val code = migrationResultFlow.collectAsState()
if (code.value == MigrationManager.CODE_SUCCESSFUL) SuccessScreen() else FailedScreen(code.value)
}

@Composable
private fun ColumnScope.SuccessScreen() {
ResultScreenTemplate(stringResource(R.string.success), Icons.Default.Done, hasButton = true, autoJump = true)
}

@Composable
private fun ColumnScope.FailedScreen(code: Int?) {
val message = errorMessage(code, LocalContext.current.resources)
val ignorable = ignorableError(code)
ResultScreenTemplate(message, Icons.Default.Warning, hasButton = ignorable, autoJump = false)
}

private fun errorMessage(code: Int?, resources: Resources): String {
return when (code) {
MigrationManager.CODE_NO_ACTION -> "No Need to Migrate!"
MigrationManager.CODE_WARNING ->
"${resources.getString(R.string.version_migration_hint_too_old)}\n${resources.getString(R.string.version_migration_hint_suggest_to_wipe_data)}"

MigrationManager.CODE_FORBIDDEN ->
"${resources.getString(R.string.version_migration_hint_too_old)}\n${resources.getString(R.string.version_migration_hint_required_to_wipe_data)}"

else -> resources.getString(R.string.failed)
}
}

private fun ignorableError(code: Int?): Boolean {
return when (code) {
MigrationManager.CODE_FORBIDDEN -> false
else -> true
}
return true
}

@Composable
private fun ColumnScope.ResultScreenTemplate(
text: String,
icon: ImageVector,
hasButton: Boolean = true,
autoJump: Boolean = false,
) {
Image(
icon, text,
Modifier
.padding(48.dp)
.align(Alignment.CenterHorizontally)
)
Text(
text,
Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center
)
if (hasButton) TextButton(
::gotoMainActivity,
Modifier.align(Alignment.CenterHorizontally),
) {
Text(
stringResource(R.string.version_migration_summary),
Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center
stringResource(android.R.string.ok),
Modifier.padding(4.dp)
)
}
if (autoJump) SideEffect {
jumpToMainActivity()
}
}

@Composable
private fun ColumnScope.OngoingScreen() {
CircularProgressIndicator(
Modifier
.padding(56.dp)
.align(Alignment.CenterHorizontally)
)
Text(
stringResource(R.string.version_migration_summary),
Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center
)
}

@Composable
private fun Options() {
IconButton(
content = {
Icon(Icons.Default.Info, stringResource(id = R.string.app_info))
},
onClick = {
navigateToAppDetailSetting(this)
}
)
}


private fun migrateImpl() {
lifecycleScope.launch {
delay(1000)
withContext(Dispatchers.IO) {
MigrationManager.migrate(this@MigrationActivity)
isCompleteFlow.value = true
migrationResultFlow.emit(
MigrationManager.migrate(this@MigrationActivity)
)
isCompletedFlow.value = true
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,7 @@
<string name="database_playlists">数据库播放列表</string>
<string name="version_migration">版本迁移</string>
<string name="version_migration_summary">正在从旧版本升级</string>
<string name="version_migration_hint_too_old">您正在从极其陈旧的版本升级!</string>
<string name="version_migration_hint_suggest_to_wipe_data">请考虑清除应用数据!</string>
<string name="version_migration_hint_required_to_wipe_data">请务必清除应用数据!</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,7 @@
<string name="database_playlists">數據庫播放列表</string>
<string name="version_migration">版本遷移</string>
<string name="version_migration_summary">正在從舊版本升級</string>
<string name="version_migration_hint_too_old">您正在從極其陳舊的版本升級!</string>
<string name="version_migration_hint_suggest_to_wipe_data">請考慮抹除應用程式資料!</string>
<string name="version_migration_hint_required_to_wipe_data">請務必抹除應用程式資料!</string>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -543,4 +543,7 @@
<string name="database_playlists">Database Playlists</string>
<string name="version_migration">Version Migration</string>
<string name="version_migration_summary">Upgrading from old version…</string>
<string name="version_migration_hint_too_old">You are upgrading from a very old version! </string>
<string name="version_migration_hint_suggest_to_wipe_data">Try to wipe app data!</string>
<string name="version_migration_hint_required_to_wipe_data">Please wipe app data!</string>
</resources>

0 comments on commit 1fac722

Please sign in to comment.