refactor(manga/details): Reduce manga variable even further

Basically telling Presenter to take full responsible for `manga` variable on keeping it up to date

Also rename `onFirstLoad` to `onCreateLate` to make it clearer that it's just onCreate but executed late and put stuff that can be executed sooner in onCreate function
This commit is contained in:
Ahmad Ansori Palembani 2024-08-24 19:47:20 +07:00
parent 4c6efe28c2
commit e9b4292295
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
7 changed files with 58 additions and 51 deletions

View file

@ -20,7 +20,6 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
import eu.kanade.tachiyomi.ui.more.AboutController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.chapter.updateTrackChapterMarkedAsRead
@ -36,6 +35,7 @@ import uy.kohesive.injekt.injectLazy
import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.chapter.interactor.UpdateChapter
import yokai.domain.manga.interactor.GetManga
import yokai.presentation.core.Constants
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
/**
@ -489,7 +489,7 @@ class NotificationReceiver : BroadcastReceiver() {
val newIntent =
Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_MANGA)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
.putExtra(MangaDetailsController.MANGA_EXTRA, manga.id)
.putExtra(Constants.MANGA_EXTRA, manga.id)
.putExtra("notificationId", manga.id.hashCode())
.putExtra("groupId", groupId)
return PendingIntent.getActivity(

View file

@ -9,9 +9,6 @@ import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler
import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.ui.base.SmallToolbarInterface
@ -33,6 +30,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.domain.chapter.interactor.GetChapter
import yokai.presentation.core.Constants
import yokai.presentation.core.util.IntentCommon
class SearchActivity : MainActivity() {
@ -156,7 +154,7 @@ class SearchActivity : MainActivity() {
SHORTCUT_MANGA, SHORTCUT_MANGA_BACK -> {
val extras = intent.extras ?: return false
if (intent.action == SHORTCUT_MANGA_BACK && preferences.openChapterInShortcuts().get()) {
val mangaId = extras.getLong(MangaDetailsController.MANGA_EXTRA)
val mangaId = extras.getLong(Constants.MANGA_EXTRA)
if (mangaId != 0L) {
val db = Injekt.get<DatabaseHelper>()
db.getManga(mangaId).executeAsBlocking()?.let { manga ->

View file

@ -68,8 +68,6 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.databinding.MangaDetailsControllerBinding
import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.icon
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
@ -143,9 +141,6 @@ import kotlin.math.max
import kotlin.math.roundToInt
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeoutOrNull
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.models.cover
import yokai.i18n.MR
import yokai.presentation.core.Constants
@ -168,27 +163,21 @@ class MangaDetailsController :
smartSearchConfig: BrowseController.SmartSearchConfig? = null,
update: Boolean = false,
shouldLockIfNeeded: Boolean = false,
) : super(
Bundle().apply {
putLong(MANGA_EXTRA, manga?.id ?: 0)
putBoolean(FROM_CATALOGUE_EXTRA, fromCatalogue)
putParcelable(SMART_SEARCH_CONFIG_EXTRA, smartSearchConfig)
putBoolean(UPDATE_EXTRA, update)
},
) {
this.manga = manga
if (manga != null) {
this.source = Injekt.get<SourceManager>().getOrStub(manga.source)
}
) : super(bundle(manga?.id, fromCatalogue, smartSearchConfig, update)) {
this.shouldLockIfNeeded = shouldLockIfNeeded
this.presenter = MangaDetailsPresenter(manga?.id!!, source!!).apply {
setCurrentManga(manga)
}
this.presenter = MangaDetailsPresenter(manga?.id!!).apply { setCurrentManga(manga) }
}
constructor(mangaId: Long) : this(
runBlocking { Injekt.get<GetManga>().awaitById(mangaId) },
)
constructor(
mangaId: Long,
fromCatalogue: Boolean = false,
smartSearchConfig: BrowseController.SmartSearchConfig? = null,
update: Boolean = false,
shouldLockIfNeeded: Boolean = false,
) : super(bundle(mangaId, fromCatalogue, smartSearchConfig, update)) {
this.shouldLockIfNeeded = shouldLockIfNeeded
this.presenter = MangaDetailsPresenter(mangaId)
}
constructor(bundle: Bundle) : this(bundle.getLong(Constants.MANGA_EXTRA)) {
val notificationId = bundle.getInt("notificationId", -1)
@ -202,8 +191,7 @@ class MangaDetailsController :
}
}
private var manga: Manga? = null
private var source: Source? = null
private val manga: Manga? get() = if (presenter.isMangaLateInitInitialized()) presenter.manga else null
private var colorAnimator: ValueAnimator? = null
override val presenter: MangaDetailsPresenter
private var coverColor: Int? = null
@ -258,7 +246,7 @@ class MangaDetailsController :
activityBinding?.appBar?.y = 0f
}
presenter.onFirstLoad()
presenter.onCreateLate()
binding.swipeRefresh.isRefreshing = presenter.isLoading
binding.swipeRefresh.setOnRefreshListener { presenter.refreshAll() }
updateToolbarTitleAlpha()
@ -652,7 +640,7 @@ class MangaDetailsController :
presenter.isLockedFromSearch =
shouldLockIfNeeded && SecureActivityDelegate.shouldBeLocked()
presenter.headerItem.isLocked = presenter.isLockedFromSearch
manga = runBlocking { presenter.refreshMangaFromDb() }
runBlocking { presenter.refreshMangaFromDb() }
presenter.syncData()
presenter.fetchChapters(refreshTracker == null)
if (refreshTracker != null) {
@ -1536,7 +1524,7 @@ class MangaDetailsController :
}
else -> {
if (presenter.source is CatalogueSource) {
val controller = BrowseSourceController(presenter.source)
val controller = BrowseSourceController(presenter.source as CatalogueSource)
router.pushController(controller.withFadeTransaction())
controller.searchWithGenre(text)
}
@ -1872,8 +1860,6 @@ class MangaDetailsController :
const val SMART_SEARCH_CONFIG_EXTRA = "smartSearchConfig"
const val FROM_CATALOGUE_EXTRA = "from_catalogue"
@Deprecated("Use the one from Constants object instead")
const val MANGA_EXTRA = Constants.MANGA_EXTRA
private enum class RangeMode {
Download,
@ -1881,6 +1867,18 @@ class MangaDetailsController :
Read,
Unread,
}
fun bundle(
mangaId: Long? = null,
fromCatalogue: Boolean = false,
smartSearchConfig: BrowseController.SmartSearchConfig? = null,
update: Boolean = false,
) = Bundle().apply {
putLong(Constants.MANGA_EXTRA, mangaId ?: 0)
putBoolean(FROM_CATALOGUE_EXTRA, fromCatalogue)
putParcelable(SMART_SEARCH_CONFIG_EXTRA, smartSearchConfig)
putBoolean(UPDATE_EXTRA, update)
}
}
inner class FloatingMangaDetailsActionModeCallback(

View file

@ -98,13 +98,13 @@ import yokai.util.lang.getString
class MangaDetailsPresenter(
val mangaId: Long,
val source: Source,
val sourceManager: SourceManager = Injekt.get(),
val preferences: PreferencesHelper = Injekt.get(),
val coverCache: CoverCache = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(),
private val chapterFilter: ChapterFilter = Injekt.get(),
internal val storageManager: StorageManager = Injekt.get(),
private val storageManager: StorageManager = Injekt.get(),
) : BaseCoroutinePresenter<MangaDetailsController>(), DownloadQueue.DownloadListener {
private val getAvailableScanlators: GetAvailableScanlators by injectLazy()
private val getChapter: GetChapter by injectLazy()
@ -116,10 +116,12 @@ class MangaDetailsPresenter(
// val currentManga get() = currentMangaInternal.asStateFlow()
lateinit var manga: Manga
fun isMangaLateInitInitialized() = ::manga.isInitialized
private val customMangaManager: CustomMangaManager by injectLazy()
private val mangaShortcutManager: MangaShortcutManager by injectLazy()
val sourceManager: SourceManager by injectLazy()
val source: Source by lazy { sourceManager.getOrStub(manga.source) }
private lateinit var chapterSort: ChapterSort
val extension by lazy { (source as? HttpSource)?.getExtension() }
@ -143,25 +145,35 @@ class MangaDetailsPresenter(
var allHistory: List<History> = emptyList()
private set
lateinit var headerItem: MangaHeaderItem
private set
val headerItem: MangaHeaderItem by lazy { MangaHeaderItem(mangaId, view?.fromCatalogue == true)}
var tabletChapterHeaderItem: MangaHeaderItem? = null
private set
var allChapterScanlators: Set<String> = emptySet()
fun onFirstLoad() {
override fun onCreate() {
val controller = view ?: return
isLockedFromSearch = controller.shouldLockIfNeeded && SecureActivityDelegate.shouldBeLocked()
if (!::manga.isInitialized) runBlocking { refreshMangaFromDb() }
// if (currentManga.value == null) return
syncData()
downloadManager.addListener(this)
LibraryUpdateJob.updateFlow
.filter { it == mangaId }
.onEach(::onUpdateManga)
.onEach { onUpdateManga() }
.launchIn(presenterScope)
tracks = db.getTracks(manga).executeAsBlocking()
}
/**
* onCreate but executed after UI layout is ready otherwise it'd only show blank screen
*/
fun onCreateLate() {
val controller = view ?: return
if (manga.isLocal()) {
refreshAll()
} else if (!manga.initialized) {
@ -174,9 +186,11 @@ class MangaDetailsPresenter(
controller.updateChapters(this.chapters)
getHistory()
}
presenterScope.launch {
setTrackItems()
}
refreshTracking(false)
}
@ -202,7 +216,7 @@ class MangaDetailsPresenter(
// TODO: Use flow to "sync" data instead
fun syncData() {
chapterSort = ChapterSort(manga, chapterFilter, preferences)
headerItem = MangaHeaderItem(mangaId, view?.fromCatalogue == true).apply {
headerItem.apply {
isTablet = view?.isTablet == true
isLocked = isLockedFromSearch
}
@ -778,7 +792,7 @@ class MangaDetailsPresenter(
}
}
private fun onUpdateManga(mangaId: Long?) = fetchChapters()
private fun onUpdateManga() = fetchChapters()
fun shareManga() {
val context = Injekt.get<Application>()

View file

@ -32,7 +32,6 @@ import coil3.request.placeholder
import com.google.android.material.button.MaterialButton
import com.google.android.material.chip.Chip
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.coil.useCustomCover
import eu.kanade.tachiyomi.data.database.models.seriesType
import eu.kanade.tachiyomi.databinding.ChapterHeaderItemBinding
import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding
@ -678,7 +677,6 @@ class MangaHeaderHolder(
error(drawable)
if (manga.favorite) networkCachePolicy(CachePolicy.READ_ONLY)
diskCachePolicy(CachePolicy.READ_ONLY)
useCustomCover(manga.favorite)
}
binding.backdrop.loadManga(manga) {
placeholder(drawable)
@ -702,7 +700,6 @@ class MangaHeaderHolder(
applyBlur()
},
)
useCustomCover(manga.favorite)
}
}

View file

@ -7,7 +7,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
class MangaHeaderItem(val mangaId: Long, var startExpanded: Boolean) :
class MangaHeaderItem(val mangaId: Long, private var startExpanded: Boolean) :
AbstractFlexibleItem<MangaHeaderHolder>() {
var isChapterHeader = false

View file

@ -33,7 +33,7 @@ import androidx.compose.ui.unit.sp
// REF: https://gist.github.com/mmolosay/584ce5c47567cb66228b76ef98c3c4e4
private val SpringStiffness = Spring.StiffnessMediumLow
private const val SpringStiffness = Spring.StiffnessMediumLow
@Composable
fun LoadingButton(