BookInfoScreen: Canceling BookInfoViewModel.onEvent + Resetting BookInfoState when exiting screen.
This commit is contained in:
parent
d6de5bc521
commit
4f521bcd1e
2 changed files with 714 additions and 679 deletions
|
|
@ -37,6 +37,7 @@ import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
|
@ -92,6 +93,12 @@ fun BookInfoScreenRoot(screen: Screen.BookInfo) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
viewModel.clearViewModel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BookInfoScreen(
|
BookInfoScreen(
|
||||||
state = state,
|
state = state,
|
||||||
onNavigate = { navigator.it() },
|
onNavigate = { navigator.it() },
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
@file:Suppress("LABEL_NAME_CLASH")
|
||||||
|
|
||||||
package ua.acclorite.book_story.presentation.screens.book_info.data
|
package ua.acclorite.book_story.presentation.screens.book_info.data
|
||||||
|
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
|
|
@ -11,6 +13,7 @@ import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
|
@ -56,10 +59,13 @@ class BookInfoViewModel @Inject constructor(
|
||||||
private val _state = MutableStateFlow(BookInfoState())
|
private val _state = MutableStateFlow(BookInfoState())
|
||||||
val state = _state.asStateFlow()
|
val state = _state.asStateFlow()
|
||||||
|
|
||||||
private var job: Job? = null
|
private var eventJob = SupervisorJob()
|
||||||
private var job2: Job? = null
|
|
||||||
|
private var snackBarJob: Job? = null
|
||||||
|
private var updateJob: Job? = null
|
||||||
|
|
||||||
fun onEvent(event: BookInfoEvent) {
|
fun onEvent(event: BookInfoEvent) {
|
||||||
|
viewModelScope.launch(eventJob + Dispatchers.Main) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is BookInfoEvent.OnShowHideChangeCoverBottomSheet -> {
|
is BookInfoEvent.OnShowHideChangeCoverBottomSheet -> {
|
||||||
_state.update {
|
_state.update {
|
||||||
|
|
@ -70,7 +76,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnChangeCover -> {
|
is BookInfoEvent.OnChangeCover -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
val image = event.context.contentResolver?.openInputStream(event.uri)?.use {
|
val image = event.context.contentResolver?.openInputStream(event.uri)?.use {
|
||||||
BitmapFactory.decodeStream(it)
|
BitmapFactory.decodeStream(it)
|
||||||
} ?: return@launch
|
} ?: return@launch
|
||||||
|
|
@ -97,7 +103,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnDeleteCover -> {
|
is BookInfoEvent.OnDeleteCover -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
if (_state.value.book.coverImage == null) {
|
if (_state.value.book.coverImage == null) {
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +126,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnCheckCoverReset -> {
|
is BookInfoEvent.OnCheckCoverReset -> {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
canResetCover = canResetCover.execute(_state.value.book.id)
|
canResetCover = canResetCover.execute(_state.value.book.id)
|
||||||
|
|
@ -130,7 +136,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnResetCoverImage -> {
|
is BookInfoEvent.OnResetCoverImage -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
val result = resetCoverImage.execute(_state.value.book.id)
|
val result = resetCoverImage.execute(_state.value.book.id)
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
|
@ -158,7 +164,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnShowHideEditTitle -> {
|
is BookInfoEvent.OnShowHideEditTitle -> {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
val shouldHide = _state.value.editTitle
|
val shouldHide = _state.value.editTitle
|
||||||
|
|
||||||
if (!shouldHide) {
|
if (!shouldHide) {
|
||||||
|
|
@ -198,7 +204,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnShowHideEditAuthor -> {
|
is BookInfoEvent.OnShowHideEditAuthor -> {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
val shouldHide = _state.value.editAuthor
|
val shouldHide = _state.value.editAuthor
|
||||||
|
|
||||||
if (!shouldHide) {
|
if (!shouldHide) {
|
||||||
|
|
@ -238,7 +244,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnShowHideEditDescription -> {
|
is BookInfoEvent.OnShowHideEditDescription -> {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
val shouldHide = _state.value.editDescription
|
val shouldHide = _state.value.editDescription
|
||||||
|
|
||||||
if (!shouldHide) {
|
if (!shouldHide) {
|
||||||
|
|
@ -278,7 +284,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnUpdateData -> {
|
is BookInfoEvent.OnUpdateData -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
val title = _state.value.titleValue.trim().replace("\n", "")
|
val title = _state.value.titleValue.trim().replace("\n", "")
|
||||||
val author = _state.value.authorValue.trim().replace("\n", "")
|
val author = _state.value.authorValue.trim().replace("\n", "")
|
||||||
val description = _state.value.descriptionValue.trim().replace("\n", "")
|
val description = _state.value.descriptionValue.trim().replace("\n", "")
|
||||||
|
|
@ -332,7 +338,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnDeleteBook -> {
|
is BookInfoEvent.OnDeleteBook -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
showDeleteDialog = false
|
showDeleteDialog = false
|
||||||
|
|
@ -365,7 +371,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnMoveBook -> {
|
is BookInfoEvent.OnMoveBook -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
showMoveDialog = false
|
showMoveDialog = false
|
||||||
|
|
@ -416,12 +422,12 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnShowSnackbar -> {
|
is BookInfoEvent.OnShowSnackbar -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
job?.cancel()
|
snackBarJob?.cancel()
|
||||||
event.snackbarState.currentSnackbarData?.dismiss()
|
event.snackbarState.currentSnackbarData?.dismiss()
|
||||||
|
|
||||||
if (event.durationMillis > 0) {
|
if (event.durationMillis > 0) {
|
||||||
job = viewModelScope.launch(Dispatchers.IO) {
|
snackBarJob = launch(Dispatchers.IO) {
|
||||||
yield()
|
yield()
|
||||||
delay(event.durationMillis)
|
delay(event.durationMillis)
|
||||||
yield()
|
yield()
|
||||||
|
|
@ -444,11 +450,11 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnLoadUpdate -> {
|
is BookInfoEvent.OnLoadUpdate -> {
|
||||||
onEvent(BookInfoEvent.OnCancelUpdate)
|
updateJob?.cancel()
|
||||||
|
updateJob = launch(Dispatchers.IO) {
|
||||||
job2 = viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
showConfirmUpdateDialog = false,
|
||||||
isLoadingUpdate = true,
|
isLoadingUpdate = true,
|
||||||
editTitle = false,
|
editTitle = false,
|
||||||
editAuthor = false,
|
editAuthor = false,
|
||||||
|
|
@ -606,7 +612,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnConfirmUpdate -> {
|
is BookInfoEvent.OnConfirmUpdate -> {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
isRefreshing = true,
|
isRefreshing = true,
|
||||||
|
|
@ -769,7 +775,8 @@ class BookInfoViewModel @Inject constructor(
|
||||||
|
|
||||||
is BookInfoEvent.OnCancelUpdate -> {
|
is BookInfoEvent.OnCancelUpdate -> {
|
||||||
_state.update {
|
_state.update {
|
||||||
job2?.cancel()
|
updateJob?.cancel()
|
||||||
|
|
||||||
it.copy(
|
it.copy(
|
||||||
showConfirmUpdateDialog = false,
|
showConfirmUpdateDialog = false,
|
||||||
isLoadingUpdate = false
|
isLoadingUpdate = false
|
||||||
|
|
@ -778,7 +785,7 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
is BookInfoEvent.OnNavigateToReaderScreen -> {
|
is BookInfoEvent.OnNavigateToReaderScreen -> {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
onEvent(BookInfoEvent.OnCancelUpdate)
|
onEvent(BookInfoEvent.OnCancelUpdate)
|
||||||
_state.value.book.id.let {
|
_state.value.book.id.let {
|
||||||
insertHistory.execute(
|
insertHistory.execute(
|
||||||
|
|
@ -800,9 +807,10 @@ class BookInfoViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun init(screen: Screen.BookInfo, onNavigate: OnNavigate) {
|
fun init(screen: Screen.BookInfo, onNavigate: OnNavigate) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val book = getBookById.execute(screen.bookId)
|
val book = getBookById.execute(screen.bookId)
|
||||||
|
|
||||||
if (book == null) {
|
if (book == null) {
|
||||||
|
|
@ -817,7 +825,27 @@ class BookInfoViewModel @Inject constructor(
|
||||||
book = book
|
book = book
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
clear()
|
||||||
|
|
||||||
onEvent(BookInfoEvent.OnCheckCoverReset)
|
onEvent(BookInfoEvent.OnCheckCoverReset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun clear() {
|
||||||
|
eventJob.cancel()
|
||||||
|
eventJob.join()
|
||||||
|
eventJob = SupervisorJob()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearViewModel() {
|
||||||
|
viewModelScope.launch(Dispatchers.Main) {
|
||||||
|
_state.update {
|
||||||
|
BookInfoState()
|
||||||
|
}
|
||||||
|
|
||||||
|
eventJob.cancel()
|
||||||
|
eventJob.join()
|
||||||
|
eventJob = SupervisorJob()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue