@@ -12,6 +12,7 @@ plugins {
|
||||
alias(mihonx.plugins.compose)
|
||||
alias(mihonx.plugins.spotless)
|
||||
|
||||
alias(libs.plugins.metro)
|
||||
alias(libs.plugins.aboutLibraries)
|
||||
alias(libs.plugins.androidx.baselineProfile)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
@@ -209,6 +210,7 @@ dependencies {
|
||||
implementation(projects.i18n)
|
||||
implementation(projects.core.archive)
|
||||
implementation(projects.core.common)
|
||||
implementation(projects.core.metro)
|
||||
implementation(projects.coreMetadata)
|
||||
implementation(projects.sourceApi)
|
||||
implementation(projects.sourceLocal)
|
||||
@@ -283,6 +285,9 @@ dependencies {
|
||||
|
||||
// Dependency injection
|
||||
implementation(libs.injekt)
|
||||
implementation(libs.metro.runtime)
|
||||
implementation(libs.metrox.viewmodel)
|
||||
implementation(libs.metrox.viewmodel.compose)
|
||||
|
||||
// Image loading
|
||||
implementation(libs.bundles.coil)
|
||||
|
||||
@@ -3,11 +3,11 @@ package eu.kanade.core.util
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import mihon.app.di.appGraph
|
||||
|
||||
@Composable
|
||||
fun ifSourcesLoaded(): Boolean {
|
||||
return remember { Injekt.get<SourceManager>().isInitialized }.collectAsState().value
|
||||
val context = LocalContext.current
|
||||
return remember { context.appGraph.sourceManager.isInitialized }.collectAsState().value
|
||||
}
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
package eu.kanade.domain
|
||||
|
||||
import eu.kanade.domain.chapter.interactor.GetAvailableScanlators
|
||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||
import eu.kanade.domain.download.interactor.DeleteDownload
|
||||
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
||||
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
||||
import eu.kanade.domain.extension.interactor.GetExtensionsByType
|
||||
import eu.kanade.domain.extension.interactor.TrustExtension
|
||||
import eu.kanade.domain.manga.interactor.GetExcludedScanlators
|
||||
import eu.kanade.domain.manga.interactor.SetExcludedScanlators
|
||||
import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.domain.source.interactor.GetEnabledSources
|
||||
import eu.kanade.domain.source.interactor.GetIncognitoState
|
||||
import eu.kanade.domain.source.interactor.GetLanguagesWithSources
|
||||
import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount
|
||||
import eu.kanade.domain.source.interactor.SetMigrateSorting
|
||||
import eu.kanade.domain.source.interactor.ToggleIncognito
|
||||
import eu.kanade.domain.source.interactor.ToggleLanguage
|
||||
import eu.kanade.domain.source.interactor.ToggleSource
|
||||
import eu.kanade.domain.source.interactor.ToggleSourcePin
|
||||
import eu.kanade.domain.track.interactor.AddTracks
|
||||
import eu.kanade.domain.track.interactor.RefreshTracks
|
||||
import eu.kanade.domain.track.interactor.SyncChapterProgressWithTrack
|
||||
import eu.kanade.domain.track.interactor.TrackChapter
|
||||
import mihon.data.extension.repository.ExtensionStoreRepositoryImpl
|
||||
import mihon.data.extension.service.ExtensionStoreService
|
||||
import mihon.domain.chapter.interactor.FilterChaptersForDownload
|
||||
import mihon.domain.extension.interactor.AddExtensionStore
|
||||
import mihon.domain.extension.interactor.GetExtensionStoreCountAsFlow
|
||||
import mihon.domain.extension.interactor.GetExtensionStores
|
||||
import mihon.domain.extension.interactor.RemoveExtensionStore
|
||||
import mihon.domain.extension.interactor.UpdateExtensionStores
|
||||
import mihon.domain.extension.repository.ExtensionStoreRepository
|
||||
import mihon.domain.migration.usecases.MigrateMangaUseCase
|
||||
import mihon.domain.source.interactor.UpdateMangaFromRemote
|
||||
import mihon.domain.upcoming.interactor.GetUpcomingManga
|
||||
import tachiyomi.data.category.CategoryRepositoryImpl
|
||||
import tachiyomi.data.chapter.ChapterRepositoryImpl
|
||||
import tachiyomi.data.history.HistoryRepositoryImpl
|
||||
import tachiyomi.data.manga.MangaRepositoryImpl
|
||||
import tachiyomi.data.release.ReleaseServiceImpl
|
||||
import tachiyomi.data.source.SourceRepositoryImpl
|
||||
import tachiyomi.data.source.StubSourceRepositoryImpl
|
||||
import tachiyomi.data.track.TrackRepositoryImpl
|
||||
import tachiyomi.data.updates.UpdatesRepositoryImpl
|
||||
import tachiyomi.domain.category.interactor.CreateCategoryWithName
|
||||
import tachiyomi.domain.category.interactor.DeleteCategory
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.interactor.RenameCategory
|
||||
import tachiyomi.domain.category.interactor.ReorderCategory
|
||||
import tachiyomi.domain.category.interactor.ResetCategoryFlags
|
||||
import tachiyomi.domain.category.interactor.SetDisplayMode
|
||||
import tachiyomi.domain.category.interactor.SetMangaCategories
|
||||
import tachiyomi.domain.category.interactor.SetSortModeForCategory
|
||||
import tachiyomi.domain.category.repository.CategoryRepository
|
||||
import tachiyomi.domain.chapter.interactor.GetBookmarkedChaptersByMangaId
|
||||
import tachiyomi.domain.chapter.interactor.GetChapter
|
||||
import tachiyomi.domain.chapter.interactor.GetChapterByUrlAndMangaId
|
||||
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
||||
import tachiyomi.domain.chapter.interactor.SetMangaDefaultChapterFlags
|
||||
import tachiyomi.domain.chapter.interactor.ShouldUpdateDbChapter
|
||||
import tachiyomi.domain.chapter.interactor.UpdateChapter
|
||||
import tachiyomi.domain.chapter.repository.ChapterRepository
|
||||
import tachiyomi.domain.history.interactor.GetHistory
|
||||
import tachiyomi.domain.history.interactor.GetNextChapters
|
||||
import tachiyomi.domain.history.interactor.GetTotalReadDuration
|
||||
import tachiyomi.domain.history.interactor.RemoveHistory
|
||||
import tachiyomi.domain.history.interactor.UpsertHistory
|
||||
import tachiyomi.domain.history.repository.HistoryRepository
|
||||
import tachiyomi.domain.manga.interactor.FetchInterval
|
||||
import tachiyomi.domain.manga.interactor.GetDuplicateLibraryManga
|
||||
import tachiyomi.domain.manga.interactor.GetFavorites
|
||||
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
||||
import tachiyomi.domain.manga.interactor.GetManga
|
||||
import tachiyomi.domain.manga.interactor.GetMangaByUrlAndSourceId
|
||||
import tachiyomi.domain.manga.interactor.GetMangaWithChapters
|
||||
import tachiyomi.domain.manga.interactor.NetworkToLocalManga
|
||||
import tachiyomi.domain.manga.interactor.ResetViewerFlags
|
||||
import tachiyomi.domain.manga.interactor.SetMangaChapterFlags
|
||||
import tachiyomi.domain.manga.interactor.UpdateMangaNotes
|
||||
import tachiyomi.domain.manga.repository.MangaRepository
|
||||
import tachiyomi.domain.release.interactor.GetApplicationRelease
|
||||
import tachiyomi.domain.release.service.ReleaseService
|
||||
import tachiyomi.domain.source.interactor.GetRemoteManga
|
||||
import tachiyomi.domain.source.interactor.GetSourcesWithNonLibraryManga
|
||||
import tachiyomi.domain.source.repository.SourceRepository
|
||||
import tachiyomi.domain.source.repository.StubSourceRepository
|
||||
import tachiyomi.domain.track.interactor.DeleteTrack
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import tachiyomi.domain.track.interactor.GetTracksPerManga
|
||||
import tachiyomi.domain.track.interactor.InsertTrack
|
||||
import tachiyomi.domain.track.repository.TrackRepository
|
||||
import tachiyomi.domain.updates.interactor.GetUpdates
|
||||
import tachiyomi.domain.updates.repository.UpdatesRepository
|
||||
import uy.kohesive.injekt.api.InjektModule
|
||||
import uy.kohesive.injekt.api.InjektRegistrar
|
||||
import uy.kohesive.injekt.api.addFactory
|
||||
import uy.kohesive.injekt.api.addSingletonFactory
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class DomainModule : InjektModule {
|
||||
|
||||
override fun InjektRegistrar.registerInjectables() {
|
||||
addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) }
|
||||
addFactory { GetCategories(get()) }
|
||||
addFactory { ResetCategoryFlags(get(), get()) }
|
||||
addFactory { SetDisplayMode(get()) }
|
||||
addFactory { SetSortModeForCategory(get(), get()) }
|
||||
addFactory { CreateCategoryWithName(get(), get()) }
|
||||
addFactory { RenameCategory(get()) }
|
||||
addFactory { ReorderCategory(get()) }
|
||||
addFactory { DeleteCategory(get(), get(), get()) }
|
||||
|
||||
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
|
||||
addFactory { GetDuplicateLibraryManga(get()) }
|
||||
addFactory { GetFavorites(get()) }
|
||||
addFactory { GetLibraryManga(get()) }
|
||||
addFactory { GetMangaWithChapters(get(), get()) }
|
||||
addFactory { GetMangaByUrlAndSourceId(get()) }
|
||||
addFactory { GetManga(get()) }
|
||||
addFactory { GetNextChapters(get(), get(), get()) }
|
||||
addFactory { GetUpcomingManga(get()) }
|
||||
addFactory { ResetViewerFlags(get()) }
|
||||
addFactory { SetMangaChapterFlags(get()) }
|
||||
addFactory { FetchInterval(get()) }
|
||||
addFactory { SetMangaDefaultChapterFlags(get(), get(), get()) }
|
||||
addFactory { SetMangaViewerFlags(get()) }
|
||||
addFactory { NetworkToLocalManga(get()) }
|
||||
addFactory { UpdateManga(get(), get()) }
|
||||
addFactory { UpdateMangaNotes(get()) }
|
||||
addFactory { SetMangaCategories(get()) }
|
||||
addFactory { GetExcludedScanlators(get()) }
|
||||
addFactory { SetExcludedScanlators(get()) }
|
||||
addFactory {
|
||||
MigrateMangaUseCase(
|
||||
get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(),
|
||||
)
|
||||
}
|
||||
|
||||
addSingletonFactory<ReleaseService> { ReleaseServiceImpl(get(), get()) }
|
||||
addFactory { GetApplicationRelease(get()) }
|
||||
|
||||
addSingletonFactory<TrackRepository> { TrackRepositoryImpl(get()) }
|
||||
addFactory { TrackChapter(get(), get(), get(), get()) }
|
||||
addFactory { AddTracks(get(), get(), get(), get()) }
|
||||
addFactory { RefreshTracks(get(), get(), get(), get()) }
|
||||
addFactory { DeleteTrack(get()) }
|
||||
addFactory { GetTracksPerManga(get()) }
|
||||
addFactory { GetTracks(get()) }
|
||||
addFactory { InsertTrack(get()) }
|
||||
addFactory { SyncChapterProgressWithTrack(get(), get(), get()) }
|
||||
|
||||
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
|
||||
addFactory { GetChapter(get()) }
|
||||
addFactory { GetChaptersByMangaId(get()) }
|
||||
addFactory { GetBookmarkedChaptersByMangaId(get()) }
|
||||
addFactory { GetChapterByUrlAndMangaId(get()) }
|
||||
addFactory { UpdateChapter(get()) }
|
||||
addFactory { SetReadStatus(get(), get(), get(), get()) }
|
||||
addFactory { ShouldUpdateDbChapter() }
|
||||
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get(), get()) }
|
||||
addFactory { GetAvailableScanlators(get()) }
|
||||
addFactory { FilterChaptersForDownload(get(), get(), get()) }
|
||||
|
||||
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
||||
addFactory { GetHistory(get()) }
|
||||
addFactory { UpsertHistory(get()) }
|
||||
addFactory { RemoveHistory(get()) }
|
||||
addFactory { GetTotalReadDuration(get()) }
|
||||
|
||||
addFactory { DeleteDownload(get(), get()) }
|
||||
|
||||
addFactory { GetExtensionsByType(get(), get()) }
|
||||
addFactory { GetExtensionSources(get()) }
|
||||
addFactory { GetExtensionLanguages(get(), get()) }
|
||||
|
||||
addSingletonFactory<UpdatesRepository> { UpdatesRepositoryImpl(get()) }
|
||||
addFactory { GetUpdates(get()) }
|
||||
|
||||
addSingletonFactory<SourceRepository> { SourceRepositoryImpl(get(), get()) }
|
||||
addSingletonFactory<StubSourceRepository> { StubSourceRepositoryImpl(get()) }
|
||||
addFactory { GetEnabledSources(get(), get()) }
|
||||
addFactory { GetLanguagesWithSources(get(), get()) }
|
||||
addFactory { GetRemoteManga(get()) }
|
||||
addFactory { GetSourcesWithFavoriteCount(get(), get()) }
|
||||
addFactory { GetSourcesWithNonLibraryManga(get()) }
|
||||
addFactory { SetMigrateSorting(get()) }
|
||||
addFactory { ToggleLanguage(get()) }
|
||||
addFactory { ToggleSource(get()) }
|
||||
addFactory { ToggleSourcePin(get()) }
|
||||
addFactory { TrustExtension(get(), get()) }
|
||||
|
||||
addSingletonFactory { ExtensionStoreService(get(), get(), get()) }
|
||||
addSingletonFactory<ExtensionStoreRepository> { ExtensionStoreRepositoryImpl(get(), get()) }
|
||||
addFactory { AddExtensionStore(get()) }
|
||||
addFactory { GetExtensionStoreCountAsFlow(get()) }
|
||||
addFactory { GetExtensionStores(get()) }
|
||||
addFactory { RemoveExtensionStore(get()) }
|
||||
addFactory { UpdateExtensionStores(get()) }
|
||||
|
||||
addFactory { ToggleIncognito(get()) }
|
||||
addFactory { GetIncognitoState(get(), get(), get()) }
|
||||
|
||||
addFactory { UpdateMangaFromRemote(get(), get(), get(), get(), get(), get(), get()) }
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,15 @@ package eu.kanade.domain.base
|
||||
|
||||
import android.content.Context
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class BasePreferences(
|
||||
val context: Context,
|
||||
preferenceStore: PreferenceStore,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package eu.kanade.domain.chapter.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.domain.chapter.repository.ChapterRepository
|
||||
|
||||
@Inject
|
||||
class GetAvailableScanlators(
|
||||
private val repository: ChapterRepository,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.chapter.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.download.interactor.DeleteDownload
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.common.util.lang.withNonCancellableContext
|
||||
@@ -11,6 +12,7 @@ import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.repository.MangaRepository
|
||||
|
||||
@Inject
|
||||
class SetReadStatus(
|
||||
private val downloadPreferences: DownloadPreferences,
|
||||
private val deleteDownload: DeleteDownload,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.chapter.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.chapter.model.copyFromSChapter
|
||||
import eu.kanade.domain.chapter.model.toSChapter
|
||||
import eu.kanade.domain.manga.interactor.GetExcludedScanlators
|
||||
@@ -29,6 +30,7 @@ import java.lang.Long.max
|
||||
import java.util.TreeSet
|
||||
import kotlin.time.Clock
|
||||
|
||||
@Inject
|
||||
class SyncChaptersWithSource(
|
||||
private val downloadManager: DownloadManager,
|
||||
private val downloadProvider: DownloadProvider,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package eu.kanade.domain.download.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import tachiyomi.core.common.util.lang.withNonCancellableContext
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
|
||||
@Inject
|
||||
class DeleteDownload(
|
||||
private val sourceManager: SourceManager,
|
||||
private val downloadManager: DownloadManager,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package eu.kanade.domain.extension.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
@Inject
|
||||
class GetExtensionLanguages(
|
||||
private val preferences: SourcePreferences,
|
||||
private val extensionManager: ExtensionManager,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package eu.kanade.domain.extension.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.extension.model.Extension
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
@Inject
|
||||
class GetExtensionSources(
|
||||
private val preferences: SourcePreferences,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.extension.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.extension.model.Extensions
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
@@ -7,6 +8,7 @@ import eu.kanade.tachiyomi.extension.model.Extension
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
@Inject
|
||||
class GetExtensionsByType(
|
||||
private val preferences: SourcePreferences,
|
||||
private val extensionManager: ExtensionManager,
|
||||
|
||||
@@ -2,10 +2,12 @@ package eu.kanade.domain.extension.interactor
|
||||
|
||||
import android.content.pm.PackageInfo
|
||||
import androidx.core.content.pm.PackageInfoCompat
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import mihon.domain.extension.repository.ExtensionStoreRepository
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
|
||||
@Inject
|
||||
class TrustExtension(
|
||||
private val repository: ExtensionStoreRepository,
|
||||
private val preferences: SourcePreferences,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package eu.kanade.domain.manga.interactor
|
||||
|
||||
import app.cash.sqldelight.async.coroutines.awaitAsList
|
||||
import dev.zacsweers.metro.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.data.Database
|
||||
import tachiyomi.data.subscribeToList
|
||||
|
||||
@Inject
|
||||
class GetExcludedScanlators(
|
||||
private val database: Database,
|
||||
) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package eu.kanade.domain.manga.interactor
|
||||
|
||||
import app.cash.sqldelight.async.coroutines.awaitAsList
|
||||
import dev.zacsweers.metro.Inject
|
||||
import tachiyomi.data.Database
|
||||
|
||||
@Inject
|
||||
class SetExcludedScanlators(
|
||||
private val database: Database,
|
||||
) {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package eu.kanade.domain.manga.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import tachiyomi.domain.manga.model.MangaUpdate
|
||||
import tachiyomi.domain.manga.repository.MangaRepository
|
||||
|
||||
@Inject
|
||||
class SetMangaViewerFlags(
|
||||
private val mangaRepository: MangaRepository,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.manga.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
@@ -9,6 +10,7 @@ import tachiyomi.domain.manga.model.MangaUpdate
|
||||
import tachiyomi.domain.manga.repository.MangaRepository
|
||||
import kotlin.time.Clock
|
||||
|
||||
@Inject
|
||||
class UpdateManga(
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val fetchInterval: FetchInterval,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package eu.kanade.domain.manga.model
|
||||
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.preference.TriState
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus
|
||||
@@ -22,7 +23,7 @@ val Manga.readerOrientation: Long
|
||||
|
||||
val Manga.downloadedFilter: TriState
|
||||
get() {
|
||||
if (Injekt.get<BasePreferences>().downloadedOnly.get()) return TriState.ENABLED_IS
|
||||
if (Injekt.get<Context>().appGraph.basePreferences.downloadedOnly.get()) return TriState.ENABLED_IS
|
||||
return when (downloadedFilterRaw) {
|
||||
Manga.CHAPTER_SHOW_DOWNLOADED -> TriState.ENABLED_IS
|
||||
Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriState.ENABLED_NOT
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
@@ -10,6 +11,7 @@ import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.domain.source.repository.SourceRepository
|
||||
import tachiyomi.source.local.isLocal
|
||||
|
||||
@Inject
|
||||
class GetEnabledSources(
|
||||
private val repository: SourceRepository,
|
||||
private val preferences: SourcePreferences,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
@@ -7,6 +8,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
||||
@Inject
|
||||
class GetIncognitoState(
|
||||
private val basePreferences: BasePreferences,
|
||||
private val sourcePreferences: SourcePreferences,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -8,6 +9,7 @@ import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.domain.source.repository.SourceRepository
|
||||
import java.util.SortedMap
|
||||
|
||||
@Inject
|
||||
class GetLanguagesWithSources(
|
||||
private val repository: SourceRepository,
|
||||
private val preferences: SourcePreferences,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
@@ -9,6 +10,7 @@ import tachiyomi.domain.source.repository.SourceRepository
|
||||
import tachiyomi.source.local.isLocal
|
||||
import java.util.Collections
|
||||
|
||||
@Inject
|
||||
class GetSourcesWithFavoriteCount(
|
||||
private val repository: SourceRepository,
|
||||
private val preferences: SourcePreferences,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
|
||||
@Inject
|
||||
class SetMigrateSorting(
|
||||
private val preferences: SourcePreferences,
|
||||
) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
|
||||
@Inject
|
||||
class ToggleIncognito(
|
||||
private val preferences: SourcePreferences,
|
||||
) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
|
||||
@Inject
|
||||
class ToggleLanguage(
|
||||
val preferences: SourcePreferences,
|
||||
) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.domain.source.model.Source
|
||||
|
||||
@Inject
|
||||
class ToggleSource(
|
||||
private val preferences: SourcePreferences,
|
||||
) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.domain.source.model.Source
|
||||
|
||||
@Inject
|
||||
class ToggleSourcePin(
|
||||
private val preferences: SourcePreferences,
|
||||
) {
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package eu.kanade.domain.source.model
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.domain.source.model.Source
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
val Source.icon: ImageBitmap?
|
||||
get() {
|
||||
return Injekt.get<ExtensionManager>().getAppIconForSource(id)
|
||||
return Injekt.get<Context>().appGraph.extensionManager.getAppIconForSource(id)
|
||||
?.toBitmap()
|
||||
?.asImageBitmap()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package eu.kanade.domain.source.service
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.domain.source.interactor.SetMigrateSorting
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import mihon.domain.migration.models.MigrationFlag
|
||||
@@ -9,6 +12,8 @@ import tachiyomi.core.common.preference.getEnum
|
||||
import tachiyomi.core.common.preference.getLongArray
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class SourcePreferences(
|
||||
preferenceStore: PreferenceStore,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.track.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.track.model.toDbTrack
|
||||
import eu.kanade.domain.track.model.toDomainTrack
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
@@ -17,14 +18,14 @@ import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
||||
import tachiyomi.domain.history.interactor.GetHistory
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.track.interactor.InsertTrack
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class AddTracks(
|
||||
private val insertTrack: InsertTrack,
|
||||
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
|
||||
private val getChaptersByMangaId: GetChaptersByMangaId,
|
||||
private val trackerManager: TrackerManager,
|
||||
private val getHistory: GetHistory,
|
||||
) {
|
||||
|
||||
// TODO: update all trackers based on common data
|
||||
@@ -55,7 +56,7 @@ class AddTracks(
|
||||
}
|
||||
|
||||
if (track.startDate <= 0) {
|
||||
val firstReadChapterDate = Injekt.get<GetHistory>().await(mangaId)
|
||||
val firstReadChapterDate = getHistory.await(mangaId)
|
||||
.sortedBy { it.readAt }
|
||||
.firstOrNull()
|
||||
?.readAt
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.track.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.track.model.toDbTrack
|
||||
import eu.kanade.domain.track.model.toDomainTrack
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
@@ -10,6 +11,7 @@ import kotlinx.coroutines.supervisorScope
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import tachiyomi.domain.track.interactor.InsertTrack
|
||||
|
||||
@Inject
|
||||
class RefreshTracks(
|
||||
private val getTracks: GetTracks,
|
||||
private val trackerManager: TrackerManager,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.domain.track.interactor
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.track.model.toDbTrack
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
@@ -12,6 +13,7 @@ import tachiyomi.domain.track.interactor.InsertTrack
|
||||
import tachiyomi.domain.track.model.Track
|
||||
import kotlin.math.max
|
||||
|
||||
@Inject
|
||||
class SyncChapterProgressWithTrack(
|
||||
private val updateChapter: UpdateChapter,
|
||||
private val insertTrack: InsertTrack,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package eu.kanade.domain.track.interactor
|
||||
|
||||
import android.content.Context
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.track.model.toDbTrack
|
||||
import eu.kanade.domain.track.model.toDomainTrack
|
||||
import eu.kanade.domain.track.service.DelayedTrackingUpdateJob
|
||||
@@ -14,6 +15,7 @@ import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import tachiyomi.domain.track.interactor.InsertTrack
|
||||
|
||||
@Inject
|
||||
class TrackChapter(
|
||||
private val getTracks: GetTracks,
|
||||
private val trackerManager: TrackerManager,
|
||||
|
||||
@@ -8,30 +8,36 @@ import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkerParameters
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.track.interactor.TrackChapter
|
||||
import eu.kanade.domain.track.store.DelayedTrackingStore
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.AppGraph
|
||||
import mihon.core.metro.metroGraph
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class DelayedTrackingUpdateJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val graph: AppGraph = context.metroGraph()
|
||||
|
||||
@Inject lateinit var getTracks: GetTracks
|
||||
|
||||
@Inject lateinit var trackChapter: TrackChapter
|
||||
|
||||
@Inject lateinit var delayedTrackingStore: DelayedTrackingStore
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
graph.inject(this)
|
||||
|
||||
if (runAttemptCount > 3) {
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
val getTracks = Injekt.get<GetTracks>()
|
||||
val trackChapter = Injekt.get<TrackChapter>()
|
||||
|
||||
val delayedTrackingStore = Injekt.get<DelayedTrackingStore>()
|
||||
|
||||
withIOContext {
|
||||
delayedTrackingStore.getItems()
|
||||
.mapNotNull {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package eu.kanade.domain.track.service
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.domain.track.model.AutoTrackState
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
||||
@@ -8,6 +11,8 @@ import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.getEnum
|
||||
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class TrackPreferences(
|
||||
private val preferenceStore: PreferenceStore,
|
||||
) {
|
||||
|
||||
@@ -2,9 +2,14 @@ package eu.kanade.domain.track.store
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class DelayedTrackingStore(context: Context) {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package eu.kanade.domain.ui
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.domain.ui.model.AppTheme
|
||||
import eu.kanade.domain.ui.model.TabletUiMode
|
||||
import eu.kanade.domain.ui.model.ThemeMode
|
||||
@@ -12,6 +15,8 @@ import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.util.Locale
|
||||
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class UiPreferences(
|
||||
preferenceStore: PreferenceStore,
|
||||
) {
|
||||
|
||||
@@ -8,10 +8,9 @@ import eu.kanade.tachiyomi.util.lang.toRelativeString
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.time.Instant
|
||||
|
||||
@Composable
|
||||
@@ -32,7 +31,7 @@ fun relativeDateText(
|
||||
): String {
|
||||
val context = LocalContext.current
|
||||
|
||||
val preferences = remember { Injekt.get<UiPreferences>() }
|
||||
val preferences = remember { context.appGraph.uiPreferences }
|
||||
val relativeTime = remember { preferences.relativeTime.get() }
|
||||
val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat.get()) }
|
||||
|
||||
|
||||
@@ -9,14 +9,15 @@ import androidx.compose.material.icons.outlined.BugReport
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import kotlinx.coroutines.launch
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
@@ -29,6 +30,7 @@ fun CrashScreen(
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val crashLogUtil = remember { context.appGraph.crashLogUtil }
|
||||
|
||||
InfoScreen(
|
||||
icon = Icons.Outlined.BugReport,
|
||||
@@ -37,7 +39,7 @@ fun CrashScreen(
|
||||
acceptText = stringResource(MR.strings.pref_dump_crash_logs),
|
||||
onAcceptClick = {
|
||||
scope.launch {
|
||||
CrashLogUtil(context).dumpLogs(exception)
|
||||
crashLogUtil.dumpLogs(exception)
|
||||
}
|
||||
},
|
||||
rejectText = stringResource(MR.strings.crash_screen_restart_application),
|
||||
|
||||
@@ -26,11 +26,12 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.manga.model.downloadedFilter
|
||||
import eu.kanade.presentation.components.TabbedDialog
|
||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.preference.TriState
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
@@ -40,8 +41,6 @@ import tachiyomi.presentation.core.components.SortItem
|
||||
import tachiyomi.presentation.core.components.TriStateItem
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.theme.active
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Composable
|
||||
fun ChapterSettingsDialog(
|
||||
@@ -65,7 +64,8 @@ fun ChapterSettingsDialog(
|
||||
)
|
||||
}
|
||||
|
||||
val downloadedOnly = remember { Injekt.get<BasePreferences>().downloadedOnly.get() }
|
||||
val context = LocalContext.current
|
||||
val downloadedOnly = remember { context.appGraph.basePreferences.downloadedOnly.get() }
|
||||
|
||||
TabbedDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
|
||||
@@ -63,10 +63,10 @@ import eu.kanade.presentation.more.settings.LocalPreferenceMinHeight
|
||||
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.MangaWithChapterCount
|
||||
import tachiyomi.domain.source.model.StubSource
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.Badge
|
||||
import tachiyomi.presentation.core.components.BadgeGroup
|
||||
@@ -74,8 +74,6 @@ import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Composable
|
||||
fun DuplicateMangaDialog(
|
||||
@@ -86,7 +84,8 @@ fun DuplicateMangaDialog(
|
||||
onMigrate: (manga: Manga) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val sourceManager = remember { Injekt.get<SourceManager>() }
|
||||
val context = LocalContext.current
|
||||
val sourceManager = remember { context.appGraph.sourceManager }
|
||||
val minHeight = LocalPreferenceMinHeight.current
|
||||
val horizontalPadding = PaddingValues(horizontal = TabbedDialogPaddings.Horizontal)
|
||||
val horizontalPaddingModifier = Modifier.padding(horizontalPadding)
|
||||
|
||||
@@ -30,6 +30,7 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
@@ -48,7 +49,6 @@ import coil3.imageLoader
|
||||
import coil3.request.CachePolicy
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.size.Size
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
@@ -57,13 +57,12 @@ import eu.kanade.tachiyomi.data.coil.ImageDecoder
|
||||
import eu.kanade.tachiyomi.data.coil.newDecoder
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.clickableNoIndication
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Composable
|
||||
fun MangaCoverDialog(
|
||||
@@ -75,7 +74,7 @@ fun MangaCoverDialog(
|
||||
onEditClick: ((EditCoverAction) -> Unit)?,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
val useNewRenderer = Injekt.get<BasePreferences>().highQualityRenderer.get()
|
||||
val useNewRenderer = LocalContext.current.appGraph.basePreferences.highQualityRenderer.get()
|
||||
val view = LocalView.current
|
||||
|
||||
Dialog(
|
||||
|
||||
@@ -86,13 +86,13 @@ import coil3.request.crossfade
|
||||
import com.mikepenz.markdown.model.markdownAnnotator
|
||||
import com.mikepenz.markdown.model.markdownAnnotatorConfig
|
||||
import com.mikepenz.markdown.utils.getUnescapedTextInNode
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.daysUntil
|
||||
import mihon.app.di.appGraph
|
||||
import org.intellij.markdown.MarkdownElementTypes
|
||||
import org.intellij.markdown.MarkdownTokenTypes
|
||||
import org.intellij.markdown.ast.findChildOfType
|
||||
@@ -105,8 +105,6 @@ import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.clickableNoIndication
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Instant
|
||||
@@ -619,7 +617,8 @@ private fun MangaSummary(
|
||||
onEditNotesClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val preferences = remember { Injekt.get<UiPreferences>() }
|
||||
val context = LocalContext.current
|
||||
val preferences = remember { context.appGraph.uiPreferences }
|
||||
val loadImages = remember { preferences.imagesInDescription.get() }
|
||||
val animProgress by animateFloatAsState(
|
||||
targetValue = if (expanded) 1f else 0f,
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -36,19 +37,16 @@ import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState
|
||||
import eu.kanade.tachiyomi.core.security.PrivacyPreferences
|
||||
import eu.kanade.tachiyomi.util.system.launchRequestPackageInstallsPermission
|
||||
import eu.kanade.tachiyomi.util.system.telemetryIncluded
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
internal class PermissionStep : OnboardingStep {
|
||||
|
||||
private val privacyPreferences: PrivacyPreferences by injectLazy()
|
||||
|
||||
private var notificationGranted by mutableStateOf(false)
|
||||
private var batteryGranted by mutableStateOf(false)
|
||||
|
||||
@@ -57,6 +55,7 @@ internal class PermissionStep : OnboardingStep {
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val context = LocalContext.current
|
||||
val privacyPreferences = remember { context.appGraph.privacyPreferences }
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
val installGranted = rememberRequestPackageInstallsPermissionState()
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -20,18 +21,14 @@ import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.more.settings.screen.SettingsDataScreen
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import tachiyomi.domain.storage.service.StoragePreferences
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Button
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
internal class StorageStep : OnboardingStep {
|
||||
|
||||
private val storagePref = Injekt.get<StoragePreferences>().baseStorageDirectory
|
||||
|
||||
private var _isComplete by mutableStateOf(false)
|
||||
|
||||
override val isComplete: Boolean
|
||||
@@ -42,6 +39,7 @@ internal class StorageStep : OnboardingStep {
|
||||
val context = LocalContext.current
|
||||
val handler = LocalUriHandler.current
|
||||
|
||||
val storagePref = remember { context.appGraph.storagePreferences.baseStorageDirectory }
|
||||
val pickStorageLocation = SettingsDataScreen.storageLocationPicker(storagePref)
|
||||
|
||||
Column(
|
||||
|
||||
@@ -3,22 +3,22 @@ package eu.kanade.presentation.more.onboarding
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import eu.kanade.domain.ui.model.setAppCompatDelegateThemeMode
|
||||
import eu.kanade.presentation.more.settings.widget.AppThemeModePreferenceWidget
|
||||
import eu.kanade.presentation.more.settings.widget.AppThemePreferenceWidget
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
internal class ThemeStep : OnboardingStep {
|
||||
|
||||
override val isComplete: Boolean = true
|
||||
|
||||
private val uiPreferences: UiPreferences = Injekt.get()
|
||||
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val context = LocalContext.current
|
||||
val uiPreferences = remember { context.appGraph.uiPreferences }
|
||||
val themeModePref = uiPreferences.themeMode
|
||||
val themeMode by themeModePref.collectAsState()
|
||||
|
||||
|
||||
+13
-16
@@ -25,13 +25,10 @@ import androidx.core.net.toUri
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.extension.interactor.TrustExtension
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.screen.advanced.ClearDatabaseScreen
|
||||
import eu.kanade.presentation.more.settings.screen.debug.DebugInfoScreen
|
||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
import eu.kanade.tachiyomi.data.library.MetadataUpdateJob
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||
import eu.kanade.tachiyomi.network.PREF_DOH_360
|
||||
import eu.kanade.tachiyomi.network.PREF_DOH_ADGUARD
|
||||
@@ -46,26 +43,24 @@ import eu.kanade.tachiyomi.network.PREF_DOH_QUAD101
|
||||
import eu.kanade.tachiyomi.network.PREF_DOH_QUAD9
|
||||
import eu.kanade.tachiyomi.network.PREF_DOH_SHECAN
|
||||
import eu.kanade.tachiyomi.ui.more.OnboardingScreen
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
||||
import eu.kanade.tachiyomi.util.system.isShizukuInstalled
|
||||
import eu.kanade.tachiyomi.util.system.powerManager
|
||||
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.appGraph
|
||||
import okhttp3.Headers
|
||||
import tachiyomi.core.common.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.common.util.lang.withUIContext
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.interactor.ResetViewerFlags
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
|
||||
object SettingsAdvancedScreen : SearchableSettings {
|
||||
@@ -80,9 +75,11 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val basePreferences = remember { Injekt.get<BasePreferences>() }
|
||||
val networkPreferences = remember { Injekt.get<NetworkPreferences>() }
|
||||
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
|
||||
val graph = remember { context.appGraph }
|
||||
val basePreferences = remember { graph.basePreferences }
|
||||
val networkPreferences = remember { graph.networkPreferences }
|
||||
val libraryPreferences = remember { graph.libraryPreferences }
|
||||
val crashLogUtil = remember { graph.crashLogUtil }
|
||||
|
||||
return listOf(
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
@@ -90,7 +87,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
subtitle = stringResource(MR.strings.pref_dump_crash_logs_summary),
|
||||
onClick = {
|
||||
scope.launch {
|
||||
CrashLogUtil(context).dumpLogs()
|
||||
crashLogUtil.dumpLogs()
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -180,7 +177,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_invalidate_download_cache),
|
||||
subtitle = stringResource(MR.strings.pref_invalidate_download_cache_summary),
|
||||
onClick = {
|
||||
Injekt.get<DownloadCache>().invalidateCache()
|
||||
context.appGraph.downloadCache.invalidateCache()
|
||||
context.toast(MR.strings.download_cache_invalidated)
|
||||
},
|
||||
),
|
||||
@@ -198,7 +195,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
networkPreferences: NetworkPreferences,
|
||||
): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val networkHelper = remember { Injekt.get<NetworkHelper>() }
|
||||
val networkHelper = remember { context.appGraph.networkHelper }
|
||||
|
||||
val userAgentPref = networkPreferences.defaultUserAgent
|
||||
val userAgent by userAgentPref.collectAsState()
|
||||
@@ -295,14 +292,14 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(MR.strings.pref_refresh_library_covers),
|
||||
onClick = { MetadataUpdateJob.startNow(context) },
|
||||
onClick = { MetadataUpdateJob.startNow(context.workManager) },
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(MR.strings.pref_reset_viewer_flags),
|
||||
subtitle = stringResource(MR.strings.pref_reset_viewer_flags_summary),
|
||||
onClick = {
|
||||
scope.launchNonCancellable {
|
||||
val success = Injekt.get<ResetViewerFlags>().await()
|
||||
val success = context.appGraph.resetViewerFlags.await()
|
||||
withUIContext {
|
||||
val message = if (success) {
|
||||
MR.strings.pref_reset_viewer_flags_success
|
||||
@@ -352,7 +349,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val extensionInstallerPref = basePreferences.extensionInstaller
|
||||
var shizukuMissing by rememberSaveable { mutableStateOf(false) }
|
||||
val trustExtension = remember { Injekt.get<TrustExtension>() }
|
||||
val trustExtension = remember { context.appGraph.trustExtension }
|
||||
|
||||
if (shizukuMissing) {
|
||||
val dismiss = { shizukuMissing = false }
|
||||
|
||||
+3
-3
@@ -22,11 +22,10 @@ import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toJavaLocalDateTime
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.time.Clock
|
||||
|
||||
object SettingsAppearanceScreen : SearchableSettings {
|
||||
@@ -37,7 +36,8 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
val uiPreferences = remember { Injekt.get<UiPreferences>() }
|
||||
val context = LocalContext.current
|
||||
val uiPreferences = remember { context.appGraph.uiPreferences }
|
||||
|
||||
return listOf(
|
||||
getThemeGroup(uiPreferences = uiPreferences),
|
||||
|
||||
+3
-6
@@ -9,17 +9,14 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.screen.browse.ExtensionStoresScreen
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
|
||||
import mihon.domain.extension.interactor.GetExtensionStoreCountAsFlow
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object SettingsBrowseScreen : SearchableSettings {
|
||||
|
||||
@@ -32,8 +29,8 @@ object SettingsBrowseScreen : SearchableSettings {
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val sourcePreferences = remember { Injekt.get<SourcePreferences>() }
|
||||
val getExtensionStoreCountAsFlow = remember { Injekt.get<GetExtensionStoreCountAsFlow>() }
|
||||
val sourcePreferences = remember { context.appGraph.sourcePreferences }
|
||||
val getExtensionStoreCountAsFlow = remember { context.appGraph.getExtensionStoreCountAsFlow }
|
||||
|
||||
val reposCount by getExtensionStoreCountAsFlow().collectAsState(0)
|
||||
|
||||
|
||||
+9
-11
@@ -51,30 +51,27 @@ import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
||||
import eu.kanade.presentation.util.relativeTimeSpanString
|
||||
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
import eu.kanade.tachiyomi.data.export.LibraryExporter
|
||||
import eu.kanade.tachiyomi.data.export.LibraryExporter.ExportOptions
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.storage.displayablePath
|
||||
import tachiyomi.core.common.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.common.util.lang.withUIContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.backup.service.BackupPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.interactor.GetFavorites
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.storage.service.StoragePreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.TextButton
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object SettingsDataScreen : SearchableSettings {
|
||||
|
||||
@@ -98,8 +95,9 @@ object SettingsDataScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||
val storagePreferences = Injekt.get<StoragePreferences>()
|
||||
val context = LocalContext.current
|
||||
val backupPreferences = remember { context.appGraph.backupPreferences }
|
||||
val storagePreferences = remember { context.appGraph.storagePreferences }
|
||||
|
||||
return listOf(
|
||||
getStorageLocationPref(storagePreferences = storagePreferences),
|
||||
@@ -230,7 +228,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
checked = false,
|
||||
onCheckedChange = {
|
||||
if (!BackupRestoreJob.isRunning(context)) {
|
||||
if (!BackupRestoreJob.isRunning(context.workManager)) {
|
||||
if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) {
|
||||
context.toast(MR.strings.restore_miui_warning)
|
||||
}
|
||||
@@ -279,9 +277,9 @@ object SettingsDataScreen : SearchableSettings {
|
||||
private fun getDataGroup(): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
|
||||
val libraryPreferences = remember { context.appGraph.libraryPreferences }
|
||||
|
||||
val chapterCache = remember { Injekt.get<ChapterCache>() }
|
||||
val chapterCache = remember { context.appGraph.chapterCache }
|
||||
var cacheReadableSizeSema by remember { mutableIntStateOf(0) }
|
||||
val cacheReadableSize = remember(cacheReadableSizeSema) { chapterCache.readableSize }
|
||||
|
||||
@@ -341,7 +339,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val getFavorites = remember { Injekt.get<GetFavorites>() }
|
||||
val getFavorites = remember { context.appGraph.getFavorites }
|
||||
var favorites by remember { mutableStateOf<List<Manga>>(emptyList()) }
|
||||
LaunchedEffect(Unit) {
|
||||
favorites = getFavorites.await()
|
||||
|
||||
+5
-5
@@ -8,19 +8,18 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import eu.kanade.presentation.category.visualName
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.widget.TriStateListDialog
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object SettingsDownloadScreen : SearchableSettings {
|
||||
|
||||
@@ -30,10 +29,11 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
val getCategories = remember { Injekt.get<GetCategories>() }
|
||||
val context = LocalContext.current
|
||||
val getCategories = remember { context.appGraph.getCategories }
|
||||
val allCategories by getCategories.subscribe().collectAsState(initial = emptyList())
|
||||
|
||||
val downloadPreferences = remember { Injekt.get<DownloadPreferences>() }
|
||||
val downloadPreferences = remember { context.appGraph.downloadPreferences }
|
||||
val parallelSourceLimit by downloadPreferences.parallelSourceLimit.collectAsState()
|
||||
val parallelPageLimit by downloadPreferences.parallelPageLimit.collectAsState()
|
||||
return listOf(
|
||||
|
||||
+9
-8
@@ -21,8 +21,7 @@ import eu.kanade.presentation.more.settings.widget.TriStateListDialog
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryScreen
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.interactor.ResetCategoryFlags
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.DEVICE_CHARGING
|
||||
@@ -38,8 +37,6 @@ import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object SettingsLibraryScreen : SearchableSettings {
|
||||
|
||||
@@ -49,8 +46,9 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
val getCategories = remember { Injekt.get<GetCategories>() }
|
||||
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
|
||||
val context = LocalContext.current
|
||||
val getCategories = remember { context.appGraph.getCategories }
|
||||
val libraryPreferences = remember { context.appGraph.libraryPreferences }
|
||||
val allCategories by getCategories.subscribe().collectAsState(initial = emptyList())
|
||||
|
||||
return listOf(
|
||||
@@ -66,6 +64,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
allCategories: List<Category>,
|
||||
libraryPreferences: LibraryPreferences,
|
||||
): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val userCategoriesCount = allCategories.filterNot(Category::isSystemCategory).size
|
||||
|
||||
@@ -98,7 +97,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
onValueChanged = {
|
||||
if (!it) {
|
||||
scope.launch {
|
||||
Injekt.get<ResetCategoryFlags>().await()
|
||||
context.appGraph.resetCategoryFlags.await()
|
||||
}
|
||||
}
|
||||
true
|
||||
@@ -172,7 +171,9 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
enabled = autoUpdateInterval > 0,
|
||||
onValueChanged = {
|
||||
// Post to event looper to allow the preference to be updated.
|
||||
ContextCompat.getMainExecutor(context).execute { LibraryUpdateJob.setupTask(context) }
|
||||
ContextCompat.getMainExecutor(context).execute {
|
||||
LibraryUpdateJob.setupTask(context)
|
||||
}
|
||||
true
|
||||
},
|
||||
),
|
||||
|
||||
+4
-3
@@ -4,18 +4,18 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.NumberFormat
|
||||
|
||||
object SettingsReaderScreen : SearchableSettings {
|
||||
@@ -26,7 +26,8 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
val readerPref = remember { Injekt.get<ReaderPreferences>() }
|
||||
val context = LocalContext.current
|
||||
val readerPref = remember { context.appGraph.readerPreferences }
|
||||
|
||||
return listOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
|
||||
+4
-4
@@ -12,13 +12,12 @@ import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported
|
||||
import eu.kanade.tachiyomi.util.system.telemetryIncluded
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object SettingsSecurityScreen : SearchableSettings {
|
||||
|
||||
@@ -28,8 +27,9 @@ object SettingsSecurityScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
val securityPreferences = remember { Injekt.get<SecurityPreferences>() }
|
||||
val privacyPreferences = remember { Injekt.get<PrivacyPreferences>() }
|
||||
val context = LocalContext.current
|
||||
val securityPreferences = remember { context.appGraph.securityPreferences }
|
||||
val privacyPreferences = remember { context.appGraph.privacyPreferences }
|
||||
return buildList(2) {
|
||||
add(getSecurityGroup(securityPreferences))
|
||||
if (!telemetryIncluded) return@buildList
|
||||
|
||||
+4
-8
@@ -44,11 +44,9 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.domain.track.model.AutoTrackState
|
||||
import eu.kanade.domain.track.service.TrackPreferences
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.anilist.AnilistApi
|
||||
import eu.kanade.tachiyomi.data.track.bangumi.BangumiApi
|
||||
import eu.kanade.tachiyomi.data.track.hikka.HikkaApi
|
||||
@@ -57,14 +55,12 @@ import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeListApi
|
||||
import eu.kanade.tachiyomi.data.track.shikimori.ShikimoriApi
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.core.common.util.lang.withUIContext
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object SettingsTrackingScreen : SearchableSettings {
|
||||
|
||||
@@ -86,9 +82,9 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
val context = LocalContext.current
|
||||
val trackPreferences = remember { Injekt.get<TrackPreferences>() }
|
||||
val trackerManager = remember { Injekt.get<TrackerManager>() }
|
||||
val sourceManager = remember { Injekt.get<SourceManager>() }
|
||||
val trackPreferences = remember { context.appGraph.trackPreferences }
|
||||
val trackerManager = remember { context.appGraph.trackerManager }
|
||||
val sourceManager = remember { context.appGraph.sourceManager }
|
||||
|
||||
var dialog by remember { mutableStateOf<Any?>(null) }
|
||||
dialog?.run {
|
||||
|
||||
@@ -30,10 +30,8 @@ import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
|
||||
import eu.kanade.presentation.util.LocalBackPress
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.data.updater.AppUpdateChecker
|
||||
import eu.kanade.tachiyomi.data.updater.RELEASE_URL
|
||||
import eu.kanade.tachiyomi.ui.more.NewUpdateScreen
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import eu.kanade.tachiyomi.util.lang.toDateTimestampString
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.isFossBuildType
|
||||
@@ -44,6 +42,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.Constants
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.lang.withUIContext
|
||||
@@ -74,6 +73,7 @@ object AboutScreen : Screen() {
|
||||
val handleBack = LocalBackPress.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
var isCheckingUpdates by remember { mutableStateOf(false) }
|
||||
val crashLogUtil = remember { context.appGraph.crashLogUtil }
|
||||
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
@@ -98,7 +98,7 @@ object AboutScreen : Screen() {
|
||||
title = stringResource(MR.strings.version),
|
||||
subtitle = getVersionName(withBuildDate = true),
|
||||
onPreferenceClick = {
|
||||
val deviceInfo = CrashLogUtil(context).getDebugInfo()
|
||||
val deviceInfo = crashLogUtil.getDebugInfo()
|
||||
context.copyToClipboard("Debug information", deviceInfo)
|
||||
},
|
||||
)
|
||||
@@ -217,7 +217,7 @@ object AboutScreen : Screen() {
|
||||
onAvailableUpdate: (GetApplicationRelease.Result.NewUpdate) -> Unit,
|
||||
onFinish: () -> Unit,
|
||||
) {
|
||||
val updateChecker = AppUpdateChecker()
|
||||
val updateChecker = context.appGraph.updateChecker
|
||||
withUIContext {
|
||||
try {
|
||||
when (val result = withIOContext { updateChecker.checkForUpdate(forceCheck = true) }) {
|
||||
@@ -279,7 +279,7 @@ object AboutScreen : Screen() {
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.toDateTimestampString(
|
||||
UiPreferences.dateFormat(
|
||||
Injekt.get<UiPreferences>().dateFormat.get(),
|
||||
Injekt.get<Context>().appGraph.uiPreferences.dateFormat.get(),
|
||||
),
|
||||
)
|
||||
} catch (_: Exception) {
|
||||
|
||||
+14
-8
@@ -32,9 +32,14 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesIntoMap
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.binding
|
||||
import dev.zacsweers.metrox.viewmodel.ViewModelKey
|
||||
import dev.zacsweers.metrox.viewmodel.metroViewModel
|
||||
import eu.kanade.presentation.browse.components.SourceIcon
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
@@ -60,8 +65,6 @@ import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
import tachiyomi.presentation.core.util.selectedBackground
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class ClearDatabaseScreen : Screen() {
|
||||
|
||||
@@ -69,7 +72,7 @@ class ClearDatabaseScreen : Screen() {
|
||||
override fun Content() {
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val viewModel = viewModel<ClearDatabaseViewModel>()
|
||||
val viewModel = metroViewModel<ClearDatabaseViewModel>()
|
||||
val state by viewModel.state.collectAsState()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
@@ -222,14 +225,17 @@ class ClearDatabaseScreen : Screen() {
|
||||
}
|
||||
}
|
||||
|
||||
class ClearDatabaseViewModel : ViewModel() {
|
||||
@Inject
|
||||
@ViewModelKey
|
||||
@ContributesIntoMap(AppScope::class, binding = binding<ViewModel>())
|
||||
class ClearDatabaseViewModel(
|
||||
private val database: Database,
|
||||
private val getSourcesWithNonLibraryManga: GetSourcesWithNonLibraryManga,
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<ClearDatabaseViewModel.State>
|
||||
field = MutableStateFlow<ClearDatabaseViewModel.State>(State.Loading)
|
||||
|
||||
private val getSourcesWithNonLibraryManga: GetSourcesWithNonLibraryManga = Injekt.get()
|
||||
private val database: Database = Injekt.get()
|
||||
|
||||
init {
|
||||
viewModelScope.launchIO {
|
||||
getSourcesWithNonLibraryManga.subscribe()
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import dev.zacsweers.metrox.viewmodel.metroViewModel
|
||||
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionStoreConfirmDialog
|
||||
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionStoreCreateDialog
|
||||
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionStoreDeleteDialog
|
||||
@@ -26,7 +27,7 @@ class ExtensionStoresScreen(
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val viewModel = viewModel<ExtensionStoresViewModel>()
|
||||
val viewModel = metroViewModel<ExtensionStoresViewModel>()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(url) {
|
||||
|
||||
+13
-7
@@ -3,6 +3,11 @@ package eu.kanade.presentation.more.settings.screen.browse
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesIntoMap
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.binding
|
||||
import dev.zacsweers.metrox.viewmodel.ViewModelKey
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -20,16 +25,17 @@ import mihon.domain.extension.interactor.RemoveExtensionStore
|
||||
import mihon.domain.extension.interactor.UpdateExtensionStores
|
||||
import mihon.domain.extension.model.ExtensionStore
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@Inject
|
||||
@ViewModelKey
|
||||
@ContributesIntoMap(AppScope::class, binding = binding<ViewModel>())
|
||||
class ExtensionStoresViewModel(
|
||||
private val getExtensionStores: GetExtensionStores = Injekt.get(),
|
||||
private val addExtensionStore: AddExtensionStore = Injekt.get(),
|
||||
private val removeExtensionStore: RemoveExtensionStore = Injekt.get(),
|
||||
private val updateExtensionStores: UpdateExtensionStores = Injekt.get(),
|
||||
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||
private val getExtensionStores: GetExtensionStores,
|
||||
private val addExtensionStore: AddExtensionStore,
|
||||
private val removeExtensionStore: RemoveExtensionStore,
|
||||
private val updateExtensionStores: UpdateExtensionStores,
|
||||
private val extensionManager: ExtensionManager,
|
||||
) : ViewModel() {
|
||||
|
||||
private val dialog = MutableStateFlow<ExtensionStoreDialog?>(null)
|
||||
|
||||
+11
-3
@@ -12,9 +12,14 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesIntoMap
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.binding
|
||||
import dev.zacsweers.metrox.viewmodel.ViewModelKey
|
||||
import dev.zacsweers.metrox.viewmodel.metroViewModel
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.WarningBanner
|
||||
import eu.kanade.presentation.util.Screen
|
||||
@@ -39,7 +44,7 @@ class CreateBackupScreen : Screen() {
|
||||
override fun Content() {
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val viewModel = viewModel<CreateBackupViewModel>()
|
||||
val viewModel = metroViewModel<CreateBackupViewModel>()
|
||||
val state by viewModel.state.collectAsState()
|
||||
|
||||
val chooseBackupDir = rememberLauncherForActivityResult(
|
||||
@@ -73,7 +78,7 @@ class CreateBackupScreen : Screen() {
|
||||
if (!BackupCreateJob.isManualJobRunning(context)) {
|
||||
try {
|
||||
chooseBackupDir.launch(BackupCreator.getFilename())
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
context.toast(MR.strings.file_picker_error)
|
||||
}
|
||||
} else {
|
||||
@@ -121,6 +126,9 @@ class CreateBackupScreen : Screen() {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
@ViewModelKey
|
||||
@ContributesIntoMap(AppScope::class, binding = binding<ViewModel>())
|
||||
class CreateBackupViewModel : ViewModel() {
|
||||
|
||||
val state: StateFlow<CreateBackupViewModel.State>
|
||||
|
||||
+21
-27
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.more.settings.screen.data
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -21,12 +20,16 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Assisted
|
||||
import dev.zacsweers.metro.AssistedFactory
|
||||
import dev.zacsweers.metro.AssistedInject
|
||||
import dev.zacsweers.metro.ContributesIntoMap
|
||||
import dev.zacsweers.metrox.viewmodel.ManualViewModelAssistedFactory
|
||||
import dev.zacsweers.metrox.viewmodel.ManualViewModelAssistedFactoryKey
|
||||
import dev.zacsweers.metrox.viewmodel.assistedMetroViewModel
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.WarningBanner
|
||||
import eu.kanade.presentation.util.Screen
|
||||
@@ -34,6 +37,7 @@ import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.backup.restore.RestoreOptions
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
@@ -44,8 +48,6 @@ import tachiyomi.presentation.core.components.SectionCard
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class RestoreBackupScreen(
|
||||
private val uri: String,
|
||||
@@ -54,12 +56,8 @@ class RestoreBackupScreen(
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val viewModel = viewModel<RestoreBackupViewModel>(
|
||||
factory = RestoreBackupViewModel.Factory,
|
||||
extras = CreationExtras {
|
||||
set(RestoreBackupViewModel.URI_KEY, uri)
|
||||
},
|
||||
)
|
||||
val viewModel =
|
||||
assistedMetroViewModel<RestoreBackupViewModel, RestoreBackupViewModel.Factory> { create(uri = uri) }
|
||||
val state by viewModel.state.collectAsState()
|
||||
|
||||
Scaffold(
|
||||
@@ -175,25 +173,21 @@ class RestoreBackupScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedInject
|
||||
class RestoreBackupViewModel(
|
||||
@Assisted private val uri: String,
|
||||
private val backupFileValidator: BackupFileValidator,
|
||||
private val context: Context,
|
||||
private val uri: String,
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<RestoreBackupViewModel.State>
|
||||
field = MutableStateFlow<RestoreBackupViewModel.State>(State())
|
||||
|
||||
companion object {
|
||||
val URI_KEY = CreationExtras.Key<String>()
|
||||
|
||||
val Factory = viewModelFactory {
|
||||
initializer {
|
||||
RestoreBackupViewModel(
|
||||
context = Injekt.get<Application>(),
|
||||
uri = get(URI_KEY)!!,
|
||||
)
|
||||
}
|
||||
}
|
||||
@AssistedFactory
|
||||
@ManualViewModelAssistedFactoryKey
|
||||
@ContributesIntoMap(AppScope::class)
|
||||
interface Factory : ManualViewModelAssistedFactory {
|
||||
fun create(uri: String): RestoreBackupViewModel
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -210,7 +204,7 @@ class RestoreBackupViewModel(
|
||||
|
||||
fun startRestore() {
|
||||
BackupRestoreJob.start(
|
||||
context = context,
|
||||
workManager = context.workManager,
|
||||
uri = uri.toUri(),
|
||||
options = state.value.options,
|
||||
)
|
||||
@@ -218,7 +212,7 @@ class RestoreBackupViewModel(
|
||||
|
||||
private fun validate(uri: Uri) {
|
||||
val results = try {
|
||||
BackupFileValidator(context).validate(uri)
|
||||
backupFileValidator.validate(uri)
|
||||
} catch (e: Exception) {
|
||||
setError(
|
||||
error = InvalidRestore(uri, e.message.toString()),
|
||||
|
||||
+2
-4
@@ -16,7 +16,6 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.profileinstaller.ProfileVerifier
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.PreferenceScaffold
|
||||
import eu.kanade.presentation.more.settings.screen.about.AboutScreen
|
||||
@@ -26,11 +25,10 @@ import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import kotlinx.coroutines.guava.await
|
||||
import kotlinx.coroutines.launch
|
||||
import mihon.app.di.appGraph
|
||||
import mihon.core.common.FeatureFlags
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class DebugInfoScreen : Screen() {
|
||||
|
||||
@@ -62,7 +60,7 @@ class DebugInfoScreen : Screen() {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val installationIdPref = remember { Injekt.get<BasePreferences>().installationId }
|
||||
val installationIdPref = remember { context.appGraph.basePreferences.installationId }
|
||||
val installationId by installationIdPref.collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
|
||||
+12
-18
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.more.settings.screen.debug
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
@@ -21,13 +20,15 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkQuery
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesIntoMap
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metrox.viewmodel.ViewModelKey
|
||||
import dev.zacsweers.metrox.viewmodel.metroViewModel
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
@@ -40,11 +41,11 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.time.Instant
|
||||
|
||||
@@ -59,7 +60,7 @@ class WorkerInfoScreen : Screen() {
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val viewModel = viewModel<WorkerInfoViewModel>(factory = WorkerInfoViewModel.Factory)
|
||||
val viewModel = metroViewModel<WorkerInfoViewModel>()
|
||||
val enqueued by viewModel.enqueued.collectAsState()
|
||||
val finished by viewModel.finished.collectAsState()
|
||||
val running by viewModel.running.collectAsState()
|
||||
@@ -120,20 +121,13 @@ class WorkerInfoScreen : Screen() {
|
||||
)
|
||||
}
|
||||
|
||||
@Inject
|
||||
@ViewModelKey
|
||||
@ContributesIntoMap(AppScope::class)
|
||||
class WorkerInfoViewModel(
|
||||
context: Context,
|
||||
private val context: Context,
|
||||
) : ViewModel() {
|
||||
|
||||
companion object {
|
||||
val Factory = viewModelFactory {
|
||||
initializer {
|
||||
WorkerInfoViewModel(
|
||||
context = Injekt.get<Application>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val workManager = context.workManager
|
||||
|
||||
val finished = workManager
|
||||
@@ -169,7 +163,7 @@ class WorkerInfoScreen : Screen() {
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.toDateTimestampString(
|
||||
UiPreferences.dateFormat(
|
||||
Injekt.get<UiPreferences>().dateFormat.get(),
|
||||
context.appGraph.uiPreferences.dateFormat.get(),
|
||||
),
|
||||
)
|
||||
appendLine("Next scheduled run: $timestamp")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.presentation.reader
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -13,6 +14,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import kotlinx.coroutines.delay
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@@ -22,7 +24,7 @@ import kotlin.time.Duration.Companion.milliseconds
|
||||
class DisplayRefreshHost {
|
||||
|
||||
internal var currentDisplayRefresh by mutableStateOf(false)
|
||||
private val readerPreferences = Injekt.get<ReaderPreferences>()
|
||||
private val readerPreferences = Injekt.get<Context>().appGraph.readerPreferences
|
||||
|
||||
internal val flashMillis = readerPreferences.flashDurationMillis
|
||||
internal val flashMode = readerPreferences.flashColor
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import eu.kanade.domain.manga.model.readerOrientation
|
||||
import eu.kanade.domain.manga.model.readingMode
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
@@ -16,6 +17,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsViewModel
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.webgpu.WebGpuViewer
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.CheckboxItem
|
||||
import tachiyomi.presentation.core.components.HeadingItem
|
||||
@@ -23,8 +25,6 @@ import tachiyomi.presentation.core.components.SettingsChipRow
|
||||
import tachiyomi.presentation.core.components.SliderItem
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.NumberFormat
|
||||
|
||||
@Composable
|
||||
@@ -43,7 +43,7 @@ internal fun ColumnScope.ReadingModePage(viewModel: ReaderSettingsViewModel) {
|
||||
}
|
||||
}
|
||||
|
||||
val default = Injekt.get<ReaderPreferences>().defaultReadingMode.get()
|
||||
val default = LocalContext.current.appGraph.readerPreferences.defaultReadingMode.get()
|
||||
val resolved = ReadingMode.fromPreference(
|
||||
when {
|
||||
readingMode == ReadingMode.DEFAULT -> default
|
||||
|
||||
@@ -7,7 +7,6 @@ import androidx.compose.material3.MaterialExpressiveTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.domain.ui.model.AppTheme
|
||||
import eu.kanade.presentation.theme.colorscheme.BaseColorScheme
|
||||
import eu.kanade.presentation.theme.colorscheme.CatppuccinColorScheme
|
||||
@@ -25,8 +24,7 @@ import eu.kanade.presentation.theme.colorscheme.TidalWaveColorScheme
|
||||
import eu.kanade.presentation.theme.colorscheme.TokyoNightColorScheme
|
||||
import eu.kanade.presentation.theme.colorscheme.YinYangColorScheme
|
||||
import eu.kanade.presentation.theme.colorscheme.YotsubaColorScheme
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import mihon.app.di.appGraph
|
||||
|
||||
@Composable
|
||||
fun TachiyomiTheme(
|
||||
@@ -34,7 +32,8 @@ fun TachiyomiTheme(
|
||||
amoled: Boolean? = null,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val uiPreferences = Injekt.get<UiPreferences>()
|
||||
val context = LocalContext.current
|
||||
val uiPreferences = remember { context.appGraph.uiPreferences }
|
||||
BaseTachiyomiTheme(
|
||||
appTheme = appTheme ?: uiPreferences.appTheme.get(),
|
||||
isAmoled = amoled ?: uiPreferences.themeDarkAmoled.get(),
|
||||
|
||||
@@ -22,21 +22,21 @@ import coil3.request.allowRgb565
|
||||
import coil3.request.crossfade
|
||||
import coil3.util.DebugLogger
|
||||
import dev.mihon.injekt.patchInjekt
|
||||
import eu.kanade.domain.DomainModule
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.createGraphFactory
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.domain.ui.model.setAppCompatDelegateThemeMode
|
||||
import eu.kanade.tachiyomi.core.security.PrivacyPreferences
|
||||
import eu.kanade.tachiyomi.crash.CrashActivity
|
||||
import eu.kanade.tachiyomi.crash.GlobalExceptionHandler
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.coil.BufferedSourceFetcher
|
||||
import eu.kanade.tachiyomi.data.coil.ImageDecoder
|
||||
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
|
||||
import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer
|
||||
import eu.kanade.tachiyomi.data.coil.MangaKeyer
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.di.AppModule
|
||||
import eu.kanade.tachiyomi.di.PreferenceModule
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
|
||||
@@ -44,6 +44,7 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
import eu.kanade.tachiyomi.util.system.animatorDurationScale
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.isDebugBuildType
|
||||
import eu.kanade.tachiyomi.util.system.notify
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
@@ -51,34 +52,68 @@ import kotlinx.coroutines.flow.onEach
|
||||
import logcat.AndroidLogcatLogger
|
||||
import logcat.LogPriority
|
||||
import logcat.LogcatLogger
|
||||
import mihon.app.di.AppGraph
|
||||
import mihon.app.di.injekt.MetroInteropModule
|
||||
import mihon.core.metro.GraphProvider
|
||||
import mihon.core.migration.Migration
|
||||
import mihon.core.migration.Migrator
|
||||
import mihon.core.migration.migrations.migrations
|
||||
import mihon.telemetry.TelemetryConfig
|
||||
import org.conscrypt.Conscrypt
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.widget.WidgetManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import uy.kohesive.injekt.api.addSingleton
|
||||
import java.security.Security
|
||||
|
||||
class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factory {
|
||||
class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factory, GraphProvider<AppGraph> {
|
||||
|
||||
private val basePreferences: BasePreferences by injectLazy()
|
||||
private val privacyPreferences: PrivacyPreferences by injectLazy()
|
||||
private val networkPreferences: NetworkPreferences by injectLazy()
|
||||
override val graph: AppGraph by lazy {
|
||||
createGraphFactory<AppGraph.Factory>().create(context = this, isDebugBuild = isDebugBuildType)
|
||||
}
|
||||
|
||||
@Inject private lateinit var preferenceStore: PreferenceStore
|
||||
|
||||
@Inject private lateinit var basePreferences: BasePreferences
|
||||
|
||||
@Inject private lateinit var privacyPreferences: PrivacyPreferences
|
||||
|
||||
@Inject private lateinit var networkPreferences: NetworkPreferences
|
||||
|
||||
@Inject private lateinit var uiPreferences: UiPreferences
|
||||
|
||||
@Inject private lateinit var coverCache: CoverCache
|
||||
|
||||
@Inject private lateinit var networkHelper: NetworkHelper
|
||||
|
||||
@Inject private lateinit var sourceManager: SourceManager
|
||||
|
||||
@Inject private lateinit var widgetManager: WidgetManager
|
||||
|
||||
@Inject private lateinit var injektMetroInteropModule: MetroInteropModule
|
||||
|
||||
@Inject private lateinit var migrations: Set<Migration>
|
||||
|
||||
private val disableIncognitoReceiver = DisableIncognitoReceiver()
|
||||
|
||||
@SuppressLint("LaunchActivityFromNotification")
|
||||
override fun onCreate() {
|
||||
super<Application>.onCreate()
|
||||
patchInjekt()
|
||||
|
||||
// Must run before the graph is built, since injecting dependencies initializes WebView and the
|
||||
// suffix can't be set once a provider exists in the process. Secondary processes die otherwise.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
val process = getProcessName()
|
||||
if (packageName != process) WebView.setDataDirectorySuffix(process)
|
||||
}
|
||||
|
||||
graph.inject(this)
|
||||
setupInjekt()
|
||||
|
||||
TelemetryConfig.init(applicationContext)
|
||||
|
||||
GlobalExceptionHandler.initialize(applicationContext, CrashActivity::class.java)
|
||||
@@ -88,16 +123,6 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
||||
}
|
||||
|
||||
// Avoid potential crashes
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
val process = getProcessName()
|
||||
if (packageName != process) WebView.setDataDirectorySuffix(process)
|
||||
}
|
||||
|
||||
Injekt.importModule(PreferenceModule(this))
|
||||
Injekt.importModule(AppModule(this))
|
||||
Injekt.importModule(DomainModule())
|
||||
|
||||
setupNotificationChannels()
|
||||
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
|
||||
@@ -143,10 +168,10 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
.onEach(TelemetryConfig::setCrashlyticsEnabled)
|
||||
.launchIn(scope)
|
||||
|
||||
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode.get())
|
||||
setAppCompatDelegateThemeMode(uiPreferences.themeMode.get())
|
||||
|
||||
// Updates widget update
|
||||
WidgetManager(Injekt.get(), Injekt.get()).apply { init(scope) }
|
||||
widgetManager.init(scope)
|
||||
|
||||
if (!LogcatLogger.isInstalled) {
|
||||
val minLogPriority = when {
|
||||
@@ -161,14 +186,22 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
initializeMigrator()
|
||||
}
|
||||
|
||||
private fun setupInjekt() {
|
||||
patchInjekt()
|
||||
Injekt.addSingleton<Application>(this)
|
||||
Injekt.addSingleton<Context>(this)
|
||||
Injekt.importModule(injektMetroInteropModule)
|
||||
}
|
||||
|
||||
private fun initializeMigrator() {
|
||||
val preferenceStore = Injekt.get<PreferenceStore>()
|
||||
val preference = preferenceStore.getInt(Preference.appStateKey("last_version_code"), 0)
|
||||
logcat { "Migration from ${preference.get()} to ${BuildConfig.VERSION_CODE}" }
|
||||
logcat {
|
||||
"Migration from ${preference.get()} to ${BuildConfig.VERSION_CODE} with ${migrations.size} migration(s)"
|
||||
}
|
||||
Migrator.initialize(
|
||||
old = preference.get(),
|
||||
new = BuildConfig.VERSION_CODE,
|
||||
migrations = migrations,
|
||||
migrations = migrations.toList(),
|
||||
onMigrationComplete = {
|
||||
logcat { "Updating last version to ${BuildConfig.VERSION_CODE}" }
|
||||
preference.set(BuildConfig.VERSION_CODE)
|
||||
@@ -178,7 +211,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
|
||||
override fun newImageLoader(context: Context): ImageLoader {
|
||||
return ImageLoader.Builder(this).apply {
|
||||
val callFactoryLazy = lazy { Injekt.get<NetworkHelper>().client }
|
||||
val callFactoryLazy = lazy { networkHelper.client }
|
||||
components {
|
||||
// NetworkFetcher.Factory
|
||||
add(OkHttpNetworkFetcherFactory(callFactoryLazy::value))
|
||||
@@ -186,10 +219,10 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
add(ImageDecoder.Factory())
|
||||
// Fetcher.Factory
|
||||
add(BufferedSourceFetcher.Factory())
|
||||
add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy))
|
||||
add(MangaCoverFetcher.MangaFactory(callFactoryLazy))
|
||||
add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy, coverCache, sourceManager))
|
||||
add(MangaCoverFetcher.MangaFactory(callFactoryLazy, coverCache, sourceManager))
|
||||
// Keyer
|
||||
add(MangaCoverKeyer())
|
||||
add(MangaCoverKeyer(coverCache))
|
||||
add(MangaKeyer())
|
||||
}
|
||||
|
||||
@@ -211,11 +244,11 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
}
|
||||
|
||||
override fun onStart(owner: LifecycleOwner) {
|
||||
SecureActivityDelegate.onApplicationStart()
|
||||
SecureActivityDelegate.onApplicationStart(this)
|
||||
}
|
||||
|
||||
override fun onStop(owner: LifecycleOwner) {
|
||||
SecureActivityDelegate.onApplicationStopped()
|
||||
SecureActivityDelegate.onApplicationStopped(this)
|
||||
}
|
||||
|
||||
override fun getPackageName(): String {
|
||||
|
||||
@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.backup
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
@@ -10,13 +11,12 @@ import okio.gzip
|
||||
import okio.source
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.IOException
|
||||
|
||||
@Inject
|
||||
class BackupDecoder(
|
||||
private val context: Context,
|
||||
private val parser: ProtoBuf = Injekt.get(),
|
||||
private val parser: ProtoBuf,
|
||||
) {
|
||||
/**
|
||||
* Decode a potentially-gzipped backup.
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package eu.kanade.tachiyomi.data.backup
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class BackupFileValidator(
|
||||
private val context: Context,
|
||||
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
private val sourceManager: SourceManager,
|
||||
private val trackerManager: TrackerManager,
|
||||
private val backupDecoder: BackupDecoder,
|
||||
) {
|
||||
|
||||
/**
|
||||
@@ -21,7 +19,7 @@ class BackupFileValidator(
|
||||
*/
|
||||
fun validate(uri: Uri): Results {
|
||||
val backup = try {
|
||||
BackupDecoder(context).decode(uri)
|
||||
backupDecoder.decode(uri)
|
||||
} catch (e: Exception) {
|
||||
throw IllegalStateException(e)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||
@@ -16,14 +17,14 @@ import tachiyomi.core.common.i18n.pluralStringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.storage.displayablePath
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class BackupNotifier(private val context: Context) {
|
||||
|
||||
private val preferences: SecurityPreferences by injectLazy()
|
||||
|
||||
@Inject
|
||||
class BackupNotifier(
|
||||
private val context: Context,
|
||||
private val preferences: SecurityPreferences,
|
||||
) {
|
||||
private val progressNotificationBuilder = context.notificationBuilder(
|
||||
Notifications.CHANNEL_BACKUP_RESTORE_PROGRESS,
|
||||
) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.BackupNotifier
|
||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
@@ -24,22 +25,33 @@ import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.AppGraph
|
||||
import mihon.app.di.appGraph
|
||||
import mihon.core.metro.metroGraph
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.backup.service.BackupPreferences
|
||||
import tachiyomi.domain.storage.service.StorageManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class BackupCreateJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val notifier = BackupNotifier(context)
|
||||
private val graph: AppGraph = context.metroGraph()
|
||||
|
||||
@Inject
|
||||
private lateinit var backupCreatorFactory: BackupCreator.Factory
|
||||
|
||||
@Inject
|
||||
private lateinit var storageManager: StorageManager
|
||||
|
||||
@Inject private lateinit var notifier: BackupNotifier
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
graph.inject(this)
|
||||
|
||||
val isAutoBackup = inputData.getBoolean(IS_AUTO_BACKUP_KEY, true)
|
||||
|
||||
if (isAutoBackup && BackupRestoreJob.isRunning(context)) return Result.retry()
|
||||
if (isAutoBackup && BackupRestoreJob.isRunning(context.workManager)) return Result.retry()
|
||||
|
||||
val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
|
||||
?: getAutomaticBackupLocation()
|
||||
@@ -51,7 +63,7 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
|
||||
?: BackupOptions()
|
||||
|
||||
return try {
|
||||
val location = BackupCreator(context, isAutoBackup).backup(uri, options)
|
||||
val location = backupCreatorFactory.create(isAutoBackup = isAutoBackup).backup(uri, options)
|
||||
if (!isAutoBackup) {
|
||||
notifier.showBackupComplete(UniFile.fromUri(context, location.toUri())!!)
|
||||
}
|
||||
@@ -78,7 +90,6 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
|
||||
}
|
||||
|
||||
private fun getAutomaticBackupLocation(): Uri? {
|
||||
val storageManager = Injekt.get<StorageManager>()
|
||||
return storageManager.getAutomaticBackupsDirectory()?.uri
|
||||
}
|
||||
|
||||
@@ -88,7 +99,7 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
|
||||
}
|
||||
|
||||
fun setupTask(context: Context, prefInterval: Int? = null) {
|
||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||
val backupPreferences = context.appGraph.backupPreferences
|
||||
val interval = prefInterval ?: backupPreferences.backupInterval.get()
|
||||
if (interval > 0) {
|
||||
val constraints = Constraints(
|
||||
|
||||
@@ -3,6 +3,9 @@ package eu.kanade.tachiyomi.data.backup.create
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.zacsweers.metro.Assisted
|
||||
import dev.zacsweers.metro.AssistedFactory
|
||||
import dev.zacsweers.metro.AssistedInject
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||
import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator
|
||||
@@ -29,29 +32,31 @@ import tachiyomi.domain.manga.interactor.GetFavorites
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.repository.MangaRepository
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.FileOutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import kotlin.time.Clock
|
||||
|
||||
@AssistedInject
|
||||
class BackupCreator(
|
||||
@Assisted private val isAutoBackup: Boolean,
|
||||
private val context: Context,
|
||||
private val isAutoBackup: Boolean,
|
||||
|
||||
private val parser: ProtoBuf = Injekt.get(),
|
||||
private val getFavorites: GetFavorites = Injekt.get(),
|
||||
private val backupPreferences: BackupPreferences = Injekt.get(),
|
||||
private val mangaRepository: MangaRepository = Injekt.get(),
|
||||
|
||||
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
|
||||
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
|
||||
private val preferenceBackupCreator: PreferenceBackupCreator = PreferenceBackupCreator(),
|
||||
private val extensionStoresBackupCreator: ExtensionStoresBackupCreator = ExtensionStoresBackupCreator(),
|
||||
private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(),
|
||||
private val parser: ProtoBuf,
|
||||
private val getFavorites: GetFavorites,
|
||||
private val backupPreferences: BackupPreferences,
|
||||
private val mangaRepository: MangaRepository,
|
||||
private val categoriesBackupCreator: CategoriesBackupCreator,
|
||||
private val mangaBackupCreator: MangaBackupCreator,
|
||||
private val preferenceBackupCreator: PreferenceBackupCreator,
|
||||
private val extensionStoresBackupCreator: ExtensionStoresBackupCreator,
|
||||
private val sourcesBackupCreator: SourcesBackupCreator,
|
||||
private val backupFileValidator: BackupFileValidator,
|
||||
) {
|
||||
@AssistedFactory
|
||||
fun interface Factory {
|
||||
fun create(isAutoBackup: Boolean): BackupCreator
|
||||
}
|
||||
|
||||
suspend fun backup(uri: Uri, options: BackupOptions): String {
|
||||
var file: UniFile? = null
|
||||
@@ -105,7 +110,7 @@ class BackupCreator(
|
||||
val fileUri = file.uri
|
||||
|
||||
// Make sure it's a valid backup file
|
||||
BackupFileValidator(context).validate(fileUri)
|
||||
backupFileValidator.validate(fileUri)
|
||||
|
||||
if (isAutoBackup) {
|
||||
backupPreferences.lastAutoBackupTimestamp.set(Clock.System.now().toEpochMilliseconds())
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||
import eu.kanade.tachiyomi.data.backup.models.backupCategoryMapper
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class CategoriesBackupCreator(
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val getCategories: GetCategories,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(): List<BackupCategory> {
|
||||
|
||||
+3
-3
@@ -1,13 +1,13 @@
|
||||
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionStore
|
||||
import eu.kanade.tachiyomi.data.backup.models.backupExtensionStoreMapper
|
||||
import mihon.domain.extension.interactor.GetExtensionStores
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class ExtensionStoresBackupCreator(
|
||||
private val getExtensionStores: GetExtensionStores = Injekt.get(),
|
||||
private val getExtensionStores: GetExtensionStores,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(): List<BackupExtensionStore> {
|
||||
|
||||
+5
-5
@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.backup.create.creators
|
||||
|
||||
import app.cash.sqldelight.async.coroutines.awaitAsList
|
||||
import app.cash.sqldelight.async.coroutines.awaitAsOne
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.create.BackupOptions
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupChapter
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
||||
@@ -14,13 +15,12 @@ import tachiyomi.data.MemoColumnAdapter
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.history.interactor.GetHistory
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class MangaBackupCreator(
|
||||
private val database: Database = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val getHistory: GetHistory = Injekt.get(),
|
||||
private val database: Database,
|
||||
private val getCategories: GetCategories,
|
||||
private val getHistory: GetHistory,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
||||
|
||||
+4
-4
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
||||
import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue
|
||||
@@ -14,12 +15,11 @@ import eu.kanade.tachiyomi.source.sourcePreferences
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class PreferenceBackupCreator(
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val preferenceStore: PreferenceStore = Injekt.get(),
|
||||
private val sourceManager: SourceManager,
|
||||
private val preferenceStore: PreferenceStore,
|
||||
) {
|
||||
|
||||
fun createApp(includePrivatePreferences: Boolean): List<BackupPreference> {
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class SourcesBackupCreator(
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val sourceManager: SourceManager,
|
||||
) {
|
||||
|
||||
operator fun invoke(mangas: List<BackupManga>): List<BackupSource> {
|
||||
|
||||
@@ -9,16 +9,19 @@ import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.BackupNotifier
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.AppGraph
|
||||
import mihon.core.metro.metroGraph
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.i18n.MR
|
||||
@@ -26,9 +29,15 @@ import tachiyomi.i18n.MR
|
||||
class BackupRestoreJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val notifier = BackupNotifier(context)
|
||||
private val graph: AppGraph = context.metroGraph()
|
||||
|
||||
@Inject private lateinit var backupRestorerFactory: BackupRestorer.Factory
|
||||
|
||||
@Inject private lateinit var notifier: BackupNotifier
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
graph.inject(this)
|
||||
|
||||
val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
|
||||
val options = inputData.getBooleanArray(OPTIONS_KEY)?.let { RestoreOptions.fromBooleanArray(it) }
|
||||
|
||||
@@ -41,7 +50,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
setForegroundSafely()
|
||||
|
||||
return try {
|
||||
BackupRestorer(context, notifier, isSync).restore(uri, options)
|
||||
backupRestorerFactory.create(notifier = notifier, isSync = isSync).restore(uri, options)
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) {
|
||||
@@ -70,12 +79,12 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun isRunning(context: Context): Boolean {
|
||||
return context.workManager.isRunning(TAG)
|
||||
fun isRunning(workManager: WorkManager): Boolean {
|
||||
return workManager.isRunning(TAG)
|
||||
}
|
||||
|
||||
fun start(
|
||||
context: Context,
|
||||
workManager: WorkManager,
|
||||
uri: Uri,
|
||||
options: RestoreOptions,
|
||||
sync: Boolean = false,
|
||||
@@ -89,11 +98,11 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
.addTag(TAG)
|
||||
.setInputData(inputData)
|
||||
.build()
|
||||
context.workManager.enqueueUniqueWork(TAG, ExistingWorkPolicy.KEEP, request)
|
||||
workManager.enqueueUniqueWork(TAG, ExistingWorkPolicy.KEEP, request)
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
context.workManager.cancelUniqueWork(TAG)
|
||||
fun stop(workManager: WorkManager) {
|
||||
workManager.cancelUniqueWork(TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.data.backup.restore
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import dev.zacsweers.metro.Assisted
|
||||
import dev.zacsweers.metro.AssistedFactory
|
||||
import dev.zacsweers.metro.AssistedInject
|
||||
import eu.kanade.tachiyomi.data.backup.BackupDecoder
|
||||
import eu.kanade.tachiyomi.data.backup.BackupNotifier
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||
@@ -24,8 +27,6 @@ import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.data.Database
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
@@ -36,18 +37,25 @@ import kotlin.concurrent.atomics.ExperimentalAtomicApi
|
||||
import kotlin.concurrent.atomics.incrementAndFetch
|
||||
|
||||
@OptIn(ExperimentalAtomicApi::class)
|
||||
@AssistedInject
|
||||
class BackupRestorer(
|
||||
@Assisted private val notifier: BackupNotifier,
|
||||
@Assisted private val isSync: Boolean,
|
||||
private val context: Context,
|
||||
private val notifier: BackupNotifier,
|
||||
private val isSync: Boolean,
|
||||
|
||||
private val database: Database = Injekt.get(),
|
||||
private val categoriesRestorer: CategoriesRestorer = CategoriesRestorer(),
|
||||
private val preferenceRestorer: PreferenceRestorer = PreferenceRestorer(context),
|
||||
private val extensionStoreRestorer: ExtensionStoreRestorer = ExtensionStoreRestorer(),
|
||||
private val mangaRestorer: MangaRestorer = MangaRestorer(),
|
||||
private val database: Database,
|
||||
private val downloadCache: DownloadCache,
|
||||
private val categoriesRestorer: CategoriesRestorer,
|
||||
private val preferenceRestorer: PreferenceRestorer,
|
||||
private val extensionStoreRestorer: ExtensionStoreRestorer,
|
||||
private val mangaRestorer: MangaRestorer,
|
||||
private val backupDecoder: BackupDecoder,
|
||||
) {
|
||||
|
||||
@AssistedFactory
|
||||
fun interface Factory {
|
||||
fun create(notifier: BackupNotifier, isSync: Boolean): BackupRestorer
|
||||
}
|
||||
|
||||
private var restoreAmount = 0
|
||||
private val restoreProgress = AtomicInt(0)
|
||||
private val errors = CopyOnWriteArrayList<Pair<Date, String>>()
|
||||
@@ -65,7 +73,7 @@ class BackupRestorer(
|
||||
// Invalidate download cache to ensure UI reflects any restored downloads
|
||||
if (options.libraryEntries) {
|
||||
try {
|
||||
Injekt.get<DownloadCache>().invalidateCache()
|
||||
downloadCache.invalidateCache()
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e) { "Failed to invalidate download cache after restore" }
|
||||
}
|
||||
@@ -85,7 +93,7 @@ class BackupRestorer(
|
||||
}
|
||||
|
||||
private suspend fun restoreFromFile(uri: Uri, options: RestoreOptions) {
|
||||
val backup = BackupDecoder(context).decode(uri)
|
||||
val backup = backupDecoder.decode(uri)
|
||||
|
||||
// Store source mapping for error messages
|
||||
val backupMaps = backup.backupSources
|
||||
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||
import tachiyomi.data.Database
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class CategoriesRestorer(
|
||||
private val database: Database = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||
private val database: Database,
|
||||
private val getCategories: GetCategories,
|
||||
private val libraryPreferences: LibraryPreferences,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(backupCategories: List<BackupCategory>) {
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionStore
|
||||
import tachiyomi.data.Database
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class ExtensionStoreRestorer(
|
||||
private val database: Database = Injekt.get(),
|
||||
private val database: Database,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
|
||||
+10
-10
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||
import app.cash.sqldelight.async.coroutines.awaitAsList
|
||||
import app.cash.sqldelight.async.coroutines.awaitAsOne
|
||||
import app.cash.sqldelight.async.coroutines.awaitAsOneOrNull
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupChapter
|
||||
@@ -23,21 +24,20 @@ import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import tachiyomi.domain.track.interactor.InsertTrack
|
||||
import tachiyomi.domain.track.model.Track
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
import kotlin.math.max
|
||||
import kotlin.time.Clock
|
||||
|
||||
@Inject
|
||||
class MangaRestorer(
|
||||
private val database: Database = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val getMangaByUrlAndSourceId: GetMangaByUrlAndSourceId = Injekt.get(),
|
||||
private val getChaptersByMangaId: GetChaptersByMangaId = Injekt.get(),
|
||||
private val updateManga: UpdateManga = Injekt.get(),
|
||||
private val getTracks: GetTracks = Injekt.get(),
|
||||
private val insertTrack: InsertTrack = Injekt.get(),
|
||||
fetchInterval: FetchInterval = Injekt.get(),
|
||||
private val database: Database,
|
||||
private val getCategories: GetCategories,
|
||||
private val getMangaByUrlAndSourceId: GetMangaByUrlAndSourceId,
|
||||
private val getChaptersByMangaId: GetChaptersByMangaId,
|
||||
private val updateManga: UpdateManga,
|
||||
private val getTracks: GetTracks,
|
||||
private val insertTrack: InsertTrack,
|
||||
fetchInterval: FetchInterval,
|
||||
) {
|
||||
|
||||
private val timeZone = TimeZone.currentSystemDefault()
|
||||
|
||||
+5
-5
@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||
@@ -21,13 +22,12 @@ import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@Inject
|
||||
class PreferenceRestorer(
|
||||
private val context: Context,
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val preferenceStore: PreferenceStore = Injekt.get(),
|
||||
private val getCategories: GetCategories,
|
||||
private val preferenceStore: PreferenceStore,
|
||||
) {
|
||||
suspend fun restoreApp(
|
||||
preferences: List<BackupPreference>,
|
||||
@@ -45,7 +45,7 @@ class PreferenceRestorer(
|
||||
|
||||
suspend fun restoreSource(preferences: List<BackupSourcePreferences>) {
|
||||
preferences.forEach {
|
||||
val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey))
|
||||
val sourcePrefs = AndroidPreferenceStore(sourcePreferences(it.sourceKey))
|
||||
restorePreferences(it.prefs, sourcePrefs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ package eu.kanade.tachiyomi.data.cache
|
||||
import android.content.Context
|
||||
import android.text.format.Formatter
|
||||
import com.jakewharton.disklrucache.DiskLruCache
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||
@@ -24,6 +27,8 @@ import java.io.IOException
|
||||
*
|
||||
* @param context the application context.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class ChapterCache(
|
||||
private val context: Context,
|
||||
private val json: Json,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package eu.kanade.tachiyomi.data.cache
|
||||
|
||||
import android.content.Context
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import java.io.File
|
||||
@@ -15,6 +18,8 @@ import java.io.InputStream
|
||||
* @param context the application context.
|
||||
* @constructor creates an instance of the cover cache.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class CoverCache(private val context: Context) {
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -31,7 +31,6 @@ import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.MangaCover
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
@@ -299,11 +298,10 @@ class MangaCoverFetcher(
|
||||
|
||||
class MangaFactory(
|
||||
private val callFactoryLazy: Lazy<Call.Factory>,
|
||||
private val coverCache: CoverCache,
|
||||
private val sourceManager: SourceManager,
|
||||
) : Fetcher.Factory<Manga> {
|
||||
|
||||
private val coverCache: CoverCache by injectLazy()
|
||||
private val sourceManager: SourceManager by injectLazy()
|
||||
|
||||
override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher {
|
||||
return MangaCoverFetcher(
|
||||
url = data.thumbnailUrl,
|
||||
@@ -321,11 +319,10 @@ class MangaCoverFetcher(
|
||||
|
||||
class MangaCoverFactory(
|
||||
private val callFactoryLazy: Lazy<Call.Factory>,
|
||||
private val coverCache: CoverCache,
|
||||
private val sourceManager: SourceManager,
|
||||
) : Fetcher.Factory<MangaCover> {
|
||||
|
||||
private val coverCache: CoverCache by injectLazy()
|
||||
private val sourceManager: SourceManager by injectLazy()
|
||||
|
||||
override fun create(data: MangaCover, options: Options, imageLoader: ImageLoader): Fetcher {
|
||||
return MangaCoverFetcher(
|
||||
url = data.url,
|
||||
|
||||
@@ -5,8 +5,6 @@ import coil3.request.Options
|
||||
import eu.kanade.domain.manga.model.hasCustomCover
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import tachiyomi.domain.manga.model.MangaCover
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import tachiyomi.domain.manga.model.Manga as DomainManga
|
||||
|
||||
class MangaKeyer : Keyer<DomainManga> {
|
||||
@@ -20,7 +18,7 @@ class MangaKeyer : Keyer<DomainManga> {
|
||||
}
|
||||
|
||||
class MangaCoverKeyer(
|
||||
private val coverCache: CoverCache = Injekt.get(),
|
||||
private val coverCache: CoverCache,
|
||||
) : Keyer<MangaCover> {
|
||||
override fun key(data: MangaCover, options: Options): String {
|
||||
return if (coverCache.getCustomCoverFile(data.mangaId).exists()) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.core.net.toUri
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -61,12 +63,14 @@ import kotlin.time.Duration.Companion.seconds
|
||||
* defined in [renewInterval] as we don't have any control over the filesystem and the user can
|
||||
* delete the folders at any time without the app noticing.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class DownloadCache(
|
||||
private val context: Context,
|
||||
private val provider: DownloadProvider = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||
private val storageManager: StorageManager = Injekt.get(),
|
||||
private val provider: DownloadProvider,
|
||||
private val sourceManager: SourceManager,
|
||||
private val extensionManager: ExtensionManager,
|
||||
private val storageManager: StorageManager,
|
||||
) {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
@@ -492,7 +496,7 @@ private object UniFileAsStringSerializer : KSerializer<UniFile?> {
|
||||
|
||||
override fun deserialize(decoder: Decoder): UniFile? {
|
||||
return if (decoder.decodeNotNullMark()) {
|
||||
UniFile.fromUri(Injekt.get<Application>(), decoder.decodeString().toUri())
|
||||
UniFile.fromUri(Injekt.get<Context>(), decoder.decodeString().toUri())
|
||||
} else {
|
||||
decoder.decodeNull()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.NetworkState
|
||||
@@ -24,9 +25,9 @@ import kotlinx.coroutines.flow.combineTransform
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import mihon.app.di.AppGraph
|
||||
import mihon.core.metro.metroGraph
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
/**
|
||||
* This worker is used to manage the downloader. The system can decide to stop the worker, in
|
||||
@@ -34,8 +35,15 @@ import uy.kohesive.injekt.api.get
|
||||
*/
|
||||
class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val downloadManager: DownloadManager = Injekt.get()
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get()
|
||||
private val graph: AppGraph = context.metroGraph()
|
||||
|
||||
@Inject private lateinit var downloadManager: DownloadManager
|
||||
|
||||
@Inject private lateinit var downloadPreferences: DownloadPreferences
|
||||
|
||||
init {
|
||||
graph.inject(this)
|
||||
}
|
||||
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
val notification = applicationContext.notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.content.Context
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.drop
|
||||
@@ -20,41 +24,37 @@ import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.chapter.interactor.GetChapter
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.domain.manga.interactor.GetManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
/**
|
||||
* This class is used to manage chapter downloads in the application. It must be instantiated once
|
||||
* and retrieved through dependency injection. You can use this class to queue new chapters or query
|
||||
* downloaded chapters.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class DownloadManager(
|
||||
private val context: Context,
|
||||
private val provider: DownloadProvider = Injekt.get(),
|
||||
private val cache: DownloadCache = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
||||
private val provider: DownloadProvider,
|
||||
private val cache: DownloadCache,
|
||||
private val getCategories: GetCategories,
|
||||
private val getManga: GetManga,
|
||||
private val getChapter: GetChapter,
|
||||
private val sourceManager: SourceManager,
|
||||
private val downloadPreferences: DownloadPreferences,
|
||||
private val downloader: Downloader,
|
||||
private val pendingDeleter: DownloadPendingDeleter,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Downloader whose only task is to download chapters.
|
||||
*/
|
||||
private val downloader = Downloader(context, provider, cache)
|
||||
|
||||
val isRunning: Boolean
|
||||
get() = downloader.isRunning
|
||||
|
||||
/**
|
||||
* Queue to delay the deletion of a list of chapters until triggered.
|
||||
*/
|
||||
private val pendingDeleter = DownloadPendingDeleter(context)
|
||||
|
||||
val queueState
|
||||
get() = downloader.queueState
|
||||
|
||||
@@ -107,7 +107,7 @@ class DownloadManager(
|
||||
fun startDownloadNow(chapterId: Long) {
|
||||
val existingDownload = getQueuedDownloadOrNull(chapterId)
|
||||
// If not in queue try to start a new download
|
||||
val toAdd = existingDownload ?: runBlocking { Download.fromChapterId(chapterId) } ?: return
|
||||
val toAdd = existingDownload ?: runBlocking { downloadFromChapterId(chapterId) } ?: return
|
||||
queueState.value.toMutableList().apply {
|
||||
existingDownload?.let { remove(it) }
|
||||
add(0, toAdd)
|
||||
@@ -116,6 +116,14 @@ class DownloadManager(
|
||||
startDownloads()
|
||||
}
|
||||
|
||||
private suspend fun downloadFromChapterId(chapterId: Long): Download? {
|
||||
val chapter = getChapter.await(chapterId) ?: return null
|
||||
val manga = getManga.await(chapter.mangaId) ?: return null
|
||||
val source = sourceManager.get(manga.source) as? HttpSource ?: return null
|
||||
|
||||
return Download(source, manga, chapter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorders the download queue.
|
||||
*
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.core.app.NotificationCompat
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
@@ -16,7 +17,6 @@ import eu.kanade.tachiyomi.util.system.notificationBuilder
|
||||
import eu.kanade.tachiyomi.util.system.notify
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
@@ -24,9 +24,11 @@ import java.util.regex.Pattern
|
||||
*
|
||||
* @param context context of application
|
||||
*/
|
||||
internal class DownloadNotifier(private val context: Context) {
|
||||
|
||||
private val preferences: SecurityPreferences by injectLazy()
|
||||
@Inject
|
||||
class DownloadNotifier(
|
||||
private val context: Context,
|
||||
private val preferences: SecurityPreferences,
|
||||
) {
|
||||
|
||||
private val progressNotificationBuilder by lazy {
|
||||
context.notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
|
||||
|
||||
@@ -2,21 +2,24 @@ package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
/**
|
||||
* Class used to keep a list of chapters for future deletion.
|
||||
*
|
||||
* @param context the application context.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class DownloadPendingDeleter(
|
||||
context: Context,
|
||||
private val json: Json = Injekt.get(),
|
||||
private val json: Json,
|
||||
) {
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.content.Context
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.util.lang.Hash.md5
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
@@ -14,8 +17,6 @@ import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.storage.service.StorageManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
@@ -24,10 +25,12 @@ import java.io.IOException
|
||||
*
|
||||
* @param context the application context.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class DownloadProvider(
|
||||
private val context: Context,
|
||||
private val storageManager: StorageManager = Injekt.get(),
|
||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||
private val storageManager: StorageManager,
|
||||
private val libraryPreferences: LibraryPreferences,
|
||||
) {
|
||||
|
||||
private val downloadsDir: UniFile?
|
||||
|
||||
@@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.coroutines.runBlocking
|
||||
@@ -11,18 +14,18 @@ import tachiyomi.domain.chapter.interactor.GetChapter
|
||||
import tachiyomi.domain.manga.interactor.GetManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
/**
|
||||
* This class is used to persist active downloads across application restarts.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class DownloadStore(
|
||||
context: Context,
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val json: Json = Injekt.get(),
|
||||
private val getManga: GetManga = Injekt.get(),
|
||||
private val getChapter: GetChapter = Injekt.get(),
|
||||
private val sourceManager: SourceManager,
|
||||
private val json: Json,
|
||||
private val getManga: GetManga,
|
||||
private val getChapter: GetChapter,
|
||||
) {
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.content.Context
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.domain.chapter.model.toSChapter
|
||||
import eu.kanade.domain.manga.model.getComicInfo
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
@@ -57,8 +60,6 @@ import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -68,34 +69,27 @@ import kotlin.time.Duration.Companion.seconds
|
||||
*
|
||||
* Its queue contains the list of chapters to download.
|
||||
*/
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class Downloader(
|
||||
private val context: Context,
|
||||
private val provider: DownloadProvider,
|
||||
private val cache: DownloadCache,
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val chapterCache: ChapterCache = Injekt.get(),
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
||||
private val xml: XML = Injekt.get(),
|
||||
private val getCategories: GetCategories = Injekt.get(),
|
||||
private val getTracks: GetTracks = Injekt.get(),
|
||||
private val sourceManager: SourceManager,
|
||||
private val chapterCache: ChapterCache,
|
||||
private val downloadPreferences: DownloadPreferences,
|
||||
private val xml: XML,
|
||||
private val getCategories: GetCategories,
|
||||
private val getTracks: GetTracks,
|
||||
private val store: DownloadStore,
|
||||
private val notifier: DownloadNotifier,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Store for persisting downloads across restarts.
|
||||
*/
|
||||
private val store = DownloadStore(context)
|
||||
|
||||
/**
|
||||
* Queue where active downloads are kept.
|
||||
*/
|
||||
private val _queueState = MutableStateFlow<List<Download>>(emptyList())
|
||||
val queueState = _queueState.asStateFlow()
|
||||
|
||||
/**
|
||||
* Notifier for the downloader state and progress.
|
||||
*/
|
||||
private val notifier by lazy { DownloadNotifier(context) }
|
||||
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
private var downloaderJob: Job? = null
|
||||
|
||||
|
||||
@@ -10,13 +10,8 @@ import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import tachiyomi.domain.chapter.interactor.GetChapter
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.interactor.GetManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
data class Download(
|
||||
@@ -71,19 +66,4 @@ data class Download(
|
||||
DOWNLOADED(3),
|
||||
ERROR(4),
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun fromChapterId(
|
||||
chapterId: Long,
|
||||
getChapter: GetChapter = Injekt.get(),
|
||||
getManga: GetManga = Injekt.get(),
|
||||
sourceManager: SourceManager = Injekt.get(),
|
||||
): Download? {
|
||||
val chapter = getChapter.await(chapterId) ?: return null
|
||||
val manga = getManga.await(chapter.mangaId) ?: return null
|
||||
val source = sourceManager.get(manga.source) as? HttpSource ?: return null
|
||||
|
||||
return Download(source, manga, chapter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,11 @@ import androidx.work.NetworkType
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkQuery
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
@@ -38,6 +40,9 @@ import kotlinx.coroutines.sync.withPermit
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.AppGraph
|
||||
import mihon.app.di.appGraph
|
||||
import mihon.core.metro.metroGraph
|
||||
import mihon.domain.chapter.interactor.FilterChaptersForDownload
|
||||
import mihon.domain.source.interactor.UpdateMangaFromRemote
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
@@ -63,8 +68,6 @@ import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.model.SourceNotInstalledException
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -78,24 +81,34 @@ import kotlin.time.Clock
|
||||
class LibraryUpdateJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val sourceManager: SourceManager = Injekt.get()
|
||||
private val libraryPreferences: LibraryPreferences = Injekt.get()
|
||||
private val downloadManager: DownloadManager = Injekt.get()
|
||||
private val getLibraryManga: GetLibraryManga = Injekt.get()
|
||||
private val getManga: GetManga = Injekt.get()
|
||||
private val fetchInterval: FetchInterval = Injekt.get()
|
||||
private val filterChaptersForDownload: FilterChaptersForDownload = Injekt.get()
|
||||
private val updateMangaFromRemote: UpdateMangaFromRemote = Injekt.get()
|
||||
private val graph: AppGraph = context.metroGraph()
|
||||
|
||||
private val notifier = LibraryUpdateNotifier(context)
|
||||
@Inject private lateinit var sourceManager: SourceManager
|
||||
|
||||
@Inject private lateinit var libraryPreferences: LibraryPreferences
|
||||
|
||||
@Inject private lateinit var downloadManager: DownloadManager
|
||||
|
||||
@Inject private lateinit var getLibraryManga: GetLibraryManga
|
||||
|
||||
@Inject private lateinit var getManga: GetManga
|
||||
|
||||
@Inject private lateinit var fetchInterval: FetchInterval
|
||||
|
||||
@Inject private lateinit var filterChaptersForDownload: FilterChaptersForDownload
|
||||
|
||||
@Inject private lateinit var updateMangaFromRemote: UpdateMangaFromRemote
|
||||
|
||||
@Inject private lateinit var notifier: LibraryUpdateNotifier
|
||||
|
||||
private var mangaToUpdate: List<LibraryManga> = mutableListOf()
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
graph.inject(this)
|
||||
|
||||
if (tags.contains(WORK_NAME_AUTO)) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
val preferences = Injekt.get<LibraryPreferences>()
|
||||
val restrictions = preferences.autoUpdateDeviceRestrictions.get()
|
||||
val restrictions = libraryPreferences.autoUpdateDeviceRestrictions.get()
|
||||
if ((DEVICE_ONLY_ON_WIFI in restrictions) && !context.isConnectedToWifi()) {
|
||||
return Result.retry()
|
||||
}
|
||||
@@ -133,7 +146,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
}
|
||||
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
val notifier = LibraryUpdateNotifier(context)
|
||||
return ForegroundInfo(
|
||||
Notifications.ID_LIBRARY_PROGRESS,
|
||||
notifier.progressNotificationBuilder.build(),
|
||||
@@ -420,7 +432,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
context: Context,
|
||||
prefInterval: Int? = null,
|
||||
) {
|
||||
val preferences = Injekt.get<LibraryPreferences>()
|
||||
val preferences = context.appGraph.libraryPreferences
|
||||
val interval = prefInterval ?: preferences.autoUpdateInterval.get()
|
||||
if (interval > 0) {
|
||||
val restrictions = preferences.autoUpdateDeviceRestrictions.get()
|
||||
@@ -469,11 +481,10 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
}
|
||||
|
||||
fun startNow(
|
||||
context: Context,
|
||||
workManager: WorkManager,
|
||||
category: Category? = null,
|
||||
): Boolean {
|
||||
val wm = context.workManager
|
||||
if (wm.isRunning(TAG)) {
|
||||
if (workManager.isRunning(TAG)) {
|
||||
// Already running either as a scheduled or manual job
|
||||
return false
|
||||
}
|
||||
@@ -486,20 +497,20 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
.addTag(WORK_NAME_MANUAL)
|
||||
.setInputData(inputData)
|
||||
.build()
|
||||
wm.enqueueUniqueWork(WORK_NAME_MANUAL, ExistingWorkPolicy.KEEP, request)
|
||||
workManager.enqueueUniqueWork(WORK_NAME_MANUAL, ExistingWorkPolicy.KEEP, request)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
val wm = context.workManager
|
||||
val workManager = context.workManager
|
||||
val workQuery = WorkQuery.Builder.fromTags(listOf(TAG))
|
||||
.addStates(listOf(WorkInfo.State.RUNNING))
|
||||
.build()
|
||||
wm.getWorkInfos(workQuery).get()
|
||||
workManager.getWorkInfos(workQuery).get()
|
||||
// Should only return one work but just in case
|
||||
.forEach {
|
||||
wm.cancelWorkById(it.id)
|
||||
workManager.cancelWorkById(it.id)
|
||||
|
||||
// Re-enqueue cancelled scheduled work
|
||||
if (it.tags.contains(WORK_NAME_AUTO)) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import coil3.imageLoader
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.transformations
|
||||
import coil3.transform.CircleCropTransformation
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.presentation.util.formatChapterNumber
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
@@ -37,15 +38,14 @@ import tachiyomi.domain.library.model.LibraryManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.math.RoundingMode
|
||||
import java.text.NumberFormat
|
||||
|
||||
@Inject
|
||||
class LibraryUpdateNotifier(
|
||||
private val context: Context,
|
||||
private val securityPreferences: SecurityPreferences = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val securityPreferences: SecurityPreferences,
|
||||
private val sourceManager: SourceManager,
|
||||
) {
|
||||
|
||||
private val percentFormatter = NumberFormat.getPercentInstance().apply {
|
||||
|
||||
@@ -7,13 +7,12 @@ import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkQuery
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
@@ -22,6 +21,8 @@ import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.AppGraph
|
||||
import mihon.core.metro.metroGraph
|
||||
import mihon.domain.source.interactor.UpdateMangaFromRemote
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
@@ -29,8 +30,6 @@ import tachiyomi.domain.library.model.LibraryManga
|
||||
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import kotlin.concurrent.atomics.AtomicInt
|
||||
import kotlin.concurrent.atomics.ExperimentalAtomicApi
|
||||
@@ -40,15 +39,21 @@ import kotlin.concurrent.atomics.fetchAndIncrement
|
||||
class MetadataUpdateJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val sourceManager: SourceManager = Injekt.get()
|
||||
private val getLibraryManga: GetLibraryManga = Injekt.get()
|
||||
private val updateMangaFromRemote: UpdateMangaFromRemote = Injekt.get()
|
||||
private val graph: AppGraph = context.metroGraph()
|
||||
|
||||
private val notifier = LibraryUpdateNotifier(context)
|
||||
@Inject private lateinit var sourceManager: SourceManager
|
||||
|
||||
@Inject private lateinit var getLibraryManga: GetLibraryManga
|
||||
|
||||
@Inject private lateinit var updateMangaFromRemote: UpdateMangaFromRemote
|
||||
|
||||
@Inject private lateinit var notifier: LibraryUpdateNotifier
|
||||
|
||||
private var mangaToUpdate: List<LibraryManga> = mutableListOf()
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
graph.inject(this)
|
||||
|
||||
setForegroundSafely()
|
||||
|
||||
addMangaToQueue()
|
||||
@@ -72,7 +77,6 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
|
||||
}
|
||||
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
val notifier = LibraryUpdateNotifier(context)
|
||||
return ForegroundInfo(
|
||||
Notifications.ID_LIBRARY_PROGRESS,
|
||||
notifier.progressNotificationBuilder.build(),
|
||||
@@ -168,9 +172,8 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
|
||||
|
||||
private const val MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD = 60
|
||||
|
||||
fun startNow(context: Context): Boolean {
|
||||
val wm = context.workManager
|
||||
if (wm.isRunning(TAG)) {
|
||||
fun startNow(workManager: WorkManager): Boolean {
|
||||
if (workManager.isRunning(TAG)) {
|
||||
// Already running either as a scheduled or manual job
|
||||
return false
|
||||
}
|
||||
@@ -178,21 +181,9 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
|
||||
.addTag(TAG)
|
||||
.addTag(WORK_NAME_MANUAL)
|
||||
.build()
|
||||
wm.enqueueUniqueWork(WORK_NAME_MANUAL, ExistingWorkPolicy.KEEP, request)
|
||||
workManager.enqueueUniqueWork(WORK_NAME_MANUAL, ExistingWorkPolicy.KEEP, request)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
val wm = context.workManager
|
||||
val workQuery = WorkQuery.Builder.fromTags(listOf(TAG))
|
||||
.addStates(listOf(WorkInfo.State.RUNNING))
|
||||
.build()
|
||||
wm.getWorkInfos(workQuery).get()
|
||||
// Should only return one work but just in case
|
||||
.forEach {
|
||||
wm.cancelWorkById(it.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import dev.zacsweers.metro.Inject
|
||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
@@ -16,7 +17,9 @@ import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||
import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.Constants
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.domain.chapter.interactor.GetChapter
|
||||
@@ -28,9 +31,6 @@ import tachiyomi.domain.manga.interactor.GetManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
||||
|
||||
/**
|
||||
@@ -40,12 +40,21 @@ import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
||||
*/
|
||||
class NotificationReceiver : BroadcastReceiver() {
|
||||
|
||||
private val getManga: GetManga by injectLazy()
|
||||
private val getChapter: GetChapter by injectLazy()
|
||||
private val updateChapter: UpdateChapter by injectLazy()
|
||||
private val downloadManager: DownloadManager by injectLazy()
|
||||
@Inject private lateinit var getManga: GetManga
|
||||
|
||||
@Inject private lateinit var getChapter: GetChapter
|
||||
|
||||
@Inject private lateinit var updateChapter: UpdateChapter
|
||||
|
||||
@Inject private lateinit var downloadManager: DownloadManager
|
||||
|
||||
@Inject private lateinit var downloadPreferences: DownloadPreferences
|
||||
|
||||
@Inject private lateinit var sourceManager: SourceManager
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
context.appGraph.inject(this)
|
||||
|
||||
when (intent.action) {
|
||||
// Dismiss notification
|
||||
ACTION_DISMISS_NOTIFICATION -> dismissNotification(context, intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1))
|
||||
@@ -161,7 +170,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
* @param context context of application
|
||||
*/
|
||||
private fun cancelRestore(context: Context) {
|
||||
BackupRestoreJob.stop(context)
|
||||
BackupRestoreJob.stop(context.workManager)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,9 +189,6 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
* @param mangaId id of manga
|
||||
*/
|
||||
private fun markAsRead(chapterUrls: Array<String>, mangaId: Long) {
|
||||
val downloadPreferences: DownloadPreferences = Injekt.get()
|
||||
val sourceManager: SourceManager = Injekt.get()
|
||||
|
||||
launchIO {
|
||||
val toUpdate = chapterUrls.mapNotNull { getChapter.await(it, mangaId) }
|
||||
.map {
|
||||
|
||||
@@ -11,6 +11,9 @@ import android.webkit.MimeTypeMap
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.contentValuesOf
|
||||
import androidx.core.net.toUri
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.SingleIn
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.storage.cacheImageDir
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
@@ -26,6 +29,8 @@ import java.io.File
|
||||
import java.io.InputStream
|
||||
import kotlin.time.Clock
|
||||
|
||||
@Inject
|
||||
@SingleIn(AppScope::class)
|
||||
class ImageSaver(
|
||||
val context: Context,
|
||||
) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user