diff --git a/core/data/src/main/java/com/puzzle/data/repository/ConfigureRepositoryImpl.kt b/core/data/src/main/java/com/puzzle/data/repository/ConfigureRepositoryImpl.kt
index a6b0bdfad..49709b59b 100644
--- a/core/data/src/main/java/com/puzzle/data/repository/ConfigureRepositoryImpl.kt
+++ b/core/data/src/main/java/com/puzzle/data/repository/ConfigureRepositoryImpl.kt
@@ -1,8 +1,10 @@
package com.puzzle.data.repository
import com.puzzle.domain.model.configure.ForceUpdate
+import com.puzzle.domain.model.configure.MaintenancePeriod
import com.puzzle.domain.repository.ConfigureRepository
import com.puzzle.network.model.configure.GetForceUpdateInfoResponse
+import com.puzzle.network.model.configure.GetMaintenancePeriodInfoResponse
import com.puzzle.network.source.configure.ConfigDataSource
import com.puzzle.network.source.configure.ConfigDataSource.Key
import javax.inject.Inject
@@ -10,10 +12,13 @@ import javax.inject.Inject
class ConfigureRepositoryImpl @Inject constructor(
private val configureDataSource: ConfigDataSource,
) : ConfigureRepository {
- override suspend fun getUpdateInfo(): ForceUpdate {
- return configureDataSource.getReferenceType(
- key = Key.getKey(ConfigDataSource.FORCE_UPDATE),
- defaultValue = GetForceUpdateInfoResponse(),
- ).toDomain()
- }
+ override suspend fun getUpdateInfo(): ForceUpdate = configureDataSource.getReferenceType(
+ key = Key.getKey(ConfigDataSource.FORCE_UPDATE),
+ defaultValue = GetForceUpdateInfoResponse(),
+ ).toDomain()
+
+ override suspend fun getMaintenancePeriod(): MaintenancePeriod = configureDataSource.getReferenceType(
+ key = Key.getKey(ConfigDataSource.MAINTENANCE_PERIOD),
+ defaultValue = GetMaintenancePeriodInfoResponse(),
+ ).toDomain()
}
diff --git a/core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt b/core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt
index 6b8c3dfc4..65d18a3aa 100644
--- a/core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt
+++ b/core/designsystem/src/main/java/com/puzzle/designsystem/component/Dialog.kt
@@ -61,6 +61,7 @@ fun PieceDialog(
fun PieceDialogDefaultTop(
title: AnnotatedString,
subText: String,
+ description: AnnotatedString? = null
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
@@ -80,6 +81,27 @@ fun PieceDialogDefaultTop(
textAlign = TextAlign.Center,
style = PieceTheme.typography.bodySM,
)
+
+ description?.let {
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .padding(top = 4.dp)
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ .padding(vertical = 12.dp),
+ ) {
+ Text(
+ text = it,
+ color = PieceTheme.colors.dark3,
+ style = PieceTheme.typography.bodySM,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ )
+ }
+ }
}
}
@@ -87,6 +109,7 @@ fun PieceDialogDefaultTop(
fun PieceDialogDefaultTop(
title: AnnotatedString,
subText: AnnotatedString,
+ description: AnnotatedString? = null
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
@@ -106,6 +129,27 @@ fun PieceDialogDefaultTop(
textAlign = TextAlign.Center,
style = PieceTheme.typography.bodySM,
)
+
+ description?.let {
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .padding(top = 4.dp)
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ .padding(vertical = 12.dp),
+ ) {
+ Text(
+ text = it,
+ color = PieceTheme.colors.dark3,
+ style = PieceTheme.typography.bodySM,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ )
+ }
+ }
}
}
@@ -113,6 +157,7 @@ fun PieceDialogDefaultTop(
fun PieceDialogDefaultTop(
title: String,
subText: AnnotatedString,
+ description: AnnotatedString? = null
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
@@ -132,6 +177,27 @@ fun PieceDialogDefaultTop(
textAlign = TextAlign.Center,
style = PieceTheme.typography.bodySM,
)
+
+ description?.let {
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .padding(top = 4.dp)
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ .padding(vertical = 12.dp),
+ ) {
+ Text(
+ text = it,
+ color = PieceTheme.colors.dark3,
+ style = PieceTheme.typography.bodySM,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ )
+ }
+ }
}
}
@@ -139,6 +205,7 @@ fun PieceDialogDefaultTop(
fun PieceDialogDefaultTop(
title: String,
subText: String,
+ description: AnnotatedString? = null
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
@@ -158,6 +225,27 @@ fun PieceDialogDefaultTop(
style = PieceTheme.typography.bodySM,
textAlign = TextAlign.Center,
)
+
+ description?.let {
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = Modifier
+ .padding(top = 4.dp)
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ .padding(vertical = 12.dp),
+ ) {
+ Text(
+ text = it,
+ color = PieceTheme.colors.dark3,
+ style = PieceTheme.typography.bodySM,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(PieceTheme.colors.light3)
+ )
+ }
+ }
}
}
@@ -346,7 +434,8 @@ fun PreviewPieceDialogDefault() {
dialogTop = {
PieceDialogDefaultTop(
title = AnnotatedString("Default Title"),
- subText = "This is a default subtitle"
+ subText = "This is a default subtitle",
+ description = AnnotatedString("This is a default description")
)
},
dialogBottom = {
diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml
index 0f3e1cb10..bcd996070 100644
--- a/core/designsystem/src/main/res/values/strings.xml
+++ b/core/designsystem/src/main/res/values/strings.xml
@@ -317,6 +317,13 @@
Piece가 새로운 버전으로\n업데이트되었어요!
여러분의 의견을 반영하여 사용성을 개선했습니다.\n지금 바로 업데이트해 보세요!
+
+ Piece가 잠시 쉬어가요!
+ 대규모 업데이트 작업을 진행하고 있어요.\n새롭게 출시될 기능들을 기대해주세요!
+ 일시 중단 시간:
+ 닫기
+
+
가입이 승인되었어요!
매일 밤 10시, 설레는 인연을 만나보세요✨
diff --git a/core/domain/src/main/java/com/puzzle/domain/model/configure/MaintenancePeriod.kt b/core/domain/src/main/java/com/puzzle/domain/model/configure/MaintenancePeriod.kt
new file mode 100644
index 000000000..078805c6a
--- /dev/null
+++ b/core/domain/src/main/java/com/puzzle/domain/model/configure/MaintenancePeriod.kt
@@ -0,0 +1,5 @@
+package com.puzzle.domain.model.configure
+
+data class MaintenancePeriod (
+ val maintenancePeriod: String
+)
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/puzzle/domain/repository/ConfigureRepository.kt b/core/domain/src/main/java/com/puzzle/domain/repository/ConfigureRepository.kt
index ead6165aa..dc7485131 100644
--- a/core/domain/src/main/java/com/puzzle/domain/repository/ConfigureRepository.kt
+++ b/core/domain/src/main/java/com/puzzle/domain/repository/ConfigureRepository.kt
@@ -1,7 +1,9 @@
package com.puzzle.domain.repository
import com.puzzle.domain.model.configure.ForceUpdate
+import com.puzzle.domain.model.configure.MaintenancePeriod
interface ConfigureRepository {
suspend fun getUpdateInfo(): ForceUpdate
+ suspend fun getMaintenancePeriod(): MaintenancePeriod
}
diff --git a/core/network/src/main/java/com/puzzle/network/model/configure/GetMaintenancePeriodInfoResponse.kt b/core/network/src/main/java/com/puzzle/network/model/configure/GetMaintenancePeriodInfoResponse.kt
new file mode 100644
index 000000000..704a4f5f9
--- /dev/null
+++ b/core/network/src/main/java/com/puzzle/network/model/configure/GetMaintenancePeriodInfoResponse.kt
@@ -0,0 +1,13 @@
+package com.puzzle.network.model.configure
+
+import com.puzzle.domain.model.configure.MaintenancePeriod
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class GetMaintenancePeriodInfoResponse(
+ val maintenancePeriod: String = ""
+) {
+ fun toDomain() = MaintenancePeriod(
+ maintenancePeriod = maintenancePeriod
+ )
+}
diff --git a/core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt b/core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt
index 72a8f4eaf..2353d4807 100644
--- a/core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt
+++ b/core/network/src/main/java/com/puzzle/network/source/configure/ConfigureDataSource.kt
@@ -1,8 +1,13 @@
package com.puzzle.network.source.configure
+import android.util.Log
+import com.google.firebase.remoteconfig.ConfigUpdate
+import com.google.firebase.remoteconfig.ConfigUpdateListener
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
+import com.google.firebase.remoteconfig.FirebaseRemoteConfigException
import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue
import com.google.firebase.remoteconfig.get
+import com.google.firebase.remoteconfig.remoteConfigSettings
import com.puzzle.network.BuildConfig
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.json.Json
@@ -16,6 +21,22 @@ class ConfigDataSource @Inject constructor(
private val remoteConfig: FirebaseRemoteConfig,
val json: Json,
) {
+
+ init {
+ val configSettings = remoteConfigSettings {
+ minimumFetchIntervalInSeconds = 0
+ }
+ remoteConfig.setConfigSettingsAsync(configSettings)
+ remoteConfig.addOnConfigUpdateListener(object : ConfigUpdateListener {
+ override fun onUpdate(configUpdate: ConfigUpdate) {
+ remoteConfig.activate()
+ }
+ override fun onError(error: FirebaseRemoteConfigException) {
+ Log.e("ConfigDataSource", "RemoteConfig Update Error: ${error.message}", error)
+ }
+ })
+ }
+
suspend inline fun getReferenceType(key: String, defaultValue: T): T {
return getReferenceType(key) ?: defaultValue
}
@@ -44,6 +65,7 @@ class ConfigDataSource @Inject constructor(
companion object Key {
const val FORCE_UPDATE = "force_update"
+ const val MAINTENANCE_PERIOD = "maintenance_period"
fun getKey(key: String): String = "${key}_AN_${BuildConfig.BUILD_TYPE}"
}
}
diff --git a/presentation/src/main/java/com/puzzle/presentation/MainActivity.kt b/presentation/src/main/java/com/puzzle/presentation/MainActivity.kt
index 789351680..f22b56b2b 100644
--- a/presentation/src/main/java/com/puzzle/presentation/MainActivity.kt
+++ b/presentation/src/main/java/com/puzzle/presentation/MainActivity.kt
@@ -96,6 +96,7 @@ class MainActivity : ComponentActivity() {
CompositionLocalProvider(LocalAnalyticsHelper provides analyticsHelper) {
val scope = rememberCoroutineScope()
val forceUpdate by viewModel.forceUpdate.collectAsStateWithLifecycle()
+ val maintenancePeriod by viewModel.maintenancePeriod.collectAsStateWithLifecycle()
val userRole by viewModel.userRole.collectAsStateWithLifecycle()
val snackBarHostState = remember { SnackbarHostState() }
val appState = rememberPieceAppState(networkMonitor = networkMonitor)
@@ -104,6 +105,7 @@ class MainActivity : ComponentActivity() {
PieceApp(
appState = appState,
forceUpdate = forceUpdate,
+ maintenancePeriod = maintenancePeriod,
snackBarHostState = snackBarHostState,
navigateToBottomNaviDestination = { bottomBarDestination ->
if (isPendingUser(bottomBarDestination, userRole)) {
@@ -150,6 +152,13 @@ class MainActivity : ComponentActivity() {
handleNotificationIntent(intent)
}
+ override fun onResume() {
+ super.onResume()
+ lifecycleScope.launch {
+ viewModel.refreshAppStatus()
+ }
+ }
+
private fun handleNotificationIntent(intent: Intent?) {
intent?.getStringExtra(NOTIFCATION_ID)?.let { id ->
viewModel.readNotification(id.toIntOrNull() ?: return@let)
diff --git a/presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt b/presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt
index c41c75175..731838f40 100644
--- a/presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt
+++ b/presentation/src/main/java/com/puzzle/presentation/MainViewModel.kt
@@ -8,6 +8,7 @@ import com.puzzle.common.event.PieceEvent
import com.puzzle.common.suspendRunCatching
import com.puzzle.common.ui.SnackBarState
import com.puzzle.domain.model.configure.ForceUpdate
+import com.puzzle.domain.model.configure.MaintenancePeriod
import com.puzzle.domain.model.error.ErrorHelper
import com.puzzle.domain.model.error.HttpResponseException
import com.puzzle.domain.model.error.HttpResponseStatus
@@ -50,6 +51,9 @@ class MainViewModel @Inject constructor(
private val _forceUpdate = MutableStateFlow(null)
val forceUpdate = _forceUpdate.asStateFlow()
+ private val _maintenancePeriod = MutableStateFlow(null)
+ val maintenancePeriod = _maintenancePeriod.asStateFlow()
+
val userRole = userRepository.getUserRole()
.stateIn(
scope = viewModelScope,
@@ -89,15 +93,16 @@ class MainViewModel @Inject constructor(
}
internal suspend fun initConfigure() = coroutineScope {
- val forceUpdateJob = launch { checkMinVersion() }
- val loadTermsJob = launch { loadTerms() }
- val loadValuePicksJob = launch { loadValuePicks() }
- val loadValueTalksJob = launch { loadValueTalks() }
-
- forceUpdateJob.join()
- loadTermsJob.join()
- loadValuePicksJob.join()
- loadValueTalksJob.join()
+ launch { checkMinVersion() }
+ launch { checkMaintenancePeriod() }
+ launch { loadTerms() }
+ launch { loadValuePicks() }
+ launch { loadValueTalks() }
+ }
+
+ internal suspend fun refreshAppStatus() = coroutineScope {
+ launch { checkMinVersion() }
+ launch { checkMaintenancePeriod() }
}
private suspend fun checkMinVersion() {
@@ -105,7 +110,15 @@ class MainViewModel @Inject constructor(
configureRepository.getUpdateInfo()
}.onSuccess {
_forceUpdate.value = it
- }.onFailure { errorHelper.sendError(it) }
+ }.onFailure { errorHelper.recordError(it) }
+ }
+
+ private suspend fun checkMaintenancePeriod() {
+ suspendRunCatching {
+ configureRepository.getMaintenancePeriod()
+ }.onSuccess {
+ _maintenancePeriod.value = it
+ }.onFailure { errorHelper.recordError(it) }
}
private suspend fun loadTerms() {
diff --git a/presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt b/presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt
new file mode 100644
index 000000000..e64d12d7d
--- /dev/null
+++ b/presentation/src/main/java/com/puzzle/presentation/maintenance/MaintenanceDialog.kt
@@ -0,0 +1,55 @@
+package com.puzzle.presentation.maintenance
+
+import android.app.Activity
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.unit.dp
+import com.puzzle.designsystem.R
+import com.puzzle.designsystem.component.PieceDialog
+import com.puzzle.designsystem.component.PieceDialogDefaultTop
+import com.puzzle.designsystem.component.PieceSolidButton
+import com.puzzle.designsystem.foundation.PieceTheme
+
+@Composable
+internal fun MaintenanceDialog(maintenancePeriodString: String) {
+
+ val context = LocalContext.current
+ val activity = context as? Activity
+
+ PieceDialog(
+ onDismissRequest = {},
+ dialogTop = {
+ PieceDialogDefaultTop(
+ title = stringResource(id = R.string.maintenance_title),
+ subText = stringResource(id = R.string.maintenance_subtext),
+ description = buildAnnotatedString {
+ append(stringResource(id = R.string.maintenance_description_prefix))
+ append(" ")
+ withStyle(
+ style = SpanStyle(color = PieceTheme.colors.subDefault)
+ ) {
+ append(maintenancePeriodString)
+ }
+ }
+ )
+ },
+ dialogBottom = {
+ PieceSolidButton(
+ label = stringResource(id = R.string.maintenance_label),
+ onClick = {
+ activity?.finishAffinity()
+ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = 20.dp, top = 12.dp),
+ )
+ }
+ )
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt b/presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt
index 3f74b7262..c2e50d390 100644
--- a/presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt
+++ b/presentation/src/main/java/com/puzzle/presentation/ui/PieceApp.kt
@@ -19,16 +19,21 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.blur
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.puzzle.common.ui.LocalSystemBarState
import com.puzzle.common.ui.NavigationBarColor
import com.puzzle.common.ui.PieceBottomBarAnimation
import com.puzzle.common.ui.StatusBarColor
+import com.puzzle.common.ui.blur
import com.puzzle.debug.DebugDrawer
import com.puzzle.designsystem.R
import com.puzzle.designsystem.component.PieceModalBottomSheet
@@ -37,26 +42,36 @@ import com.puzzle.designsystem.component.PieceSnackBarHost
import com.puzzle.designsystem.component.PieceTopShadowFab
import com.puzzle.designsystem.foundation.PieceTheme
import com.puzzle.domain.model.configure.ForceUpdate
+import com.puzzle.domain.model.configure.MaintenancePeriod
import com.puzzle.navigation.MatchingGraphBaseRoute
import com.puzzle.navigation.Route
+import com.puzzle.presentation.maintenance.MaintenanceDialog
import com.puzzle.presentation.navigation.AppBottomBar
import com.puzzle.presentation.navigation.AppNavHost
import com.puzzle.presentation.network.NetworkScreen
import com.puzzle.presentation.update.ForceUpdateDialog
+import com.puzzle.presentation.update.isShowForceUpdateDialog
import kotlinx.coroutines.launch
@Composable
internal fun PieceApp(
appState: PieceAppState,
forceUpdate: ForceUpdate?,
+ maintenancePeriod: MaintenancePeriod?,
snackBarHostState: SnackbarHostState,
navigateToBottomNaviDestination: (Route) -> Unit,
) {
val scope = rememberCoroutineScope()
+ val context = LocalContext.current
+
+ val maintenanceString = maintenancePeriod?.maintenancePeriod?.takeIf { it.isNotBlank() }
+ val isUpdateNeeded = maintenanceString == null && isShowForceUpdateDialog(context, forceUpdate)
+ val isShowingPopup = maintenanceString != null || isUpdateNeeded
DebugDrawer(navController = appState.navController) {
PieceModalBottomSheet(bottomSheetState = appState.bottomSheetState) {
Scaffold(
+ modifier = Modifier.blur(isShowingPopup),
containerColor = PieceTheme.colors.white,
bottomBar = {
PieceBottomBarAnimation(
@@ -111,7 +126,13 @@ internal fun PieceApp(
)
NetworkScreen(appState.networkState)
- ForceUpdateDialog(forceUpdate)
+
+ if (maintenanceString != null) {
+ MaintenanceDialog(maintenancePeriodString = maintenanceString)
+ } else if (isUpdateNeeded) {
+ ForceUpdateDialog()
+ }
+
SetSystemBarColor(appState)
}
}
diff --git a/presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt b/presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt
index cee9044ea..37b0c9604 100644
--- a/presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt
+++ b/presentation/src/main/java/com/puzzle/presentation/update/ForceUpdateDialog.kt
@@ -5,11 +5,6 @@ import android.content.Intent
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@@ -23,51 +18,44 @@ import com.puzzle.domain.model.configure.ForceUpdate
import com.puzzle.presentation.BuildConfig
@Composable
-internal fun ForceUpdateDialog(forceUpdate: ForceUpdate?) {
+internal fun ForceUpdateDialog() {
val context = LocalContext.current
- var isDialogVisible by remember { mutableStateOf(false) }
- LaunchedEffect(forceUpdate) {
- isDialogVisible = isShowForceUpdateDialog(context, forceUpdate)
- }
-
- if (isDialogVisible) {
- PieceDialog(
- onDismissRequest = {},
- dialogTop = {
- PieceDialogDefaultTop(
- title = stringResource(R.string.update_title),
- subText = stringResource(R.string.update_subtext),
- )
- },
- dialogBottom = {
- PieceSolidButton(
- label = stringResource(R.string.update_app),
- onClick = {
- val intent = Intent(
- Intent.ACTION_VIEW,
- BuildConfig.PIECE_MARKET_URL.toUri()
- )
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- context.startActivity(intent)
- },
- modifier = Modifier
- .fillMaxWidth()
- .padding(bottom = 20.dp, top = 12.dp),
- )
- },
- )
- }
+ PieceDialog(
+ onDismissRequest = {},
+ dialogTop = {
+ PieceDialogDefaultTop(
+ title = stringResource(R.string.update_title),
+ subText = stringResource(R.string.update_subtext),
+ )
+ },
+ dialogBottom = {
+ PieceSolidButton(
+ label = stringResource(R.string.update_app),
+ onClick = {
+ val intent = Intent(
+ Intent.ACTION_VIEW,
+ BuildConfig.PIECE_MARKET_URL.toUri()
+ )
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ context.startActivity(intent)
+ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = 20.dp, top = 12.dp),
+ )
+ },
+ )
}
-private fun isShowForceUpdateDialog(
+internal fun isShowForceUpdateDialog(
context: Context,
info: ForceUpdate?,
): Boolean {
if (info == null) return false
- val currentVersion = context.packageManager.getPackageInfo(context.packageName, 0).versionName
- return checkShouldUpdate(currentVersion!!, info.minVersion)
+ val currentVersion = context.packageManager.getPackageInfo(context.packageName, 0).versionName ?: return false
+ return checkShouldUpdate(currentVersion, info.minVersion)
}
/**