Skip to content

Commit

Permalink
Merge branch 'develop' into feature/#310-representation-rule-ui-prese…
Browse files Browse the repository at this point in the history
…ntation
  • Loading branch information
murjune committed Sep 2, 2023
2 parents b84b3ca + a0b9101 commit eeeb491
Show file tree
Hide file tree
Showing 51 changed files with 1,218 additions and 577 deletions.
11 changes: 11 additions & 0 deletions app/src/main/java/hous/release/android/di/ReducerModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityRetainedComponent
import hous.release.android.presentation.our_rules.event.AddRuleReducer
import hous.release.android.presentation.our_rules.event.MainRuleReducer
import hous.release.android.presentation.our_rules.event.UpdateRuleReducer
import hous.release.android.presentation.our_rules.viewmodel.AddRuleEvent
import hous.release.android.presentation.our_rules.viewmodel.AddRuleState
import hous.release.android.presentation.our_rules.viewmodel.MainRulesEvent
import hous.release.android.presentation.our_rules.viewmodel.MainRulesState
import hous.release.android.presentation.our_rules.viewmodel.UpdateRuleEvent
import hous.release.android.presentation.our_rules.viewmodel.UpdateRuleState
import hous.release.android.util.event.Reducer
import javax.inject.Qualifier

Expand All @@ -23,6 +26,10 @@ abstract class ReducerModule {
@AddRule
@Binds
abstract fun bindAddRuleReducer(addRuleReducer: AddRuleReducer): Reducer<AddRuleState, AddRuleEvent>

@UpdateRule
@Binds
abstract fun bindUpdateRuleReducer(updateRuleReducer: UpdateRuleReducer): Reducer<UpdateRuleState, UpdateRuleEvent>
}

@Retention(AnnotationRetention.BINARY)
Expand All @@ -32,3 +39,7 @@ annotation class MainRules
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class AddRule

@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class UpdateRule
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ fun BasicUpdateRuleScreen(
ruleName: String = "",
description: String = "",
photos: List<PhotoUiModel> = emptyList(),
isFocusOn: Boolean = false,
onDisposeFocus: () -> Unit = {},
addRule: () -> Unit = { },
changeName: (String) -> Unit = {},
changeDescription: (String) -> Unit = {},
Expand All @@ -49,7 +51,12 @@ fun BasicUpdateRuleScreen(
) {
val focusManager = LocalFocusManager.current
val (focusRequester) = FocusRequester.createRefs()
AutoFocusOnInitializeEffect { focusRequester.requestFocus() }
AutoFocusOnInitializeEffect {
if (isFocusOn) {
focusRequester.requestFocus()
onDisposeFocus()
}
}

Column(
modifier = Modifier.fillMaxSize().pointerInput(Unit) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package hous.release.android.presentation.our_rules.event

import hous.release.android.presentation.our_rules.model.PhotoUiModel
import hous.release.android.presentation.our_rules.viewmodel.UpdateRuleEvent
import hous.release.android.presentation.our_rules.viewmodel.UpdateRuleState
import hous.release.android.util.event.Reducer
import timber.log.Timber
import javax.inject.Inject

class UpdateRuleReducer @Inject constructor() : Reducer<UpdateRuleState, UpdateRuleEvent> {
override fun dispatch(state: UpdateRuleState, event: UpdateRuleEvent): UpdateRuleState {
return when (event) {
is UpdateRuleEvent.InitRule -> {
state.copy(
id = event.id,
name = event.name,
description = event.description,
photos = event.photos
)
}

is UpdateRuleEvent.ChangeDescription -> {
state.copy(description = event.description)
}

is UpdateRuleEvent.ChangeName -> {
state.copy(name = event.name)
}

is UpdateRuleEvent.LoadImage -> {
val newPhotos = event.photos.map { photo ->
PhotoUiModel.from(photo)
}
val updatedPhotos = state.photos + newPhotos
Timber.e("LoadImage: updatedPhotos: $updatedPhotos")
state.copy(
photos = updatedPhotos
)
}

is UpdateRuleEvent.DeleteImage -> {
val filteredPhotos = state.photos.filter { photo ->
photo != event.photo
}
state.copy(
photos = filteredPhotos
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import hous.release.android.R
import hous.release.android.presentation.our_rules.component.LoadingBar
import hous.release.android.presentation.our_rules.component.dialog.AddRuleLimitedDialog
import hous.release.android.presentation.our_rules.component.dialog.AddRuleOutDialog
import hous.release.android.presentation.our_rules.component.dialog.UpdateRuleOutDialog
import hous.release.android.presentation.our_rules.model.DetailRuleUiModel
import hous.release.android.presentation.our_rules.screen.AddRuleScreen
import hous.release.android.presentation.our_rules.screen.MainRuleScreen
Expand All @@ -32,6 +33,8 @@ import hous.release.android.presentation.our_rules.viewmodel.AddRuleSideEffect
import hous.release.android.presentation.our_rules.viewmodel.AddRuleViewModel
import hous.release.android.presentation.our_rules.viewmodel.MainRuleSideEffect
import hous.release.android.presentation.our_rules.viewmodel.MainRuleViewModel
import hous.release.android.presentation.our_rules.viewmodel.UpdateRuleSideEffect
import hous.release.android.presentation.our_rules.viewmodel.UpdateRuleViewModel
import hous.release.android.presentation.practice.findActivity
import hous.release.android.util.ToastMessageUtil
import hous.release.domain.entity.Photo
Expand Down Expand Up @@ -63,7 +66,7 @@ private fun NavGraphBuilder.mainRuleScreen(
val activity = LocalContext.current.findActivity()
val viewModel = hiltViewModel<MainRuleViewModel>()
val uiState = viewModel.uiState.collectAsStateWithLifecycle()

var isLoading by remember { mutableStateOf(false) }
var isShowLimitedAddRuleDialog by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
viewModel.sideEffect.collect { event ->
Expand All @@ -76,6 +79,11 @@ private fun NavGraphBuilder.mainRuleScreen(
isShowLimitedAddRuleDialog = true
}
}

is MainRuleSideEffect.LoadingBar -> {
Timber.d("LoadingBar: ${event.isLoading}")
isLoading = event.isLoading
}
}
}
}
Expand All @@ -84,6 +92,7 @@ private fun NavGraphBuilder.mainRuleScreen(
isShowLimitedAddRuleDialog = false
})
}
if (isLoading) LoadingBar()

MainRuleScreen(
detailRule = uiState.value.detailRule,
Expand All @@ -94,11 +103,13 @@ private fun NavGraphBuilder.mainRuleScreen(
onNavigateToAddRule = viewModel::canAddRule,
onNavigateToUpdateRule = navController::navigateUpdateRule,
onFinish = activity::finish,
refresh = viewModel::fetchMainRules
refresh = viewModel::fetchMainRules,
deleteRule = viewModel::deleteRule,
)
}
}

@OptIn(ExperimentalLifecycleComposeApi::class)
private fun NavGraphBuilder.updateRuleScreen(
navController: NavController
) {
Expand All @@ -108,9 +119,90 @@ private fun NavGraphBuilder.updateRuleScreen(
navController.previousBackStackEntry?.savedStateHandle?.get<DetailRuleUiModel>(
RulesScreens.DETAIL_RULE_KEY
)?.let { detailRule ->
val viewModel = hiltViewModel<UpdateRuleViewModel>()
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
var isOutDialogShow by remember { mutableStateOf(false) }
var isLoading by remember { mutableStateOf(false) }
val context = LocalContext.current
val takePhotoFromAlbumLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.PickMultipleVisualMedia(5)
) { uriList ->
if (uriList.isNotEmpty()) {
viewModel.loadImage(uriList.map { Photo.from(it.toString()) })
}
}
val onBack: () -> Unit = { navController.popBackStack() }
val onOpenGallery = {
takePhotoFromAlbumLauncher.launch(
PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.ImageOnly
)
)
}
LaunchedEffect(Unit) {
viewModel.init(detailRule)
}
LaunchedEffect(Unit) {
viewModel.sideEffect.collect { event ->
when (event) {
is UpdateRuleSideEffect.IDLE -> Unit
is UpdateRuleSideEffect.DuplicateToast -> {
ToastMessageUtil.showToast(
context,
context.getString(R.string.our_rule_duplicate_rule)
)
}

is UpdateRuleSideEffect.ShowLimitImageToast -> {
ToastMessageUtil.showToast(
context,
context.getString(R.string.our_rule_limit_photo_count)
)
}

is UpdateRuleSideEffect.LoadingBar -> {
isLoading = event.isLoading
}

is UpdateRuleSideEffect.PopBackStack -> {
onBack()
}
}
}
}

val onBackPressed = {
if (uiState.value.name.isNotBlank()) {
isOutDialogShow = true
} else {
Timber.d("onBackPressed")
onBack()
}
}
BackHandler(viewModel.isChangeRuleContent(detailRule), onBackPressed)
if (isLoading) LoadingBar()

if (isOutDialogShow) {
UpdateRuleOutDialog(
onConfirm = {
isOutDialogShow = false
onBack()
},
onDismiss = {
isOutDialogShow = false
}
)
}
UpdateRuleScreen(
rule = detailRule,
onBack = navController::popBackStack
ruleName = uiState.value.name,
description = uiState.value.description,
photos = uiState.value.photos,
changeName = viewModel::changeName,
changeDescription = viewModel::changeDescription,
updateRule = viewModel::updateRule,
deletePhoto = viewModel::deleteImage,
onBack = onBackPressed,
onOpenGallery = onOpenGallery
)
} ?: run {
Timber.e("DetailRuleUiModel is null")
Expand Down Expand Up @@ -146,7 +238,6 @@ private fun NavGraphBuilder.addRuleScreen(onBack: () -> Unit) {
when (event) {
is AddRuleSideEffect.IDLE -> Unit
is AddRuleSideEffect.DuplicateToast -> {
isLoading = false
ToastMessageUtil.showToast(
context,
context.getString(R.string.our_rule_duplicate_rule)
Expand All @@ -165,12 +256,10 @@ private fun NavGraphBuilder.addRuleScreen(onBack: () -> Unit) {
}

is AddRuleSideEffect.PopBackStack -> {
isLoading = false
onBack()
}

is AddRuleSideEffect.ShowLimitRuleCountDialog -> {
isLoading = false
isShowLimitedDialog = true
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package hous.release.android.presentation.our_rules.screen

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.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import hous.release.android.R
Expand All @@ -20,7 +24,11 @@ fun AddRuleScreen(
onOpenGallery: () -> Unit = {},
onBack: () -> Unit = {}
) {
var isFocus by remember { mutableStateOf(true) }
val onDisposeFocus = { isFocus = false }
BasicUpdateRuleScreen(
isFocusOn = isFocus,
onDisposeFocus = onDisposeFocus,
title = stringResource(id = R.string.our_rule_add_new_rule_title),
trailingTitle = stringResource(id = R.string.our_rule_add_new_rule),
ruleName = ruleName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
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.platform.LocalLifecycleOwner
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import hous.release.android.presentation.our_rules.component.dialog.DeleteRuleDialog
import hous.release.android.presentation.our_rules.component.main.DetailRuleBottomSheetContent
import hous.release.android.presentation.our_rules.component.main.MainRuleContent
import hous.release.android.presentation.our_rules.model.DetailRuleUiModel
Expand All @@ -29,6 +34,7 @@ fun MainRuleScreen(
mainRules: List<Rule> = emptyList(),
searchQuery: String = "",
fetchDetailRuleById: (Int) -> Unit = {},
deleteRule: () -> Unit = {},
onSearch: (String) -> Unit = {},
onNavigateToUpdateRule: (DetailRuleUiModel) -> Unit = {},
onNavigateToAddRule: () -> Unit = {},
Expand All @@ -40,6 +46,7 @@ fun MainRuleScreen(
initialValue = ModalBottomSheetValue.Hidden,
skipHalfExpanded = true
)
var isShowDeleteRuleDialog by remember { mutableStateOf(false) }
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
Expand All @@ -59,18 +66,31 @@ fun MainRuleScreen(
bottomSheetState.hide()
}
}
if (isShowDeleteRuleDialog) {
DeleteRuleDialog(
onConfirm = {
coroutineScope.launch {
deleteRule()
isShowDeleteRuleDialog = false
bottomSheetState.hide()
}
},
onDismiss = { isShowDeleteRuleDialog = false }
)
}

ModalBottomSheetLayout(
sheetState = bottomSheetState,
sheetContent = {
DetailRuleBottomSheetContent(
detailRule = detailRule,
onNavigateToUpdateRule = onNavigateToUpdateRule,
onDeleteRule = {
onNavigateToUpdateRule = { detailRule ->
coroutineScope.launch {
bottomSheetState.hide()
onNavigateToUpdateRule(detailRule)
}
}
},
onDeleteRule = { isShowDeleteRuleDialog = true }
)
},
sheetShape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp),
Expand Down
Loading

0 comments on commit eeeb491

Please sign in to comment.