From 1a767421863ddb565eecc38da8cc554f45f00a41 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Wed, 5 Nov 2025 21:51:22 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[FEAT/#411]=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EA=B3=B5=EC=A7=80=20=EB=8B=A4=EC=9D=B4=EC=96=BC=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/TerningServerNoticeDialog.kt | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt diff --git a/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt b/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt new file mode 100644 index 00000000..21d66497 --- /dev/null +++ b/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt @@ -0,0 +1,96 @@ +package com.terning.feature.splash.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.component.dialog.NoticeDialogButton +import com.terning.core.designsystem.component.dialog.TerningNoticeDialog +import com.terning.core.designsystem.theme.Back +import com.terning.core.designsystem.theme.Black +import com.terning.core.designsystem.theme.Grey150 +import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.Grey350 +import com.terning.core.designsystem.theme.Grey500 +import com.terning.core.designsystem.theme.TerningMain +import com.terning.core.designsystem.theme.TerningMain2 +import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White +import com.terning.feature.splash.R + +@Composable +internal fun TerningServerNoticeDialog( + onDismissButtonClick: () -> Unit, + onUpdateButtonClick: () -> Unit, +) { + TerningNoticeDialog( + titleText = stringResource(R.string.dialog_title), + bodyText = stringResource(R.string.dailog_bodytitle), + ) { + Column( + modifier = Modifier + .clip(RoundedCornerShape(5.dp)) + .background(Back) + .padding( + vertical = 18.dp, + horizontal = 58.dp + ) + ) { + Text( + text = stringResource(R.string.dialog_server_over_title), + style = TerningTheme.typography.body6, + color = Black, + ) + Text( + text = stringResource(R.string.dialog_server_over_day), + style = TerningTheme.typography.detail4, + color = Grey500 + ) + } + Spacer(modifier = Modifier.height(26.dp)) + Row( + modifier = it, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + NoticeDialogButton( + text = stringResource(R.string.dialog_dismiss), + contentColor = Grey350, + pressedContainerColor = Grey200, + containerColor = Grey150, + onClick = onDismissButtonClick, + modifier = Modifier.weight(1f) + ) + NoticeDialogButton( + text = stringResource(R.string.dialog_detail), + contentColor = White, + pressedContainerColor = TerningMain2, + containerColor = TerningMain, + onClick = onUpdateButtonClick, + modifier = Modifier.weight(1f) + ) + } + } +} + +@Preview(showBackground = true, widthDp = 360, heightDp = 780) +@Composable +private fun TerningPatchUpdateDialogPreview() { + TerningPointTheme { + TerningServerNoticeDialog( + onDismissButtonClick = {}, + onUpdateButtonClick = {}, + ) + } +} From d5da9298639253ffe25dc7626fdb15982a32c682 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 01:56:11 +0900 Subject: [PATCH 02/10] =?UTF-8?q?[FEAT/#411]=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EA=B3=B5=EC=A7=80=20=EB=8B=A4=EC=9D=B4=EC=96=BC=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../splash/component/TerningServerNoticeDialog.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt b/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt index 21d66497..31ba96fd 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt @@ -33,10 +33,10 @@ import com.terning.feature.splash.R @Composable internal fun TerningServerNoticeDialog( onDismissButtonClick: () -> Unit, - onUpdateButtonClick: () -> Unit, + onDetailButtonClick: () -> Unit, ) { TerningNoticeDialog( - titleText = stringResource(R.string.dialog_title), + titleText = stringResource(R.string.dialog_server_title), bodyText = stringResource(R.string.dailog_bodytitle), ) { Column( @@ -53,6 +53,7 @@ internal fun TerningServerNoticeDialog( style = TerningTheme.typography.body6, color = Black, ) + Spacer(modifier = Modifier.height(8.dp)) Text( text = stringResource(R.string.dialog_server_over_day), style = TerningTheme.typography.detail4, @@ -77,7 +78,7 @@ internal fun TerningServerNoticeDialog( contentColor = White, pressedContainerColor = TerningMain2, containerColor = TerningMain, - onClick = onUpdateButtonClick, + onClick = onDetailButtonClick, modifier = Modifier.weight(1f) ) } @@ -90,7 +91,7 @@ private fun TerningPatchUpdateDialogPreview() { TerningPointTheme { TerningServerNoticeDialog( onDismissButtonClick = {}, - onUpdateButtonClick = {}, + onDetailButtonClick = {}, ) } } From 091f483735fd52fd5a7cc5d10997876aa3ae3769 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 01:56:19 +0900 Subject: [PATCH 03/10] =?UTF-8?q?[FEAT/#411]=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EA=B3=B5=EC=A7=80=20=EB=8B=A4=EC=9D=B4=EC=96=BC=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/splash/src/main/res/values/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/feature/splash/src/main/res/values/strings.xml b/feature/splash/src/main/res/values/strings.xml index da9308db..b8909616 100644 --- a/feature/splash/src/main/res/values/strings.xml +++ b/feature/splash/src/main/res/values/strings.xml @@ -6,4 +6,14 @@ 다음에 하기 업데이트 하기 업데이트 하러 가기 + + 터닝 서비스 종료 안내 + 그동안 터닝을 사랑해주신 모든 분들께\n + 진심으로 감사의 말씀을 드립니다.\n + ‘터닝’은 11월 25일부로 서비스가 종료될 예정이며,\n + 자세한 사항은 공지 내용을 확인해주세요. + 서비스 종료 예정일 + 2025년 11월 25일 + 닫기 + 자세히 보기 \ No newline at end of file From 387f9113ee9d7b72b2c9d6cd3ce47e0c4bdd45ac Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 02:32:23 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[FEAT/#411]=20=EC=83=88=EB=A1=AD=EA=B2=8C?= =?UTF-8?q?=20=EB=8B=A4=EC=9D=B4=EC=96=BC=EB=A1=9C=EA=B7=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/TerningServerNoticeDialog.kt | 106 +++++++++++------- .../splash/src/main/res/values/strings.xml | 4 +- 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt b/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt index 31ba96fd..b41cee8f 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/component/TerningServerNoticeDialog.kt @@ -10,18 +10,23 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties import com.terning.core.designsystem.component.dialog.NoticeDialogButton -import com.terning.core.designsystem.component.dialog.TerningNoticeDialog import com.terning.core.designsystem.theme.Back import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.Grey150 import com.terning.core.designsystem.theme.Grey200 import com.terning.core.designsystem.theme.Grey350 +import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.Grey500 import com.terning.core.designsystem.theme.TerningMain import com.terning.core.designsystem.theme.TerningMain2 @@ -35,52 +40,75 @@ internal fun TerningServerNoticeDialog( onDismissButtonClick: () -> Unit, onDetailButtonClick: () -> Unit, ) { - TerningNoticeDialog( - titleText = stringResource(R.string.dialog_server_title), - bodyText = stringResource(R.string.dailog_bodytitle), + Dialog( + onDismissRequest = { }, + properties = DialogProperties( + dismissOnBackPress = false, + dismissOnClickOutside = false, + usePlatformDefaultWidth = false, + ) ) { Column( + horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier - .clip(RoundedCornerShape(5.dp)) - .background(Back) - .padding( - vertical = 18.dp, - horizontal = 58.dp - ) + .padding(horizontal = 28.dp) + .background(color = White, shape = RoundedCornerShape(20.dp)) + .padding(12.dp) ) { Text( - text = stringResource(R.string.dialog_server_over_title), - style = TerningTheme.typography.body6, - color = Black, + text = stringResource(R.string.dialog_server_title), + style = TerningTheme.typography.title2, + color = Grey500, + modifier = Modifier.padding(top = 20.dp) ) - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(20.dp)) Text( - text = stringResource(R.string.dialog_server_over_day), - style = TerningTheme.typography.detail4, - color = Grey500 - ) - } - Spacer(modifier = Modifier.height(26.dp)) - Row( - modifier = it, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - NoticeDialogButton( - text = stringResource(R.string.dialog_dismiss), - contentColor = Grey350, - pressedContainerColor = Grey200, - containerColor = Grey150, - onClick = onDismissButtonClick, - modifier = Modifier.weight(1f) - ) - NoticeDialogButton( - text = stringResource(R.string.dialog_detail), - contentColor = White, - pressedContainerColor = TerningMain2, - containerColor = TerningMain, - onClick = onDetailButtonClick, - modifier = Modifier.weight(1f) + text = stringResource(R.string.dialog_bodytitle), + style = TerningTheme.typography.body4.copy(textAlign = TextAlign.Center), + overflow = TextOverflow.Clip, + color = Grey400, ) + Spacer(modifier = Modifier.height(26.dp)) + Column( + modifier = Modifier + .clip(RoundedCornerShape(5.dp)) + .background(Back) + .padding( + vertical = 18.dp, + horizontal = 58.dp + ) + ) { + Text( + text = stringResource(R.string.dialog_server_over_title), + style = TerningTheme.typography.body6, + color = Black, + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = stringResource(R.string.dialog_server_over_day), + style = TerningTheme.typography.detail4, + color = Grey500 + ) + } + Spacer(modifier = Modifier.height(26.dp)) + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + NoticeDialogButton( + text = stringResource(R.string.dialog_dismiss), + contentColor = Grey350, + pressedContainerColor = Grey200, + containerColor = Grey150, + onClick = onDismissButtonClick, + modifier = Modifier.weight(1f) + ) + NoticeDialogButton( + text = stringResource(R.string.dialog_detail), + contentColor = White, + pressedContainerColor = TerningMain2, + containerColor = TerningMain, + onClick = onDetailButtonClick, + modifier = Modifier.weight(1f) + ) + } } } } diff --git a/feature/splash/src/main/res/values/strings.xml b/feature/splash/src/main/res/values/strings.xml index b8909616..e5a4d914 100644 --- a/feature/splash/src/main/res/values/strings.xml +++ b/feature/splash/src/main/res/values/strings.xml @@ -8,7 +8,7 @@ 업데이트 하러 가기 터닝 서비스 종료 안내 - 그동안 터닝을 사랑해주신 모든 분들께\n + 그동안 터닝을 사랑해주신 모든 분들께\n 진심으로 감사의 말씀을 드립니다.\n ‘터닝’은 11월 25일부로 서비스가 종료될 예정이며,\n 자세한 사항은 공지 내용을 확인해주세요. @@ -16,4 +16,4 @@ 2025년 11월 25일 닫기 자세히 보기 - \ No newline at end of file + From 9d40bb55a3e3b70c7689d657682c4fbfa2196bba Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 02:38:48 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[FEAT/#411]=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EB=9C=AC=20=EC=8B=9C=EA=B0=81=20=EB=A1=9C?= =?UTF-8?q?=EC=BB=AC=EC=A0=80=EC=9E=A5=EC=86=8C=EC=97=90=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/terning/core/local/TerningDataStore.kt | 3 ++- .../java/com/terning/core/local/TerningDataStoreImpl.kt | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/core/local/src/main/java/com/terning/core/local/TerningDataStore.kt b/core/local/src/main/java/com/terning/core/local/TerningDataStore.kt index 23d3bef8..80678ead 100644 --- a/core/local/src/main/java/com/terning/core/local/TerningDataStore.kt +++ b/core/local/src/main/java/com/terning/core/local/TerningDataStore.kt @@ -7,5 +7,6 @@ interface TerningDataStore { var userId: Long var alarmAvailable: Boolean var hasRequestedPermission: Boolean + var serverNoticeTimestamp: Long fun clearInfo() -} \ No newline at end of file +} diff --git a/core/local/src/main/java/com/terning/core/local/TerningDataStoreImpl.kt b/core/local/src/main/java/com/terning/core/local/TerningDataStoreImpl.kt index 4d0bc4dc..5df74c64 100644 --- a/core/local/src/main/java/com/terning/core/local/TerningDataStoreImpl.kt +++ b/core/local/src/main/java/com/terning/core/local/TerningDataStoreImpl.kt @@ -31,6 +31,10 @@ class TerningDataStoreImpl @Inject constructor( get() = dataStore.getBoolean(PERMISSION_REQUESTED, false) set(value) = dataStore.edit { putBoolean(PERMISSION_REQUESTED, value) } + override var serverNoticeTimestamp: Long + get() = dataStore.getLong(LAST_NOTICE_TIME, 0L) + set(value) = dataStore.edit { putLong(LAST_NOTICE_TIME, value) } + override fun clearInfo() { dataStore.edit().clear().apply() } @@ -42,5 +46,6 @@ class TerningDataStoreImpl @Inject constructor( private const val USER_ID = "USER_ID" private const val ALARM = "ALARM" private const val PERMISSION_REQUESTED = "PERMISSION_REQUESTED" + private const val LAST_NOTICE_TIME = "LAST_NOTICE_TIME" } -} \ No newline at end of file +} From 10e6ea8342dca5002caeadbe03a83d5c7a0189c8 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 02:39:01 +0900 Subject: [PATCH 06/10] =?UTF-8?q?[FEAT/#411]=20=EA=B7=B8=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/repositoryimpl/UserRepositoryImpl.kt | 29 ++++++++++++++++++- .../domain/user/repository/UserRepository.kt | 3 ++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt b/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt index 1234c274..8d73eeb8 100644 --- a/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt +++ b/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt @@ -48,4 +48,31 @@ class UserRepositoryImpl @Inject constructor( override fun clearInfo() { terningDataStore.clearInfo() } -} \ No newline at end of file + + override fun hasNoticeCooldownPassed(): Boolean { + val lastShownTimestamp = terningDataStore.serverNoticeTimestamp + + // 2. 0L이면 (앱 설치 후 본 적 없음) -> 무조건 true 반환 (공지 보여줘야 함) + if (lastShownTimestamp == 0L) { + return true + } + + // 3. 현재 시간 가져오기 + val currentTime = System.currentTimeMillis() + + // 4. (현재 시간 - 저장된 시간) = 경과 시간 + val elapsedTime = currentTime - lastShownTimestamp + + // 5. 경과 시간이 3시간(밀리초)보다 크면 true + return elapsedTime > THREE_HOURS_MS + } + + override fun setNoticeTimestampToNow() { + terningDataStore.serverNoticeTimestamp = System.currentTimeMillis() + } + + companion object { + // 3시간을 밀리초로 환산한 값 + private const val THREE_HOURS_MS = 3 * 60 * 60 * 1000L + } +} diff --git a/domain/user/src/main/java/com/terning/domain/user/repository/UserRepository.kt b/domain/user/src/main/java/com/terning/domain/user/repository/UserRepository.kt index a55eaa25..82c809b3 100644 --- a/domain/user/src/main/java/com/terning/domain/user/repository/UserRepository.kt +++ b/domain/user/src/main/java/com/terning/domain/user/repository/UserRepository.kt @@ -26,4 +26,7 @@ interface UserRepository { fun getPermissionRequested(): Boolean fun clearInfo() + + fun hasNoticeCooldownPassed(): Boolean + fun setNoticeTimestampToNow() } From 855fe8cbd2190875f5ceff6c198d412ddd0d46d6 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 02:39:15 +0900 Subject: [PATCH 07/10] =?UTF-8?q?[FEAT/#411]=20=EA=B7=B8=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20presentation=20=EA=B3=84=EC=B8=B5=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/update/entity/UpdateState.kt | 3 ++- .../com/terning/feature/splash/SplashRoute.kt | 27 +++++++++++++++++-- .../terning/feature/splash/SplashUiState.kt | 2 ++ .../terning/feature/splash/SplashViewModel.kt | 16 +++++++++-- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/domain/update/src/main/java/com/terning/domain/update/entity/UpdateState.kt b/domain/update/src/main/java/com/terning/domain/update/entity/UpdateState.kt index f875f327..13ba7e9b 100644 --- a/domain/update/src/main/java/com/terning/domain/update/entity/UpdateState.kt +++ b/domain/update/src/main/java/com/terning/domain/update/entity/UpdateState.kt @@ -5,4 +5,5 @@ sealed class UpdateState { data object NoUpdateAvailable : UpdateState() data class MajorUpdateAvailable(val title: String, val content: String) : UpdateState() data class PatchUpdateAvailable(val title: String, val content: String) : UpdateState() -} \ No newline at end of file + data object ServerNoticeAvailable: UpdateState() +} diff --git a/feature/splash/src/main/java/com/terning/feature/splash/SplashRoute.kt b/feature/splash/src/main/java/com/terning/feature/splash/SplashRoute.kt index 5c3590b0..da0d1565 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/SplashRoute.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/SplashRoute.kt @@ -1,5 +1,7 @@ package com.terning.feature.splash +import android.content.Context +import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -15,6 +17,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview +import androidx.core.net.toUri import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver @@ -29,9 +32,9 @@ import com.terning.core.designsystem.theme.TerningMain import com.terning.core.designsystem.theme.TerningPointTheme import com.terning.core.designsystem.theme.White import com.terning.core.designsystem.type.DeeplinkType -import com.terning.feature.splash.SplashUiState import com.terning.feature.splash.component.TerningMajorUpdateDialog import com.terning.feature.splash.component.TerningPatchUpdateDialog +import com.terning.feature.splash.component.TerningServerNoticeDialog import kotlinx.coroutines.launch @Composable @@ -106,7 +109,11 @@ internal fun SplashRoute( SplashScreen( splashUiState = updateState.toUi(), onUpdateButtonClick = context::launchPlayStore, - onUpdateSkipButtonClick = viewModel::checkIfAccessTokenAvailable + onUpdateSkipButtonClick = viewModel::checkIfAccessTokenAvailable, + onDetailButtonClick = { + navigateToServerWebView(context) + viewModel.checkIfAccessTokenAvailable() + } ) } @@ -115,6 +122,7 @@ private fun SplashScreen( splashUiState: SplashUiState, onUpdateButtonClick: () -> Unit, onUpdateSkipButtonClick: () -> Unit, + onDetailButtonClick: () -> Unit, ) { when (splashUiState) { is SplashUiState.MajorUpdateAvailable -> { @@ -138,6 +146,13 @@ private fun SplashScreen( } } + is SplashUiState.ServerNoticeAvailable -> { + TerningServerNoticeDialog( + onDismissButtonClick = onUpdateSkipButtonClick, + onDetailButtonClick = onDetailButtonClick, + ) + } + else -> {} } @@ -156,6 +171,13 @@ private fun SplashScreen( } } +private fun navigateToServerWebView(context: Context) { + CustomTabsIntent.Builder().build().launchUrl(context, SERVER_URL.toUri()) +} + +private const val SERVER_URL = + "https://abundant-quiver-13f.notion.site/2a22867b52c180649a5bfdf1704820a3?pvs=73" + @Preview(showBackground = true) @Composable private fun SplashScreenPreview() { @@ -164,6 +186,7 @@ private fun SplashScreenPreview() { splashUiState = SplashUiState.NoUpdateAvailable, onUpdateButtonClick = {}, onUpdateSkipButtonClick = {}, + onDetailButtonClick = {}, ) } } diff --git a/feature/splash/src/main/java/com/terning/feature/splash/SplashUiState.kt b/feature/splash/src/main/java/com/terning/feature/splash/SplashUiState.kt index e9fd8263..85610a60 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/SplashUiState.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/SplashUiState.kt @@ -9,6 +9,7 @@ sealed class SplashUiState { data object NoUpdateAvailable : SplashUiState() data class MajorUpdateAvailable(val title: String, val content: String) : SplashUiState() data class PatchUpdateAvailable(val title: String, val content: String) : SplashUiState() + data object ServerNoticeAvailable : SplashUiState() } fun UpdateState.toUi(): SplashUiState = when (this) { @@ -16,4 +17,5 @@ fun UpdateState.toUi(): SplashUiState = when (this) { UpdateState.NoUpdateAvailable -> SplashUiState.NoUpdateAvailable is UpdateState.MajorUpdateAvailable -> SplashUiState.MajorUpdateAvailable(title, content) is UpdateState.PatchUpdateAvailable -> SplashUiState.PatchUpdateAvailable(title, content) + is UpdateState.ServerNoticeAvailable -> SplashUiState.ServerNoticeAvailable } diff --git a/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt b/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt index e04448fe..ceab0acf 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt @@ -18,7 +18,7 @@ import javax.inject.Inject @HiltViewModel class SplashViewModel @Inject constructor( private val userRepository: UserRepository, - private val getLatestVersionUseCase: GetUpdateStateUseCase + private val getLatestVersionUseCase: GetUpdateStateUseCase, ) : ViewModel() { private val _sideEffects = MutableSharedFlow() @@ -47,6 +47,18 @@ class SplashViewModel @Inject constructor( private fun checkIfUpdateNotAvailable(updateState: UpdateState) { if (updateState is UpdateState.NoUpdateAvailable) { + checkServerNotice() + } + } + + private fun checkServerNotice() = viewModelScope.launch { + // 3시간 지났는지 확인 + if (userRepository.hasNoticeCooldownPassed()) { + // 지났으면 UI 상태 변경 + _updateState.value = UpdateState.ServerNoticeAvailable + // 다이얼로그가 뜬 시각 설정 + userRepository.setNoticeTimestampToNow() + } else { checkIfAccessTokenAvailable() } } @@ -58,4 +70,4 @@ class SplashViewModel @Inject constructor( companion object { private const val DELAY_TIME = 500L } -} \ No newline at end of file +} From 2d46018f64664215bcd97fa471e1d599c8e32d27 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 02:40:00 +0900 Subject: [PATCH 08/10] =?UTF-8?q?[FEAT/#411]=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/user/repositoryimpl/UserRepositoryImpl.kt | 9 +-------- .../java/com/terning/feature/splash/SplashViewModel.kt | 3 --- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt b/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt index 8d73eeb8..4278feb1 100644 --- a/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt +++ b/data/user/src/main/java/com/terning/data/user/repositoryimpl/UserRepositoryImpl.kt @@ -52,18 +52,12 @@ class UserRepositoryImpl @Inject constructor( override fun hasNoticeCooldownPassed(): Boolean { val lastShownTimestamp = terningDataStore.serverNoticeTimestamp - // 2. 0L이면 (앱 설치 후 본 적 없음) -> 무조건 true 반환 (공지 보여줘야 함) - if (lastShownTimestamp == 0L) { - return true - } + if (lastShownTimestamp == 0L) return true - // 3. 현재 시간 가져오기 val currentTime = System.currentTimeMillis() - // 4. (현재 시간 - 저장된 시간) = 경과 시간 val elapsedTime = currentTime - lastShownTimestamp - // 5. 경과 시간이 3시간(밀리초)보다 크면 true return elapsedTime > THREE_HOURS_MS } @@ -72,7 +66,6 @@ class UserRepositoryImpl @Inject constructor( } companion object { - // 3시간을 밀리초로 환산한 값 private const val THREE_HOURS_MS = 3 * 60 * 60 * 1000L } } diff --git a/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt b/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt index ceab0acf..b7f7b2aa 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/SplashViewModel.kt @@ -52,11 +52,8 @@ class SplashViewModel @Inject constructor( } private fun checkServerNotice() = viewModelScope.launch { - // 3시간 지났는지 확인 if (userRepository.hasNoticeCooldownPassed()) { - // 지났으면 UI 상태 변경 _updateState.value = UpdateState.ServerNoticeAvailable - // 다이얼로그가 뜬 시각 설정 userRepository.setNoticeTimestampToNow() } else { checkIfAccessTokenAvailable() From 9adf5021a8776e092234553271defe38cfa59c6a Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 02:42:01 +0900 Subject: [PATCH 09/10] [FEAT/#411] 1.3.8 -> 1.4.0 version update --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7ec1801e..92e57073 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,8 +2,8 @@ compileSdk = "35" minSdk = "28" targetSdk = "35" -versionName = "1.3.8" -versionCode = "103080" +versionName = "1.4.0" +versionCode = "104000" jvmTarget = "1.8" ## Android gradle plugin From 08606293c042be42bdf2699aaae3a9630dfcc86c Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 10 Nov 2025 02:45:26 +0900 Subject: [PATCH 10/10] [FEAT/#411] readme update --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a447e8a..fc1c6150 100644 --- a/README.md +++ b/README.md @@ -114,11 +114,12 @@
+## ANDROID ARTICLE +🔗 [TERNING TISTORY](https://terning.tistory.com/category/Android) ## DESIGN SYSTEM 🔗 [TERNING DESIGN SYSTEM](https://teamterning.github.io/Terning-Android/index.html) - ## KANBAN BOARD 🔗 [TERNING PROJECT](https://github.com/orgs/teamterning/projects/1)