Add update check for Gitee source
This commit is contained in:
parent
0cb60d15b2
commit
52d6b0698d
|
@ -13,11 +13,13 @@ class CrashHandler(private val context: Context) : UncaughtExceptionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun uncaughtException(p0: Thread, p1: Throwable) {
|
override fun uncaughtException(p0: Thread, p1: Throwable) {
|
||||||
Looper.prepare()
|
if (Looper.myLooper() == null) {
|
||||||
|
Looper.prepare()
|
||||||
|
}
|
||||||
Toast.makeText(context, p1.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, p1.message, Toast.LENGTH_LONG).show()
|
||||||
Looper.loop()
|
Looper.loop()
|
||||||
p1.printStackTrace()
|
p1.printStackTrace()
|
||||||
Log.e("RLog", "uncaughtException: ${p1.message}" )
|
Log.e("RLog", "uncaughtException: ${p1.message}")
|
||||||
android.os.Process.killProcess(android.os.Process.myPid());
|
android.os.Process.killProcess(android.os.Process.myPid());
|
||||||
exitProcess(1)
|
exitProcess(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package me.ash.reader.data.entity
|
package me.ash.reader.data.entity
|
||||||
|
|
||||||
data class GitHubRelease(
|
data class LatestRelease(
|
||||||
val html_url: String? = null,
|
val html_url: String? = null,
|
||||||
val tag_name: String? = null,
|
val tag_name: String? = null,
|
||||||
val name: String? = null,
|
val name: String? = null,
|
30
app/src/main/java/me/ash/reader/data/entity/Version.kt
Normal file
30
app/src/main/java/me/ash/reader/data/entity/Version.kt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package me.ash.reader.data.entity
|
||||||
|
|
||||||
|
class Version(identifiers: List<String>) {
|
||||||
|
private var major: Int = 0
|
||||||
|
private var minor: Int = 0
|
||||||
|
private var point: Int = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
major = identifiers.getOrNull(0)?.toIntOrNull() ?: 0
|
||||||
|
minor = identifiers.getOrNull(1)?.toIntOrNull() ?: 0
|
||||||
|
point = identifiers.getOrNull(2)?.toIntOrNull() ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() : this(listOf())
|
||||||
|
constructor(string: String?) : this(string?.split(".") ?: listOf())
|
||||||
|
|
||||||
|
fun whetherNeedUpdate(current: Version, skip: Version): Boolean = this > current && this > skip
|
||||||
|
|
||||||
|
operator fun compareTo(target: Version): Int = when {
|
||||||
|
major > target.major -> 1
|
||||||
|
major < target.major -> -1
|
||||||
|
minor > target.minor -> 1
|
||||||
|
minor < target.minor -> -1
|
||||||
|
point > target.point -> 1
|
||||||
|
point < target.point -> -1
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString() = "$major.$minor.$point"
|
||||||
|
}
|
|
@ -6,13 +6,12 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.entity.Version
|
||||||
import me.ash.reader.data.module.ApplicationScope
|
import me.ash.reader.data.module.ApplicationScope
|
||||||
import me.ash.reader.data.module.DispatcherIO
|
import me.ash.reader.data.module.DispatcherIO
|
||||||
import me.ash.reader.data.source.AppNetworkDataSource
|
import me.ash.reader.data.source.AppNetworkDataSource
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.*
|
||||||
import me.ash.reader.ui.ext.dataStore
|
|
||||||
import me.ash.reader.ui.ext.put
|
|
||||||
import me.ash.reader.ui.ext.skipVersionNumber
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AppRepository @Inject constructor(
|
class AppRepository @Inject constructor(
|
||||||
|
@ -24,55 +23,44 @@ class AppRepository @Inject constructor(
|
||||||
@DispatcherIO
|
@DispatcherIO
|
||||||
private val dispatcherIO: CoroutineDispatcher,
|
private val dispatcherIO: CoroutineDispatcher,
|
||||||
) {
|
) {
|
||||||
suspend fun checkUpdate() {
|
suspend fun checkUpdate(): Boolean = withContext(dispatcherIO) {
|
||||||
withContext(dispatcherIO) {
|
return@withContext try {
|
||||||
try {
|
val latest =
|
||||||
val latest = appNetworkDataSource.getReleaseLatest()
|
appNetworkDataSource.getReleaseLatest(context.getString(R.string.update_link))
|
||||||
val latestVersion = latest.tag_name?.formatVersion() ?: listOf()
|
val latestVersion = Version(latest.tag_name)
|
||||||
val latestLog = latest.body ?: ""
|
// val latestVersion = Version("0.7.3")
|
||||||
val latestPublishDate = latest.published_at ?: ""
|
val skipVersion = Version(context.skipVersionNumber)
|
||||||
val latestSize = latest.assets
|
val currentVersion = context.getCurrentVersion()
|
||||||
?.first()
|
val latestLog = latest.body ?: ""
|
||||||
?.size
|
val latestPublishDate = latest.published_at ?: latest.created_at ?: ""
|
||||||
?: 0
|
val latestSize = latest.assets
|
||||||
val latestDownloadUrl = latest.assets
|
?.first()
|
||||||
?.first()
|
?.size
|
||||||
?.browser_download_url
|
?: 0
|
||||||
?: ""
|
val latestDownloadUrl = latest.assets
|
||||||
val currentVersion = context
|
?.first()
|
||||||
.packageManager
|
?.browser_download_url
|
||||||
.getPackageInfo(context.packageName, 0)
|
?: ""
|
||||||
.versionName
|
|
||||||
.formatVersion()
|
|
||||||
|
|
||||||
Log.i("RLog", "current version ${currentVersion.joinToString(".")}")
|
Log.i("RLog", "current version $currentVersion")
|
||||||
if (latestVersion > context.skipVersionNumber.formatVersion() && latestVersion > currentVersion) {
|
if (latestVersion.whetherNeedUpdate(currentVersion, skipVersion)) {
|
||||||
Log.i("RLog", "new version ${latestVersion.joinToString(".")}")
|
Log.i("RLog", "new version $latestVersion")
|
||||||
context.dataStore.put(
|
context.dataStore.put(
|
||||||
DataStoreKeys.NewVersionNumber,
|
DataStoreKeys.NewVersionNumber,
|
||||||
latestVersion.joinToString(".")
|
latestVersion.toString()
|
||||||
)
|
)
|
||||||
context.dataStore.put(DataStoreKeys.NewVersionLog, latestLog)
|
context.dataStore.put(DataStoreKeys.NewVersionLog, latestLog)
|
||||||
context.dataStore.put(DataStoreKeys.NewVersionPublishDate, latestPublishDate)
|
context.dataStore.put(DataStoreKeys.NewVersionPublishDate, latestPublishDate)
|
||||||
context.dataStore.put(DataStoreKeys.NewVersionSize, latestSize)
|
context.dataStore.put(DataStoreKeys.NewVersionSize, latestSize)
|
||||||
context.dataStore.put(DataStoreKeys.NewVersionDownloadUrl, latestDownloadUrl)
|
context.dataStore.put(DataStoreKeys.NewVersionDownloadUrl, latestDownloadUrl)
|
||||||
}
|
true
|
||||||
this
|
} else {
|
||||||
} catch (e: Exception) {
|
false
|
||||||
Log.e("RLog", "checkUpdate: ${e.message}")
|
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Log.e("RLog", "checkUpdate: ${e.message}")
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.formatVersion(): List<String> = this.split(".")
|
|
||||||
|
|
||||||
operator fun List<String>.compareTo(target: List<String>): Int {
|
|
||||||
for (i in 0 until minOf(size, target.size)) {
|
|
||||||
val a = this[i].toIntOrNull() ?: 0
|
|
||||||
val b = target[i].toIntOrNull() ?: 0
|
|
||||||
if (a < b) return -1
|
|
||||||
if (a > b) return 1
|
|
||||||
}
|
|
||||||
return if (size == target.size) 0 else if (size > target.size) 1 else -1
|
|
||||||
}
|
|
|
@ -1,13 +1,14 @@
|
||||||
package me.ash.reader.data.source
|
package me.ash.reader.data.source
|
||||||
|
|
||||||
import me.ash.reader.data.entity.GitHubRelease
|
import me.ash.reader.data.entity.LatestRelease
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Url
|
||||||
|
|
||||||
interface AppNetworkDataSource {
|
interface AppNetworkDataSource {
|
||||||
@GET("https://api.github.com/repos/Ashinch/ReadYou/releases/latest")
|
@GET
|
||||||
suspend fun getReleaseLatest(): GitHubRelease
|
suspend fun getReleaseLatest(@Url url: String): LatestRelease
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private var instance: AppNetworkDataSource? = null
|
private var instance: AppNetworkDataSource? = null
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package me.ash.reader.ui.component
|
package me.ash.reader.ui.component
|
||||||
|
|
||||||
|
import android.view.SoundEffectConstants
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
@ -21,6 +22,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
@ -36,6 +38,8 @@ fun Banner(
|
||||||
action: (@Composable () -> Unit)? = null,
|
action: (@Composable () -> Unit)? = null,
|
||||||
onClick: () -> Unit = {},
|
onClick: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
val view = LocalView.current
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
@ -48,7 +52,10 @@ fun Banner(
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.clip(RoundedCornerShape(32.dp))
|
.clip(RoundedCornerShape(32.dp))
|
||||||
.background(backgroundColor alwaysLight true)
|
.background(backgroundColor alwaysLight true)
|
||||||
.clickable { onClick() }
|
.clickable {
|
||||||
|
view.playSoundEffect(SoundEffectConstants.CLICK)
|
||||||
|
onClick()
|
||||||
|
}
|
||||||
.padding(16.dp, 20.dp),
|
.padding(16.dp, 20.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -3,9 +3,13 @@ package me.ash.reader.ui.ext
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
|
import me.ash.reader.data.entity.Version
|
||||||
|
|
||||||
fun Context.findActivity(): Activity? = when (this) {
|
fun Context.findActivity(): Activity? = when (this) {
|
||||||
is Activity -> this
|
is Activity -> this
|
||||||
is ContextWrapper -> baseContext.findActivity()
|
is ContextWrapper -> baseContext.findActivity()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.getCurrentVersion(): Version =
|
||||||
|
Version(packageManager.getPackageInfo(packageName, 0).versionName)
|
|
@ -29,9 +29,8 @@ import androidx.navigation.NavHostController
|
||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.entity.Version
|
||||||
import me.ash.reader.data.repository.SyncWorker.Companion.getIsSyncing
|
import me.ash.reader.data.repository.SyncWorker.Companion.getIsSyncing
|
||||||
import me.ash.reader.data.repository.compareTo
|
|
||||||
import me.ash.reader.data.repository.formatVersion
|
|
||||||
import me.ash.reader.ui.component.Banner
|
import me.ash.reader.ui.component.Banner
|
||||||
import me.ash.reader.ui.component.DisplayText
|
import me.ash.reader.ui.component.DisplayText
|
||||||
import me.ash.reader.ui.component.FeedbackIconButton
|
import me.ash.reader.ui.component.FeedbackIconButton
|
||||||
|
@ -62,21 +61,20 @@ fun FeedsPage(
|
||||||
onScrollToPage: (targetPage: Int) -> Unit = {},
|
onScrollToPage: (targetPage: Int) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val skipVersionNumber =
|
|
||||||
context.dataStore.data
|
|
||||||
.map { it[DataStoreKeys.SkipVersionNumber.key] ?: "" }
|
|
||||||
.collectAsState(initial = "")
|
|
||||||
.value
|
|
||||||
.formatVersion()
|
|
||||||
val newVersionNumber =
|
|
||||||
context.dataStore.data
|
|
||||||
.map { it[DataStoreKeys.NewVersionNumber.key] ?: "" }
|
|
||||||
.collectAsState(initial = "")
|
|
||||||
.value
|
|
||||||
.formatVersion()
|
|
||||||
|
|
||||||
val viewState = feedsViewModel.viewState.collectAsStateValue()
|
val viewState = feedsViewModel.viewState.collectAsStateValue()
|
||||||
|
|
||||||
|
val skipVersion = context.dataStore.data
|
||||||
|
.map { it[DataStoreKeys.SkipVersionNumber.key] ?: "" }
|
||||||
|
.map { Version(it) }
|
||||||
|
.collectAsState(initial = Version())
|
||||||
|
.value
|
||||||
|
val latestVersion = context.dataStore.data
|
||||||
|
.map { it[DataStoreKeys.NewVersionNumber.key] ?: "" }
|
||||||
|
.map { Version(it) }
|
||||||
|
.collectAsState(initial = Version())
|
||||||
|
.value
|
||||||
|
val currentVersion by remember { mutableStateOf(context.getCurrentVersion()) }
|
||||||
|
|
||||||
val owner = LocalLifecycleOwner.current
|
val owner = LocalLifecycleOwner.current
|
||||||
var isSyncing by remember { mutableStateOf(false) }
|
var isSyncing by remember { mutableStateOf(false) }
|
||||||
syncWorkLiveData.observe(owner) {
|
syncWorkLiveData.observe(owner) {
|
||||||
|
@ -132,7 +130,7 @@ fun FeedsPage(
|
||||||
imageVector = Icons.Outlined.Settings,
|
imageVector = Icons.Outlined.Settings,
|
||||||
contentDescription = stringResource(R.string.settings),
|
contentDescription = stringResource(R.string.settings),
|
||||||
tint = MaterialTheme.colorScheme.onSurface,
|
tint = MaterialTheme.colorScheme.onSurface,
|
||||||
showBadge = newVersionNumber > skipVersionNumber,
|
showBadge = latestVersion.whetherNeedUpdate(currentVersion, skipVersion),
|
||||||
) {
|
) {
|
||||||
navController.navigate(RouteName.SETTINGS)
|
navController.navigate(RouteName.SETTINGS)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,13 @@ import androidx.compose.ui.zIndex
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
import me.ash.reader.data.repository.compareTo
|
import me.ash.reader.data.entity.Version
|
||||||
import me.ash.reader.data.repository.formatVersion
|
|
||||||
import me.ash.reader.ui.component.Banner
|
import me.ash.reader.ui.component.Banner
|
||||||
import me.ash.reader.ui.component.DisplayText
|
import me.ash.reader.ui.component.DisplayText
|
||||||
import me.ash.reader.ui.component.FeedbackIconButton
|
import me.ash.reader.ui.component.FeedbackIconButton
|
||||||
import me.ash.reader.ui.ext.DataStoreKeys
|
import me.ash.reader.ui.ext.DataStoreKeys
|
||||||
import me.ash.reader.ui.ext.dataStore
|
import me.ash.reader.ui.ext.dataStore
|
||||||
|
import me.ash.reader.ui.ext.getCurrentVersion
|
||||||
import me.ash.reader.ui.page.common.RouteName
|
import me.ash.reader.ui.page.common.RouteName
|
||||||
import me.ash.reader.ui.theme.palette.onLight
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@ -36,18 +36,17 @@ fun SettingsPage(
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var updateDialogVisible by remember { mutableStateOf(false) }
|
var updateDialogVisible by remember { mutableStateOf(false) }
|
||||||
val skipVersionNumber =
|
val skipVersion = context.dataStore.data
|
||||||
context.dataStore.data
|
.map { it[DataStoreKeys.SkipVersionNumber.key] ?: "" }
|
||||||
.map { it[DataStoreKeys.SkipVersionNumber.key] ?: "" }
|
.map { Version(it) }
|
||||||
.collectAsState(initial = "")
|
.collectAsState(initial = Version())
|
||||||
.value
|
.value
|
||||||
.formatVersion()
|
val latestVersion = context.dataStore.data
|
||||||
val newVersionNumber =
|
.map { it[DataStoreKeys.NewVersionNumber.key] ?: "" }
|
||||||
context.dataStore.data
|
.map { Version(it) }
|
||||||
.map { it[DataStoreKeys.NewVersionNumber.key] ?: "" }
|
.collectAsState(initial = Version())
|
||||||
.collectAsState(initial = "")
|
.value
|
||||||
.value
|
val currentVersion by remember { mutableStateOf(context.getCurrentVersion()) }
|
||||||
.formatVersion()
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -78,13 +77,13 @@ fun SettingsPage(
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
Box {
|
Box {
|
||||||
if (newVersionNumber > skipVersionNumber) {
|
if (latestVersion.whetherNeedUpdate(currentVersion, skipVersion)) {
|
||||||
Banner(
|
Banner(
|
||||||
modifier = Modifier.zIndex(1f),
|
modifier = Modifier.zIndex(1f),
|
||||||
title = stringResource(R.string.get_new_updates),
|
title = stringResource(R.string.get_new_updates),
|
||||||
desc = stringResource(
|
desc = stringResource(
|
||||||
R.string.get_new_updates_desc,
|
R.string.get_new_updates_desc,
|
||||||
newVersionNumber.joinToString(".")
|
latestVersion.toString(),
|
||||||
),
|
),
|
||||||
icon = Icons.Outlined.Lightbulb,
|
icon = Icons.Outlined.Lightbulb,
|
||||||
action = {
|
action = {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
import android.view.SoundEffectConstants
|
import android.view.SoundEffectConstants
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
|
@ -31,10 +32,13 @@ import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
import me.ash.reader.ui.component.CurlyCornerShape
|
import me.ash.reader.ui.component.CurlyCornerShape
|
||||||
import me.ash.reader.ui.component.FeedbackIconButton
|
import me.ash.reader.ui.component.FeedbackIconButton
|
||||||
|
import me.ash.reader.ui.ext.*
|
||||||
import me.ash.reader.ui.theme.palette.alwaysLight
|
import me.ash.reader.ui.theme.palette.alwaysLight
|
||||||
import me.ash.reader.ui.theme.palette.onLight
|
import me.ash.reader.ui.theme.palette.onLight
|
||||||
|
|
||||||
|
@ -42,12 +46,16 @@ import me.ash.reader.ui.theme.palette.onLight
|
||||||
@Composable
|
@Composable
|
||||||
fun TipsAndSupport(
|
fun TipsAndSupport(
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
|
updateViewModel: UpdateViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val viewState = updateViewModel.viewState.collectAsStateValue()
|
||||||
val githubLink = stringResource(R.string.github_link)
|
val githubLink = stringResource(R.string.github_link)
|
||||||
val telegramLink = stringResource(R.string.telegram_link)
|
val telegramLink = stringResource(R.string.telegram_link)
|
||||||
var version by remember { mutableStateOf("") }
|
val isLatestVersion = stringResource(R.string.is_latest_version)
|
||||||
|
var currentVersion by remember { mutableStateOf("") }
|
||||||
var pressAMP by remember { mutableStateOf(16f) }
|
var pressAMP by remember { mutableStateOf(16f) }
|
||||||
val animatedPress by animateFloatAsState(
|
val animatedPress by animateFloatAsState(
|
||||||
targetValue = pressAMP,
|
targetValue = pressAMP,
|
||||||
|
@ -55,7 +63,7 @@ fun TipsAndSupport(
|
||||||
)
|
)
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
version = context.packageManager.getPackageInfo(context.packageName, 0).versionName
|
currentVersion = context.getCurrentVersion().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
@ -100,6 +108,28 @@ fun TipsAndSupport(
|
||||||
view.playSoundEffect(SoundEffectConstants.CLICK)
|
view.playSoundEffect(SoundEffectConstants.CLICK)
|
||||||
pressAMP = 16f
|
pressAMP = 16f
|
||||||
},
|
},
|
||||||
|
onTap = {
|
||||||
|
scope.launch {
|
||||||
|
context.dataStore.put(DataStoreKeys.SkipVersionNumber, "")
|
||||||
|
updateViewModel.dispatch(
|
||||||
|
UpdateViewAction.CheckUpdate(
|
||||||
|
{
|
||||||
|
context.dataStore.put(
|
||||||
|
DataStoreKeys.SkipVersionNumber,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
if (!it) Toast.makeText(
|
||||||
|
context,
|
||||||
|
isLatestVersion,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
@ -135,7 +165,7 @@ fun TipsAndSupport(
|
||||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
||||||
contentColor = MaterialTheme.colorScheme.tertiary,
|
contentColor = MaterialTheme.colorScheme.tertiary,
|
||||||
) {
|
) {
|
||||||
Text(text = version)
|
Text(text = currentVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
@ -199,6 +229,11 @@ fun TipsAndSupport(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
UpdateDialog(
|
||||||
|
visible = viewState.updateDialogVisible,
|
||||||
|
onDismissRequest = { updateViewModel.dispatch(UpdateViewAction.Hide) },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
|
@ -58,6 +58,7 @@ fun UpdateDialog(
|
||||||
val newVersionSize = context.dataStore.data
|
val newVersionSize = context.dataStore.data
|
||||||
.map { it[DataStoreKeys.NewVersionSize.key] ?: 0 }
|
.map { it[DataStoreKeys.NewVersionSize.key] ?: 0 }
|
||||||
.map { it / 1024f / 1024f }
|
.map { it / 1024f / 1024f }
|
||||||
|
.map { if (it > 0f) " ${String.format("%.2f", it)} MB" else "" }
|
||||||
.collectAsState(initial = 0)
|
.collectAsState(initial = 0)
|
||||||
.value
|
.value
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ fun UpdateDialog(
|
||||||
onClick = {
|
onClick = {
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(R.string.update, String.format("%.2f", newVersionSize)))
|
Text(text = stringResource(R.string.update) + newVersionSize)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = {
|
dismissButton = {
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package me.ash.reader.ui.page.settings
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.ash.reader.data.repository.AppRepository
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class UpdateViewModel @Inject constructor(
|
||||||
|
private val appRepository: AppRepository,
|
||||||
|
) : ViewModel() {
|
||||||
|
private val _viewState = MutableStateFlow(UpdateViewState())
|
||||||
|
val viewState: StateFlow<UpdateViewState> = _viewState.asStateFlow()
|
||||||
|
|
||||||
|
fun dispatch(action: UpdateViewAction) {
|
||||||
|
when (action) {
|
||||||
|
is UpdateViewAction.Show -> changeUpdateDialogVisible(true)
|
||||||
|
is UpdateViewAction.Hide -> changeUpdateDialogVisible(false)
|
||||||
|
is UpdateViewAction.CheckUpdate -> checkUpdate(
|
||||||
|
action.preProcessor,
|
||||||
|
action.postProcessor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkUpdate(
|
||||||
|
preProcessor: suspend () -> Unit = {},
|
||||||
|
postProcessor: suspend (Boolean) -> Unit = {}
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
preProcessor()
|
||||||
|
appRepository.checkUpdate().let {
|
||||||
|
if (it) changeUpdateDialogVisible(true)
|
||||||
|
postProcessor(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun changeUpdateDialogVisible(visible: Boolean) {
|
||||||
|
_viewState.update {
|
||||||
|
it.copy(
|
||||||
|
updateDialogVisible = visible
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class UpdateViewState(
|
||||||
|
val updateDialogVisible: Boolean = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed class UpdateViewAction {
|
||||||
|
object Show : UpdateViewAction()
|
||||||
|
object Hide : UpdateViewAction()
|
||||||
|
|
||||||
|
data class CheckUpdate(
|
||||||
|
val preProcessor: suspend () -> Unit = {},
|
||||||
|
val postProcessor: suspend (Boolean) -> Unit = {}
|
||||||
|
) : UpdateViewAction()
|
||||||
|
}
|
|
@ -111,8 +111,9 @@
|
||||||
<string name="open_source_licenses">开放源代码许可</string>
|
<string name="open_source_licenses">开放源代码许可</string>
|
||||||
<string name="github_link">https://github.com/Ashinch/ReadYou</string>
|
<string name="github_link">https://github.com/Ashinch/ReadYou</string>
|
||||||
<string name="telegram_link">https://t.me/ReadYouApp</string>
|
<string name="telegram_link">https://t.me/ReadYouApp</string>
|
||||||
<string name="update_link">https://api.github.com/repos/Ashinch/ReadYou/releases/latest</string>
|
<string name="update_link">https://gitee.com/api/v5/repos/Ashinch/ReadYou/releases/latest</string>
|
||||||
<string name="change_log">更新日志</string>
|
<string name="change_log">更新日志</string>
|
||||||
<string name="update">更新 %1$s MB</string>
|
<string name="update">更新</string>
|
||||||
<string name="skip_this_version">跳过这个版本</string>
|
<string name="skip_this_version">跳过这个版本</string>
|
||||||
|
<string name="is_latest_version">已是最新版本</string>
|
||||||
</resources>
|
</resources>
|
|
@ -113,6 +113,7 @@
|
||||||
<string name="telegram_link">https://t.me/ReadYouApp</string>
|
<string name="telegram_link">https://t.me/ReadYouApp</string>
|
||||||
<string name="update_link">https://api.github.com/repos/Ashinch/ReadYou/releases/latest</string>
|
<string name="update_link">https://api.github.com/repos/Ashinch/ReadYou/releases/latest</string>
|
||||||
<string name="change_log">Change Log</string>
|
<string name="change_log">Change Log</string>
|
||||||
<string name="update">Update %1$s MB</string>
|
<string name="update">Update</string>
|
||||||
<string name="skip_this_version">Skip This Version</string>
|
<string name="skip_this_version">Skip This Version</string>
|
||||||
|
<string name="is_latest_version">This is the latest version</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue
Block a user