Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 9 additions & 3 deletions app/src/main/java/com/daedan/festabook/di/FestaBookAppGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import androidx.fragment.app.Fragment
import com.daedan.festabook.FestaBookApp
import com.daedan.festabook.di.viewmodel.MetroViewModelFactory
import com.daedan.festabook.logging.DefaultFirebaseLogger
import com.daedan.festabook.presentation.main.MainActivity
import com.daedan.festabook.presentation.NotificationPermissionManager
import com.daedan.festabook.presentation.placeDetail.PlaceDetailActivity
import com.daedan.festabook.presentation.placeDetail.PlaceDetailViewModel
import com.daedan.festabook.presentation.splash.AppVersionManager
import com.daedan.festabook.presentation.splash.SplashActivity
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
Expand All @@ -26,8 +28,6 @@ interface FestaBookAppGraph {

fun inject(app: FestaBookApp)

fun inject(activity: MainActivity)

fun inject(activity: SplashActivity)

fun inject(activity: PlaceDetailActivity)
Expand All @@ -40,6 +40,12 @@ interface FestaBookAppGraph {
val defaultFirebaseLogger: DefaultFirebaseLogger

val metroViewModelFactory: MetroViewModelFactory

val notificationPermissionManagerFactory: NotificationPermissionManager.Factory

val appVersionManagerFactory: AppVersionManager.Factory

val placeDetailViewModelFactory: PlaceDetailViewModel.Factory
}

val Context.appGraph get() = (applicationContext as FestaBookApp).festaBookGraph
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,57 @@ package com.daedan.festabook.presentation

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import com.daedan.festabook.logging.DefaultFirebaseLogger
import com.daedan.festabook.presentation.explore.ExploreViewModel
import com.daedan.festabook.presentation.explore.navigation.exploreNavGraph
import com.daedan.festabook.presentation.main.FestabookRoute
import com.daedan.festabook.presentation.main.MainViewModel
import com.daedan.festabook.presentation.main.navigation.mainNavGraph
import com.daedan.festabook.presentation.main.rememberFestabookNavigator
import com.daedan.festabook.presentation.news.NewsViewModel
import com.daedan.festabook.presentation.placeDetail.PlaceDetailViewModel
import com.daedan.festabook.presentation.setting.SettingViewModel
import com.daedan.festabook.presentation.splash.AppVersionManager
import com.daedan.festabook.presentation.platform.rememberAppGraph
import com.daedan.festabook.presentation.platform.rememberAppVersionManager
import com.daedan.festabook.presentation.platform.rememberLocationSource
import com.daedan.festabook.presentation.splash.SplashViewModel
import com.daedan.festabook.presentation.splash.navigation.splashNavGraph
import com.naver.maps.map.util.FusedLocationSource

@Composable
fun FestabookScreen(
appVersionManager: AppVersionManager,
notificationPermissionManager: NotificationPermissionManager,
placeDetailViewModelFactory: PlaceDetailViewModel.Factory,
defaultViewModelFactory: ViewModelProvider.Factory,
locationSource: FusedLocationSource,
logger: DefaultFirebaseLogger,
onAppFinish: () -> Unit,
modifier: Modifier = Modifier,
newsViewModel: NewsViewModel = viewModel(),
mainViewModel: MainViewModel = viewModel(),
settingViewModel: SettingViewModel = viewModel(),
splashViewModel: SplashViewModel = viewModel(),
exploreViewModel: ExploreViewModel = viewModel(),
) {
val appGraph = rememberAppGraph()
val locationSource = rememberLocationSource()
val festabookNavigator = rememberFestabookNavigator()

val appVersionManager =
rememberAppVersionManager(
factory = appGraph.appVersionManagerFactory,
onUpdateSuccess = { splashViewModel.handleVersionCheckResult(Result.success(false)) },
onUpdateFailure = { splashViewModel.handleVersionCheckResult(Result.failure(Exception("Update failed"))) },
)

NavHost(
modifier = modifier,
startDestination = festabookNavigator.startRoute,
navController = festabookNavigator.navController,
) {
splashNavGraph(
viewModel = splashViewModel,
appGraph = appGraph,
appVersionManager = appVersionManager,
onNavigateToExplore = { festabookNavigator.navigate(FestabookRoute.Explore) },
onNavigateToMain = { festabookNavigator.navigate(FestabookRoute.Main) },
onFinishApp = { festabookNavigator.popBackStack() },
onFinishApp = onAppFinish,
)
exploreNavGraph(
viewModel = exploreViewModel,
appGraph = appGraph,
onBackClick = { festabookNavigator.popBackStack() },
onNavigateToMain = { festabookNavigator.navigate(FestabookRoute.Main) },
)
mainNavGraph(
placeDetailViewModelFactory = placeDetailViewModelFactory,
defaultViewModelFactory = defaultViewModelFactory,
notificationPermissionManager = notificationPermissionManager,
appGraph = appGraph,
onAppFinish = onAppFinish,
locationSource = locationSource,
logger = logger,
onSubscriptionConfirm = { festabookNavigator.navigate(FestabookRoute.Main) },
festabookNavigator = festabookNavigator,
settingViewModel = settingViewModel,
mainViewModel = mainViewModel,
newsViewModel = newsViewModel,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarData
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
Expand Down Expand Up @@ -34,6 +35,8 @@ class SnackbarManager(
private val actionLabel: String,
private val errorMessages: Map<KClass<out ApiResultException>, String>,
private val defaultErrorMessage: String,
private val permissionDeniedMessage: String,
private val moveToSettingLabel: String,
) {
fun show(message: String) {
hostState.currentSnackbarData?.dismiss()
Expand All @@ -50,6 +53,21 @@ class SnackbarManager(
val message = errorMessages[throwable::class] ?: defaultErrorMessage
show(message)
}

fun showPermissionDeniedSnackbar(onOpenSettings: () -> Unit) {
hostState.currentSnackbarData?.dismiss()
scope.launch {
val result =
hostState.showSnackbar(
message = permissionDeniedMessage,
actionLabel = moveToSettingLabel,
duration = SnackbarDuration.Short,
)
if (result == SnackbarResult.ActionPerformed) {
onOpenSettings()
}
}
}
}

@Composable
Expand All @@ -62,6 +80,8 @@ fun rememberAppSnackbarManager(
val networkErrorMessage = stringResource(R.string.error_network_exception)
val unknownErrorMessage = stringResource(R.string.error_unknown_exception)
val actionLabel = stringResource(R.string.fail_snackbar_confirm)
val permissionDeniedMessage = stringResource(R.string.notification_permission_denied_message)
val moveToSettingLabel = stringResource(R.string.move_to_setting_text)

val errorMessages =
remember {
Expand All @@ -74,6 +94,14 @@ fun rememberAppSnackbarManager(
}

return remember(snackbarHostState, scope) {
SnackbarManager(snackbarHostState, scope, actionLabel, errorMessages, unknownErrorMessage)
SnackbarManager(
snackbarHostState,
scope,
actionLabel,
errorMessages,
unknownErrorMessage,
permissionDeniedMessage,
moveToSettingLabel,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package com.daedan.festabook.presentation.explore.navigation

import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import com.daedan.festabook.presentation.explore.ExploreViewModel
import com.daedan.festabook.di.FestaBookAppGraph
import com.daedan.festabook.presentation.explore.component.ExploreScreen
import com.daedan.festabook.presentation.main.FestabookRoute

fun NavGraphBuilder.exploreNavGraph(
viewModel: ExploreViewModel,
appGraph: FestaBookAppGraph,
onBackClick: () -> Unit,
onNavigateToMain: () -> Unit,
) {
composable<FestabookRoute.Explore> {
ExploreScreen(
viewModel = viewModel,
viewModel = viewModel(factory = appGraph.metroViewModelFactory),
onBackClick = onBackClick,
onNavigateToMain = { onNavigateToMain() },
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
Expand All @@ -25,27 +26,47 @@ import com.daedan.festabook.R
import com.daedan.festabook.domain.model.Festival
import com.daedan.festabook.domain.model.Organization
import com.daedan.festabook.domain.model.Poster
import com.daedan.festabook.presentation.NotificationPermissionManager
import com.daedan.festabook.presentation.common.ObserveAsEvents
import com.daedan.festabook.presentation.common.component.LoadingStateScreen
import com.daedan.festabook.presentation.common.formatFestivalPeriod
import com.daedan.festabook.presentation.home.HomeViewModel
import com.daedan.festabook.presentation.home.LineUpItemGroupUiModel
import com.daedan.festabook.presentation.home.LineupItemUiModel
import com.daedan.festabook.presentation.home.LineupUiState
import com.daedan.festabook.presentation.home.adapter.FestivalUiState
import com.daedan.festabook.presentation.setting.SettingViewModel
import com.daedan.festabook.presentation.theme.FestabookColor
import java.time.LocalDate
import java.time.LocalDateTime

@Composable
fun HomeScreen(
viewModel: HomeViewModel,
settingViewModel: SettingViewModel,
notificationPermissionManager: NotificationPermissionManager,
onNavigateToExplore: () -> Unit,
onShowSnackBar: (String) -> Unit,
onShowErrorSnackbar: (Throwable) -> Unit,
modifier: Modifier = Modifier,
onShowErrorSnackbar: (Throwable) -> Unit = {}, // TODO Fragment 제거 시 필수 파라미터로 변경
) {
val context = LocalContext.current
val festivalUiState by viewModel.festivalUiState.collectAsStateWithLifecycle()
val lineupUiState by viewModel.lineupUiState.collectAsStateWithLifecycle()
val currentOnShowErrorSnackbar by rememberUpdatedState(onShowErrorSnackbar)

ObserveAsEvents(flow = settingViewModel.permissionCheckEvent) {
notificationPermissionManager.requestNotificationPermission(context)
}

ObserveAsEvents(flow = settingViewModel.success) {
onShowSnackBar(context.getString(R.string.setting_notice_enabled))
}

ObserveAsEvents(flow = settingViewModel.error) {
currentOnShowErrorSnackbar(it)
}

LaunchedEffect(festivalUiState) {
when (val state = festivalUiState) {
is FestivalUiState.Error -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import com.daedan.festabook.presentation.NotificationPermissionManager
import com.daedan.festabook.presentation.home.HomeViewModel
import com.daedan.festabook.presentation.home.component.HomeScreen
import com.daedan.festabook.presentation.main.MainTabRoute
import com.daedan.festabook.presentation.main.MainViewModel
import com.daedan.festabook.presentation.main.component.FirstVisitDialog
import com.daedan.festabook.presentation.setting.SettingViewModel

fun NavGraphBuilder.homeNavGraph(
viewModel: HomeViewModel,
mainViewModel: MainViewModel,
settingViewModel: SettingViewModel,
notificationPermissionManager: NotificationPermissionManager,
onShowSnackbar: (String) -> Unit,
onShowErrorSnackbar: (Throwable) -> Unit,
onSubscriptionConfirm: () -> Unit,
onNavigateToExplore: () -> Unit,
Expand All @@ -29,6 +34,9 @@ fun NavGraphBuilder.homeNavGraph(
viewModel = viewModel,
onShowErrorSnackbar = onShowErrorSnackbar,
onNavigateToExplore = onNavigateToExplore,
settingViewModel = settingViewModel,
notificationPermissionManager = notificationPermissionManager,
onShowSnackBar = onShowSnackbar,
)
}
}
Loading