Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2619cf2
(FEAT)[droidknights#422] RouteSessionDetail api 생성 및 기존 RouteModel 제거
s9hn Jun 5, 2025
3bfb09a
(FEAT)[droidknights#422] SessionScreen 이동 적용
s9hn Jun 5, 2025
13450c0
(FEAT)[droidknights#422] SessionDetailScreen 이동 적용
s9hn Jun 5, 2025
b50b367
(REFACTOR)[droidknights#422] SessionDetailViewModelTest, SessionListV…
s9hn Jun 5, 2025
eb61a5c
(TEST)[droidknights#422] SessionListViewModelTest 이동 테스트 추가
s9hn Jun 5, 2025
c582315
(TEST)[droidknights#422] SessionDetailViewModelTest 이동 테스트 추가
s9hn Jun 5, 2025
92b6515
(REFACTOR)[droidknights#422] MainActivity에서 navigateSessionDetail 이동 …
s9hn Jun 5, 2025
d123c17
(REFACTOR)[droidknights#422] Router 모듈의 Navigate 함수에 Navigate 파라미터 추가…
s9hn Jun 5, 2025
e98b684
(REFACTOR)[droidknights#422] 기존 Route 인터페이스 제거 및 Router-api의 Route 적용
s9hn Jun 5, 2025
08ded06
(FEAT)[droidknights#422] MainTab 이동 구현
s9hn Jun 5, 2025
fb95ac2
(REFACTOR)[droidknights#422] 사용하지 않는 Navigate 함수 제거
s9hn Jun 5, 2025
b0723f1
(REFACTOR)[droidknights#422] 테스트 함수 이름 한글화
s9hn Jun 5, 2025
40a0260
(REFACTOR)[droidknights#422] 메인탭 이동에 대한 네비게이션 옵션을 MainNavigator가 지정할 …
s9hn Jun 5, 2025
39b1776
(TEST)[droidknights#422] MainViewModelTest 탭 이동 테스트 구현
s9hn Jun 5, 2025
a640a3b
(REFACTOR)[droidknights#422] InternalLaunchedRouter 스택이 쌓이지 않는 문제 해결
s9hn Jun 5, 2025
eb67da0
(REFACTOR)[droidknights#422] RouteModel -> MainTabRoute 네이밍 수정
s9hn Jun 8, 2025
22dd11e
(REFACTOR)[droidknights#422] CI 에러 해결
s9hn Jun 8, 2025
f1a42d7
(REFACTOR)[droidknights#422] Router 모듈 단위 테스트 Navigate 파라미터 수정
s9hn Jun 9, 2025
bcb2ddb
(BUILD)[droidknights#422] resolve conflict merge
s9hn Jun 9, 2025
e68c283
(BUILD)[droidknights#422] Resolve merge conflict
s9hn Jun 10, 2025
e06ec15
(BUILD)[droidknights#422] Resolve merge conflict
s9hn Jun 10, 2025
96ee20a
(REFACTOR)[droidknights#422] SessionDetailViewModelTest, SessionListV…
s9hn Jun 5, 2025
e7fc219
(TEST)[droidknights#422] SessionListViewModelTest 이동 테스트 추가
s9hn Jun 5, 2025
da9e2d1
(TEST)[droidknights#422] SessionDetailViewModelTest 이동 테스트 추가
s9hn Jun 5, 2025
0522371
(REFACTOR)[droidknights#422] MainActivity에서 navigateSessionDetail 이동 …
s9hn Jun 5, 2025
dd27ac3
(REFACTOR)[droidknights#422] 기존 Route 인터페이스 제거 및 Router-api의 Route 적용
s9hn Jun 5, 2025
6537d19
(REFACTOR)[droidknights#422] 테스트 함수 이름 한글화
s9hn Jun 5, 2025
c7eddf6
(TEST)[droidknights#422] MainViewModelTest 탭 이동 테스트 구현
s9hn Jun 5, 2025
e5653eb
(REFACTOR)[droidknights#422] InternalLaunchedRouter 스택이 쌓이지 않는 문제 해결
s9hn Jun 5, 2025
471024a
(REFACTOR)[droidknights#422] RouteModel -> MainTabRoute 네이밍 수정
s9hn Jun 8, 2025
35dc54e
(REFACTOR)[droidknights#422] CI 에러 해결
s9hn Jun 8, 2025
ca458d9
(REFACTOR)[droidknights#422] MainViewModel, MainNavigator의 navigate 책…
s9hn Jun 10, 2025
bdc068f
(REFACTOR)[droidknights#422] Bookmark 이동 구현
s9hn Jun 10, 2025
7e0aae8
(REFACTOR)[droidknights#422] Setting 이동 구현
s9hn Jun 10, 2025
84c440d
(REFACTOR)[droidknights#422] Home 이동 구현
s9hn Jun 10, 2025
e2fff12
(BUILD)[droidknights#422] Resolve merge conflict
s9hn Jun 10, 2025
c59f0a5
(REFACTOR)[droidknights#422] 개행 추가
s9hn Jun 10, 2025
13315e5
(REFACTOR)[droidknights#422] MainTabRoute saveState, launchSingleTop …
s9hn Jun 10, 2025
644dda6
Merge branch '2025/app' into feature/#422-router
taehwandev Jun 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/navigation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ android {
}

dependencies {
implementation(projects.core.router.routerApi)
implementation(libs.kotlinx.serialization.json)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.droidknights.app.core.navigation

import com.droidknights.app.core.router.api.model.Route
import kotlinx.serialization.Serializable

sealed interface MainTabRoute : Route {
val saveState: Boolean
val launchSingleTop: Boolean

@Serializable
data object Home : MainTabRoute {
override val saveState: Boolean = true
override val launchSingleTop: Boolean = true
}

@Serializable
data object Setting : MainTabRoute {
override val saveState: Boolean = true
override val launchSingleTop: Boolean = true
}

@Serializable
data object Bookmark : MainTabRoute {
override val saveState: Boolean = true
override val launchSingleTop: Boolean = true
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.droidknights.app.core.router.api.model.Route

interface Navigator {

suspend fun navigate(route: Route)
suspend fun navigate(route: Route, saveState: Boolean = false, launchSingleTop: Boolean = false)

suspend fun navigateWeb(url: String)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import com.droidknights.app.core.router.internal.viewmodel.RouteSideEffect
import com.droidknights.app.core.router.internal.viewmodel.RouterViewModel
Expand Down Expand Up @@ -44,7 +45,17 @@ private fun InternalLaunchedRouter(
}

is RouteSideEffect.Navigate -> {
navHostController.navigate(sideEffect.route)
navHostController.navigate(sideEffect.route) {
if (sideEffect.saveState) {
navHostController.graph.findStartDestination().route?.let {
popUpTo(it) {
saveState = true
}
}
restoreState = true
}
launchSingleTop = sideEffect.launchSingleTop
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import com.droidknights.app.core.router.api.model.Route

internal sealed interface InternalRoute {

data class Navigate(val route: Route) : InternalRoute
data class Navigate(
val route: Route,
val saveState: Boolean,
val launchSingleTop: Boolean,
) : InternalRoute

data class NavigateWeb(val url: String) : InternalRoute

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ internal class NavigatorImpl @Inject constructor() : Navigator, InternalNavigato

override val channel = Channel<InternalRoute>(Channel.BUFFERED)

override suspend fun navigate(route: Route) {
channel.send(InternalRoute.Navigate(route = route))
override suspend fun navigate(route: Route, saveState: Boolean, launchSingleTop: Boolean) {
channel.send(
InternalRoute.Navigate(
route = route,
saveState = saveState,
launchSingleTop = launchSingleTop,
)
)
}

override suspend fun navigateWeb(url: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ internal sealed interface RouteSideEffect {

data class Navigate(
val route: Route,
val saveState: Boolean,
val launchSingleTop: Boolean,
) : RouteSideEffect

data class NavigateWeb(val url: String) : RouteSideEffect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ internal class RouterViewModel @Inject constructor(
navigator.channel.receiveAsFlow()
.map { router ->
when (router) {
is InternalRoute.Navigate -> RouteSideEffect.Navigate(router.route)
is InternalRoute.Navigate -> RouteSideEffect.Navigate(
router.route,
router.saveState,
router.launchSingleTop,
)

is InternalRoute.NavigateWeb -> RouteSideEffect.NavigateWeb(router.url)

is InternalRoute.NavigateBack -> RouteSideEffect.NavigateBack
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ internal class NavigatorImplTest {
navigator.channel.consumeAsFlow().test {
// fake route 테스트
navigator.navigate(FakeRoute)
Assertions.assertEquals(InternalRoute.Navigate(FakeRoute), awaitItem())
Assertions.assertEquals(
InternalRoute.Navigate(
route = FakeRoute,
saveState = false,
launchSingleTop = false,
),
awaitItem(),
)

// Back 테스트
navigator.navigateBack()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,21 @@ internal class RouterViewModelTest {

viewModel.sideEffect.test {
// move 테스트
mockChannel.send(InternalRoute.Navigate(route = FakeRoute))
Assertions.assertEquals(RouteSideEffect.Navigate(route = FakeRoute), awaitItem())
mockChannel.send(
InternalRoute.Navigate(
route = FakeRoute,
saveState = true,
launchSingleTop = false,
),
)
Assertions.assertEquals(
RouteSideEffect.Navigate(
route = FakeRoute,
saveState = true,
launchSingleTop = false,
),
awaitItem(),
)

// Back 테스트
mockChannel.send(InternalRoute.NavigateBack)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
Expand All @@ -34,6 +37,10 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.droidknights.app.core.designsystem.theme.KnightsTheme
import com.droidknights.app.core.model.session.Session
import com.droidknights.app.core.navigation.MainTabRoute.Bookmark
import com.droidknights.app.core.navigation.MainTabRoute.Home
import com.droidknights.app.core.navigation.MainTabRoute.Setting
import com.droidknights.app.core.router.api.model.Route
import com.droidknights.app.feature.bookmark.component.BookmarkCard
import com.droidknights.app.feature.bookmark.component.BookmarkItem
import com.droidknights.app.feature.bookmark.component.BookmarkTimelineItem
Expand All @@ -51,13 +58,22 @@ import kotlinx.coroutines.flow.collectLatest
internal fun BookmarkRoute(
onShowErrorSnackBar: (throwable: Throwable?) -> Unit,
viewModel: BookmarkViewModel = hiltViewModel(),
selectedTabRoute: State<Route> = remember { mutableStateOf(Bookmark) },
) {
val bookmarkUiState by viewModel.bookmarkUiState.collectAsStateWithLifecycle()

LaunchedEffect(true) {
viewModel.errorFlow.collectLatest { onShowErrorSnackBar(it) }
}

LaunchedEffect(selectedTabRoute.value) {
when (selectedTabRoute.value) {
Home -> viewModel.navigateHome()
Setting -> viewModel.navigateSetting()
Bookmark -> Unit
}
}

Box(
modifier = Modifier
.fillMaxSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import androidx.lifecycle.viewModelScope
import com.droidknights.app.core.domain.session.usecase.api.DeleteBookmarkedSessionUseCase
import com.droidknights.app.core.domain.session.usecase.api.GetBookmarkedSessionsUseCase
import com.droidknights.app.core.model.session.Session
import com.droidknights.app.core.navigation.MainTabRoute.Home
import com.droidknights.app.core.navigation.MainTabRoute.Setting
import com.droidknights.app.core.router.api.Navigator
import com.droidknights.app.feature.bookmark.model.BookmarkItemUiState
import com.droidknights.app.feature.bookmark.model.BookmarkUiState
Expand Down Expand Up @@ -127,6 +129,22 @@ class BookmarkViewModel @Inject constructor(
}.launchIn(viewModelScope)
}

fun navigateSetting() = viewModelScope.launch {
navigator.navigate(
route = Setting,
saveState = Setting.saveState,
launchSingleTop = Setting.launchSingleTop,
)
}

fun navigateHome() = viewModelScope.launch {
navigator.navigate(
route = Home,
saveState = Home.saveState,
launchSingleTop = Home.launchSingleTop,
)
}

fun redirectToSessionScreen(session: Session) {
val state = _bookmarkUiState.value
if (state !is BookmarkUiState.Success || state.isEditMode) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package com.droidknights.app.feature.bookmark.navigation

import androidx.navigation.NavController
import androidx.compose.runtime.State
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.droidknights.app.core.navigation.MainTabRoute
import com.droidknights.app.core.navigation.MainTabRoute.Bookmark
import com.droidknights.app.core.router.api.model.Route
import com.droidknights.app.feature.bookmark.BookmarkRoute

fun NavController.navigateBookmark(navOptions: NavOptions) {
navigate(MainTabRoute.Bookmark, navOptions)
}

fun NavGraphBuilder.bookmarkNavGraph(
selectedTabRoute: State<Route>,
onShowErrorSnackBar: (throwable: Throwable?) -> Unit,
) {
composable<MainTabRoute.Bookmark> {
composable<Bookmark> {
BookmarkRoute(
selectedTabRoute = selectedTabRoute,
onShowErrorSnackBar = onShowErrorSnackBar,
)
}
Expand Down
Loading
Loading