mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	manga-refresh-state (#8090)
This commit is contained in:
		| @@ -24,4 +24,8 @@ class GetMangaWithChapters( | ||||
|     suspend fun awaitManga(id: Long): Manga { | ||||
|         return mangaRepository.getMangaById(id) | ||||
|     } | ||||
|  | ||||
|     suspend fun awaitChapters(id: Long): List<Chapter> { | ||||
|         return chapterRepository.getChapterByMangaId(id) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -295,7 +295,7 @@ private fun MangaScreenSmallImpl( | ||||
|         val topPadding = contentPadding.calculateTopPadding() | ||||
|  | ||||
|         SwipeRefresh( | ||||
|             state = rememberSwipeRefreshState(state.isRefreshingInfo || state.isRefreshingChapter), | ||||
|             state = rememberSwipeRefreshState(state.isRefreshingData), | ||||
|             onRefresh = onRefresh, | ||||
|             swipeEnabled = !chapters.any { it.selected }, | ||||
|             indicatorPadding = contentPadding, | ||||
| @@ -429,7 +429,7 @@ fun MangaScreenLargeImpl( | ||||
|     val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues() | ||||
|     val (topBarHeight, onTopBarHeightChanged) = remember { mutableStateOf(0) } | ||||
|     SwipeRefresh( | ||||
|         state = rememberSwipeRefreshState(state.isRefreshingInfo || state.isRefreshingChapter), | ||||
|         state = rememberSwipeRefreshState(state.isRefreshingData), | ||||
|         onRefresh = onRefresh, | ||||
|         swipeEnabled = !chapters.any { it.selected }, | ||||
|         indicatorPadding = PaddingValues( | ||||
|   | ||||
| @@ -47,6 +47,7 @@ import eu.kanade.tachiyomi.util.chapter.getChapterSort | ||||
| import eu.kanade.tachiyomi.util.lang.launchIO | ||||
| import eu.kanade.tachiyomi.util.lang.launchNonCancellable | ||||
| import eu.kanade.tachiyomi.util.lang.toRelativeString | ||||
| import eu.kanade.tachiyomi.util.lang.withIOContext | ||||
| import eu.kanade.tachiyomi.util.lang.withUIContext | ||||
| import eu.kanade.tachiyomi.util.preference.asHotFlow | ||||
| import eu.kanade.tachiyomi.util.removeCovers | ||||
| @@ -67,6 +68,7 @@ import kotlinx.coroutines.flow.filter | ||||
| import kotlinx.coroutines.flow.launchIn | ||||
| import kotlinx.coroutines.flow.map | ||||
| import kotlinx.coroutines.flow.update | ||||
| import kotlinx.coroutines.isActive | ||||
| import kotlinx.coroutines.launch | ||||
| import kotlinx.coroutines.supervisorScope | ||||
| import kotlinx.coroutines.withContext | ||||
| @@ -84,7 +86,6 @@ class MangaPresenter( | ||||
|     val mangaId: Long, | ||||
|     val isFromSource: Boolean, | ||||
|     private val basePreferences: BasePreferences = Injekt.get(), | ||||
|     private val uiPreferences: UiPreferences = Injekt.get(), | ||||
|     private val downloadPreferences: DownloadPreferences = Injekt.get(), | ||||
|     private val libraryPreferences: LibraryPreferences = Injekt.get(), | ||||
|     private val trackManager: TrackManager = Injekt.get(), | ||||
| @@ -112,9 +113,6 @@ class MangaPresenter( | ||||
|     private val successState: MangaScreenState.Success? | ||||
|         get() = state.value as? MangaScreenState.Success | ||||
|  | ||||
|     private var fetchMangaJob: Job? = null | ||||
|     private var fetchChaptersJob: Job? = null | ||||
|  | ||||
|     private var observeDownloadsStatusJob: Job? = null | ||||
|     private var observeDownloadsPageJob: Job? = null | ||||
|  | ||||
| @@ -161,57 +159,30 @@ class MangaPresenter( | ||||
|     override fun onCreate(savedState: Bundle?) { | ||||
|         super.onCreate(savedState) | ||||
|  | ||||
|         presenterScope.launchIO { | ||||
|             val manga = getMangaAndChapters.awaitManga(mangaId) | ||||
|  | ||||
|             if (!manga.favorite) { | ||||
|                 setMangaDefaultChapterFlags.await(manga) | ||||
|             } | ||||
|  | ||||
|             // Show what we have earlier. | ||||
|             // Defaults set by the block above won't apply until next update but it doesn't matter | ||||
|             // since we don't have any chapter yet. | ||||
|             _state.update { | ||||
|                 MangaScreenState.Success( | ||||
|                     manga = manga, | ||||
|                     source = Injekt.get<SourceManager>().getOrStub(manga.source), | ||||
|                     isFromSource = isFromSource, | ||||
|                     trackingAvailable = trackManager.hasLoggedServices(), | ||||
|                     chapters = emptyList(), | ||||
|                     isRefreshingChapter = true, | ||||
|                     isIncognitoMode = incognitoMode, | ||||
|                     isDownloadedOnlyMode = downloadedOnlyMode, | ||||
|                     dialog = null, | ||||
|                 ) | ||||
|             } | ||||
|         val toChapterItemsParams: List<DomainChapter>.(manga: DomainManga) -> List<ChapterItem> = { manga -> | ||||
|             val uiPreferences = Injekt.get<UiPreferences>() | ||||
|             toChapterItems( | ||||
|                 context = view?.activity ?: Injekt.get<Application>(), | ||||
|                 manga = manga, | ||||
|                 dateRelativeTime = uiPreferences.relativeTime().get(), | ||||
|                 dateFormat = UiPreferences.dateFormat(uiPreferences.dateFormat().get()), | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         // For UI changes | ||||
|         presenterScope.launch { | ||||
|             getMangaAndChapters.subscribe(mangaId) | ||||
|                 .distinctUntilChanged() | ||||
|                 .collectLatest { (manga, chapters) -> | ||||
|                     val chapterItems = chapters.toChapterItems( | ||||
|                         context = view?.activity ?: Injekt.get<Application>(), | ||||
|                         manga = manga, | ||||
|                         dateRelativeTime = uiPreferences.relativeTime().get(), | ||||
|                         dateFormat = UiPreferences.dateFormat(uiPreferences.dateFormat().get()), | ||||
|                     ) | ||||
|                     val chapterItems = chapters.toChapterItemsParams(manga) | ||||
|                     updateSuccessState { | ||||
|                         it.copy( | ||||
|                             manga = manga, | ||||
|                             chapters = chapterItems, | ||||
|                             isRefreshingChapter = false, | ||||
|                             isRefreshingInfo = false, | ||||
|                         ) | ||||
|                     } | ||||
|  | ||||
|                     observeTrackers() | ||||
|                     observeTrackingCount() | ||||
|                     observeDownloads() | ||||
|  | ||||
|                     if (!manga.initialized) { | ||||
|                         fetchAllFromSource(manualFetch = false) | ||||
|                     } else if (chapterItems.isEmpty()) { | ||||
|                         fetchChaptersFromSource() | ||||
|                     } | ||||
|                 } | ||||
|         } | ||||
|  | ||||
| @@ -222,11 +193,63 @@ class MangaPresenter( | ||||
|         basePreferences.downloadedOnly() | ||||
|             .asHotFlow { downloadedOnlyMode = it } | ||||
|             .launchIn(presenterScope) | ||||
|  | ||||
|         // This block runs once on create | ||||
|         presenterScope.launchIO { | ||||
|             val manga = getMangaAndChapters.awaitManga(mangaId) | ||||
|             val chapters = getMangaAndChapters.awaitChapters(mangaId) | ||||
|                 .toChapterItemsParams(manga) | ||||
|  | ||||
|             if (!manga.favorite) { | ||||
|                 setMangaDefaultChapterFlags.await(manga) | ||||
|             } | ||||
|  | ||||
|             val needRefreshInfo = !manga.initialized | ||||
|             val needRefreshChapter = chapters.isEmpty() | ||||
|  | ||||
|             // Show what we have earlier. | ||||
|             _state.update { | ||||
|                 MangaScreenState.Success( | ||||
|                     manga = manga, | ||||
|                     source = Injekt.get<SourceManager>().getOrStub(manga.source), | ||||
|                     isFromSource = isFromSource, | ||||
|                     trackingAvailable = trackManager.hasLoggedServices(), | ||||
|                     chapters = chapters, | ||||
|                     isRefreshingData = needRefreshInfo || needRefreshChapter, | ||||
|                     isIncognitoMode = incognitoMode, | ||||
|                     isDownloadedOnlyMode = downloadedOnlyMode, | ||||
|                     dialog = null, | ||||
|                 ) | ||||
|             } | ||||
|  | ||||
|             // Start observe tracking since it only needs mangaId | ||||
|             observeTrackers() | ||||
|             observeTrackingCount() | ||||
|  | ||||
|             // Fetch info-chapters when needed | ||||
|             if (presenterScope.isActive) { | ||||
|                 val fetchFromSourceTasks = listOf( | ||||
|                     async { if (needRefreshInfo) fetchMangaFromSource() }, | ||||
|                     async { if (needRefreshChapter) fetchChaptersFromSource() }, | ||||
|                 ) | ||||
|                 fetchFromSourceTasks.awaitAll() | ||||
|             } | ||||
|  | ||||
|             // Initial loading finished | ||||
|             updateSuccessState { it.copy(isRefreshingData = false) } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun fetchAllFromSource(manualFetch: Boolean = true) { | ||||
|         fetchMangaFromSource(manualFetch) | ||||
|         fetchChaptersFromSource(manualFetch) | ||||
|         presenterScope.launch { | ||||
|             updateSuccessState { it.copy(isRefreshingData = true) } | ||||
|             val fetchFromSourceTasks = listOf( | ||||
|                 async { fetchMangaFromSource(manualFetch) }, | ||||
|                 async { fetchChaptersFromSource(manualFetch) }, | ||||
|             ) | ||||
|             fetchFromSourceTasks.awaitAll() | ||||
|             updateSuccessState { it.copy(isRefreshingData = false) } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Manga info - start | ||||
| @@ -234,10 +257,8 @@ class MangaPresenter( | ||||
|     /** | ||||
|      * Fetch manga information from source. | ||||
|      */ | ||||
|     private fun fetchMangaFromSource(manualFetch: Boolean = false) { | ||||
|         if (fetchMangaJob?.isActive == true) return | ||||
|         fetchMangaJob = presenterScope.launchIO { | ||||
|             updateSuccessState { it.copy(isRefreshingInfo = true) } | ||||
|     private suspend fun fetchMangaFromSource(manualFetch: Boolean = false) { | ||||
|         withIOContext { | ||||
|             try { | ||||
|                 successState?.let { | ||||
|                     val networkManga = it.source.getMangaDetails(it.manga.toSManga()) | ||||
| @@ -246,7 +267,6 @@ class MangaPresenter( | ||||
|             } catch (e: Throwable) { | ||||
|                 withUIContext { view?.onFetchMangaInfoError(e) } | ||||
|             } | ||||
|             updateSuccessState { it.copy(isRefreshingInfo = false) } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -534,10 +554,8 @@ class MangaPresenter( | ||||
|     /** | ||||
|      * Requests an updated list of chapters from the source. | ||||
|      */ | ||||
|     private fun fetchChaptersFromSource(manualFetch: Boolean = false) { | ||||
|         if (fetchChaptersJob?.isActive == true) return | ||||
|         fetchChaptersJob = presenterScope.launchIO { | ||||
|             updateSuccessState { it.copy(isRefreshingChapter = true) } | ||||
|     private suspend fun fetchChaptersFromSource(manualFetch: Boolean = false) { | ||||
|         withIOContext { | ||||
|             try { | ||||
|                 successState?.let { successState -> | ||||
|                     val chapters = successState.source.getChapterList(successState.manga.toSManga()) | ||||
| @@ -555,7 +573,6 @@ class MangaPresenter( | ||||
|             } catch (e: Throwable) { | ||||
|                 withUIContext { view?.onFetchChaptersError(e) } | ||||
|             } | ||||
|             updateSuccessState { it.copy(isRefreshingChapter = false) } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1082,8 +1099,7 @@ sealed class MangaScreenState { | ||||
|         val chapters: List<ChapterItem>, | ||||
|         val trackingAvailable: Boolean = false, | ||||
|         val trackingCount: Int = 0, | ||||
|         val isRefreshingInfo: Boolean = false, | ||||
|         val isRefreshingChapter: Boolean = false, | ||||
|         val isRefreshingData: Boolean = false, | ||||
|         val isIncognitoMode: Boolean = false, | ||||
|         val isDownloadedOnlyMode: Boolean = false, | ||||
|         val dialog: MangaPresenter.Dialog? = null, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user