Make MangaCoverViewModel collect manga only while subscribed (#3716)

Assisted-by: Claude:claude-opus-5
This commit is contained in:
AntsyLich
2026-08-08 11:57:55 +06:00
committed by GitHub
parent ed274e26fd
commit 0834884335
5 changed files with 16 additions and 15 deletions
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.manga
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.initializer
@@ -19,10 +20,14 @@ import eu.kanade.tachiyomi.data.saver.Location
import eu.kanade.tachiyomi.util.editCover import eu.kanade.tachiyomi.util.editCover
import eu.kanade.tachiyomi.util.system.getBitmapOrNull import eu.kanade.tachiyomi.util.system.getBitmapOrNull
import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toShareIntent
import kotlinx.coroutines.flow.update import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.WhileSubscribed
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import mihon.core.viewmodel.StateViewModel
import tachiyomi.core.common.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
@@ -33,6 +38,7 @@ import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.time.Duration.Companion.seconds
class MangaCoverViewModel( class MangaCoverViewModel(
private val mangaId: Long, private val mangaId: Long,
@@ -42,7 +48,7 @@ class MangaCoverViewModel(
private val updateManga: UpdateManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
val snackbarHostState: SnackbarHostState = SnackbarHostState(), val snackbarHostState: SnackbarHostState = SnackbarHostState(),
) : StateViewModel<Manga?>(null) { ) : ViewModel() {
companion object { companion object {
val MANGA_ID_KEY = CreationExtras.Key<Long>() val MANGA_ID_KEY = CreationExtras.Key<Long>()
@@ -56,12 +62,9 @@ class MangaCoverViewModel(
} }
} }
init { val state: StateFlow<Manga?> = getManga.subscribe(mangaId)
viewModelScope.launchIO { .flowOn(Dispatchers.IO)
getManga.subscribe(mangaId) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), null)
.collect { newManga -> mutableState.update { newManga } }
}
}
fun saveCover(context: Context) { fun saveCover(context: Context) {
viewModelScope.launch { viewModelScope.launch {
@@ -147,7 +150,6 @@ class MangaCoverViewModel(
} }
fun deleteCustomCover(context: Context) { fun deleteCustomCover(context: Context) {
val mangaId = state.value?.id ?: return
viewModelScope.launchIO { viewModelScope.launchIO {
try { try {
coverCache.deleteCustomCover(mangaId) coverCache.deleteCustomCover(mangaId)
@@ -6,7 +6,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -250,7 +249,7 @@ class MangaScreen(
set(MangaCoverViewModel.MANGA_ID_KEY, successState.manga.id) set(MangaCoverViewModel.MANGA_ID_KEY, successState.manga.id)
}, },
) )
val manga by sm.state.collectAsState() val manga by sm.state.collectAsStateWithLifecycle()
if (manga != null) { if (manga != null) {
val getContent = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { val getContent = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
if (it == null) return@rememberLauncherForActivityResult if (it == null) return@rememberLauncherForActivityResult
@@ -33,7 +33,7 @@ class MangaRepositoryImpl(
.awaitAsOne() .awaitAsOne()
} }
override suspend fun getMangaByIdAsFlow(id: Long): Flow<Manga> { override fun getMangaByIdAsFlow(id: Long): Flow<Manga> {
return database.mangasQueries return database.mangasQueries
.getMangaById(id, MangaMapper::mapManga) .getMangaById(id, MangaMapper::mapManga)
.subscribeToOne() .subscribeToOne()
@@ -19,7 +19,7 @@ class GetManga(
} }
} }
suspend fun subscribe(id: Long): Flow<Manga> { fun subscribe(id: Long): Flow<Manga> {
return mangaRepository.getMangaByIdAsFlow(id) return mangaRepository.getMangaByIdAsFlow(id)
} }
@@ -10,7 +10,7 @@ interface MangaRepository {
suspend fun getMangaById(id: Long): Manga suspend fun getMangaById(id: Long): Manga
suspend fun getMangaByIdAsFlow(id: Long): Flow<Manga> fun getMangaByIdAsFlow(id: Long): Flow<Manga>
suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga?