Skip to content

Commit

Permalink
DashBoard 디테일 잡기 (#64)
Browse files Browse the repository at this point in the history
* chore: add systemBarInsetPadding

* feat: bottom sheet collapse when system back button trigger

* style: ktlintFormat

* feat: bottomSheetScaffoldState hoist to appState (#65)

* chore: add remember resources
  • Loading branch information
murjune authored Feb 15, 2025
1 parent 15e478b commit cb5c6a9
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 23 deletions.
2 changes: 2 additions & 0 deletions app/src/main/kotlin/com/chipichipi/dobedobe/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
Expand All @@ -21,6 +22,7 @@ import kotlinx.coroutines.launch
import org.koin.androidx.compose.KoinAndroidContext
import org.koin.androidx.viewmodel.ext.android.viewModel

@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModel()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.chipichipi.dobedobe.navigation

import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
Expand All @@ -25,6 +26,7 @@ import com.chipichipi.dobedobe.feature.setting.navigation.navigateToSetting
import com.chipichipi.dobedobe.feature.setting.navigation.settingScreen
import com.chipichipi.dobedobe.ui.DobeDobeAppState

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun DobeDobeNavHost(
appState: DobeDobeAppState,
Expand All @@ -33,6 +35,7 @@ internal fun DobeDobeNavHost(
) {
val navController = appState.navController
val backStackEntry by navController.currentBackStackEntryAsState()
val bottomSheetScaffoldState = appState.bottomSheetScaffoldState

NavHost(
navController = navController,
Expand All @@ -43,10 +46,14 @@ internal fun DobeDobeNavHost(
) {
dashboardScreen(
onShowSnackbar = onShowSnackbar,
bottomSheetScaffoldState = bottomSheetScaffoldState,
navigateToAddGoal = navController::navigateToAddGoal,
navigateToGoalDetail = navController::navigateToGoalDetail,
navigateToSetting = navController::navigateToSetting,
navigateToSearchGoal = navController::navigateToSearchGoal,
navigateToSearchGoal = {
navController.navigateToSearchGoal()
appState.partiallyExpand()
},
)

goalGraph(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.chipichipi.dobedobe.ui

import androidx.compose.material3.BottomSheetScaffoldState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SheetValue
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.material3.rememberStandardBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
Expand All @@ -9,10 +14,17 @@ import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun rememberDobeDobeAppState(
coroutineScope: CoroutineScope = rememberCoroutineScope(),
bottomSheetScaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberStandardBottomSheetState(
initialValue = SheetValue.PartiallyExpanded,
),
),
navController: NavHostController = rememberNavController(),
): DobeDobeAppState {
return remember(
Expand All @@ -21,21 +33,30 @@ internal fun rememberDobeDobeAppState(
) {
DobeDobeAppState(
coroutineScope = coroutineScope,
bottomSheetScaffoldState = bottomSheetScaffoldState,
navController = navController,
)
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Stable
class DobeDobeAppState(
coroutineScope: CoroutineScope,
val coroutineScope: CoroutineScope,
val bottomSheetScaffoldState: BottomSheetScaffoldState,
val navController: NavHostController,
) {
fun navigateToBack(from: NavBackStackEntry) {
if (from.lifecycleIsResumed()) {
navController.popBackStack()
}
}

fun partiallyExpand() {
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.partialExpand()
}
}
}

private fun NavBackStackEntry.lifecycleIsResumed() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.chipichipi.dobedobe.feature.dashboard

import android.net.Uri
import android.os.Build
import androidx.activity.compose.BackHandler
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.core.Animatable
Expand All @@ -11,22 +12,25 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.BottomSheetScaffoldState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.SheetValue
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.material3.rememberStandardBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
Expand All @@ -39,20 +43,24 @@ import com.chipichipi.dobedobe.core.model.DashboardPhoto
import com.chipichipi.dobedobe.feature.dashboard.component.DashboardEditMode
import com.chipichipi.dobedobe.feature.dashboard.component.DashboardViewMode
import com.chipichipi.dobedobe.feature.dashboard.component.ExpandedPhotoFrame
import com.chipichipi.dobedobe.feature.dashboard.model.CharacterResources
import com.chipichipi.dobedobe.feature.dashboard.model.DashboardModeState
import com.chipichipi.dobedobe.feature.dashboard.model.DashboardPhotoState
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.skydoves.cloudy.cloudy
import kotlinx.coroutines.launch
import org.koin.androidx.compose.koinViewModel

private const val ANIMATION_DURATION = 500

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun DashboardRoute(
onShowSnackbar: suspend (String, String?) -> Boolean,
bottomSheetScaffoldState: BottomSheetScaffoldState,
navigateToAddGoal: () -> Unit,
navigateToGoalDetail: (Long) -> Unit,
navigateToSetting: () -> Unit,
Expand All @@ -67,6 +75,7 @@ internal fun DashboardRoute(
modifier = modifier.fillMaxSize(),
onShowSnackbar = onShowSnackbar,
uiState = uiState,
bottomSheetScaffoldState = bottomSheetScaffoldState,
setGoalNotificationEnabled = viewModel::setGoalNotificationEnabled,
disableSystemNotificationDialog = viewModel::disableSystemNotificationDialog,
navigateToAddGoal = navigateToAddGoal,
Expand All @@ -83,10 +92,12 @@ internal fun DashboardRoute(
)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DashboardScreen(
onShowSnackbar: suspend (String, String?) -> Boolean,
uiState: DashboardUiState,
bottomSheetScaffoldState: BottomSheetScaffoldState,
setGoalNotificationEnabled: (Boolean) -> Unit,
disableSystemNotificationDialog: () -> Unit,
navigateToAddGoal: () -> Unit,
Expand Down Expand Up @@ -119,6 +130,7 @@ private fun DashboardScreen(
DashboardBody(
modifier = modifier,
uiState = uiState,
bottomSheetScaffoldState = bottomSheetScaffoldState,
setGoalNotificationEnabled = setGoalNotificationEnabled,
disableSystemNotificationDialog = disableSystemNotificationDialog,
navigateToAddGoal = navigateToAddGoal,
Expand All @@ -142,6 +154,7 @@ private fun DashboardScreen(
@Composable
private fun DashboardBody(
uiState: DashboardUiState.Success,
bottomSheetScaffoldState: BottomSheetScaffoldState,
setGoalNotificationEnabled: (Boolean) -> Unit,
disableSystemNotificationDialog: () -> Unit,
navigateToAddGoal: () -> Unit,
Expand All @@ -162,11 +175,6 @@ private fun DashboardBody(
SharedTransitionLayout(
modifier = modifier,
) {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberStandardBottomSheetState(
initialValue = SheetValue.PartiallyExpanded,
),
)
val photoFramesState = rememberDashboardPhotoFramesState(
photoState = uiState.photoState,
)
Expand All @@ -177,10 +185,16 @@ private fun DashboardBody(
}
}
}
val resources = remember(uiState.character) { CharacterResources.from(uiState.character) }

DobeDobeBottomSheetScaffold(
modifier = Modifier
.fillMaxSize()
.paint(
painterResource(id = resources.backgroundRes),
contentScale = ContentScale.FillBounds,
)
.statusBarsPadding()
.then(
if (isEditMode) {
Modifier.cloudy(35)
Expand All @@ -193,6 +207,8 @@ private fun DashboardBody(
val isExpanded by remember {
derivedStateOf { bottomSheetScaffoldState.bottomSheetState.targetValue == SheetValue.Expanded }
}
val coroutineScope = rememberCoroutineScope()

GoalBottomSheetContent(
isExpanded = isExpanded,
goals = uiState.goals,
Expand All @@ -203,6 +219,14 @@ private fun DashboardBody(
modifier = Modifier
.padding(top = 8.dp),
)

BackHandler(
enabled = isExpanded,
) {
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.partialExpand()
}
}
},
sheetPeekHeight = 330.dp,
) { innerPadding ->
Expand All @@ -223,7 +247,13 @@ private fun DashboardBody(
onToggleMode = onToggleMode,
navigateToGoalDetail = navigateToGoalDetail,
navigateToSetting = navigateToSetting,
character = uiState.character,
resources = resources,
modifier = Modifier
.fillMaxSize()
.paint(
painterResource(id = resources.backgroundRes),
contentScale = ContentScale.FillBounds,
),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@ import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import com.chipichipi.dobedobe.core.designsystem.theme.DobeDobeTheme
import com.chipichipi.dobedobe.core.model.CharacterType
import com.chipichipi.dobedobe.feature.dashboard.DashboardPhotoFramesState
import com.chipichipi.dobedobe.feature.dashboard.model.BubbleGoal
import com.chipichipi.dobedobe.feature.dashboard.model.CharacterResources
Expand All @@ -27,6 +23,7 @@ import com.chipichipi.dobedobe.feature.dashboard.model.DashboardPhotoState
@Composable
internal fun SharedTransitionScope.DashboardViewMode(
isViewMode: Boolean,
resources: CharacterResources,
photoState: List<DashboardPhotoState>,
bubbleGoal: BubbleGoal,
photoFramesState: DashboardPhotoFramesState,
Expand All @@ -35,18 +32,10 @@ internal fun SharedTransitionScope.DashboardViewMode(
onToggleMode: () -> Unit,
navigateToSetting: () -> Unit,
navigateToGoalDetail: (Long) -> Unit,
character: CharacterType,
modifier: Modifier = Modifier,
) {
val resources = CharacterResources.from(character)

Column(
modifier = modifier
.fillMaxSize()
.paint(
painterResource(id = resources.backgroundRes),
contentScale = ContentScale.FillBounds,
),
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
) {
DashboardViewModeTopAppBar(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.chipichipi.dobedobe.feature.dashboard.navigation

import androidx.compose.material3.BottomSheetScaffoldState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
Expand All @@ -14,8 +16,10 @@ fun NavController.navigateToDashboard(
navOptions: NavOptions,
) = navigate(route = DashboardRoute, navOptions)

@OptIn(ExperimentalMaterial3Api::class)
fun NavGraphBuilder.dashboardScreen(
onShowSnackbar: suspend (String, String?) -> Boolean,
bottomSheetScaffoldState: BottomSheetScaffoldState,
navigateToAddGoal: () -> Unit,
navigateToGoalDetail: (Long) -> Unit,
navigateToSearchGoal: () -> Unit,
Expand All @@ -24,6 +28,7 @@ fun NavGraphBuilder.dashboardScreen(
composable<DashboardRoute> {
DashboardRoute(
onShowSnackbar = onShowSnackbar,
bottomSheetScaffoldState = bottomSheetScaffoldState,
navigateToAddGoal = navigateToAddGoal,
navigateToGoalDetail = navigateToGoalDetail,
navigateToSetting = navigateToSetting,
Expand Down

0 comments on commit cb5c6a9

Please sign in to comment.