From b16f0b84d4cfa7f44329149124b737b5264f7a37 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 26 Apr 2025 18:50:49 +0900 Subject: [PATCH 01/16] =?UTF-8?q?[FEAT/#382]=20imageUrl=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../messageservice/TerningMessagingService.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index 158ac44a..d1cd8295 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -43,11 +43,13 @@ class TerningMessagingService : FirebaseMessagingService() { val title = intent?.getStringExtra(TITLE).orEmpty() val body = intent?.getStringExtra(BODY).orEmpty() val type = intent?.getStringExtra(TYPE).orEmpty() + val imageUrl = intent?.getStringExtra(IMAGE_URL).orEmpty() sendNotification( title = title, body = body, - type = type + type = type, + imageUrl = imageUrl ) } @@ -61,15 +63,22 @@ class TerningMessagingService : FirebaseMessagingService() { val title = message.data[TITLE].orEmpty() val body = message.data[BODY].orEmpty() val type = message.data[TYPE].orEmpty() + val imageUrl = message.data[IMAGE_URL].orEmpty() sendNotification( title = title, body = body, - type = type + type = type, + imageUrl = imageUrl ) } - private fun sendNotification(title: String, body: String, type: String) { + private fun sendNotification( + title: String, + body: String, + type: String, + imageUrl: String + ) { val notifyId = Random().nextInt() val intent = navigatorProvider.getMainActivityIntent(deeplink = type).apply { action = Intent.ACTION_VIEW @@ -109,5 +118,6 @@ class TerningMessagingService : FirebaseMessagingService() { private const val TITLE: String = "title" private const val BODY: String = "body" private const val TYPE: String = "type" + private const val IMAGE_URL: String = "imageUrl" } } \ No newline at end of file From 6214e64436410c676127b4a5d8ec3eecf73a1f9b Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 28 Apr 2025 16:41:06 +0900 Subject: [PATCH 02/16] =?UTF-8?q?[FEAT/#382]=20=ED=91=B8=EC=8B=9C=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20LargeIcon=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/firebase/build.gradle.kts | 3 ++ .../messageservice/TerningMessagingService.kt | 42 +++++++++++++------ feature/main/build.gradle.kts | 1 + 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/core/firebase/build.gradle.kts b/core/firebase/build.gradle.kts index 60eaa8ce..6bde3226 100644 --- a/core/firebase/build.gradle.kts +++ b/core/firebase/build.gradle.kts @@ -23,4 +23,7 @@ dependencies { implementation(libs.firebase.analytics) implementation(libs.firebase.messaging) implementation(libs.firebase.config) + + // coil + implementation(libs.coil.compose) } \ No newline at end of file diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index d1cd8295..43428d9b 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -5,9 +5,11 @@ import android.app.NotificationManager import android.app.PendingIntent import android.content.Intent import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat import androidx.core.content.getSystemService import androidx.core.net.toUri +import coil3.BitmapImage +import coil3.ImageLoader +import coil3.request.ImageRequest import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import com.terning.core.firebase.R @@ -97,20 +99,33 @@ class TerningMessagingService : FirebaseMessagingService() { setSmallIcon(R.mipmap.ic_terning_launcher) setContentTitle(title) setContentText(body) - setPriority(NotificationManagerCompat.IMPORTANCE_HIGH) + setAutoCancel(true) + setPriority(NotificationCompat.PRIORITY_HIGH) setContentIntent(pendingIntent) } - - getSystemService()?.run { - createNotificationChannel( - NotificationChannel( - channelId, - channelId, - NotificationManager.IMPORTANCE_HIGH, - ), + val notificationManager = getSystemService() + notificationManager?.createNotificationChannel( + NotificationChannel( + channelId, + channelId, + NotificationManager.IMPORTANCE_HIGH ) - notify(notifyId, notificationBuilder.build()) - } + ) + val imageLoader = ImageLoader(this) + val request = ImageRequest.Builder(this) + .data(imageUrl) + .target( + onSuccess = { image -> + val bitmap = (image as BitmapImage).bitmap + notificationBuilder.setLargeIcon(bitmap) + notificationManager?.notify(notifyId, notificationBuilder.build()) + }, + onError = { + notificationManager?.notify(notifyId, notificationBuilder.build()) + } + ) + .build() + imageLoader.enqueue(request) } companion object { @@ -120,4 +135,5 @@ class TerningMessagingService : FirebaseMessagingService() { private const val TYPE: String = "type" private const val IMAGE_URL: String = "imageUrl" } -} \ No newline at end of file +} + diff --git a/feature/main/build.gradle.kts b/feature/main/build.gradle.kts index 97106181..be6323e8 100644 --- a/feature/main/build.gradle.kts +++ b/feature/main/build.gradle.kts @@ -11,6 +11,7 @@ android { dependencies { // core implementation(projects.core.navigator) + implementation(projects.core.firebase) // feature implementation(projects.feature.calendar) From 18aacdba8374b095e3e875668865d12b696b1c94 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 28 Apr 2025 18:42:52 +0900 Subject: [PATCH 03/16] =?UTF-8?q?[FEAT/#382]=20=EC=83=81=ED=83=9C=EB=B0=94?= =?UTF-8?q?,=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=EB=B0=94=20?= =?UTF-8?q?=EC=83=89=EC=83=81=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/calendar/CalendarRoute.kt | 8 +++++++ .../com/terning/feature/home/HomeRoute.kt | 22 ++++++++----------- .../feature/mypage/mypage/MyPageRoute.kt | 11 +++------- .../mypage/profileedit/ProfileEditRoute.kt | 7 ++---- .../feature/search/search/SearchRoute.kt | 8 +++++++ 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index 8a050444..0d0ed27d 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -23,11 +23,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.component.topappbar.CalendarTopAppBar import com.terning.core.designsystem.extension.getWeekIndexContainingSelectedDate import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.White import com.terning.feature.calendar.calendar.component.ScreenTransition import com.terning.feature.calendar.calendar.component.WeekDaysHeader import com.terning.feature.calendar.calendar.model.CalendarUiState @@ -48,6 +50,12 @@ fun CalendarRoute( val uiState by viewModel.uiState.collectAsStateWithLifecycle() val amplitudeTracker = LocalTracker.current + val systemUiController = rememberSystemUiController() + + LaunchedEffect(Unit) { + systemUiController.setStatusBarColor(color = White) + systemUiController.setNavigationBarColor(color = White) + } CalendarScreen( uiState = uiState, diff --git a/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt b/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt index f6264aac..261e15dd 100644 --- a/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt +++ b/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt @@ -19,7 +19,6 @@ import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -106,19 +105,11 @@ fun HomeRoute( } val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor( - color = White - ) - systemUiController.setNavigationBarColor( - color = White - ) - } - val lifecycleOwner = LocalLifecycleOwner.current - val context = LocalContext.current - - val amplitudeTracker = LocalTracker.current + LaunchedEffect(Unit) { + systemUiController.setStatusBarColor(color = White) + systemUiController.setNavigationBarColor(color = White) + } LaunchedEffect(key1 = true) { viewModel.getProfile() @@ -127,6 +118,9 @@ fun HomeRoute( viewModel.getRecommendInternFlow() } + val lifecycleOwner = LocalLifecycleOwner.current + val context = LocalContext.current + LaunchedEffect(viewModel.homeSideEffect, lifecycleOwner) { viewModel.homeSideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) .collect { sideEffect -> @@ -138,6 +132,8 @@ fun HomeRoute( } } + val amplitudeTracker = LocalTracker.current + HomeScreen( paddingValues = paddingValues, navigateToIntern = { diff --git a/feature/mypage/src/main/java/com/terning/feature/mypage/mypage/MyPageRoute.kt b/feature/mypage/src/main/java/com/terning/feature/mypage/mypage/MyPageRoute.kt index 13c438bd..c80f7b24 100644 --- a/feature/mypage/src/main/java/com/terning/feature/mypage/mypage/MyPageRoute.kt +++ b/feature/mypage/src/main/java/com/terning/feature/mypage/mypage/MyPageRoute.kt @@ -28,7 +28,6 @@ import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -107,17 +106,13 @@ fun MyPageRoute( viewModel.updateAlarmAvailability(isGranted) } - SideEffect { - systemUiController.setStatusBarColor( - color = Back - ) + LaunchedEffect(Unit) { + systemUiController.setStatusBarColor(color = Back) } DisposableEffect(lifecycleOwner) { onDispose { - systemUiController.setStatusBarColor( - color = White - ) + systemUiController.setStatusBarColor(color = White) } } diff --git a/feature/mypage/src/main/java/com/terning/feature/mypage/profileedit/ProfileEditRoute.kt b/feature/mypage/src/main/java/com/terning/feature/mypage/profileedit/ProfileEditRoute.kt index e3fae490..78f09f9a 100644 --- a/feature/mypage/src/main/java/com/terning/feature/mypage/profileedit/ProfileEditRoute.kt +++ b/feature/mypage/src/main/java/com/terning/feature/mypage/profileedit/ProfileEditRoute.kt @@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -54,10 +53,8 @@ fun ProfileEditRoute( val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor( - color = White - ) + LaunchedEffect(Unit) { + systemUiController.setStatusBarColor(color = White) } LaunchedEffect(key1 = true) { diff --git a/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt b/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt index cfc2bb0f..57c3e38a 100644 --- a/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt +++ b/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt @@ -22,6 +22,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.component.image.TerningImage @@ -56,6 +57,13 @@ fun SearchRoute( val amplitudeTracker = LocalTracker.current + val systemUiController = rememberSystemUiController() + + LaunchedEffect(Unit) { + systemUiController.setStatusBarColor(color = White) + systemUiController.setNavigationBarColor(color = White) + } + LaunchedEffect(key1 = true) { viewModel.getSearchViews() viewModel.getSearchScraps() From 16fed9c823508934f38271a89e7a3b99385e8f2d Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 28 Apr 2025 18:47:37 +0900 Subject: [PATCH 04/16] =?UTF-8?q?[FEAT/#382]=20=ED=99=94=EB=A9=B4=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=ED=95=98=EB=8A=94=20=EB=B7=B0=20=EB=94=A5=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/navigation/CalendarNavigation.kt | 10 +++++++++- .../feature/home/navigation/HometNavigation.kt | 14 +++++++++++++- .../search/search/navigation/SearchNavigation.kt | 11 ++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt index 2590ac67..9aa93ee9 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt @@ -7,10 +7,12 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import androidx.navigation.navDeepLink import com.terning.core.navigation.MainTabRoute import com.terning.feature.calendar.calendar.CalendarRoute import kotlinx.serialization.Serializable +private const val CALENDAR_PATH: String = "terning://calendar" fun NavController.navigateCalendar(navOptions: NavOptions? = null) { navigate( @@ -23,7 +25,13 @@ fun NavGraphBuilder.calendarNavGraph( navigateIntern: (Long) -> Unit, paddingValues: PaddingValues ) { - composable { + composable( + deepLinks = listOf( + navDeepLink( + basePath = CALENDAR_PATH + ) + ) + ) { CalendarRoute( modifier = Modifier.padding(paddingValues), navigateToAnnouncement = navigateIntern diff --git a/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt b/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt index 57996f9e..f508df6b 100644 --- a/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt +++ b/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt @@ -1,14 +1,19 @@ package com.terning.feature.home.navigation +import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.PaddingValues import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import androidx.navigation.navDeepLink import com.terning.core.navigation.MainTabRoute import com.terning.feature.home.HomeRoute import kotlinx.serialization.Serializable +private const val HOME_PATH: String = "terning://home" + fun NavController.navigateHome(navOptions: NavOptions? = null) { navigate( route = Home, @@ -16,12 +21,19 @@ fun NavController.navigateHome(navOptions: NavOptions? = null) { ) } +@RequiresApi(Build.VERSION_CODES.TIRAMISU) fun NavGraphBuilder.homeNavGraph( paddingValues: PaddingValues, navigateToCalendar: () -> Unit, navigateToIntern: (Long) -> Unit ) { - composable { + composable( + deepLinks = listOf( + navDeepLink( + basePath = HOME_PATH + ) + ) + ) { HomeRoute( paddingValues = paddingValues, navigateToCalendar = navigateToCalendar, diff --git a/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt b/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt index f3be18a9..a6e31ffe 100644 --- a/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt +++ b/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt @@ -5,10 +5,13 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import androidx.navigation.navDeepLink import com.terning.core.navigation.MainTabRoute import com.terning.feature.search.search.SearchRoute import kotlinx.serialization.Serializable +private const val SEARCH_PATH: String = "terning://search" + fun NavController.navigateSearch(navOptions: NavOptions? = null) { navigate( route = Search, @@ -21,7 +24,13 @@ fun NavGraphBuilder.searchNavGraph( navigateSearchProcess: () -> Unit, navigateIntern: (Long) -> Unit, ) { - composable { + composable ( + deepLinks = listOf( + navDeepLink( + basePath = SEARCH_PATH + ) + ) + ){ SearchRoute( paddingValues = paddingValues, navigateToSearchProcess = navigateSearchProcess, From 86bc36a2233f33a11a080268f30f6cef483578e1 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 00:21:48 +0900 Subject: [PATCH 05/16] =?UTF-8?q?[FEAT/#382]=20=ED=8F=AC=EA=B7=B8=EB=9D=BC?= =?UTF-8?q?=EC=9A=B4=EB=93=9C=20=EC=97=AC=EB=B6=80=EB=A5=BC=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=ED=95=9C=20=EC=95=8C=EB=A6=BC=20=EC=9C=A0=ED=98=95=20?= =?UTF-8?q?=EB=B6=84=EA=B8=B0=EC=B2=98=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../messageservice/TerningMessagingService.kt | 38 ++++++++++++++++++- .../com/terning/feature/main/MainActivity.kt | 2 + .../com/terning/feature/main/MainNavigator.kt | 10 ++++- .../com/terning/feature/main/MainScreen.kt | 20 +++++++++- .../com/terning/feature/splash/SplashRoute.kt | 32 ++++++++++------ .../splash/navigation/SplashNavigation.kt | 4 ++ 6 files changed, 91 insertions(+), 15 deletions(-) diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index 43428d9b..cc45097a 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -1,8 +1,10 @@ package com.terning.core.firebase.messageservice +import android.app.ActivityManager import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent +import android.content.Context import android.content.Intent import androidx.core.app.NotificationCompat import androidx.core.content.getSystemService @@ -82,9 +84,31 @@ class TerningMessagingService : FirebaseMessagingService() { imageUrl: String ) { val notifyId = Random().nextInt() - val intent = navigatorProvider.getMainActivityIntent(deeplink = type).apply { + val isForeground = isAppInForeground() + val redirect: String = when (type) { + "CALENDAR" -> if (isForeground) { + "terning://calendar" + } else { + "terning://splash?redirect=calendar" + } + + "HOME" -> if (isForeground) { + "terning://home" + } else { + "terning://splash?redirect=home" + } + + "SEARCH" -> if (isForeground) { + "terning://search" + } else { + "terning://splash?redirect=search" + } + + else -> "" + } + val intent = navigatorProvider.getMainActivityIntent(deeplink = redirect).apply { action = Intent.ACTION_VIEW - data = type.toUri() + data = redirect.toUri() flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } val pendingIntent = PendingIntent.getActivity( @@ -128,6 +152,16 @@ class TerningMessagingService : FirebaseMessagingService() { imageLoader.enqueue(request) } + private fun isAppInForeground(): Boolean { + val appProcesses = + (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).runningAppProcesses + val packageName = packageName + return appProcesses?.any { + it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && + it.processName == packageName + } == true + } + companion object { private const val CHANNEL_ID: String = "terning" private const val TITLE: String = "title" diff --git a/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt b/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt index bc056217..5d7a34c5 100644 --- a/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt +++ b/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt @@ -28,10 +28,12 @@ class MainActivity : ComponentActivity() { setContent { val navigator: MainNavigator = rememberMainNavigator() val redirect: String? = intent.data?.getQueryParameter(REDIRECT) + val host: String? = intent.data?.host TerningPointTheme { CompositionLocalProvider(LocalTracker provides tracker) { MainScreen( + host = host, redirect = redirect, navigator = navigator ) diff --git a/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt b/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt index e24ad623..613ff83c 100644 --- a/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt +++ b/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt @@ -8,9 +8,12 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions +import com.terning.feature.calendar.calendar.navigation.Calendar import com.terning.feature.calendar.calendar.navigation.navigateCalendar +import com.terning.feature.home.navigation.Home import com.terning.feature.home.navigation.navigateHome import com.terning.feature.mypage.mypage.navigation.navigateMyPage +import com.terning.feature.search.search.navigation.Search import com.terning.feature.search.search.navigation.navigateSearch import com.terning.feature.splash.navigation.Splash @@ -22,7 +25,12 @@ class MainNavigator( @Composable get() = navController .currentBackStackEntryAsState().value?.destination - fun getStartDestination(redirect: String?) = Splash(redirect = redirect) + fun getStartDestination(redirect: String?, host: String?) = when (host) { + "search" -> Search + "home" -> Home + "calendar" -> Calendar + else -> Splash(redirect) + } val currentTab: MainTab? @Composable get() = MainTab.find { tab -> diff --git a/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt b/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt index 3a380111..5fe50554 100644 --- a/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt +++ b/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt @@ -51,6 +51,7 @@ import com.terning.feature.onboarding.signin.navigation.navigateSignIn import com.terning.feature.onboarding.signin.navigation.signInNavGraph import com.terning.feature.onboarding.signup.navigation.navigateSignUp import com.terning.feature.onboarding.signup.navigation.signUpNavGraph +import com.terning.feature.search.search.navigation.navigateSearch import com.terning.feature.search.search.navigation.searchNavGraph import com.terning.feature.search.searchprocess.navigation.navigateSearchProcess import com.terning.feature.search.searchprocess.navigation.searchProcessNavGraph @@ -62,6 +63,7 @@ import kotlinx.coroutines.launch @RequiresApi(Build.VERSION_CODES.TIRAMISU) @Composable fun MainScreen( + host: String?, redirect: String?, navigator: MainNavigator = rememberMainNavigator(), ) { @@ -140,7 +142,7 @@ fun MainScreen( ExitTransition.None }, navController = navigator.navController, - startDestination = navigator.getStartDestination(redirect) + startDestination = navigator.getStartDestination(redirect = redirect, host = host) ) { splashNavGraph( navigateHome = { @@ -159,6 +161,22 @@ fun MainScreen( ).build() ) }, + navigateCalendar = { + navigator.navController.navigateCalendar( + navOptions = NavOptions.Builder().setPopUpTo( + route = Splash(redirect), + inclusive = true + ).build() + ) + }, + navigateSearch = { + navigator.navController.navigateSearch( + navOptions = NavOptions.Builder().setPopUpTo( + route = Splash(redirect), + inclusive = true + ).build() + ) + } ) homeNavGraph( paddingValues = paddingValues, 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 d97f3746..d8b85852 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 @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -38,20 +37,19 @@ internal fun SplashRoute( redirect: String?, navigateToHome: () -> Unit, navigateToSignIn: () -> Unit, + navigateToCalendar: () -> Unit, + navigateToSearch: () -> Unit, viewModel: SplashViewModel = hiltViewModel(), ) { - val systemUiController = rememberSystemUiController() val lifecycleOwner = LocalLifecycleOwner.current val context = LocalContext.current val updateState by viewModel.updateState.collectAsStateWithLifecycle() - SideEffect { - systemUiController.setStatusBarColor( - color = TerningMain - ) - systemUiController.setNavigationBarColor( - color = TerningMain - ) + val systemUiController = rememberSystemUiController() + + LaunchedEffect(Unit) { + systemUiController.setStatusBarColor(color = TerningMain) + systemUiController.setNavigationBarColor(color = TerningMain) } DisposableEffect(lifecycleOwner) { @@ -77,8 +75,20 @@ internal fun SplashRoute( .collect { sideEffect -> when (sideEffect) { is SplashSideEffect.HasAccessToken -> { - if (sideEffect.hasAccessToken) navigateToHome() - else navigateToSignIn() + if (sideEffect.hasAccessToken) { + if (redirect?.isBlank() == false) { + when (redirect) { + "calendar" -> navigateToCalendar() + "home" -> navigateToHome() + "search" -> navigateToSearch() + else -> {} + } + } else { + navigateToHome() + } + } else { + navigateToSignIn() + } } } } diff --git a/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt b/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt index 183dd5c4..b7f8678b 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt @@ -14,6 +14,8 @@ private const val SPLASH_PATH: String = "terning://splash" fun NavGraphBuilder.splashNavGraph( navigateHome: () -> Unit, navigateSignIn: () -> Unit, + navigateSearch: () -> Unit, + navigateCalendar: () -> Unit ) { composable( deepLinks = listOf( @@ -27,6 +29,8 @@ fun NavGraphBuilder.splashNavGraph( redirect = args.redirect, navigateToHome = navigateHome, navigateToSignIn = navigateSignIn, + navigateToSearch = navigateSearch, + navigateToCalendar = navigateCalendar ) } } From 8dd57a1b9ba61b2d43068f6d0e0905f48c46b22a Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 01:27:55 +0900 Subject: [PATCH 06/16] =?UTF-8?q?[FEAT/#382]=20=EB=94=A5=EB=A7=81=ED=81=AC?= =?UTF-8?q?=20=EA=B3=A0=EC=A0=95=20=EA=B0=92=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/terning/core/designsystem/util/DeeplinkDefaults.kt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt diff --git a/core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt b/core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt new file mode 100644 index 00000000..0089ee88 --- /dev/null +++ b/core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt @@ -0,0 +1,6 @@ +package com.terning.core.designsystem.util + +object DeeplinkDefaults { + const val REDIRECT: String = "redirect" + fun build(base: String) = "terning://${base}" +} \ No newline at end of file From a07c08828c90b3169825dcc4d3a41de7472dc191 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 01:28:04 +0900 Subject: [PATCH 07/16] =?UTF-8?q?[FEAT/#382]=20=EB=A6=AC=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EB=A0=89=ED=8A=B8=20enum=20class=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/designsystem/type/NotificationRedirect.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 core/designsystem/src/main/java/com/terning/core/designsystem/type/NotificationRedirect.kt diff --git a/core/designsystem/src/main/java/com/terning/core/designsystem/type/NotificationRedirect.kt b/core/designsystem/src/main/java/com/terning/core/designsystem/type/NotificationRedirect.kt new file mode 100644 index 00000000..9b85a3d8 --- /dev/null +++ b/core/designsystem/src/main/java/com/terning/core/designsystem/type/NotificationRedirect.kt @@ -0,0 +1,12 @@ +package com.terning.core.designsystem.type + +enum class NotificationRedirect(val path: String) { + CALENDAR("calendar"), + HOME("home"), + SEARCH("search"); + + companion object { + fun from(type: String?): NotificationRedirect? = + entries.firstOrNull { it.path.equals(type, ignoreCase = true) } + } +} From 28b07bec2a83a5edd1ab1b8f813ae1407566b2f9 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 01:28:20 +0900 Subject: [PATCH 08/16] =?UTF-8?q?[FEAT/#382]=20:core:designsystem=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/firebase/build.gradle.kts | 1 + feature/main/build.gradle.kts | 1 + 2 files changed, 2 insertions(+) diff --git a/core/firebase/build.gradle.kts b/core/firebase/build.gradle.kts index 6bde3226..ffbed7eb 100644 --- a/core/firebase/build.gradle.kts +++ b/core/firebase/build.gradle.kts @@ -11,6 +11,7 @@ android { dependencies { //core implementation(projects.core.navigator) + implementation(projects.core.designsystem) // domain implementation(projects.domain.user) diff --git a/feature/main/build.gradle.kts b/feature/main/build.gradle.kts index be6323e8..79698c6e 100644 --- a/feature/main/build.gradle.kts +++ b/feature/main/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { // core implementation(projects.core.navigator) implementation(projects.core.firebase) + implementation(projects.core.designsystem) // feature implementation(projects.feature.calendar) From 14f2a9118f1e20be21ed1dd15300efffb6010d3e Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 01:28:52 +0900 Subject: [PATCH 09/16] =?UTF-8?q?[FEAT/#382]=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=ED=9A=A8=EC=9C=A8=EC=A0=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../messageservice/TerningMessagingService.kt | 90 ++++++++----------- .../calendar/navigation/CalendarNavigation.kt | 5 +- .../home/navigation/HometNavigation.kt | 5 +- .../com/terning/feature/main/MainActivity.kt | 3 +- .../search/navigation/SearchNavigation.kt | 9 +- .../com/terning/feature/splash/SplashRoute.kt | 17 ++-- .../splash/navigation/SplashNavigation.kt | 5 +- 7 files changed, 59 insertions(+), 75 deletions(-) diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index cc45097a..963ab91c 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -14,6 +14,9 @@ import coil3.ImageLoader import coil3.request.ImageRequest import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage +import com.terning.core.designsystem.type.NotificationRedirect +import com.terning.core.designsystem.util.DeeplinkDefaults +import com.terning.core.designsystem.util.DeeplinkDefaults.REDIRECT import com.terning.core.firebase.R import com.terning.domain.user.repository.UserRepository import com.terning.navigator.NavigatorProvider @@ -40,40 +43,38 @@ class TerningMessagingService : FirebaseMessagingService() { override fun handleIntent(intent: Intent?) { super.handleIntent(intent) - if (intent?.getStringExtra(TITLE)?.isEmpty() == true - || !userRepository.getAlarmAvailable() - ) return - - val title = intent?.getStringExtra(TITLE).orEmpty() - val body = intent?.getStringExtra(BODY).orEmpty() - val type = intent?.getStringExtra(TYPE).orEmpty() - val imageUrl = intent?.getStringExtra(IMAGE_URL).orEmpty() - - sendNotification( - title = title, - body = body, - type = type, - imageUrl = imageUrl + extractInformation( + title = intent?.getStringExtra(TITLE), + body = intent?.getStringExtra(BODY), + type = intent?.getStringExtra(TYPE), + imageUrl = intent?.getStringExtra(IMAGE_URL) ) } override fun onMessageReceived(message: RemoteMessage) { super.onMessageReceived(message) - if (message.data.isEmpty() - || !userRepository.getAlarmAvailable() - ) return + extractInformation( + title = message.data[TITLE], + body = message.data[BODY], + type = message.data[TYPE], + imageUrl = message.data[IMAGE_URL] + ) + } - val title = message.data[TITLE].orEmpty() - val body = message.data[BODY].orEmpty() - val type = message.data[TYPE].orEmpty() - val imageUrl = message.data[IMAGE_URL].orEmpty() + private fun extractInformation( + title: String?, + body: String?, + type: String?, + imageUrl: String? + ) { + if (title.isNullOrEmpty() || !userRepository.getAlarmAvailable()) return sendNotification( title = title, - body = body, - type = type, - imageUrl = imageUrl + body = body.orEmpty(), + type = type.orEmpty(), + imageUrl = imageUrl.orEmpty() ) } @@ -85,30 +86,10 @@ class TerningMessagingService : FirebaseMessagingService() { ) { val notifyId = Random().nextInt() val isForeground = isAppInForeground() - val redirect: String = when (type) { - "CALENDAR" -> if (isForeground) { - "terning://calendar" - } else { - "terning://splash?redirect=calendar" - } - - "HOME" -> if (isForeground) { - "terning://home" - } else { - "terning://splash?redirect=home" - } - - "SEARCH" -> if (isForeground) { - "terning://search" - } else { - "terning://splash?redirect=search" - } - - else -> "" - } - val intent = navigatorProvider.getMainActivityIntent(deeplink = redirect).apply { + val deeplink = buildRedirect(type, isForeground) + val intent = navigatorProvider.getMainActivityIntent(deeplink = deeplink).apply { action = Intent.ACTION_VIEW - data = redirect.toUri() + data = deeplink.toUri() flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP } val pendingIntent = PendingIntent.getActivity( @@ -117,9 +98,8 @@ class TerningMessagingService : FirebaseMessagingService() { intent, PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_MUTABLE ) - val channelId: String = CHANNEL_ID val notificationBuilder = - NotificationCompat.Builder(this, channelId).apply { + NotificationCompat.Builder(this, CHANNEL_ID).apply { setSmallIcon(R.mipmap.ic_terning_launcher) setContentTitle(title) setContentText(body) @@ -130,8 +110,8 @@ class TerningMessagingService : FirebaseMessagingService() { val notificationManager = getSystemService() notificationManager?.createNotificationChannel( NotificationChannel( - channelId, - channelId, + CHANNEL_ID, + CHANNEL_ID, NotificationManager.IMPORTANCE_HIGH ) ) @@ -149,6 +129,7 @@ class TerningMessagingService : FirebaseMessagingService() { } ) .build() + imageLoader.enqueue(request) } @@ -162,6 +143,13 @@ class TerningMessagingService : FirebaseMessagingService() { } == true } + private fun buildRedirect(type: String, isForeground: Boolean): String { + val base = NotificationRedirect.from(type) ?: return "" + + return if (isForeground) DeeplinkDefaults.build(base.path) + else DeeplinkDefaults.build("splash?$REDIRECT=${base.path}") + } + companion object { private const val CHANNEL_ID: String = "terning" private const val TITLE: String = "title" diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt index 9aa93ee9..7c4c10aa 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt @@ -8,12 +8,11 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable import androidx.navigation.navDeepLink +import com.terning.core.designsystem.util.DeeplinkDefaults import com.terning.core.navigation.MainTabRoute import com.terning.feature.calendar.calendar.CalendarRoute import kotlinx.serialization.Serializable -private const val CALENDAR_PATH: String = "terning://calendar" - fun NavController.navigateCalendar(navOptions: NavOptions? = null) { navigate( route = Calendar, @@ -28,7 +27,7 @@ fun NavGraphBuilder.calendarNavGraph( composable( deepLinks = listOf( navDeepLink( - basePath = CALENDAR_PATH + basePath = DeeplinkDefaults.build("calendar") ) ) ) { diff --git a/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt b/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt index f508df6b..3108a889 100644 --- a/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt +++ b/feature/home/src/main/java/com/terning/feature/home/navigation/HometNavigation.kt @@ -8,12 +8,11 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable import androidx.navigation.navDeepLink +import com.terning.core.designsystem.util.DeeplinkDefaults import com.terning.core.navigation.MainTabRoute import com.terning.feature.home.HomeRoute import kotlinx.serialization.Serializable -private const val HOME_PATH: String = "terning://home" - fun NavController.navigateHome(navOptions: NavOptions? = null) { navigate( route = Home, @@ -30,7 +29,7 @@ fun NavGraphBuilder.homeNavGraph( composable( deepLinks = listOf( navDeepLink( - basePath = HOME_PATH + basePath = DeeplinkDefaults.build("home") ) ) ) { diff --git a/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt b/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt index 5d7a34c5..1231edb9 100644 --- a/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt +++ b/feature/main/src/main/java/com/terning/feature/main/MainActivity.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.CompositionLocalProvider import com.terning.core.analytics.AmplitudeTracker import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.designsystem.util.DeeplinkDefaults.REDIRECT import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -43,8 +44,6 @@ class MainActivity : ComponentActivity() { } companion object { - private const val REDIRECT: String = "redirect" - fun getIntent( context: Context, ) = Intent(context, MainActivity::class.java) diff --git a/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt b/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt index a6e31ffe..7156f064 100644 --- a/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt +++ b/feature/search/src/main/java/com/terning/feature/search/search/navigation/SearchNavigation.kt @@ -6,12 +6,11 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable import androidx.navigation.navDeepLink +import com.terning.core.designsystem.util.DeeplinkDefaults import com.terning.core.navigation.MainTabRoute import com.terning.feature.search.search.SearchRoute import kotlinx.serialization.Serializable -private const val SEARCH_PATH: String = "terning://search" - fun NavController.navigateSearch(navOptions: NavOptions? = null) { navigate( route = Search, @@ -24,13 +23,13 @@ fun NavGraphBuilder.searchNavGraph( navigateSearchProcess: () -> Unit, navigateIntern: (Long) -> Unit, ) { - composable ( + composable( deepLinks = listOf( navDeepLink( - basePath = SEARCH_PATH + basePath = DeeplinkDefaults.build("search") ) ) - ){ + ) { SearchRoute( paddingValues = paddingValues, navigateToSearchProcess = navigateSearchProcess, 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 d8b85852..1c3a560d 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 @@ -27,6 +27,7 @@ import com.terning.core.designsystem.extension.getVersionName import com.terning.core.designsystem.extension.launchPlayStore import com.terning.core.designsystem.theme.TerningMain import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.designsystem.type.NotificationRedirect import com.terning.domain.update.entity.UpdateState import com.terning.feature.splash.component.TerningMajorUpdateDialog import com.terning.feature.splash.component.TerningPatchUpdateDialog @@ -76,15 +77,15 @@ internal fun SplashRoute( when (sideEffect) { is SplashSideEffect.HasAccessToken -> { if (sideEffect.hasAccessToken) { - if (redirect?.isBlank() == false) { - when (redirect) { - "calendar" -> navigateToCalendar() - "home" -> navigateToHome() - "search" -> navigateToSearch() - else -> {} - } - } else { + if (redirect.isNullOrBlank()) { navigateToHome() + } else { + when (NotificationRedirect.from(redirect)) { + NotificationRedirect.CALENDAR -> navigateToCalendar() + NotificationRedirect.HOME -> navigateToHome() + NotificationRedirect.SEARCH -> navigateToSearch() + else -> navigateToHome() + } } } else { navigateToSignIn() diff --git a/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt b/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt index b7f8678b..30110352 100644 --- a/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt +++ b/feature/splash/src/main/java/com/terning/feature/splash/navigation/SplashNavigation.kt @@ -4,13 +4,12 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import androidx.navigation.navDeepLink import androidx.navigation.toRoute +import com.terning.core.designsystem.util.DeeplinkDefaults import com.terning.core.navigation.Route import com.terning.feature.splash.SplashRoute import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -private const val SPLASH_PATH: String = "terning://splash" - fun NavGraphBuilder.splashNavGraph( navigateHome: () -> Unit, navigateSignIn: () -> Unit, @@ -20,7 +19,7 @@ fun NavGraphBuilder.splashNavGraph( composable( deepLinks = listOf( navDeepLink( - basePath = SPLASH_PATH + basePath = DeeplinkDefaults.build("splash") ) ) ) { From 10853db6efa67bde19283770d2b0de8d0d31dc3a Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 01:34:31 +0900 Subject: [PATCH 10/16] =?UTF-8?q?[FEAT/#382]=20MainNavigator=20enum=20clas?= =?UTF-8?q?s=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/designsystem/util/DeeplinkDefaults.kt | 1 + .../java/com/terning/feature/main/MainNavigator.kt | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt b/core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt index 0089ee88..211113ff 100644 --- a/core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt +++ b/core/designsystem/src/main/java/com/terning/core/designsystem/util/DeeplinkDefaults.kt @@ -2,5 +2,6 @@ package com.terning.core.designsystem.util object DeeplinkDefaults { const val REDIRECT: String = "redirect" + fun build(base: String) = "terning://${base}" } \ No newline at end of file diff --git a/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt b/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt index 613ff83c..9fd4f965 100644 --- a/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt +++ b/feature/main/src/main/java/com/terning/feature/main/MainNavigator.kt @@ -8,6 +8,7 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions +import com.terning.core.designsystem.type.NotificationRedirect import com.terning.feature.calendar.calendar.navigation.Calendar import com.terning.feature.calendar.calendar.navigation.navigateCalendar import com.terning.feature.home.navigation.Home @@ -25,12 +26,13 @@ class MainNavigator( @Composable get() = navController .currentBackStackEntryAsState().value?.destination - fun getStartDestination(redirect: String?, host: String?) = when (host) { - "search" -> Search - "home" -> Home - "calendar" -> Calendar - else -> Splash(redirect) - } + fun getStartDestination(redirect: String?, host: String?) = + when (NotificationRedirect.from(host)) { + NotificationRedirect.SEARCH -> Search + NotificationRedirect.HOME -> Home + NotificationRedirect.CALENDAR -> Calendar + else -> Splash(redirect) + } val currentTab: MainTab? @Composable get() = MainTab.find { tab -> From a0950d9d5101eea78553dc88a63b57b8d2c206e3 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 02:23:02 +0900 Subject: [PATCH 11/16] =?UTF-8?q?[FEAT/#382]=20buildDeeplink=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/firebase/messageservice/TerningMessagingService.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index 963ab91c..07585352 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -86,7 +86,7 @@ class TerningMessagingService : FirebaseMessagingService() { ) { val notifyId = Random().nextInt() val isForeground = isAppInForeground() - val deeplink = buildRedirect(type, isForeground) + val deeplink = buildDeeplink(type, isForeground) val intent = navigatorProvider.getMainActivityIntent(deeplink = deeplink).apply { action = Intent.ACTION_VIEW data = deeplink.toUri() @@ -143,7 +143,7 @@ class TerningMessagingService : FirebaseMessagingService() { } == true } - private fun buildRedirect(type: String, isForeground: Boolean): String { + private fun buildDeeplink(type: String, isForeground: Boolean): String { val base = NotificationRedirect.from(type) ?: return "" return if (isForeground) DeeplinkDefaults.build(base.path) From 3d11f5f54f55e15ac39cf51f4d1a200087dd915f Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 29 Apr 2025 02:23:29 +0900 Subject: [PATCH 12/16] =?UTF-8?q?[CHORE/#382]=20=ED=95=9C=20=EC=A4=84=20?= =?UTF-8?q?=EA=B3=B5=EB=B0=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/firebase/messageservice/TerningMessagingService.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index 07585352..70e54a97 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -158,4 +158,3 @@ class TerningMessagingService : FirebaseMessagingService() { private const val IMAGE_URL: String = "imageUrl" } } - From 565f4e010bf6cea77f5753b5cc23c9436d579bd7 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Wed, 30 Apr 2025 00:48:24 +0900 Subject: [PATCH 13/16] =?UTF-8?q?[CHORE/#382]=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../firebase/messageservice/TerningMessagingService.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index 70e54a97..c52df024 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -136,10 +136,11 @@ class TerningMessagingService : FirebaseMessagingService() { private fun isAppInForeground(): Boolean { val appProcesses = (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).runningAppProcesses - val packageName = packageName return appProcesses?.any { - it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && - it.processName == packageName + val isForeground = + it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND + val isCurrentApp = it.processName == packageName + isForeground && isCurrentApp } == true } From fbf686d8c1ecd2e988b27c1d7881ca2d3b52797b Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Wed, 30 Apr 2025 00:52:25 +0900 Subject: [PATCH 14/16] =?UTF-8?q?[CHORE/#382]=20=EC=A4=84=EB=B0=94?= =?UTF-8?q?=EA=BF=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/firebase/messageservice/TerningMessagingService.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt index c52df024..aa680ddd 100644 --- a/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt +++ b/core/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.kt @@ -136,10 +136,12 @@ class TerningMessagingService : FirebaseMessagingService() { private fun isAppInForeground(): Boolean { val appProcesses = (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).runningAppProcesses + return appProcesses?.any { val isForeground = it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND val isCurrentApp = it.processName == packageName + isForeground && isCurrentApp } == true } From 8d6da4d32937e81c9a46e1f78f128969fdb2fa7d Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Wed, 30 Apr 2025 16:23:45 +0900 Subject: [PATCH 15/16] =?UTF-8?q?[CHORE/#382]=20Splash=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=EC=97=90=20onDispose=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terning/feature/calendar/calendar/CalendarRoute.kt | 9 --------- .../src/main/java/com/terning/feature/home/HomeRoute.kt | 8 -------- .../com/terning/feature/search/search/SearchRoute.kt | 8 -------- .../main/java/com/terning/feature/splash/SplashRoute.kt | 8 ++++++++ 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index 0d0ed27d..40babcd3 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -23,13 +23,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.component.topappbar.CalendarTopAppBar import com.terning.core.designsystem.extension.getWeekIndexContainingSelectedDate import com.terning.core.designsystem.theme.Grey200 -import com.terning.core.designsystem.theme.White import com.terning.feature.calendar.calendar.component.ScreenTransition import com.terning.feature.calendar.calendar.component.WeekDaysHeader import com.terning.feature.calendar.calendar.model.CalendarUiState @@ -50,13 +48,6 @@ fun CalendarRoute( val uiState by viewModel.uiState.collectAsStateWithLifecycle() val amplitudeTracker = LocalTracker.current - val systemUiController = rememberSystemUiController() - - LaunchedEffect(Unit) { - systemUiController.setStatusBarColor(color = White) - systemUiController.setNavigationBarColor(color = White) - } - CalendarScreen( uiState = uiState, navigateToAnnouncement = navigateToAnnouncement, diff --git a/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt b/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt index 261e15dd..e1a3c0fb 100644 --- a/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt +++ b/feature/home/src/main/java/com/terning/feature/home/HomeRoute.kt @@ -40,7 +40,6 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionStatus import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState -import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.R.raw.paging_loading_animation @@ -104,13 +103,6 @@ fun HomeRoute( } } - val systemUiController = rememberSystemUiController() - - LaunchedEffect(Unit) { - systemUiController.setStatusBarColor(color = White) - systemUiController.setNavigationBarColor(color = White) - } - LaunchedEffect(key1 = true) { viewModel.getProfile() viewModel.getFilteringInfo() diff --git a/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt b/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt index 57c3e38a..cfc2bb0f 100644 --- a/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt +++ b/feature/search/src/main/java/com/terning/feature/search/search/SearchRoute.kt @@ -22,7 +22,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle -import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.component.image.TerningImage @@ -57,13 +56,6 @@ fun SearchRoute( val amplitudeTracker = LocalTracker.current - val systemUiController = rememberSystemUiController() - - LaunchedEffect(Unit) { - systemUiController.setStatusBarColor(color = White) - systemUiController.setNavigationBarColor(color = White) - } - LaunchedEffect(key1 = true) { viewModel.getSearchViews() viewModel.getSearchScraps() 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 1c3a560d..49a5fbbc 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 @@ -27,6 +27,7 @@ import com.terning.core.designsystem.extension.getVersionName import com.terning.core.designsystem.extension.launchPlayStore 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.NotificationRedirect import com.terning.domain.update.entity.UpdateState import com.terning.feature.splash.component.TerningMajorUpdateDialog @@ -53,6 +54,13 @@ internal fun SplashRoute( systemUiController.setNavigationBarColor(color = TerningMain) } + DisposableEffect(lifecycleOwner) { + onDispose { + systemUiController.setStatusBarColor(color = White) + systemUiController.setNavigationBarColor(color = White) + } + } + DisposableEffect(lifecycleOwner) { val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { From a08dc32152a1cb6249c3a47940733a00b8b0f8e9 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Wed, 30 Apr 2025 16:38:34 +0900 Subject: [PATCH 16/16] =?UTF-8?q?[CHORE/#382]=20splashNavOptions=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/terning/feature/main/MainScreen.kt | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt b/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt index 5fe50554..2dbbb7f5 100644 --- a/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt +++ b/feature/main/src/main/java/com/terning/feature/main/MainScreen.kt @@ -70,12 +70,9 @@ fun MainScreen( val context = LocalContext.current var backPressedState by remember { mutableStateOf(true) } var backPressedTime = 0L - val snackBarHostState = remember { SnackbarHostState() } val coroutineScope = rememberCoroutineScope() - val amplitudeTracker = LocalTracker.current - BackHandler(enabled = backPressedState) { if (System.currentTimeMillis() - backPressedTime <= 3000) { (context as Activity).finish() @@ -91,6 +88,12 @@ fun MainScreen( backPressedTime = System.currentTimeMillis() } + val amplitudeTracker = LocalTracker.current + val splashNavOptions = NavOptions.Builder().setPopUpTo( + route = Splash(redirect), + inclusive = true + ).build() + Scaffold( snackbarHost = { SnackbarHost( @@ -146,36 +149,16 @@ fun MainScreen( ) { splashNavGraph( navigateHome = { - navigator.navController.navigateHome( - navOptions = NavOptions.Builder().setPopUpTo( - route = Splash(redirect), - inclusive = true - ).build() - ) + navigator.navController.navigateHome(navOptions = splashNavOptions) }, navigateSignIn = { - navigator.navController.navigateSignIn( - navOptions = NavOptions.Builder().setPopUpTo( - route = Splash(redirect), - inclusive = true - ).build() - ) + navigator.navController.navigateSignIn(navOptions = splashNavOptions) }, navigateCalendar = { - navigator.navController.navigateCalendar( - navOptions = NavOptions.Builder().setPopUpTo( - route = Splash(redirect), - inclusive = true - ).build() - ) + navigator.navController.navigateCalendar(navOptions = splashNavOptions) }, navigateSearch = { - navigator.navController.navigateSearch( - navOptions = NavOptions.Builder().setPopUpTo( - route = Splash(redirect), - inclusive = true - ).build() - ) + navigator.navController.navigateSearch(navOptions = splashNavOptions) } ) homeNavGraph(