diff --git a/core/designsystem/src/main/java/com/goalpanzi/mission_mate/core/designsystem/util/StatusBarUtil.kt b/core/designsystem/src/main/java/com/goalpanzi/mission_mate/core/designsystem/util/StatusBarUtil.kt new file mode 100644 index 0000000..62cf9fc --- /dev/null +++ b/core/designsystem/src/main/java/com/goalpanzi/mission_mate/core/designsystem/util/StatusBarUtil.kt @@ -0,0 +1,20 @@ +package com.goalpanzi.mission_mate.core.designsystem.util + +import android.app.Activity +import android.content.Context +import androidx.core.view.WindowCompat + +fun isLightStatusBars(context: Activity): Boolean { + val window = context.window + val insetsController = WindowCompat.getInsetsController(window, window.decorView) + return insetsController.isAppearanceLightStatusBars +} + +fun setStatusBar(context: Context, isLight: Boolean) { + if (context is Activity) { + val window = context.window + val insetsController = WindowCompat.getInsetsController(window, window.decorView) + if (insetsController.isAppearanceLightStatusBars != isLight) + insetsController.isAppearanceLightStatusBars = isLight + } +} diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/UserStroyScreen.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/UserStroyScreen.kt index 01f0298..7d5b743 100644 --- a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/UserStroyScreen.kt +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/UserStroyScreen.kt @@ -1,15 +1,20 @@ package com.goalpanzi.mission_mate.feature.board.screen +import android.app.Activity import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentWidth @@ -18,10 +23,12 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.paint -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale @@ -33,6 +40,7 @@ import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import coil.request.ImageRequest import com.goalpanzi.mission_mate.core.designsystem.component.StableImage +import com.goalpanzi.mission_mate.core.designsystem.ext.clickableWithoutRipple import com.goalpanzi.mission_mate.core.designsystem.theme.ColorBlack_FF000000 import com.goalpanzi.mission_mate.core.designsystem.theme.ColorWhite_FFFFFFFF import com.goalpanzi.mission_mate.core.designsystem.theme.MissionMateTypography @@ -53,16 +61,18 @@ fun UserStoryScreen( ) { val dateTime = LocalDateTime.parse(verifiedAt) val formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd") + val statusBarPaddingValue = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + var isVisibleSpacer by remember { mutableStateOf(true) } Box( modifier = Modifier .fillMaxSize() - .background(ColorWhite_FFFFFFFF) .navigationBarsPadding() ) { Box( modifier = Modifier .fillMaxSize() + .background(ColorBlack_FF000000) .statusBarsPadding() ) { AsyncImage( @@ -70,22 +80,27 @@ fun UserStoryScreen( .data(URLDecoder.decode(imageUrl, StandardCharsets.UTF_8.toString())) .build(), contentDescription = null, - modifier = Modifier.fillMaxSize(), - contentScale = ContentScale.FillBounds, + modifier = Modifier + .fillMaxSize() + .clickableWithoutRipple { + isVisibleSpacer = !isVisibleSpacer + }, + contentScale = ContentScale.Fit, filterQuality = FilterQuality.None ) + } + if (isVisibleSpacer) { + Spacer( + modifier = Modifier + .fillMaxWidth() + .height(statusBarPaddingValue + 80.dp) + .background(ColorBlack_FF000000.copy(alpha = 0.7f)) + ) Row( modifier = Modifier .fillMaxWidth() - .background( - brush = Brush.verticalGradient( - colors = listOf( - ColorBlack_FF000000.copy(alpha = 0.4f), - Color.Transparent - ) - ) - ) + .statusBarsPadding() .height(93.dp) .padding(horizontal = 24.dp, vertical = 14.dp) ) { @@ -123,7 +138,10 @@ fun UserStoryScreen( ) IconButton( - onClick = onClickClose, + onClick = { + onClickClose() + //setStatusBar(context, true) + }, modifier = Modifier.wrapContentSize() ) { Icon( diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewScreen.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewScreen.kt index 95b4480..6ac9a45 100644 --- a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewScreen.kt +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewScreen.kt @@ -10,12 +10,16 @@ import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentWidth @@ -53,6 +57,7 @@ import coil.request.ImageRequest import com.goalpanzi.mission_mate.core.designsystem.component.MissionMateButton import com.goalpanzi.mission_mate.core.designsystem.component.MissionMateButtonType import com.goalpanzi.mission_mate.core.designsystem.component.StableImage +import com.goalpanzi.mission_mate.core.designsystem.ext.clickableWithoutRipple import com.goalpanzi.mission_mate.core.designsystem.theme.ColorBlack_FF000000 import com.goalpanzi.mission_mate.core.designsystem.theme.ColorWhite_FFFFFFFF import com.goalpanzi.mission_mate.core.designsystem.theme.MissionMateTypography @@ -83,7 +88,6 @@ fun VerificationPreviewRoute( showProgress = true } UploadEvent.Success -> { - showProgress = false onUploadSuccess() } UploadEvent.Error -> { @@ -94,18 +98,16 @@ fun VerificationPreviewRoute( } VerificationPreviewScreen( + isUploading = showProgress, onClickClose = onClickClose, uiState = uiState, onClickUpload = viewModel::uploadImage ) - - if (showProgress) { - ProgressBar() - } } @Composable fun VerificationPreviewScreen( + isUploading: Boolean, onClickClose: () -> Unit, uiState: VerificationPreviewUiState, onClickUpload: (File) -> Unit @@ -113,31 +115,43 @@ fun VerificationPreviewScreen( val context = LocalContext.current val dateTime = LocalDateTime.now() val formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd") + val statusBarPaddingValue = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + var isVisibleSpacer by remember { mutableStateOf(true) } Box( modifier = Modifier .fillMaxSize() - .background(ColorWhite_FFFFFFFF) .navigationBarsPadding() ) { - Box( - modifier = Modifier - .fillMaxSize() - .statusBarsPadding() - ) { - when (uiState) { - VerificationPreviewUiState.Loading -> VerificationPreviewLoading() - is VerificationPreviewUiState.Success -> { + when (uiState) { + VerificationPreviewUiState.Loading -> VerificationPreviewLoading() + is VerificationPreviewUiState.Success -> { + Box( + modifier = Modifier + .fillMaxSize() + .background(ColorBlack_FF000000) + .statusBarsPadding() + ) { + AsyncImage( model = ImageRequest.Builder(context) .data(uiState.imageUrl) .build(), contentDescription = null, - modifier = Modifier.fillMaxSize(), - contentScale = ContentScale.FillBounds, + modifier = Modifier.fillMaxSize().clickableWithoutRipple { + isVisibleSpacer = !isVisibleSpacer + }, + contentScale = ContentScale.Fit, filterQuality = FilterQuality.None ) - + } + if (isVisibleSpacer) { + Spacer( + modifier = Modifier + .fillMaxWidth() + .height(statusBarPaddingValue + 80.dp) + .background(ColorBlack_FF000000.copy(alpha = 0.7f)) + ) Row( modifier = Modifier .fillMaxWidth() @@ -149,6 +163,7 @@ fun VerificationPreviewScreen( ) ) ) + .statusBarsPadding() .height(93.dp) .padding(horizontal = 24.dp, vertical = 14.dp) ) { @@ -186,7 +201,10 @@ fun VerificationPreviewScreen( ) IconButton( - onClick = onClickClose, + onClick = { + onClickClose() + //setStatusBar(context, true) + }, modifier = Modifier.wrapContentSize() ) { Icon( @@ -196,9 +214,11 @@ fun VerificationPreviewScreen( ) } } + UploadButton( context = context, filePath = uiState.imageUrl.toUri(), + isUploading = isUploading, onClickUpload = onClickUpload ) } @@ -211,6 +231,7 @@ fun VerificationPreviewScreen( fun BoxScope.UploadButton( context: Context, filePath: Uri, + isUploading: Boolean, onClickUpload: (File) -> Unit ) { val multipleEventsCutter = remember { MultipleEventsCutter.get() } @@ -220,7 +241,7 @@ fun BoxScope.UploadButton( .padding(horizontal = 24.dp, vertical = 36.dp) .fillMaxWidth() .navigationBarsPadding(), - buttonType = MissionMateButtonType.ACTIVE, + buttonType = if(isUploading) MissionMateButtonType.DISABLED else MissionMateButtonType.ACTIVE, onClick = { multipleEventsCutter.processEvent { val file = ImageCompressor.getCompressedImage(context, filePath) @@ -228,11 +249,19 @@ fun BoxScope.UploadButton( } } ) { - Text( - text = stringResource(id = R.string.upload), - style = MissionMateTypography.body_xl_bold, - color = ColorWhite_FFFFFFFF - ) + if(isUploading){ + CircularProgressIndicator( + modifier = Modifier.size(24.dp), + color = ColorWhite_FFFFFFFF, + strokeWidth = 3.dp + ) + }else { + Text( + text = stringResource(id = R.string.upload), + style = MissionMateTypography.body_lg_bold, + color = ColorWhite_FFFFFFFF + ) + } } } @@ -257,6 +286,7 @@ fun VerificationPreviewLoading() { fun ProgressBar() { Box( modifier = Modifier + .fillMaxSize() .statusBarsPadding() .navigationBarsPadding() ) { @@ -270,6 +300,7 @@ fun ProgressBar() { @Composable fun VerificationPreviewScreenPreview() { VerificationPreviewScreen( + isUploading = false, onClickClose = {}, uiState = VerificationPreviewUiState.Success( characterUiModel = CharacterUiModel.RABBIT, @@ -284,6 +315,7 @@ fun VerificationPreviewScreenPreview() { @Composable fun VerificationPreviewScreenLoadingPreview() { VerificationPreviewScreen( + isUploading = false, onClickClose = {}, uiState = VerificationPreviewUiState.Loading, onClickUpload = {} diff --git a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewViewModel.kt b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewViewModel.kt index 87d36f4..2d477db 100644 --- a/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewViewModel.kt +++ b/feature/board/src/main/java/com/goalpanzi/mission_mate/feature/board/screen/VerificationPreviewViewModel.kt @@ -1,5 +1,6 @@ package com.goalpanzi.mission_mate.feature.board.screen +import android.util.Log import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -87,3 +88,4 @@ sealed interface UploadEvent { data object Success : UploadEvent data object Error : UploadEvent } + diff --git a/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavHost.kt b/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavHost.kt index f5315ff..6845671 100644 --- a/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavHost.kt +++ b/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavHost.kt @@ -1,13 +1,20 @@ package com.goalpanzi.mission_mate.feature.main.component +import android.app.Activity import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.navigation.compose.NavHost +import androidx.navigation.compose.currentBackStackEntryAsState import com.goalpanzi.mission_mate.core.designsystem.theme.ColorWhite_FFFFFFFF +import com.goalpanzi.mission_mate.core.designsystem.util.isLightStatusBars +import com.goalpanzi.mission_mate.core.designsystem.util.setStatusBar import com.goalpanzi.mission_mate.feature.board.boardDetailNavGraph import com.goalpanzi.mission_mate.feature.board.boardFinishNavGraph import com.goalpanzi.mission_mate.feature.board.boardNavGraph @@ -30,6 +37,18 @@ internal fun MainNavHost( startDestination: String, padding: PaddingValues ) { + val context = LocalContext.current + val currentBackStackEntry by navigator.navController.currentBackStackEntryAsState() + val currentRoute = currentBackStackEntry?.destination?.route + + LaunchedEffect(currentRoute) { + if (navigator.isDarkStatusBarScreen(currentRoute)) { + setStatusBar(context, false) + } else if(!isLightStatusBars(context as Activity)){ + setStatusBar(context, true) + } + } + Box( modifier = modifier .fillMaxSize() @@ -142,4 +161,4 @@ internal fun MainNavHost( ) } } -} \ No newline at end of file +} diff --git a/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavigator.kt b/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavigator.kt index 6636201..6fc8e0e 100644 --- a/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavigator.kt +++ b/feature/main/src/main/java/com/goalpanzi/mission_mate/feature/main/component/MainNavigator.kt @@ -91,6 +91,11 @@ class MainNavigator( fun navigationToVerificationPreview(missionId: Long, imageUrl : Uri) { navController.navigateToVerificationPreview(missionId, imageUrl) } + + fun isDarkStatusBarScreen(currentRoute: String?): Boolean { + return currentRoute?.contains("RouteModel.VerificationPreview") == true + || currentRoute?.contains("RouteModel.UserStory") == true + } } @Composable @@ -98,4 +103,4 @@ internal fun rememberMainNavigator( navController: NavHostController = rememberNavController() ) : MainNavigator = remember(navController) { MainNavigator(navController) -} \ No newline at end of file +}