Skip to content

Commit 58165f6

Browse files
committed
refactor: encapsulate save change channel within NoteResult state
- Add `checkSaveChangeChannel` to the `NoteResult` data class to bundle the event stream with the UI state. - Update `NoteViewModel` to provide the channel via the `NoteResult` state flow instead of a standalone property. - Remove the `checkSaveChangeChannel` parameter from `AdaptiveMainScreen`, `NoteDetailScreen`, and `NoteDetail` composables to simplify function signatures. - Adjust `NoteDetail` to observe the channel directly from the provided `NoteResult` object. - Clean up unused imports and update UI previews to reflect the state changes.
1 parent b394982 commit 58165f6

5 files changed

Lines changed: 11 additions & 24 deletions

File tree

app/android/src/main/java/com/softartdev/notedelight/ScreenshootPreview.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import com.softartdev.notedelight.ui.main.NoteDetailBody
2525
import com.softartdev.notedelight.ui.settings.AdaptiveSettingsScreen
2626
import com.softartdev.notedelight.ui.signin.SignInScreenBody
2727
import com.softartdev.theme.material3.PreferableMaterialTheme
28-
import kotlinx.coroutines.channels.Channel
2928
import kotlinx.coroutines.flow.flowOf
3029
import kotlinx.datetime.LocalDateTime
3130

@@ -149,7 +148,6 @@ private fun StoreNotesScreen() {
149148
noteDetailState = remember { mutableStateOf(NoteResult(note = selectedNote)) },
150149
onMainAction = {},
151150
onNoteAction = {},
152-
checkSaveChangeChannel = Channel()
153151
)
154152
}
155153

core/presentation/src/commonMain/kotlin/com/softartdev/notedelight/presentation/note/NoteResult.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.softartdev.notedelight.presentation.note
22

33
import com.softartdev.notedelight.model.Note
4+
import kotlinx.coroutines.channels.Channel
45

56
data class NoteResult(
67
val loading: Boolean = false,
78
val note: Note? = null,
9+
val checkSaveChangeChannel: Channel<Unit> = Channel()
810
) {
911
fun showLoading(): NoteResult = copy(loading = true)
1012
fun hideLoading(): NoteResult = copy(loading = false)

core/presentation/src/commonMain/kotlin/com/softartdev/notedelight/presentation/note/NoteViewModel.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import com.softartdev.notedelight.usecase.note.SaveNoteUseCase
1717
import com.softartdev.notedelight.usecase.note.UpdateTitleUseCase
1818
import com.softartdev.notedelight.util.CoroutineDispatchers
1919
import kotlinx.coroutines.Job
20-
import kotlinx.coroutines.channels.Channel
2120
import kotlinx.coroutines.flow.MutableStateFlow
2221
import kotlinx.coroutines.flow.StateFlow
2322
import kotlinx.coroutines.flow.update
@@ -35,12 +34,11 @@ class NoteViewModel(
3534
private val coroutineDispatchers: CoroutineDispatchers,
3635
) : ViewModel() {
3736
private val logger = Logger.withTag(this@NoteViewModel::class.simpleName.toString())
38-
private val mutableStateFlow: MutableStateFlow<NoteResult> = MutableStateFlow(NoteResult())
37+
private val mutableStateFlow: MutableStateFlow<NoteResult> = MutableStateFlow(
38+
value = NoteResult(checkSaveChangeChannel = adaptiveInteractor.checkSaveChangeChannel)
39+
)
3940
val stateFlow: StateFlow<NoteResult> = mutableStateFlow
4041

41-
val checkSaveChangeChannel: Channel<Unit>
42-
get() = adaptiveInteractor.checkSaveChangeChannel
43-
4442
private var noteId: Long
4543
set(value) { adaptiveInteractor.selectedNoteIdStateFlow.value = value }
4644
get() = requireNotNull(adaptiveInteractor.selectedNoteIdStateFlow.value)

core/ui/src/commonMain/kotlin/com/softartdev/notedelight/ui/main/AdaptiveMainScreen.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import com.softartdev.notedelight.presentation.note.NoteViewModel
3232
import com.softartdev.notedelight.ui.NavBackHandler
3333
import com.softartdev.notedelight.ui.VerticalPaneExpansionDragHandle
3434
import com.softartdev.theme.material3.PreferableMaterialTheme
35-
import kotlinx.coroutines.channels.Channel
3635
import kotlinx.coroutines.launch
3736
import org.koin.compose.koinInject
3837
import org.koin.compose.viewmodel.koinViewModel
@@ -55,7 +54,6 @@ fun AdaptiveMainScreen(
5554
onMainAction = mainViewModel::onAction,
5655
noteDetailState = noteViewModel.stateFlow.collectAsState(),
5756
onNoteAction = noteViewModel::onAction,
58-
checkSaveChangeChannel = noteViewModel.checkSaveChangeChannel
5957
)
6058
}
6159

@@ -67,7 +65,6 @@ fun AdaptiveMainScreen(
6765
onMainAction: (action: MainAction) -> Unit,
6866
noteDetailState: State<NoteResult>,
6967
onNoteAction: (action: NoteAction) -> Unit,
70-
checkSaveChangeChannel: Channel<Unit>
7168
) {
7269
val coroutineScope = rememberCoroutineScope()
7370
val navigator: ThreePaneScaffoldNavigator<Long> = rememberListDetailPaneScaffoldNavigator<Long>()
@@ -81,7 +78,7 @@ fun AdaptiveMainScreen(
8178
directive = navigator.scaffoldDirective,
8279
value = navigator.scaffoldValue,
8380
listPane = { MainScreen(noteListResultState, onMainAction, snackbarHostState = snackbarHostState) },
84-
detailPane = { NoteDetailScreen(noteDetailState, onNoteAction, checkSaveChangeChannel) },
81+
detailPane = { NoteDetailScreen(noteDetailState, onNoteAction) },
8582
paneExpansionDragHandle = ThreePaneScaffoldScope::VerticalPaneExpansionDragHandle,
8683
paneExpansionState = paneExpansionState
8784
)

core/ui/src/commonMain/kotlin/com/softartdev/notedelight/ui/main/NoteDetail.kt

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import androidx.compose.runtime.LaunchedEffect
2727
import androidx.compose.runtime.State
2828
import androidx.compose.runtime.collectAsState
2929
import androidx.compose.runtime.derivedStateOf
30-
import androidx.compose.runtime.getValue
3130
import androidx.compose.runtime.remember
3231
import androidx.compose.ui.Alignment
3332
import androidx.compose.ui.Modifier
@@ -38,14 +37,13 @@ import androidx.compose.ui.unit.dp
3837
import com.softartdev.notedelight.presentation.note.NoteAction
3938
import com.softartdev.notedelight.presentation.note.NoteResult
4039
import com.softartdev.notedelight.presentation.note.NoteViewModel
41-
import com.softartdev.notedelight.ui.NavBackHandler
4240
import com.softartdev.notedelight.ui.MainDetailPanePlaceholder
41+
import com.softartdev.notedelight.ui.NavBackHandler
4342
import com.softartdev.notedelight.ui.TooltipIconButton
4443
import com.softartdev.notedelight.util.DELETE_NOTE_BUTTON_TAG
4544
import com.softartdev.notedelight.util.EDIT_TITLE_BUTTON_TAG
4645
import com.softartdev.notedelight.util.SAVE_NOTE_BUTTON_TAG
4746
import com.softartdev.theme.material3.PreferableMaterialTheme
48-
import kotlinx.coroutines.channels.Channel
4947
import kotlinx.coroutines.flow.receiveAsFlow
5048
import notedelight.core.ui.generated.resources.Res
5149
import notedelight.core.ui.generated.resources.action_delete_note
@@ -62,28 +60,22 @@ fun NoteDetail(noteViewModel: NoteViewModel) {
6260
noteViewModel.launchCollectingSelectedNoteId()
6361
}
6462
val noteDetailState: State<NoteResult> = noteViewModel.stateFlow.collectAsState()
65-
NoteDetailScreen(noteDetailState, noteViewModel::onAction, noteViewModel.checkSaveChangeChannel)
63+
NoteDetailScreen(noteDetailState, noteViewModel::onAction)
6664
}
6765

6866
@Composable
6967
fun NoteDetailScreen(
7068
noteDetailState: State<NoteResult>,
7169
onAction: (NoteAction) -> Unit,
72-
checkSaveChangeChannel: Channel<Unit>
7370
) = when (noteDetailState.value.note) {
7471
null -> MainDetailPanePlaceholder()
75-
else -> NoteDetail(
76-
result = noteDetailState.value,
77-
onAction = onAction,
78-
checkSaveChangeChannel = checkSaveChangeChannel
79-
)
72+
else -> NoteDetail(noteDetailState.value, onAction)
8073
}
8174

8275
@Composable
8376
fun NoteDetail(
8477
result: NoteResult,
8578
onAction: (NoteAction) -> Unit,
86-
checkSaveChangeChannel: Channel<Unit>
8779
) {
8880
// Change selected note on adaptive (tablet) layout must change the text too.
8981
// The `rememberTextFieldState` and `rememberSaveable` doesn't support `key` parameters.
@@ -94,8 +86,8 @@ fun NoteDetail(
9486
initialSelection = TextRange(result.note?.text?.length ?: 0)
9587
)
9688
}
97-
LaunchedEffect(checkSaveChangeChannel) {
98-
checkSaveChangeChannel.receiveAsFlow().collect {
89+
LaunchedEffect(key1 = result.checkSaveChangeChannel) {
90+
result.checkSaveChangeChannel.receiveAsFlow().collect {
9991
onAction(NoteAction.ShowCheckSaveChangeDialog(textState.text))
10092
}
10193
}

0 commit comments

Comments
 (0)