├── .editorconfig
├── .gitattributes
├── .github
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── feature_request.yml
│ └── issue_report.yml
├── PULL_REQUEST_TEMPLATE.md
├── readme-images
│ ├── app-icon.inkscape.svg
│ ├── app-icon.webp
│ ├── material snackbar.png
│ ├── screens.gif
│ └── share menu.png
├── runner-files
│ └── ci-gradle.properties
└── workflows
│ ├── build_check.yml
│ ├── build_push.yml
│ └── mirror.yml
├── .gitignore
├── .renovaterc.json5
├── CHANGELOG.md
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle.kts
├── proguard-android-optimize.txt
├── proguard-rules.pro
└── src
│ ├── debug
│ ├── ic_launcher-playstore.png
│ ├── ic_launcher-web.png
│ └── res
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ └── strings.xml
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── ic_launcher-web.png
│ ├── java
│ │ ├── eu
│ │ │ └── kanade
│ │ │ │ └── tachiyomi
│ │ │ │ ├── App.kt
│ │ │ │ ├── AppInfo.kt
│ │ │ │ ├── AppProvider.kt
│ │ │ │ ├── annotations
│ │ │ │ └── Nsfw.kt
│ │ │ │ ├── appwidget
│ │ │ │ ├── TachiyomiWidgetManager.kt
│ │ │ │ ├── UpdatesGridGlanceReceiver.kt
│ │ │ │ ├── UpdatesGridGlanceWidget.kt
│ │ │ │ ├── components
│ │ │ │ │ ├── LockedWidget.kt
│ │ │ │ │ ├── UpdatesMangaCover.kt
│ │ │ │ │ └── UpdatesWidget.kt
│ │ │ │ └── util
│ │ │ │ │ └── GlanceUtils.kt
│ │ │ │ ├── core
│ │ │ │ └── storage
│ │ │ │ │ ├── AndroidStorageFolderProvider.kt
│ │ │ │ │ ├── FolderProvider.kt
│ │ │ │ │ └── preference
│ │ │ │ │ └── PreferenceExtension.kt
│ │ │ │ ├── data
│ │ │ │ ├── backup
│ │ │ │ │ ├── BackupConst.kt
│ │ │ │ │ ├── BackupFileValidator.kt
│ │ │ │ │ ├── BackupNotifier.kt
│ │ │ │ │ ├── create
│ │ │ │ │ │ ├── BackupCreator.kt
│ │ │ │ │ │ ├── BackupCreatorJob.kt
│ │ │ │ │ │ ├── BackupOptions.kt
│ │ │ │ │ │ └── creators
│ │ │ │ │ │ │ ├── CategoriesBackupCreator.kt
│ │ │ │ │ │ │ ├── MangaBackupCreator.kt
│ │ │ │ │ │ │ ├── PreferenceBackupCreator.kt
│ │ │ │ │ │ │ └── SourcesBackupCreator.kt
│ │ │ │ │ ├── models
│ │ │ │ │ │ ├── Backup.kt
│ │ │ │ │ │ ├── BackupCategory.kt
│ │ │ │ │ │ ├── BackupChapter.kt
│ │ │ │ │ │ ├── BackupHistory.kt
│ │ │ │ │ │ ├── BackupManga.kt
│ │ │ │ │ │ ├── BackupPreference.kt
│ │ │ │ │ │ ├── BackupSource.kt
│ │ │ │ │ │ └── BackupTracking.kt
│ │ │ │ │ └── restore
│ │ │ │ │ │ ├── BackupRestoreJob.kt
│ │ │ │ │ │ ├── BackupRestorer.kt
│ │ │ │ │ │ └── restorers
│ │ │ │ │ │ ├── CategoriesBackupRestorer.kt
│ │ │ │ │ │ ├── MangaBackupRestorer.kt
│ │ │ │ │ │ └── PreferenceBackupRestorer.kt
│ │ │ │ ├── cache
│ │ │ │ │ ├── ChapterCache.kt
│ │ │ │ │ └── CoverCache.kt
│ │ │ │ ├── coil
│ │ │ │ │ ├── BufferedSourceFetcher.kt
│ │ │ │ │ ├── CoverViewTarget.kt
│ │ │ │ │ ├── LibraryMangaImageTarget.kt
│ │ │ │ │ ├── MangaCoverFetcher.kt
│ │ │ │ │ ├── MangaCoverKeyer.kt
│ │ │ │ │ ├── TachiyomiImageDecoder.kt
│ │ │ │ │ └── Utils.kt
│ │ │ │ ├── database
│ │ │ │ │ ├── models
│ │ │ │ │ │ ├── Category.kt
│ │ │ │ │ │ ├── CategoryImpl.kt
│ │ │ │ │ │ ├── Chapter.kt
│ │ │ │ │ │ ├── ChapterImpl.kt
│ │ │ │ │ │ ├── History.kt
│ │ │ │ │ │ ├── HistoryImpl.kt
│ │ │ │ │ │ ├── LibraryManga.kt
│ │ │ │ │ │ ├── Manga.kt
│ │ │ │ │ │ ├── MangaCategory.kt
│ │ │ │ │ │ ├── MangaChapter.kt
│ │ │ │ │ │ ├── MangaChapterHistory.kt
│ │ │ │ │ │ ├── MangaImpl.kt
│ │ │ │ │ │ ├── SearchMetadata.kt
│ │ │ │ │ │ ├── SourceIdMangaCount.kt
│ │ │ │ │ │ ├── Track.kt
│ │ │ │ │ │ └── TrackImpl.kt
│ │ │ │ │ └── queries
│ │ │ │ │ │ └── SearchMetadataQueries.kt
│ │ │ │ ├── download
│ │ │ │ │ ├── DownloadCache.kt
│ │ │ │ │ ├── DownloadJob.kt
│ │ │ │ │ ├── DownloadManager.kt
│ │ │ │ │ ├── DownloadNotifier.kt
│ │ │ │ │ ├── DownloadPendingDeleter.kt
│ │ │ │ │ ├── DownloadProvider.kt
│ │ │ │ │ ├── DownloadStore.kt
│ │ │ │ │ ├── Downloader.kt
│ │ │ │ │ └── model
│ │ │ │ │ │ ├── Download.kt
│ │ │ │ │ │ └── DownloadQueue.kt
│ │ │ │ ├── library
│ │ │ │ │ ├── CustomMangaManager.kt
│ │ │ │ │ ├── LibraryUpdateJob.kt
│ │ │ │ │ └── LibraryUpdateNotifier.kt
│ │ │ │ ├── notification
│ │ │ │ │ ├── NotificationHandler.kt
│ │ │ │ │ ├── NotificationReceiver.kt
│ │ │ │ │ └── Notifications.kt
│ │ │ │ ├── preference
│ │ │ │ │ ├── DelayedLibrarySuggestionsJob.kt
│ │ │ │ │ ├── PreferenceKeys.kt
│ │ │ │ │ ├── PreferenceValues.kt
│ │ │ │ │ ├── PreferencesHelper.kt
│ │ │ │ │ └── SharedPreferencesDataStore.kt
│ │ │ │ ├── track
│ │ │ │ │ ├── DelayedTrackingUpdateJob.kt
│ │ │ │ │ ├── EnhancedTrackService.kt
│ │ │ │ │ ├── TrackManager.kt
│ │ │ │ │ ├── TrackPreferences.kt
│ │ │ │ │ ├── TrackService.kt
│ │ │ │ │ ├── UnattendedTrackService.kt
│ │ │ │ │ ├── anilist
│ │ │ │ │ │ ├── Anilist.kt
│ │ │ │ │ │ ├── AnilistApi.kt
│ │ │ │ │ │ ├── AnilistInterceptor.kt
│ │ │ │ │ │ ├── AnilistUtils.kt
│ │ │ │ │ │ └── dto
│ │ │ │ │ │ │ ├── ALAddManga.kt
│ │ │ │ │ │ │ ├── ALFuzzyDate.kt
│ │ │ │ │ │ │ ├── ALManga.kt
│ │ │ │ │ │ │ ├── ALOAuth.kt
│ │ │ │ │ │ │ ├── ALSearch.kt
│ │ │ │ │ │ │ ├── ALSearchItem.kt
│ │ │ │ │ │ │ ├── ALUser.kt
│ │ │ │ │ │ │ └── ALUserList.kt
│ │ │ │ │ ├── bangumi
│ │ │ │ │ │ ├── Bangumi.kt
│ │ │ │ │ │ ├── BangumiApi.kt
│ │ │ │ │ │ ├── BangumiInterceptor.kt
│ │ │ │ │ │ ├── BangumiUtils.kt
│ │ │ │ │ │ └── dto
│ │ │ │ │ │ │ ├── BGMCollectionResponse.kt
│ │ │ │ │ │ │ ├── BGMOAuth.kt
│ │ │ │ │ │ │ ├── BGMSearch.kt
│ │ │ │ │ │ │ └── BGMUser.kt
│ │ │ │ │ ├── kavita
│ │ │ │ │ │ ├── Kavita.kt
│ │ │ │ │ │ ├── KavitaApi.kt
│ │ │ │ │ │ ├── KavitaInterceptor.kt
│ │ │ │ │ │ └── KavitaModels.kt
│ │ │ │ │ ├── kitsu
│ │ │ │ │ │ ├── Kitsu.kt
│ │ │ │ │ │ ├── KitsuApi.kt
│ │ │ │ │ │ ├── KitsuDateHelper.kt
│ │ │ │ │ │ ├── KitsuInterceptor.kt
│ │ │ │ │ │ ├── KitsuUtils.kt
│ │ │ │ │ │ └── dto
│ │ │ │ │ │ │ ├── KitsuAddManga.kt
│ │ │ │ │ │ │ ├── KitsuListSearch.kt
│ │ │ │ │ │ │ ├── KitsuOAuth.kt
│ │ │ │ │ │ │ ├── KitsuSearch.kt
│ │ │ │ │ │ │ ├── KitsuSearchItemCover.kt
│ │ │ │ │ │ │ └── KitsuUser.kt
│ │ │ │ │ ├── komga
│ │ │ │ │ │ ├── Komga.kt
│ │ │ │ │ │ ├── KomgaApi.kt
│ │ │ │ │ │ └── KomgaDto.kt
│ │ │ │ │ ├── mangaupdates
│ │ │ │ │ │ ├── MangaUpdates.kt
│ │ │ │ │ │ ├── MangaUpdatesApi.kt
│ │ │ │ │ │ ├── MangaUpdatesInterceptor.kt
│ │ │ │ │ │ └── dto
│ │ │ │ │ │ │ ├── MUContext.kt
│ │ │ │ │ │ │ ├── MUImage.kt
│ │ │ │ │ │ │ ├── MUListItem.kt
│ │ │ │ │ │ │ ├── MULoginResponse.kt
│ │ │ │ │ │ │ ├── MURating.kt
│ │ │ │ │ │ │ ├── MURecord.kt
│ │ │ │ │ │ │ ├── MUSearch.kt
│ │ │ │ │ │ │ ├── MUSeries.kt
│ │ │ │ │ │ │ ├── MUStatus.kt
│ │ │ │ │ │ │ └── MUUrl.kt
│ │ │ │ │ ├── model
│ │ │ │ │ │ └── TrackSearch.kt
│ │ │ │ │ ├── myanimelist
│ │ │ │ │ │ ├── MyAnimeList.kt
│ │ │ │ │ │ ├── MyAnimeListApi.kt
│ │ │ │ │ │ ├── MyAnimeListInterceptor.kt
│ │ │ │ │ │ ├── MyAnimeListUtils.kt
│ │ │ │ │ │ └── dto
│ │ │ │ │ │ │ ├── MALList.kt
│ │ │ │ │ │ │ ├── MALManga.kt
│ │ │ │ │ │ │ ├── MALOAuth.kt
│ │ │ │ │ │ │ ├── MALSearch.kt
│ │ │ │ │ │ │ ├── MALUser.kt
│ │ │ │ │ │ │ └── MALUserListSearch.kt
│ │ │ │ │ ├── shikimori
│ │ │ │ │ │ ├── Shikimori.kt
│ │ │ │ │ │ ├── ShikimoriApi.kt
│ │ │ │ │ │ ├── ShikimoriInterceptor.kt
│ │ │ │ │ │ ├── ShikimoriUtils.kt
│ │ │ │ │ │ └── dto
│ │ │ │ │ │ │ ├── SMAddMangaResponse.kt
│ │ │ │ │ │ │ ├── SMManga.kt
│ │ │ │ │ │ │ ├── SMOAuth.kt
│ │ │ │ │ │ │ ├── SMUser.kt
│ │ │ │ │ │ │ └── SMUserListEntry.kt
│ │ │ │ │ └── suwayomi
│ │ │ │ │ │ ├── Suwayomi.kt
│ │ │ │ │ │ ├── TachideskApi.kt
│ │ │ │ │ │ └── TachideskDto.kt
│ │ │ │ └── updater
│ │ │ │ │ ├── AppDownloadInstallJob.kt
│ │ │ │ │ ├── AppUpdateBroadcast.kt
│ │ │ │ │ ├── AppUpdateChecker.kt
│ │ │ │ │ ├── AppUpdateJob.kt
│ │ │ │ │ ├── AppUpdateNotifier.kt
│ │ │ │ │ ├── AppUpdateResult.kt
│ │ │ │ │ └── GithubRelease.kt
│ │ │ │ ├── extension
│ │ │ │ ├── ExtensionInstallNotifier.kt
│ │ │ │ ├── ExtensionInstallerJob.kt
│ │ │ │ ├── ExtensionManager.kt
│ │ │ │ ├── ExtensionUpdateJob.kt
│ │ │ │ ├── api
│ │ │ │ │ └── ExtensionApi.kt
│ │ │ │ ├── installer
│ │ │ │ │ ├── Installer.kt
│ │ │ │ │ └── ShizukuInstaller.kt
│ │ │ │ ├── model
│ │ │ │ │ ├── Extension.kt
│ │ │ │ │ ├── InstallStep.kt
│ │ │ │ │ ├── InstalledExtensionsOrder.kt
│ │ │ │ │ └── LoadResult.kt
│ │ │ │ └── util
│ │ │ │ │ ├── ExtensionInstallBroadcast.kt
│ │ │ │ │ ├── ExtensionInstallReceiver.kt
│ │ │ │ │ ├── ExtensionInstaller.kt
│ │ │ │ │ └── ExtensionLoader.kt
│ │ │ │ ├── smartsearch
│ │ │ │ └── SmartSearchEngine.kt
│ │ │ │ ├── source
│ │ │ │ ├── LocalSource.kt
│ │ │ │ ├── SourceExtensions.kt
│ │ │ │ ├── SourceManager.kt
│ │ │ │ ├── models
│ │ │ │ │ └── SMangaExtensions.kt
│ │ │ │ └── online
│ │ │ │ │ ├── all
│ │ │ │ │ ├── Cubari.kt
│ │ │ │ │ └── MangaDex.kt
│ │ │ │ │ └── english
│ │ │ │ │ └── MangaPlus.kt
│ │ │ │ ├── ui
│ │ │ │ ├── base
│ │ │ │ │ ├── BaseToolbar.kt
│ │ │ │ │ ├── CenteredToolbar.kt
│ │ │ │ │ ├── ExpandedAppBarLayout.kt
│ │ │ │ │ ├── FloatingToolbar.kt
│ │ │ │ │ ├── MaterialFastScroll.kt
│ │ │ │ │ ├── MaterialMenuSheet.kt
│ │ │ │ │ ├── MaterialMenuSheetItem.kt
│ │ │ │ │ ├── MiniSearchView.kt
│ │ │ │ │ ├── activity
│ │ │ │ │ │ ├── BaseActivity.kt
│ │ │ │ │ │ └── BaseThemedActivity.kt
│ │ │ │ │ ├── controller
│ │ │ │ │ │ ├── BaseComposeController.kt
│ │ │ │ │ │ ├── BaseController.kt
│ │ │ │ │ │ ├── BaseCoroutineComposeController.kt
│ │ │ │ │ │ ├── BaseCoroutineController.kt
│ │ │ │ │ │ ├── BaseLegacyController.kt
│ │ │ │ │ │ ├── CrossFadeChangeHandler.kt
│ │ │ │ │ │ ├── DialogController.kt
│ │ │ │ │ │ ├── FadeChangeHandler.kt
│ │ │ │ │ │ └── OneWayFadeChangeHandler.kt
│ │ │ │ │ ├── holder
│ │ │ │ │ │ ├── BaseFlexibleViewHolder.kt
│ │ │ │ │ │ └── BaseViewHolder.kt
│ │ │ │ │ └── presenter
│ │ │ │ │ │ ├── BaseCoroutinePresenter.kt
│ │ │ │ │ │ └── StateCoroutinePresenter.kt
│ │ │ │ ├── category
│ │ │ │ │ ├── CategoryAdapter.kt
│ │ │ │ │ ├── CategoryController.kt
│ │ │ │ │ ├── CategoryHolder.kt
│ │ │ │ │ ├── CategoryItem.kt
│ │ │ │ │ ├── CategoryPresenter.kt
│ │ │ │ │ ├── ManageCategoryDialog.kt
│ │ │ │ │ └── addtolibrary
│ │ │ │ │ │ ├── AddCategoryItem.kt
│ │ │ │ │ │ └── SetCategoriesSheet.kt
│ │ │ │ ├── crash
│ │ │ │ │ ├── CrashActivity.kt
│ │ │ │ │ └── GlobalExceptionHandler.kt
│ │ │ │ ├── download
│ │ │ │ │ ├── DownloadAdapter.kt
│ │ │ │ │ ├── DownloadBottomPresenter.kt
│ │ │ │ │ ├── DownloadBottomSheet.kt
│ │ │ │ │ ├── DownloadButton.kt
│ │ │ │ │ ├── DownloadHeaderHolder.kt
│ │ │ │ │ ├── DownloadHeaderItem.kt
│ │ │ │ │ ├── DownloadHolder.kt
│ │ │ │ │ ├── DownloadItem.kt
│ │ │ │ │ └── DownloadSwipeTutorialItem.kt
│ │ │ │ ├── extension
│ │ │ │ │ ├── ExtensionAdapter.kt
│ │ │ │ │ ├── ExtensionBottomPresenter.kt
│ │ │ │ │ ├── ExtensionBottomSheet.kt
│ │ │ │ │ ├── ExtensionDividerItemDecoration.kt
│ │ │ │ │ ├── ExtensionFilterController.kt
│ │ │ │ │ ├── ExtensionGroupHolder.kt
│ │ │ │ │ ├── ExtensionGroupItem.kt
│ │ │ │ │ ├── ExtensionHolder.kt
│ │ │ │ │ ├── ExtensionItem.kt
│ │ │ │ │ ├── ExtensionViewUtils.kt
│ │ │ │ │ ├── RecyclerViewPagerAdapter.kt
│ │ │ │ │ ├── RecyclerWithScrollerView.kt
│ │ │ │ │ └── details
│ │ │ │ │ │ ├── ExtensionDetailsController.kt
│ │ │ │ │ │ ├── ExtensionDetailsHeaderAdapter.kt
│ │ │ │ │ │ ├── ExtensionDetailsPresenter.kt
│ │ │ │ │ │ └── ExtensionSettingsDividerItemDecoration.kt
│ │ │ │ ├── library
│ │ │ │ │ ├── FilteredLibraryController.kt
│ │ │ │ │ ├── LibraryBadge.kt
│ │ │ │ │ ├── LibraryCategoryAdapter.kt
│ │ │ │ │ ├── LibraryCategoryGestureDetector.kt
│ │ │ │ │ ├── LibraryController.kt
│ │ │ │ │ ├── LibraryFastScroll.kt
│ │ │ │ │ ├── LibraryGestureDetector.kt
│ │ │ │ │ ├── LibraryGridHolder.kt
│ │ │ │ │ ├── LibraryGroup.kt
│ │ │ │ │ ├── LibraryHeaderGestureDetector.kt
│ │ │ │ │ ├── LibraryHeaderHolder.kt
│ │ │ │ │ ├── LibraryHeaderItem.kt
│ │ │ │ │ ├── LibraryHolder.kt
│ │ │ │ │ ├── LibraryItem.kt
│ │ │ │ │ ├── LibraryListHolder.kt
│ │ │ │ │ ├── LibraryMangaItem.kt
│ │ │ │ │ ├── LibraryPlaceholderItem.kt
│ │ │ │ │ ├── LibraryPresenter.kt
│ │ │ │ │ ├── LibrarySort.kt
│ │ │ │ │ ├── SearchGlobalItem.kt
│ │ │ │ │ ├── category
│ │ │ │ │ │ ├── CategoryItem.kt
│ │ │ │ │ │ └── CategoryRecyclerView.kt
│ │ │ │ │ ├── compose
│ │ │ │ │ │ ├── LibraryComposeController.kt
│ │ │ │ │ │ └── LibraryComposePresenter.kt
│ │ │ │ │ ├── display
│ │ │ │ │ │ ├── LibraryBadgesView.kt
│ │ │ │ │ │ ├── LibraryCategoryView.kt
│ │ │ │ │ │ ├── LibraryDisplayView.kt
│ │ │ │ │ │ └── TabbedLibraryDisplaySheet.kt
│ │ │ │ │ ├── filter
│ │ │ │ │ │ ├── ExpandedFilterItem.kt
│ │ │ │ │ │ ├── ExpandedFilterSheet.kt
│ │ │ │ │ │ ├── FilterBottomSheet.kt
│ │ │ │ │ │ ├── FilterTagGroup.kt
│ │ │ │ │ │ ├── LibraryFilter.kt
│ │ │ │ │ │ └── ManageFilterItem.kt
│ │ │ │ │ └── models
│ │ │ │ │ │ └── LibraryItem.kt
│ │ │ │ ├── main
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ ├── SearchActivity.kt
│ │ │ │ │ └── TabsAnimator.kt
│ │ │ │ ├── manga
│ │ │ │ │ ├── EditMangaDialog.kt
│ │ │ │ │ ├── FullCoverDialog.kt
│ │ │ │ │ ├── MangaDetailsAdapter.kt
│ │ │ │ │ ├── MangaDetailsController.kt
│ │ │ │ │ ├── MangaDetailsDivider.kt
│ │ │ │ │ ├── MangaDetailsPresenter.kt
│ │ │ │ │ ├── MangaHeaderHolder.kt
│ │ │ │ │ ├── MangaHeaderItem.kt
│ │ │ │ │ ├── chapter
│ │ │ │ │ │ ├── BaseChapterAdapter.kt
│ │ │ │ │ │ ├── BaseChapterHolder.kt
│ │ │ │ │ │ ├── BaseChapterItem.kt
│ │ │ │ │ │ ├── ChapterFilterLayout.kt
│ │ │ │ │ │ ├── ChapterHolder.kt
│ │ │ │ │ │ ├── ChapterItem.kt
│ │ │ │ │ │ └── ChaptersSortBottomSheet.kt
│ │ │ │ │ └── track
│ │ │ │ │ │ ├── TrackAdapter.kt
│ │ │ │ │ │ ├── TrackHolder.kt
│ │ │ │ │ │ ├── TrackItem.kt
│ │ │ │ │ │ ├── TrackSearchItem.kt
│ │ │ │ │ │ └── TrackingBottomSheet.kt
│ │ │ │ ├── migration
│ │ │ │ │ ├── BaseMigrationPresenter.kt
│ │ │ │ │ ├── MangaAdapter.kt
│ │ │ │ │ ├── MangaHolder.kt
│ │ │ │ │ ├── MangaItem.kt
│ │ │ │ │ ├── MigrationController.kt
│ │ │ │ │ ├── MigrationFlags.kt
│ │ │ │ │ ├── MigrationPresenter.kt
│ │ │ │ │ ├── SearchController.kt
│ │ │ │ │ ├── SearchPresenter.kt
│ │ │ │ │ ├── SelectionHeader.kt
│ │ │ │ │ ├── SourceAdapter.kt
│ │ │ │ │ ├── SourceHolder.kt
│ │ │ │ │ ├── SourceItem.kt
│ │ │ │ │ └── manga
│ │ │ │ │ │ ├── design
│ │ │ │ │ │ ├── MigrationBottomSheetDialog.kt
│ │ │ │ │ │ ├── MigrationSourceAdapter.kt
│ │ │ │ │ │ ├── MigrationSourceHolder.kt
│ │ │ │ │ │ ├── MigrationSourceItem.kt
│ │ │ │ │ │ └── PreMigrationController.kt
│ │ │ │ │ │ └── process
│ │ │ │ │ │ ├── MigratingManga.kt
│ │ │ │ │ │ ├── MigrationListController.kt
│ │ │ │ │ │ ├── MigrationProcedureConfig.kt
│ │ │ │ │ │ ├── MigrationProcessAdapter.kt
│ │ │ │ │ │ ├── MigrationProcessHolder.kt
│ │ │ │ │ │ └── MigrationProcessItem.kt
│ │ │ │ ├── more
│ │ │ │ │ ├── AboutController.kt
│ │ │ │ │ ├── OverflowDialog.kt
│ │ │ │ │ └── stats
│ │ │ │ │ │ ├── StatsController.kt
│ │ │ │ │ │ ├── StatsHelper.kt
│ │ │ │ │ │ ├── StatsLegendAdapter.kt
│ │ │ │ │ │ ├── StatsPresenter.kt
│ │ │ │ │ │ └── details
│ │ │ │ │ │ ├── HeaderStatsDetailsAdapter.kt
│ │ │ │ │ │ ├── StatsDetailsAdapter.kt
│ │ │ │ │ │ ├── StatsDetailsChartLayout.kt
│ │ │ │ │ │ ├── StatsDetailsController.kt
│ │ │ │ │ │ └── StatsDetailsPresenter.kt
│ │ │ │ ├── reader
│ │ │ │ │ ├── PageIndicatorTextView.kt
│ │ │ │ │ ├── ReaderActivity.kt
│ │ │ │ │ ├── ReaderColorFilterView.kt
│ │ │ │ │ ├── ReaderNavGestureDetector.kt
│ │ │ │ │ ├── ReaderNavView.kt
│ │ │ │ │ ├── ReaderNavigationOverlayView.kt
│ │ │ │ │ ├── ReaderSlider.kt
│ │ │ │ │ ├── ReaderViewModel.kt
│ │ │ │ │ ├── SaveImageNotifier.kt
│ │ │ │ │ ├── chapter
│ │ │ │ │ │ ├── ReaderChapterItem.kt
│ │ │ │ │ │ └── ReaderChapterSheet.kt
│ │ │ │ │ ├── loader
│ │ │ │ │ │ ├── ArchivePageLoader.kt
│ │ │ │ │ │ ├── ChapterLoader.kt
│ │ │ │ │ │ ├── DirectoryPageLoader.kt
│ │ │ │ │ │ ├── DownloadPageLoader.kt
│ │ │ │ │ │ ├── EpubPageLoader.kt
│ │ │ │ │ │ ├── HttpPageLoader.kt
│ │ │ │ │ │ └── PageLoader.kt
│ │ │ │ │ ├── model
│ │ │ │ │ │ ├── ChapterTransition.kt
│ │ │ │ │ │ ├── InsertPage.kt
│ │ │ │ │ │ ├── ReaderChapter.kt
│ │ │ │ │ │ ├── ReaderItem.kt
│ │ │ │ │ │ ├── ReaderPage.kt
│ │ │ │ │ │ ├── SplitPage.kt
│ │ │ │ │ │ └── ViewerChapters.kt
│ │ │ │ │ ├── settings
│ │ │ │ │ │ ├── OrientationType.kt
│ │ │ │ │ │ ├── PageLayout.kt
│ │ │ │ │ │ ├── ReaderBackgroundColor.kt
│ │ │ │ │ │ ├── ReaderBottomButton.kt
│ │ │ │ │ │ ├── ReaderFilterView.kt
│ │ │ │ │ │ ├── ReaderGeneralView.kt
│ │ │ │ │ │ ├── ReaderPagedView.kt
│ │ │ │ │ │ ├── ReadingModeType.kt
│ │ │ │ │ │ └── TabbedReaderSettingsSheet.kt
│ │ │ │ │ └── viewer
│ │ │ │ │ │ ├── BaseViewer.kt
│ │ │ │ │ │ ├── GestureDetectorWithLongTap.kt
│ │ │ │ │ │ ├── MissingChapters.kt
│ │ │ │ │ │ ├── ReaderButton.kt
│ │ │ │ │ │ ├── ReaderErrorView.kt
│ │ │ │ │ │ ├── ReaderPageImageView.kt
│ │ │ │ │ │ ├── ReaderProgressIndicator.kt
│ │ │ │ │ │ ├── ReaderTransitionView.kt
│ │ │ │ │ │ ├── ViewerConfig.kt
│ │ │ │ │ │ ├── ViewerNavigation.kt
│ │ │ │ │ │ ├── navigation
│ │ │ │ │ │ ├── DisabledNavigation.kt
│ │ │ │ │ │ ├── EdgeNavigation.kt
│ │ │ │ │ │ ├── KindlishNavigation.kt
│ │ │ │ │ │ ├── LNavigation.kt
│ │ │ │ │ │ └── RightAndLeftNavigation.kt
│ │ │ │ │ │ ├── pager
│ │ │ │ │ │ ├── Pager.kt
│ │ │ │ │ │ ├── PagerConfig.kt
│ │ │ │ │ │ ├── PagerPageHolder.kt
│ │ │ │ │ │ ├── PagerTransitionHolder.kt
│ │ │ │ │ │ ├── PagerViewer.kt
│ │ │ │ │ │ ├── PagerViewerAdapter.kt
│ │ │ │ │ │ └── PagerViewers.kt
│ │ │ │ │ │ └── webtoon
│ │ │ │ │ │ ├── WebtoonAdapter.kt
│ │ │ │ │ │ ├── WebtoonBaseHolder.kt
│ │ │ │ │ │ ├── WebtoonConfig.kt
│ │ │ │ │ │ ├── WebtoonFrame.kt
│ │ │ │ │ │ ├── WebtoonLayoutManager.kt
│ │ │ │ │ │ ├── WebtoonPageHolder.kt
│ │ │ │ │ │ ├── WebtoonRecyclerView.kt
│ │ │ │ │ │ ├── WebtoonSubsamplingImageView.kt
│ │ │ │ │ │ ├── WebtoonTransitionHolder.kt
│ │ │ │ │ │ └── WebtoonViewer.kt
│ │ │ │ ├── recents
│ │ │ │ │ ├── DateItem.kt
│ │ │ │ │ ├── RecentMangaAdapter.kt
│ │ │ │ │ ├── RecentMangaDivider.kt
│ │ │ │ │ ├── RecentMangaFooterHolder.kt
│ │ │ │ │ ├── RecentMangaHeaderItem.kt
│ │ │ │ │ ├── RecentMangaHolder.kt
│ │ │ │ │ ├── RecentMangaItem.kt
│ │ │ │ │ ├── RecentsController.kt
│ │ │ │ │ ├── RecentsPresenter.kt
│ │ │ │ │ ├── RecentsViewType.kt
│ │ │ │ │ └── options
│ │ │ │ │ │ ├── RecentsGeneralView.kt
│ │ │ │ │ │ ├── RecentsHistoryView.kt
│ │ │ │ │ │ ├── RecentsUpdatesView.kt
│ │ │ │ │ │ └── TabbedRecentsOptionsSheet.kt
│ │ │ │ ├── security
│ │ │ │ │ ├── BiometricActivity.kt
│ │ │ │ │ └── SecureActivityDelegate.kt
│ │ │ │ ├── setting
│ │ │ │ │ ├── LongClickablePreference.kt
│ │ │ │ │ ├── PreferenceDSL.kt
│ │ │ │ │ ├── SettingsComposeController.kt
│ │ │ │ │ ├── SettingsControllerInterface.kt
│ │ │ │ │ ├── SettingsLegacyController.kt
│ │ │ │ │ ├── ThemePreference.kt
│ │ │ │ │ ├── controllers
│ │ │ │ │ │ ├── SettingsAdvancedController.kt
│ │ │ │ │ │ ├── SettingsAppearanceController.kt
│ │ │ │ │ │ ├── SettingsBrowseController.kt
│ │ │ │ │ │ ├── SettingsDataController.kt
│ │ │ │ │ │ ├── SettingsDownloadController.kt
│ │ │ │ │ │ ├── SettingsGeneralController.kt
│ │ │ │ │ │ ├── SettingsLibraryController.kt
│ │ │ │ │ │ ├── SettingsMainController.kt
│ │ │ │ │ │ ├── SettingsReaderController.kt
│ │ │ │ │ │ ├── SettingsSecurityController.kt
│ │ │ │ │ │ ├── SettingsSourcesController.kt
│ │ │ │ │ │ ├── SettingsTrackingController.kt
│ │ │ │ │ │ ├── database
│ │ │ │ │ │ │ ├── ClearDatabaseController.kt
│ │ │ │ │ │ │ ├── ClearDatabasePresenter.kt
│ │ │ │ │ │ │ └── ClearDatabaseSourceItem.kt
│ │ │ │ │ │ ├── debug
│ │ │ │ │ │ │ ├── BackupSchemaController.kt
│ │ │ │ │ │ │ ├── DebugController.kt
│ │ │ │ │ │ │ ├── DebugInfoItem.kt
│ │ │ │ │ │ │ ├── WorkerInfoController.kt
│ │ │ │ │ │ │ └── WorkerInfoPresenter.kt
│ │ │ │ │ │ ├── legacy
│ │ │ │ │ │ │ └── SettingsDataLegacyController.kt
│ │ │ │ │ │ └── search
│ │ │ │ │ │ │ ├── SettingsSearchAdapter.kt
│ │ │ │ │ │ │ ├── SettingsSearchController.kt
│ │ │ │ │ │ │ ├── SettingsSearchHelper.kt
│ │ │ │ │ │ │ ├── SettingsSearchHolder.kt
│ │ │ │ │ │ │ └── SettingsSearchItem.kt
│ │ │ │ │ └── track
│ │ │ │ │ │ ├── AnilistLoginActivity.kt
│ │ │ │ │ │ ├── BangumiLoginActivity.kt
│ │ │ │ │ │ ├── BaseOAuthLoginActivity.kt
│ │ │ │ │ │ ├── MyAnimeListLoginActivity.kt
│ │ │ │ │ │ └── ShikimoriLoginActivity.kt
│ │ │ │ ├── source
│ │ │ │ │ ├── BrowseController.kt
│ │ │ │ │ ├── LangHolder.kt
│ │ │ │ │ ├── LangItem.kt
│ │ │ │ │ ├── SourceAdapter.kt
│ │ │ │ │ ├── SourceDividerItemDecoration.kt
│ │ │ │ │ ├── SourceHolder.kt
│ │ │ │ │ ├── SourceItem.kt
│ │ │ │ │ ├── SourcePresenter.kt
│ │ │ │ │ ├── browse
│ │ │ │ │ │ ├── BrowseSourceController.kt
│ │ │ │ │ │ ├── BrowseSourceGridHolder.kt
│ │ │ │ │ │ ├── BrowseSourceHolder.kt
│ │ │ │ │ │ ├── BrowseSourceItem.kt
│ │ │ │ │ │ ├── BrowseSourceListHolder.kt
│ │ │ │ │ │ ├── BrowseSourcePager.kt
│ │ │ │ │ │ ├── BrowseSourcePresenter.kt
│ │ │ │ │ │ ├── LatestUpdatesPager.kt
│ │ │ │ │ │ ├── NoResultsException.kt
│ │ │ │ │ │ ├── Pager.kt
│ │ │ │ │ │ ├── ProgressItem.kt
│ │ │ │ │ │ ├── SavedSearchExtensions.kt
│ │ │ │ │ │ ├── SavedSearchesAdapter.kt
│ │ │ │ │ │ └── SourceFilterSheet.kt
│ │ │ │ │ ├── filter
│ │ │ │ │ │ ├── CheckboxItem.kt
│ │ │ │ │ │ ├── GroupItem.kt
│ │ │ │ │ │ ├── HeaderItem.kt
│ │ │ │ │ │ ├── SectionItems.kt
│ │ │ │ │ │ ├── SelectItem.kt
│ │ │ │ │ │ ├── SeparatorItem.kt
│ │ │ │ │ │ ├── SortGroup.kt
│ │ │ │ │ │ ├── SortItem.kt
│ │ │ │ │ │ ├── TextItem.kt
│ │ │ │ │ │ └── TriStateItem.kt
│ │ │ │ │ └── globalsearch
│ │ │ │ │ │ ├── GlobalSearchAdapter.kt
│ │ │ │ │ │ ├── GlobalSearchCardAdapter.kt
│ │ │ │ │ │ ├── GlobalSearchController.kt
│ │ │ │ │ │ ├── GlobalSearchHolder.kt
│ │ │ │ │ │ ├── GlobalSearchItem.kt
│ │ │ │ │ │ ├── GlobalSearchMangaHolder.kt
│ │ │ │ │ │ ├── GlobalSearchMangaItem.kt
│ │ │ │ │ │ └── GlobalSearchPresenter.kt
│ │ │ │ └── webview
│ │ │ │ │ ├── BaseWebViewActivity.kt
│ │ │ │ │ ├── WebViewActivity.kt
│ │ │ │ │ ├── WebViewScreen.kt
│ │ │ │ │ └── WebViewScreenModel.kt
│ │ │ │ ├── util
│ │ │ │ ├── BackupUtil.kt
│ │ │ │ ├── CrashLogUtil.kt
│ │ │ │ ├── MangaExtensions.kt
│ │ │ │ ├── PermissionUtil.kt
│ │ │ │ ├── PkceUtil.kt
│ │ │ │ ├── PreferenceExtensions.kt
│ │ │ │ ├── TimeUtil.kt
│ │ │ │ ├── WindowSize.kt
│ │ │ │ ├── chapter
│ │ │ │ │ ├── ChapterFilter.kt
│ │ │ │ │ ├── ChapterSanitizer.kt
│ │ │ │ │ ├── ChapterSort.kt
│ │ │ │ │ ├── ChapterSourceSync.kt
│ │ │ │ │ ├── ChapterTrackSync.kt
│ │ │ │ │ ├── ChapterUtil.kt
│ │ │ │ │ └── NoChaptersException.kt
│ │ │ │ ├── compose
│ │ │ │ │ ├── ColorSchemeExtensions.kt
│ │ │ │ │ └── Locals.kt
│ │ │ │ ├── lang
│ │ │ │ │ ├── DateExtensions.kt
│ │ │ │ │ ├── EnumExtensions.kt
│ │ │ │ │ ├── Hash.kt
│ │ │ │ │ ├── RetryWithDelay.kt
│ │ │ │ │ ├── RxExtensions.kt
│ │ │ │ │ └── StringExtensions.kt
│ │ │ │ ├── manga
│ │ │ │ │ ├── MangaCoverMetadata.kt
│ │ │ │ │ ├── MangaShortcutManager.kt
│ │ │ │ │ └── MangaUtil.kt
│ │ │ │ ├── storage
│ │ │ │ │ ├── DiskUtil.kt
│ │ │ │ │ ├── FileExtensions.kt
│ │ │ │ │ └── OkioExtensions.kt
│ │ │ │ ├── system
│ │ │ │ │ ├── AuthenticatorUtil.kt
│ │ │ │ │ ├── BooleanExtensions.kt
│ │ │ │ │ ├── CoilExtensions.kt
│ │ │ │ │ ├── ContextExtensions.kt
│ │ │ │ │ ├── DateExtensions.kt
│ │ │ │ │ ├── GLUtil.kt
│ │ │ │ │ ├── HashCode.kt
│ │ │ │ │ ├── ImageUtil.kt
│ │ │ │ │ ├── IntentExtensions.kt
│ │ │ │ │ ├── LocaleHelper.kt
│ │ │ │ │ ├── MaterialAlertDialogExtensions.kt
│ │ │ │ │ ├── NumberExtensions.kt
│ │ │ │ │ ├── PackageManagerExtensions.kt
│ │ │ │ │ ├── RxUtil.kt
│ │ │ │ │ ├── SideNavMode.kt
│ │ │ │ │ ├── ThemeUtil.kt
│ │ │ │ │ ├── Themes.kt
│ │ │ │ │ └── WindowInsetsExtensions.kt
│ │ │ │ └── view
│ │ │ │ │ ├── BottomSheetExtensions.kt
│ │ │ │ │ ├── ControllerExtensions.kt
│ │ │ │ │ ├── DeferredField.kt
│ │ │ │ │ ├── ImageViewExtensions.kt
│ │ │ │ │ ├── ViewExtensions.kt
│ │ │ │ │ └── ViewGroupExtensions.kt
│ │ │ │ └── widget
│ │ │ │ ├── AutofitRecyclerView.kt
│ │ │ │ ├── BaseTabbedScrollView.kt
│ │ │ │ ├── DrawerSwipeCloseListener.kt
│ │ │ │ ├── E2EBottomSheetDialog.kt
│ │ │ │ ├── EmptyView.kt
│ │ │ │ ├── EstimatedItemHeight.kt
│ │ │ │ ├── GifViewTarget.kt
│ │ │ │ ├── GridLayoutManagerAccurateOffset.kt
│ │ │ │ ├── IgnoreFirstSpinnerListener.kt
│ │ │ │ ├── LinearLayoutManagerAccurateOffset.kt
│ │ │ │ ├── MaterialSpinnerView.kt
│ │ │ │ ├── MenuSheetItemView.kt
│ │ │ │ ├── MinMaxNumberPicker.kt
│ │ │ │ ├── OutlineSpan.kt
│ │ │ │ ├── PreCachingLayoutManager.kt
│ │ │ │ ├── RecyclerViewPagerAdapter.kt
│ │ │ │ ├── RevealAnimationView.kt
│ │ │ │ ├── SimpleAnimationListener.kt
│ │ │ │ ├── SimpleNavigationView.kt
│ │ │ │ ├── SimpleTextWatcher.kt
│ │ │ │ ├── SortTextView.kt
│ │ │ │ ├── StaggeredGridLayoutManagerAccurateOffset.kt
│ │ │ │ ├── StatefulNestedScrollView.kt
│ │ │ │ ├── TabbedBottomSheet.kt
│ │ │ │ ├── TachiyomiTextInputEditText.kt
│ │ │ │ ├── TriStateCheckBox.kt
│ │ │ │ ├── ViewPagerAdapter.kt
│ │ │ │ ├── materialdialogs
│ │ │ │ ├── CustomDialogTitle.kt
│ │ │ │ ├── TriStateMultiChoiceDialogAdapter.kt
│ │ │ │ └── TriStateMultiChoiceViewHolder.kt
│ │ │ │ └── preference
│ │ │ │ ├── AdaptiveTitlePreferenceCategory.kt
│ │ │ │ ├── EditTextResetPreference.kt
│ │ │ │ ├── IntListMatPreference.kt
│ │ │ │ ├── ListMatPreference.kt
│ │ │ │ ├── LoginDialogPreference.kt
│ │ │ │ ├── MatPreference.kt
│ │ │ │ ├── MultiListMatPreference.kt
│ │ │ │ ├── SwitchPreferenceCategory.kt
│ │ │ │ ├── TrackLoginDialog.kt
│ │ │ │ ├── TrackLogoutDialog.kt
│ │ │ │ ├── TrackerPreference.kt
│ │ │ │ └── TriStateListPreference.kt
│ │ └── yokai
│ │ │ ├── core
│ │ │ ├── CrashlyticsLogWriter.kt
│ │ │ ├── RollingUniFileLogWriter.kt
│ │ │ ├── di
│ │ │ │ ├── AppModule.kt
│ │ │ │ ├── DomainModule.kt
│ │ │ │ └── PreferenceModule.kt
│ │ │ ├── metadata
│ │ │ │ └── ComicInfo.kt
│ │ │ └── migration
│ │ │ │ ├── Migration.kt
│ │ │ │ ├── MigrationCompletedListener.kt
│ │ │ │ ├── MigrationContext.kt
│ │ │ │ ├── MigrationJobFactory.kt
│ │ │ │ ├── MigrationStrategy.kt
│ │ │ │ ├── MigrationStrategyFactory.kt
│ │ │ │ ├── Migrator.kt
│ │ │ │ └── migrations
│ │ │ │ ├── CutoutMigration.kt
│ │ │ │ ├── ExtensionInstallerEnumMigration.kt
│ │ │ │ ├── Migrations.kt
│ │ │ │ ├── RepoJsonMigration.kt
│ │ │ │ ├── SetupAppUpdateMigration.kt
│ │ │ │ ├── SetupBackupCreateMigration.kt
│ │ │ │ ├── SetupExtensionUpdateMigration.kt
│ │ │ │ ├── SetupLibraryUpdateMigration.kt
│ │ │ │ └── ThePurgeMigration.kt
│ │ │ ├── data
│ │ │ ├── category
│ │ │ │ └── CategoryRepositoryImpl.kt
│ │ │ ├── chapter
│ │ │ │ └── ChapterRepositoryImpl.kt
│ │ │ ├── extension
│ │ │ │ └── repo
│ │ │ │ │ └── ExtensionRepoRepositoryImpl.kt
│ │ │ ├── history
│ │ │ │ └── HistoryRepositoryImpl.kt
│ │ │ ├── library
│ │ │ │ └── custom
│ │ │ │ │ └── CustomMangaRepositoryImpl.kt
│ │ │ ├── manga
│ │ │ │ ├── MangaRepositoryImpl.kt
│ │ │ │ └── models
│ │ │ │ │ └── MangaExtensions.kt
│ │ │ └── track
│ │ │ │ └── TrackRepositoryImpl.kt
│ │ │ ├── domain
│ │ │ ├── DialogHostState.kt
│ │ │ ├── Result.kt
│ │ │ ├── SplashState.kt
│ │ │ ├── backup
│ │ │ │ └── BackupPreferences.kt
│ │ │ ├── base
│ │ │ │ ├── BasePreferences.kt
│ │ │ │ └── models
│ │ │ │ │ └── Version.kt
│ │ │ ├── category
│ │ │ │ ├── CategoryRepository.kt
│ │ │ │ └── interactor
│ │ │ │ │ ├── DeleteCategories.kt
│ │ │ │ │ ├── GetCategories.kt
│ │ │ │ │ ├── InsertCategories.kt
│ │ │ │ │ ├── SetMangaCategories.kt
│ │ │ │ │ └── UpdateCategories.kt
│ │ │ ├── chapter
│ │ │ │ ├── ChapterRepository.kt
│ │ │ │ └── interactor
│ │ │ │ │ ├── DeleteChapter.kt
│ │ │ │ │ ├── GetAvailableScanlators.kt
│ │ │ │ │ ├── GetChapter.kt
│ │ │ │ │ ├── InsertChapter.kt
│ │ │ │ │ └── UpdateChapter.kt
│ │ │ ├── download
│ │ │ │ └── DownloadPreferences.kt
│ │ │ ├── extension
│ │ │ │ ├── interactor
│ │ │ │ │ └── TrustExtension.kt
│ │ │ │ └── repo
│ │ │ │ │ ├── ExtensionRepoRepository.kt
│ │ │ │ │ ├── exception
│ │ │ │ │ └── SaveExtensionRepoException.kt
│ │ │ │ │ ├── interactor
│ │ │ │ │ ├── CreateExtensionRepo.kt
│ │ │ │ │ ├── DeleteExtensionRepo.kt
│ │ │ │ │ ├── GetExtensionRepo.kt
│ │ │ │ │ ├── GetExtensionRepoCount.kt
│ │ │ │ │ ├── ReplaceExtensionRepo.kt
│ │ │ │ │ └── UpdateExtensionRepo.kt
│ │ │ │ │ └── service
│ │ │ │ │ └── ExtensionRepoService.kt
│ │ │ ├── history
│ │ │ │ ├── HistoryRepository.kt
│ │ │ │ └── interactor
│ │ │ │ │ ├── GetHistory.kt
│ │ │ │ │ └── UpsertHistory.kt
│ │ │ ├── library
│ │ │ │ ├── LibraryPreferences.kt
│ │ │ │ └── custom
│ │ │ │ │ ├── CustomMangaRepository.kt
│ │ │ │ │ ├── exception
│ │ │ │ │ └── SaveCustomMangaException.kt
│ │ │ │ │ ├── interactor
│ │ │ │ │ ├── CreateCustomManga.kt
│ │ │ │ │ ├── DeleteCustomManga.kt
│ │ │ │ │ ├── GetCustomManga.kt
│ │ │ │ │ └── RelinkCustomManga.kt
│ │ │ │ │ └── model
│ │ │ │ │ └── CustomMangaInfo.kt
│ │ │ ├── manga
│ │ │ │ ├── MangaRepository.kt
│ │ │ │ └── interactor
│ │ │ │ │ ├── GetLibraryManga.kt
│ │ │ │ │ ├── GetManga.kt
│ │ │ │ │ ├── InsertManga.kt
│ │ │ │ │ └── UpdateManga.kt
│ │ │ ├── recents
│ │ │ │ ├── RecentsPreferences.kt
│ │ │ │ └── interactor
│ │ │ │ │ └── GetRecents.kt
│ │ │ ├── source
│ │ │ │ ├── SourcePreferences.kt
│ │ │ │ └── browse
│ │ │ │ │ └── filter
│ │ │ │ │ ├── FilterSerializer.kt
│ │ │ │ │ ├── FilterTypeSerializer.kt
│ │ │ │ │ ├── interactor
│ │ │ │ │ ├── DeleteSavedSearch.kt
│ │ │ │ │ ├── GetSavedSearch.kt
│ │ │ │ │ └── InsertSavedSearch.kt
│ │ │ │ │ └── models
│ │ │ │ │ └── SavedSearch.kt
│ │ │ ├── storage
│ │ │ │ ├── StorageManager.kt
│ │ │ │ └── StoragePreferences.kt
│ │ │ ├── track
│ │ │ │ ├── TrackRepository.kt
│ │ │ │ └── interactor
│ │ │ │ │ ├── DeleteTrack.kt
│ │ │ │ │ ├── GetTrack.kt
│ │ │ │ │ └── InsertTrack.kt
│ │ │ └── ui
│ │ │ │ ├── UiPreferences.kt
│ │ │ │ └── settings
│ │ │ │ └── ReaderPreferences.kt
│ │ │ ├── presentation
│ │ │ ├── Scaffold.kt
│ │ │ ├── StatsScreenState.kt
│ │ │ ├── component
│ │ │ │ ├── AppBar.kt
│ │ │ │ ├── AppIcon.kt
│ │ │ │ ├── Banners.kt
│ │ │ │ ├── CircularProgressIndicator.kt
│ │ │ │ ├── EmptyScreen.kt
│ │ │ │ ├── Gap.kt
│ │ │ │ ├── LabeledCheckbox.kt
│ │ │ │ ├── LoadingButton.kt
│ │ │ │ ├── LoadingButtonComposeView.kt
│ │ │ │ ├── ThemeItem.kt
│ │ │ │ ├── ToolTip.kt
│ │ │ │ ├── TrackLogoIcon.kt
│ │ │ │ ├── preference
│ │ │ │ │ ├── Preference.kt
│ │ │ │ │ ├── PreferenceCommon.kt
│ │ │ │ │ ├── PreferenceItem.kt
│ │ │ │ │ └── widget
│ │ │ │ │ │ ├── BasePreferenceWidget.kt
│ │ │ │ │ │ ├── EditTextPreferenceWidget.kt
│ │ │ │ │ │ ├── InfoWidget.kt
│ │ │ │ │ │ ├── ListPreferenceWidget.kt
│ │ │ │ │ │ ├── MultiListPreferenceWidget.kt
│ │ │ │ │ │ ├── PreferenceGroupHeader.kt
│ │ │ │ │ │ ├── SliderPreferenceWidget.kt
│ │ │ │ │ │ ├── SwitchPreferenceWidget.kt
│ │ │ │ │ │ ├── TextPreferenceWidget.kt
│ │ │ │ │ │ ├── TrackingPreferenceWidget.kt
│ │ │ │ │ │ └── TriStateListDialog.kt
│ │ │ │ └── recyclerview
│ │ │ │ │ └── VertPaddingDecoration.kt
│ │ │ ├── extension
│ │ │ │ ├── ExtensionDetailsController.kt
│ │ │ │ └── repo
│ │ │ │ │ ├── ExtensionRepoController.kt
│ │ │ │ │ ├── ExtensionRepoScreen.kt
│ │ │ │ │ ├── ExtensionRepoScreenModel.kt
│ │ │ │ │ └── component
│ │ │ │ │ └── ExtensionRepoItem.kt
│ │ │ ├── library
│ │ │ │ ├── LibraryContent.kt
│ │ │ │ └── components
│ │ │ │ │ ├── CommonMangaItem.kt
│ │ │ │ │ └── LazyLibraryGrid.kt
│ │ │ ├── onboarding
│ │ │ │ ├── InfoScreen.kt
│ │ │ │ ├── OnboardingController.kt
│ │ │ │ ├── OnboardingScreen.kt
│ │ │ │ └── steps
│ │ │ │ │ ├── OnboardingStep.kt
│ │ │ │ │ ├── PermissionStep.kt
│ │ │ │ │ ├── StorageStep.kt
│ │ │ │ │ └── ThemeStep.kt
│ │ │ ├── reader
│ │ │ │ └── ChapterTransition.kt
│ │ │ ├── settings
│ │ │ │ ├── ComposableSettings.kt
│ │ │ │ ├── SettingsCommonWidget.kt
│ │ │ │ └── screen
│ │ │ │ │ ├── SettingsDataScreen.kt
│ │ │ │ │ ├── about
│ │ │ │ │ ├── AboutDialogs.kt
│ │ │ │ │ ├── AboutLibraryLicenseScreen.kt
│ │ │ │ │ ├── AboutLicenseScreen.kt
│ │ │ │ │ └── AboutScreen.kt
│ │ │ │ │ └── data
│ │ │ │ │ ├── AlertDialogs.kt
│ │ │ │ │ ├── Storage.kt
│ │ │ │ │ └── StorageInfo.kt
│ │ │ ├── theme
│ │ │ │ ├── Constants.kt
│ │ │ │ ├── Theme.kt
│ │ │ │ └── Typography.kt
│ │ │ └── webview
│ │ │ │ └── WebViewScreenContent.kt
│ │ │ └── util
│ │ │ ├── EpubReader.kt
│ │ │ ├── Levenshtein.kt
│ │ │ ├── LewdMangaChecker.kt
│ │ │ ├── ModifierExtensions.kt
│ │ │ ├── Navigation.kt
│ │ │ ├── SQLDelight.kt
│ │ │ └── coil
│ │ │ └── ImageViewExtensions.kt
│ └── res
│ │ ├── anim-ldrtl
│ │ └── fade_in_grow_from_top.xml
│ │ ├── anim
│ │ ├── enter_from_top.xml
│ │ ├── exit_to_top.xml
│ │ ├── fade_in_grow_from_top.xml
│ │ ├── fade_in_long.xml
│ │ └── fade_out_short.xml
│ │ ├── animator
│ │ └── icon_btn_state_list_anim.xml
│ │ ├── color-night
│ │ └── primary_container.xml
│ │ ├── color
│ │ ├── accent_text_btn_color_selector.xml
│ │ ├── action_bar_tint_alpha.xml
│ │ ├── bottom_nav_item_selector.xml
│ │ ├── bottom_nav_text_selector.xml
│ │ ├── button_action_selector.xml
│ │ ├── draggable_card_foreground.xml
│ │ ├── expanded_filter_text_selector.xml
│ │ ├── ext_bg_selector.xml
│ │ ├── ext_button_text_selector.xml
│ │ ├── library_comfortable_grid_foreground.xml
│ │ ├── library_comfortable_subtitle_selector.xml
│ │ ├── library_comfortable_title_selector.xml
│ │ ├── library_grid_foreground.xml
│ │ ├── library_stroke_selector.xml
│ │ ├── mtrl_btn_bg_selector.xml
│ │ ├── on_secondary_highlight.xml
│ │ ├── primary_button_text_color_selector.xml
│ │ ├── primary_container.xml
│ │ ├── ripple_nav.xml
│ │ ├── secondary_alpha.xml
│ │ ├── secondary_container.xml
│ │ ├── secondary_highlight.xml
│ │ ├── slider_active_track_color.xml
│ │ ├── slider_inactive_track_color.xml
│ │ ├── slider_tick_inactive.xml
│ │ ├── status_bar.xml
│ │ ├── surface_alpha.xml
│ │ ├── switch_thumb_tint.xml
│ │ ├── tabs_selector.xml
│ │ ├── tabs_selector_alt.xml
│ │ ├── tabs_selector_background.xml
│ │ ├── text_box_stroke_selector.xml
│ │ ├── text_btn_color_selector.xml
│ │ ├── text_color_hint.xml
│ │ ├── text_color_secondary.xml
│ │ └── text_input_stroke.xml
│ │ ├── drawable-en-rCA
│ │ └── ic_flag_en.xml
│ │ ├── drawable-en-rGB
│ │ └── ic_flag_en.xml
│ │ ├── drawable-en-rUS
│ │ └── ic_flag_en.xml
│ │ ├── drawable-nodpi
│ │ ├── ic_manga_updates.webp
│ │ ├── ic_tracker_anilist.webp
│ │ ├── ic_tracker_bangumi.webp
│ │ ├── ic_tracker_kavita.webp
│ │ ├── ic_tracker_kitsu.webp
│ │ ├── ic_tracker_komga.webp
│ │ ├── ic_tracker_mal.webp
│ │ ├── ic_tracker_shikimori.webp
│ │ └── ic_tracker_suwayomi.webp
│ │ ├── drawable
│ │ ├── anim_browse_filled_to_outline.xml
│ │ ├── anim_browse_outline_to_filled.xml
│ │ ├── anim_check_box_blank_to_checked_24dp.xml
│ │ ├── anim_check_box_checked_to_blank_24dp.xml
│ │ ├── anim_check_box_checked_to_indeterminate_24dp.xml
│ │ ├── anim_check_box_checked_to_x_24dp.xml
│ │ ├── anim_check_box_x_to_blank_24dp.xml
│ │ ├── anim_checkbox_blank_to_x_24dp.xml
│ │ ├── anim_checkbox_indeterminate_to_blank_24dp.xml
│ │ ├── anim_crop_to_free.xml
│ │ ├── anim_dl_to_check_to_dl.xml
│ │ ├── anim_expand_less_to_more.xml
│ │ ├── anim_expand_more_to_less.xml
│ │ ├── anim_free_to_crop.xml
│ │ ├── anim_incog_to_read.xml
│ │ ├── anim_lib_filled_to_outline.xml
│ │ ├── anim_lib_outline_to_filled.xml
│ │ ├── anim_outline_to_filled.xml
│ │ ├── anim_read_to_incog.xml
│ │ ├── anim_recents_filled_to_outline.xml
│ │ ├── anim_recents_outline_to_filled.xml
│ │ ├── anim_tachij2k_splash.xml
│ │ ├── appwidget_background.xml
│ │ ├── appwidget_cover_error.xml
│ │ ├── bg_sheet_gradient.xml
│ │ ├── border_circle.xml
│ │ ├── bottom_sheet_rounded_background.xml
│ │ ├── bubble_drawable.xml
│ │ ├── card_item_selector.xml
│ │ ├── chapter_nav.xml
│ │ ├── circle_progress.xml
│ │ ├── draggable_pill.xml
│ │ ├── expanded_filter_ripple.xml
│ │ ├── filled_circle.xml
│ │ ├── full_gradient.xml
│ │ ├── gradient_shape.xml
│ │ ├── ic_add_24dp.xml
│ │ ├── ic_appearance_outline_24dp.xml
│ │ ├── ic_arrow_back_24dp.xml
│ │ ├── ic_arrow_downward_24dp.xml
│ │ ├── ic_arrow_drop_down_24dp.xml
│ │ ├── ic_arrow_drop_up_24dp.xml
│ │ ├── ic_arrow_end_24dp.xml
│ │ ├── ic_arrow_forward_24dp.xml
│ │ ├── ic_arrow_start_24dp.xml
│ │ ├── ic_arrow_upward_24dp.xml
│ │ ├── ic_author_24dp.xml
│ │ ├── ic_backup_restore_24dp.xml
│ │ ├── ic_blank_24dp.xml
│ │ ├── ic_blank_28dp.xml
│ │ ├── ic_book_24dp.xml
│ │ ├── ic_book_open_split_24dp.xml
│ │ ├── ic_book_open_variant_24dp.xml
│ │ ├── ic_bookmark_24dp.xml
│ │ ├── ic_bookmark_border_24dp.xml
│ │ ├── ic_bookmark_off_24dp.xml
│ │ ├── ic_brief.xml
│ │ ├── ic_brightness_day_24dp.xml
│ │ ├── ic_broken_image_24dp.xml
│ │ ├── ic_browse_24dp.xml
│ │ ├── ic_browse_off_24dp.xml
│ │ ├── ic_browse_outline_24dp.xml
│ │ ├── ic_browse_selector_24dp.xml
│ │ ├── ic_bug_report_24dp.xml
│ │ ├── ic_calendar_text_outline_24dp.xml
│ │ ├── ic_check_24dp.xml
│ │ ├── ic_check_box_24dp.xml
│ │ ├── ic_check_box_indeterminate_24dp.xml
│ │ ├── ic_check_box_outline_blank_24dp.xml
│ │ ├── ic_check_box_x_24dp.xml
│ │ ├── ic_check_circle_24dp.xml
│ │ ├── ic_chevron_right_24dp.xml
│ │ ├── ic_close_24dp.xml
│ │ ├── ic_close_circle_24dp.xml
│ │ ├── ic_cloud_24dp.xml
│ │ ├── ic_code_24dp.xml
│ │ ├── ic_code_blocks_24dp.xml
│ │ ├── ic_content_copy_24dp.xml
│ │ ├── ic_delete_24dp.xml
│ │ ├── ic_discord_24dp.xml
│ │ ├── ic_done_24dp.xml
│ │ ├── ic_done_all_24dp.xml
│ │ ├── ic_download_off_24dp.xml
│ │ ├── ic_drag_handle_24dp.xml
│ │ ├── ic_edit_24dp.xml
│ │ ├── ic_expand_less_24dp.xml
│ │ ├── ic_expand_more_24dp.xml
│ │ ├── ic_extension_update_24dp.xml
│ │ ├── ic_extension_updated_24dp.xml
│ │ ├── ic_eye_24dp.xml
│ │ ├── ic_eye_down_24dp.xml
│ │ ├── ic_eye_off_24dp.xml
│ │ ├── ic_eye_off_down_24dp.xml
│ │ ├── ic_eye_off_range_24dp.xml
│ │ ├── ic_eye_off_up_24dp.xml
│ │ ├── ic_eye_range_24dp.xml
│ │ ├── ic_eye_remove_outline_24dp.xml
│ │ ├── ic_eye_up_24dp.xml
│ │ ├── ic_facebook_24dp.xml
│ │ ├── ic_file_download_24dp.xml
│ │ ├── ic_file_open_24dp.xml
│ │ ├── ic_filter_list_24dp.xml
│ │ ├── ic_flag_all.xml
│ │ ├── ic_flag_ar.xml
│ │ ├── ic_flag_bg.xml
│ │ ├── ic_flag_bn.xml
│ │ ├── ic_flag_br.xml
│ │ ├── ic_flag_ca.xml
│ │ ├── ic_flag_cn.xml
│ │ ├── ic_flag_cs.xml
│ │ ├── ic_flag_da.xml
│ │ ├── ic_flag_de.xml
│ │ ├── ic_flag_el.xml
│ │ ├── ic_flag_en.xml
│ │ ├── ic_flag_es.xml
│ │ ├── ic_flag_es_419.xml
│ │ ├── ic_flag_fa.xml
│ │ ├── ic_flag_fi.xml
│ │ ├── ic_flag_fil.xml
│ │ ├── ic_flag_fr.xml
│ │ ├── ic_flag_he.xml
│ │ ├── ic_flag_hi.xml
│ │ ├── ic_flag_hk.xml
│ │ ├── ic_flag_hu.xml
│ │ ├── ic_flag_id.xml
│ │ ├── ic_flag_in.xml
│ │ ├── ic_flag_it.xml
│ │ ├── ic_flag_ja.xml
│ │ ├── ic_flag_ko.xml
│ │ ├── ic_flag_korea.xml
│ │ ├── ic_flag_kr.xml
│ │ ├── ic_flag_lt.xml
│ │ ├── ic_flag_mm.xml
│ │ ├── ic_flag_mn.xml
│ │ ├── ic_flag_ms.xml
│ │ ├── ic_flag_my.xml
│ │ ├── ic_flag_ne.xml
│ │ ├── ic_flag_nl.xml
│ │ ├── ic_flag_nn.xml
│ │ ├── ic_flag_pl.xml
│ │ ├── ic_flag_pt.xml
│ │ ├── ic_flag_ro.xml
│ │ ├── ic_flag_ru.xml
│ │ ├── ic_flag_sh.xml
│ │ ├── ic_flag_sv.xml
│ │ ├── ic_flag_th.xml
│ │ ├── ic_flag_tr.xml
│ │ ├── ic_flag_uk.xml
│ │ ├── ic_flag_vi.xml
│ │ ├── ic_flag_zh.xml
│ │ ├── ic_flip_to_back_24dp.xml
│ │ ├── ic_format_list_numbered_24dp.xml
│ │ ├── ic_github_24dp.xml
│ │ ├── ic_glasses_24dp.xml
│ │ ├── ic_heart_24dp.xml
│ │ ├── ic_heart_off_24dp.xml
│ │ ├── ic_heart_outline_24dp.xml
│ │ ├── ic_help_24dp.xml
│ │ ├── ic_help_outline_24dp.xml
│ │ ├── ic_history_24dp.xml
│ │ ├── ic_history_off_24dp.xml
│ │ ├── ic_incognito_24dp.xml
│ │ ├── ic_incognito_circle_24dp.xml
│ │ ├── ic_indeterminate_check_box_24dp.xml
│ │ ├── ic_info_24dp.xml
│ │ ├── ic_info_outline_24dp.xml
│ │ ├── ic_label_24dp.xml
│ │ ├── ic_label_outline_24dp.xml
│ │ ├── ic_language_24dp.xml
│ │ ├── ic_launcher_monochrome.xml
│ │ ├── ic_libary_filled_24dp.xml
│ │ ├── ic_library_outline_24dp.xml
│ │ ├── ic_library_selector_24dp.xml
│ │ ├── ic_lock_24dp.xml
│ │ ├── ic_more_vert_24dp.xml
│ │ ├── ic_new_releases_24dp.xml
│ │ ├── ic_open_in_new_24dp.xml
│ │ ├── ic_open_in_webview_24dp.xml
│ │ ├── ic_outline_photo_24dp.xml
│ │ ├── ic_outline_save_24dp.xml
│ │ ├── ic_outline_settings_24dp.xml
│ │ ├── ic_outline_share_24dp.xml
│ │ ├── ic_page_next_outline_24dp.xml
│ │ ├── ic_page_previous_outline_24dp.xml
│ │ ├── ic_pause_24dp.xml
│ │ ├── ic_photo_24dp.xml
│ │ ├── ic_pin_24dp.xml
│ │ ├── ic_pin_outline_24dp.xml
│ │ ├── ic_play_arrow_24dp.xml
│ │ ├── ic_plus_24dp.xml
│ │ ├── ic_progress_clock_24dp.xml
│ │ ├── ic_query_stats_24dp.xml
│ │ ├── ic_radio_button_unchecked_24dp.xml
│ │ ├── ic_read_24dp.xml
│ │ ├── ic_read_outline_24dp.xml
│ │ ├── ic_reader_continuous_vertical_24dp.xml
│ │ ├── ic_reader_default_24dp.xml
│ │ ├── ic_reader_ltr_24dp.xml
│ │ ├── ic_reader_rtl_24dp.xml
│ │ ├── ic_reader_vertical_24dp.xml
│ │ ├── ic_reader_webtoon_24dp.xml
│ │ ├── ic_recent_read_32dp.xml
│ │ ├── ic_recent_read_outline_24dp.xml
│ │ ├── ic_recents_filled_24dp.xml
│ │ ├── ic_recents_outline_24dp.xml
│ │ ├── ic_recents_selector_24dp.xml
│ │ ├── ic_reddit_24dp.xml
│ │ ├── ic_refresh_24dp.xml
│ │ ├── ic_report_24dp.xml
│ │ ├── ic_rounded_tooltip_24dp.xml
│ │ ├── ic_save_24dp.xml
│ │ ├── ic_save_all_outline_24dp.xml
│ │ ├── ic_screen_lock_landscape_24dp.xml
│ │ ├── ic_screen_lock_portrait_24dp.xml
│ │ ├── ic_screen_rotation_24dp.xml
│ │ ├── ic_search_24dp.xml
│ │ ├── ic_search_off_24dp.xml
│ │ ├── ic_security_24dp.xml
│ │ ├── ic_select_all_24dp.xml
│ │ ├── ic_select_none_24dp.xml
│ │ ├── ic_settings_24dp.xml
│ │ ├── ic_share_24dp.xml
│ │ ├── ic_share_all_outline_24dp.xml
│ │ ├── ic_show_all_categories_24dp.xml
│ │ ├── ic_shuffle_24dp.xml
│ │ ├── ic_single_page_24dp.xml
│ │ ├── ic_skip_next_24.xml
│ │ ├── ic_skip_previous_24.xml
│ │ ├── ic_sort_24dp.xml
│ │ ├── ic_sort_by_alpha_24dp.xml
│ │ ├── ic_sort_by_numeric_24dp.xml
│ │ ├── ic_star_12dp.xml
│ │ ├── ic_start_reading_24dp.xml
│ │ ├── ic_stay_current_landscape_24dp.xml
│ │ ├── ic_stay_current_portrait_24dp.xml
│ │ ├── ic_storage_24dp.xml
│ │ ├── ic_style_24dp.xml
│ │ ├── ic_swap_calls_24dp.xml
│ │ ├── ic_swap_vert_24dp.xml
│ │ ├── ic_sync_24dp.xml
│ │ ├── ic_system_update_24dp.xml
│ │ ├── ic_tachi.xml
│ │ ├── ic_tachi_monochrome_launcher.xml
│ │ ├── ic_tachij2k.xml
│ │ ├── ic_tachij2k_notification.xml
│ │ ├── ic_tracker_manga_updates.webp
│ │ ├── ic_translate_24dp.xml
│ │ ├── ic_tune_24dp.xml
│ │ ├── ic_unfold_less_horizontal_24dp.xml
│ │ ├── ic_unfold_more_horizontal_24dp.xml
│ │ ├── ic_ungroup_24dp.xml
│ │ ├── ic_view_list_24dp.xml
│ │ ├── ic_view_module_24dp.xml
│ │ ├── ic_warning_white_24dp.xml
│ │ ├── ic_x_24dp.xml
│ │ ├── ic_yokai.xml
│ │ ├── ic_yokai_splash.xml
│ │ ├── image_border_background.xml
│ │ ├── item_background_borderless_on_secondary.xml
│ │ ├── library_grid_selector.xml
│ │ ├── library_grid_selector_overlay.xml
│ │ ├── line_chart_fill.xml
│ │ ├── line_divider.xml
│ │ ├── list_item_selector.xml
│ │ ├── material_list_item_selector.xml
│ │ ├── oval.xml
│ │ ├── oval_ripple.xml
│ │ ├── reader_toolbar_ripple.xml
│ │ ├── rect_ripple.xml
│ │ ├── round_clear_border.xml
│ │ ├── round_play_background.xml
│ │ ├── round_ripple.xml
│ │ ├── round_textview_border.xml
│ │ ├── rounded_item_background.xml
│ │ ├── rounded_preview_rect.xml
│ │ ├── rounded_ripple.xml
│ │ ├── sc_extensions_48dp.xml
│ │ ├── shape_gradient_start_shadow.xml
│ │ ├── shape_gradient_top_shadow.xml
│ │ ├── square_ripple.xml
│ │ ├── tab_highlight_indicator.xml
│ │ ├── tab_indicator.xml
│ │ ├── theme_selected_border.xml
│ │ ├── thumb_drawable.xml
│ │ ├── transparent_item_selector.xml
│ │ ├── unread_angled_badge.xml
│ │ └── updates_grid_widget_preview.webp
│ │ ├── layout-h600dp
│ │ └── common_view_empty.xml
│ │ ├── layout-land
│ │ └── stats_details_controller.xml
│ │ ├── layout-sw600dp-land
│ │ └── manga_header_item.xml
│ │ ├── layout-sw600dp-port
│ │ └── manga_header_item.xml
│ │ ├── layout-w720dp
│ │ └── main_activity.xml
│ │ ├── layout
│ │ ├── add_category_item.xml
│ │ ├── appwidget_loading.xml
│ │ ├── bottom_menu_sheet.xml
│ │ ├── browse_controller.xml
│ │ ├── browse_source_controller.xml
│ │ ├── categories_controller.xml
│ │ ├── categories_item.xml
│ │ ├── catergory_text_view.xml
│ │ ├── chapter_filter_layout.xml
│ │ ├── chapter_header_item.xml
│ │ ├── chapter_sort_bottom_sheet.xml
│ │ ├── chapters_item.xml
│ │ ├── clear_database_controller.xml
│ │ ├── clear_database_source_item.xml
│ │ ├── common_spinner_item.xml
│ │ ├── common_view_empty.xml
│ │ ├── custom_dialog_title_message.xml
│ │ ├── custom_marker_view.xml
│ │ ├── debug_info_item.xml
│ │ ├── dialog_quadstate.xml
│ │ ├── dialog_text_input.xml
│ │ ├── download_bottom_sheet.xml
│ │ ├── download_button.xml
│ │ ├── download_header.xml
│ │ ├── download_item.xml
│ │ ├── download_swipe_tut_item.xml
│ │ ├── edit_manga_dialog.xml
│ │ ├── expanded_filter_item.xml
│ │ ├── expanded_filter_item_text_view.xml
│ │ ├── expanded_filter_sheet.xml
│ │ ├── extension_card_header.xml
│ │ ├── extension_card_item.xml
│ │ ├── extension_detail_controller.xml
│ │ ├── extension_detail_header.xml
│ │ ├── extensions_bottom_sheet.xml
│ │ ├── filter_bottom_sheet.xml
│ │ ├── filter_tag_group.xml
│ │ ├── full_cover_dialog.xml
│ │ ├── genre_chip.xml
│ │ ├── in_library_badge.xml
│ │ ├── library_badges_layout.xml
│ │ ├── library_category_header_item.xml
│ │ ├── library_category_layout.xml
│ │ ├── library_controller.xml
│ │ ├── library_display_layout.xml
│ │ ├── library_grid_recycler.xml
│ │ ├── list_chart_legend.xml
│ │ ├── list_stats_details.xml
│ │ ├── listitem_tristatechoice.xml
│ │ ├── main_activity.xml
│ │ ├── manga_category_dialog.xml
│ │ ├── manga_details_controller.xml
│ │ ├── manga_grid_item.xml
│ │ ├── manga_header_item.xml
│ │ ├── manga_list_item.xml
│ │ ├── manga_recycler_autofit.xml
│ │ ├── material_fastscroll.xml
│ │ ├── material_spinner_view.xml
│ │ ├── material_text_button.xml
│ │ ├── menu_sheet_item.xml
│ │ ├── migration_bottom_sheet.xml
│ │ ├── migration_card_item.xml
│ │ ├── migration_controller.xml
│ │ ├── migration_list_controller.xml
│ │ ├── migration_process_item.xml
│ │ ├── migration_source_item.xml
│ │ ├── navigation_view_checkbox.xml
│ │ ├── navigation_view_checkedtext.xml
│ │ ├── navigation_view_group.xml
│ │ ├── navigation_view_radio.xml
│ │ ├── navigation_view_spinner.xml
│ │ ├── navigation_view_text.xml
│ │ ├── navigation_view_tristatebox.xml
│ │ ├── pre_migration_controller.xml
│ │ ├── pref_about_links.xml
│ │ ├── pref_account_login.xml
│ │ ├── pref_tracker_item.xml
│ │ ├── pref_widget_imageview.xml
│ │ ├── preference_widget_material_switch.xml
│ │ ├── reader_activity.xml
│ │ ├── reader_chapter_item.xml
│ │ ├── reader_chapters_sheet.xml
│ │ ├── reader_color_filter.xml
│ │ ├── reader_error.xml
│ │ ├── reader_general_layout.xml
│ │ ├── reader_nav.xml
│ │ ├── reader_paged_layout.xml
│ │ ├── reader_transition_view.xml
│ │ ├── recent_chapters_section_item.xml
│ │ ├── recent_manga_item.xml
│ │ ├── recent_sub_chapter_item.xml
│ │ ├── recents_controller.xml
│ │ ├── recents_footer_item.xml
│ │ ├── recents_general_view.xml
│ │ ├── recents_header_item.xml
│ │ ├── recents_history_view.xml
│ │ ├── recents_updates_view.xml
│ │ ├── recycler_with_scroller.xml
│ │ ├── rounded_category_hopper.xml
│ │ ├── set_categories_sheet.xml
│ │ ├── settings_search_controller.xml
│ │ ├── settings_search_controller_card.xml
│ │ ├── sort_text_view.xml
│ │ ├── source_filter_sheet.xml
│ │ ├── source_filter_sheet_saved_search.xml
│ │ ├── source_global_search_controller.xml
│ │ ├── source_global_search_controller_card.xml
│ │ ├── source_global_search_controller_card_item.xml
│ │ ├── source_header_item.xml
│ │ ├── source_item.xml
│ │ ├── source_progress_item.xml
│ │ ├── stats_controller.xml
│ │ ├── stats_details_chart.xml
│ │ ├── stats_details_controller.xml
│ │ ├── sub_debug_controller.xml
│ │ ├── tabbed_bottom_sheet.xml
│ │ ├── tachi_overflow_layout.xml
│ │ ├── theme_item.xml
│ │ ├── themes_preference.xml
│ │ ├── track_chapters_dialog.xml
│ │ ├── track_item.xml
│ │ ├── track_score_dialog.xml
│ │ ├── track_search_item.xml
│ │ ├── tracking_bottom_sheet.xml
│ │ ├── tri_state_check_box.xml
│ │ ├── unread_download_badge.xml
│ │ └── webview_activity.xml
│ │ ├── menu
│ │ ├── bottom_navigation.xml
│ │ ├── browse_source.xml
│ │ ├── catalogue_main.xml
│ │ ├── catalogue_new_list.xml
│ │ ├── chapter_download.xml
│ │ ├── chapter_single.xml
│ │ ├── clear_database.xml
│ │ ├── download_queue.xml
│ │ ├── download_single.xml
│ │ ├── extension_details.xml
│ │ ├── extension_main.xml
│ │ ├── filtered_library.xml
│ │ ├── generic_selection.xml
│ │ ├── library.xml
│ │ ├── library_selection.xml
│ │ ├── manga_details.xml
│ │ ├── manga_details_tag.xml
│ │ ├── manga_details_title.xml
│ │ ├── migration_list.xml
│ │ ├── migration_main.xml
│ │ ├── migration_single.xml
│ │ ├── pre_migration.xml
│ │ ├── reader.xml
│ │ ├── recents.xml
│ │ ├── search.xml
│ │ ├── settings_backup.xml
│ │ ├── settings_main.xml
│ │ ├── settings_sources.xml
│ │ ├── stats_bar.xml
│ │ ├── sub_debug_info.xml
│ │ └── webview.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_local_source.webp
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_local_source.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_local_source.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_local_source.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_local_source.webp
│ │ ├── values-night-v31
│ │ ├── colors_appwidget.xml
│ │ └── themes.xml
│ │ ├── values-night
│ │ ├── attrs.xml
│ │ ├── color_lavender.xml
│ │ └── colors.xml
│ │ ├── values-v28
│ │ └── arrays.xml
│ │ ├── values-v31
│ │ ├── colors_appwidget.xml
│ │ └── themes.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── attrs.xml
│ │ ├── color_lavender.xml
│ │ ├── colors.xml
│ │ ├── colors_appwidget.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ids.xml
│ │ ├── styles.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── backup_rules.xml
│ │ ├── network_security_config.xml
│ │ ├── provider_paths.xml
│ │ ├── s_pen_actions.xml
│ │ ├── searchable.xml
│ │ └── updates_grid_glance_widget_info.xml
│ ├── nightly
│ └── res
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ └── strings.xml
│ ├── standard
│ ├── AndroidManifest.xml
│ └── google-services.json
│ └── test
│ └── java
│ ├── eu
│ └── kanade
│ │ └── tachiyomi
│ │ └── data
│ │ └── updater
│ │ └── AppUpdateCheckerTest.kt
│ └── yokai
│ ├── core
│ └── migration
│ │ └── MigratorTest.kt
│ └── util
│ └── LevenshteinTest.kt
├── build.gradle.kts
├── buildSrc
├── .gitignore
├── build.gradle.kts
├── settings.gradle.kts
└── src
│ └── main
│ └── kotlin
│ ├── AndroidConfig.kt
│ ├── LocalesConfigPlugin.kt
│ ├── yokai.android.application.compose.gradle.kts
│ ├── yokai.android.application.gradle.kts
│ ├── yokai.android.library.compose.gradle.kts
│ ├── yokai.android.library.gradle.kts
│ └── yokai
│ └── build
│ └── ProjectExtensions.kt
├── core
├── archive
│ ├── build.gradle.kts
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── yokai
│ │ └── core
│ │ └── archive
│ │ ├── ArchiveEntry.kt
│ │ ├── ArchiveInputStream.kt
│ │ ├── ArchiveReader.kt
│ │ ├── EpubReader.kt
│ │ ├── ZipWriter.kt
│ │ └── util
│ │ └── UniFileExtensions.kt
└── main
│ ├── build.gradle.kts
│ └── src
│ ├── androidMain
│ ├── AndroidManifest.xml
│ └── kotlin
│ │ ├── eu
│ │ └── kanade
│ │ │ └── tachiyomi
│ │ │ ├── core
│ │ │ └── preference
│ │ │ │ ├── AndroidPreference.kt
│ │ │ │ └── AndroidPreferenceStore.kt
│ │ │ ├── network
│ │ │ ├── AndroidCookieJar.kt
│ │ │ ├── DohProviders.kt
│ │ │ ├── JavaScriptEngine.kt
│ │ │ ├── NetworkHelper.kt
│ │ │ ├── OkHttpExtensions.kt
│ │ │ ├── ProgressResponseBody.kt
│ │ │ ├── Requests.kt
│ │ │ └── interceptor
│ │ │ │ ├── CloudflareInterceptor.kt
│ │ │ │ ├── IgnoreGzipInterceptor.kt
│ │ │ │ ├── RateLimitInterceptor.kt
│ │ │ │ ├── SpecificHostRateLimitInterceptor.kt
│ │ │ │ ├── UncaughtExceptionInterceptor.kt
│ │ │ │ ├── UserAgentInterceptor.kt
│ │ │ │ └── WebViewInterceptor.kt
│ │ │ └── util
│ │ │ └── system
│ │ │ ├── DensityExtensions.kt
│ │ │ ├── DeviceUtil.kt
│ │ │ ├── ToastExtensions.kt
│ │ │ ├── UniFileExtensions.kt
│ │ │ ├── WebViewClientCompat.kt
│ │ │ └── WebViewUtil.kt
│ │ └── yokai
│ │ └── util
│ │ └── lang
│ │ └── RxCoroutineBridge.kt
│ ├── commonMain
│ └── kotlin
│ │ └── eu
│ │ └── kanade
│ │ └── tachiyomi
│ │ ├── core
│ │ ├── preference
│ │ │ ├── Preference.kt
│ │ │ └── PreferenceStore.kt
│ │ └── security
│ │ │ └── SecurityPreferences.kt
│ │ ├── network
│ │ ├── NetworkPreferences.kt
│ │ └── ProgressListener.kt
│ │ └── util
│ │ └── system
│ │ ├── CoroutinesExtensions.kt
│ │ └── KermitExtensions.kt
│ └── iosMain
│ └── kotlin
│ └── eu
│ └── kanade
│ └── tachiyomi
│ └── core
│ └── preference
│ ├── DarwinPreference.kt
│ └── DarwinPreferenceStore.kt
├── data
├── build.gradle.kts
└── src
│ ├── androidMain
│ ├── AndroidManifest.xml
│ └── kotlin
│ │ └── yokai
│ │ └── data
│ │ ├── AndroidDatabaseHandler.kt
│ │ └── TransactionContext.kt
│ └── commonMain
│ ├── kotlin
│ └── yokai
│ │ └── data
│ │ ├── DatabaseAdapter.kt
│ │ ├── DatabaseHandler.kt
│ │ ├── source
│ │ └── browse
│ │ │ └── filter
│ │ │ └── SavedSearchRepositoryImpl.kt
│ │ └── util
│ │ └── SqlDelightUtil.kt
│ └── sqldelight
│ └── tachiyomi
│ ├── data
│ ├── categories.sq
│ ├── chapters.sq
│ ├── custom_manga_info.sq
│ ├── extension_repos.sq
│ ├── history.sq
│ ├── manga_sync.sq
│ ├── mangas.sq
│ ├── mangas_categories.sq
│ └── saved_search.sq
│ ├── migrations
│ ├── 1.sqm
│ ├── 10.sqm
│ ├── 11.sqm
│ ├── 12.sqm
│ ├── 13.sqm
│ ├── 14.sqm
│ ├── 15.sqm
│ ├── 16.sqm
│ ├── 17.sqm
│ ├── 18.sqm
│ ├── 19.sqm
│ ├── 2.sqm
│ ├── 20.sqm
│ ├── 21.sqm
│ ├── 22.sqm
│ ├── 23.sqm
│ ├── 24.sqm
│ ├── 25.sqm
│ ├── 26.sqm
│ ├── 27.sqm
│ ├── 28.sqm
│ ├── 3.sqm
│ ├── 4.sqm
│ ├── 5.sqm
│ ├── 6.sqm
│ ├── 7.sqm
│ ├── 8.sqm
│ └── 9.sqm
│ └── view
│ ├── library_view.sq
│ └── scanlators_view.sq
├── domain
├── build.gradle.kts
└── src
│ ├── commonMain
│ └── kotlin
│ │ ├── eu
│ │ └── kanade
│ │ │ └── tachiyomi
│ │ │ └── domain
│ │ │ └── manga
│ │ │ └── models
│ │ │ └── Manga.kt
│ │ └── yokai
│ │ └── domain
│ │ ├── category
│ │ └── models
│ │ │ └── CategoryUpdate.kt
│ │ ├── chapter
│ │ ├── models
│ │ │ └── ChapterUpdate.kt
│ │ └── services
│ │ │ └── ChapterRecognition.kt
│ │ ├── extension
│ │ └── repo
│ │ │ ├── model
│ │ │ └── ExtensionRepo.kt
│ │ │ └── service
│ │ │ └── ExtensionRepoDto.kt
│ │ ├── manga
│ │ └── models
│ │ │ ├── Manga.kt
│ │ │ ├── MangaCover.kt
│ │ │ └── MangaUpdate.kt
│ │ └── source
│ │ └── browse
│ │ └── filter
│ │ ├── SavedSearchRepository.kt
│ │ └── models
│ │ └── RawSavedSearch.kt
│ └── commonTest
│ └── kotlin
│ └── yokai
│ └── domain
│ └── chapter
│ └── services
│ └── ChapterRecognitionTest.kt
├── gradle.properties
├── gradle
├── androidx.versions.toml
├── compose.versions.toml
├── kotlinx.versions.toml
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── i18n
├── README.md
├── build.gradle.kts
└── src
│ ├── androidMain
│ ├── AndroidManifest.xml
│ └── kotlin
│ │ └── yokai
│ │ └── util
│ │ └── lang
│ │ └── MokoExtensions.kt
│ └── commonMain
│ └── moko-resources
│ ├── ar
│ ├── plurals.xml
│ └── strings.xml
│ ├── az
│ ├── plurals.xml
│ └── strings.xml
│ ├── base
│ ├── plurals.xml
│ └── strings.xml
│ ├── bg
│ ├── plurals.xml
│ └── strings.xml
│ ├── bn
│ ├── plurals.xml
│ └── strings.xml
│ ├── ca
│ ├── plurals.xml
│ └── strings.xml
│ ├── ceb
│ ├── plurals.xml
│ └── strings.xml
│ ├── cs
│ ├── plurals.xml
│ └── strings.xml
│ ├── cv
│ ├── plurals.xml
│ └── strings.xml
│ ├── de
│ ├── plurals.xml
│ └── strings.xml
│ ├── el
│ ├── plurals.xml
│ └── strings.xml
│ ├── eo
│ ├── plurals.xml
│ └── strings.xml
│ ├── es
│ ├── plurals.xml
│ └── strings.xml
│ ├── eu
│ ├── plurals.xml
│ └── strings.xml
│ ├── fa
│ ├── plurals.xml
│ └── strings.xml
│ ├── fi
│ ├── plurals.xml
│ └── strings.xml
│ ├── fil
│ ├── plurals.xml
│ └── strings.xml
│ ├── fr
│ ├── plurals.xml
│ └── strings.xml
│ ├── gl
│ ├── plurals.xml
│ └── strings.xml
│ ├── ha
│ ├── plurals.xml
│ └── strings.xml
│ ├── hi
│ ├── plurals.xml
│ └── strings.xml
│ ├── hr
│ ├── plurals.xml
│ └── strings.xml
│ ├── hu
│ ├── plurals.xml
│ └── strings.xml
│ ├── in
│ ├── plurals.xml
│ └── strings.xml
│ ├── it
│ ├── plurals.xml
│ └── strings.xml
│ ├── iw
│ ├── plurals.xml
│ └── strings.xml
│ ├── ja
│ ├── plurals.xml
│ └── strings.xml
│ ├── jv
│ ├── plurals.xml
│ └── strings.xml
│ ├── ka
│ ├── plurals.xml
│ └── strings.xml
│ ├── kk
│ ├── plurals.xml
│ └── strings.xml
│ ├── km
│ ├── plurals.xml
│ └── strings.xml
│ ├── ko
│ ├── plurals.xml
│ └── strings.xml
│ ├── lt
│ ├── plurals.xml
│ └── strings.xml
│ ├── lv
│ ├── plurals.xml
│ └── strings.xml
│ ├── mn
│ ├── plurals.xml
│ └── strings.xml
│ ├── ms
│ ├── plurals.xml
│ └── strings.xml
│ ├── my
│ ├── plurals.xml
│ └── strings.xml
│ ├── nb-rNO
│ ├── plurals.xml
│ └── strings.xml
│ ├── ne
│ ├── plurals.xml
│ └── strings.xml
│ ├── nl
│ ├── plurals.xml
│ └── strings.xml
│ ├── nn
│ ├── plurals.xml
│ └── strings.xml
│ ├── om
│ ├── plurals.xml
│ └── strings.xml
│ ├── or
│ ├── plurals.xml
│ └── strings.xml
│ ├── pl
│ ├── plurals.xml
│ └── strings.xml
│ ├── pt-rBR
│ ├── plurals.xml
│ └── strings.xml
│ ├── pt
│ ├── plurals.xml
│ └── strings.xml
│ ├── ro
│ ├── plurals.xml
│ └── strings.xml
│ ├── ru
│ ├── plurals.xml
│ └── strings.xml
│ ├── sc
│ ├── plurals.xml
│ └── strings.xml
│ ├── si
│ ├── plurals.xml
│ └── strings.xml
│ ├── sk
│ ├── plurals.xml
│ └── strings.xml
│ ├── sq
│ ├── plurals.xml
│ └── strings.xml
│ ├── sr
│ ├── plurals.xml
│ └── strings.xml
│ ├── sv
│ ├── plurals.xml
│ └── strings.xml
│ ├── te
│ ├── plurals.xml
│ └── strings.xml
│ ├── th
│ ├── plurals.xml
│ └── strings.xml
│ ├── ti
│ ├── plurals.xml
│ └── strings.xml
│ ├── tl
│ ├── plurals.xml
│ └── strings.xml
│ ├── tr
│ ├── plurals.xml
│ └── strings.xml
│ ├── uk
│ ├── plurals.xml
│ └── strings.xml
│ ├── ur
│ ├── plurals.xml
│ └── strings.xml
│ ├── vi
│ ├── plurals.xml
│ └── strings.xml
│ ├── zh-rCN
│ ├── plurals.xml
│ └── strings.xml
│ └── zh-rTW
│ ├── plurals.xml
│ └── strings.xml
├── ktlintCodeStyle.xml
├── presentation
├── core
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── yokai
│ │ │ └── presentation
│ │ │ └── core
│ │ │ ├── AppBar.kt
│ │ │ ├── Constants.kt
│ │ │ ├── Scrollbar.kt
│ │ │ ├── components
│ │ │ ├── LazyGrid.kt
│ │ │ ├── LinkIcon.kt
│ │ │ └── VerticalFastScroller.kt
│ │ │ ├── icons
│ │ │ ├── CustomIcons.kt
│ │ │ ├── Discord.kt
│ │ │ ├── GitHub.kt
│ │ │ └── LocalSource.kt
│ │ │ └── util
│ │ │ ├── IntentCommon.kt
│ │ │ └── PaddingValues.kt
│ │ └── res
│ │ └── values
│ │ └── colors.xml
└── widget
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── proguard-rules.pro
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── yokai
│ │ └── presentation
│ │ └── widget
│ │ ├── TachiyomiWidgetManager.kt
│ │ ├── UpdatesGridGlanceReceiver.kt
│ │ ├── UpdatesGridGlanceWidget.kt
│ │ ├── components
│ │ ├── LockedWidget.kt
│ │ ├── UpdatesMangaCover.kt
│ │ └── UpdatesWidget.kt
│ │ └── util
│ │ └── GlanceUtils.kt
│ └── res
│ ├── drawable
│ ├── appwidget_background.xml
│ └── appwidget_cover_error.xml
│ ├── values-v31
│ └── colors.xml
│ └── values
│ └── dimens.xml
├── settings.gradle.kts
└── source
└── api
├── build.gradle.kts
├── consumer-proguard.pro
└── src
├── androidMain
├── AndroidManifest.xml
└── kotlin
│ └── eu
│ └── kanade
│ └── tachiyomi
│ └── util
│ └── RxExtension.kt
└── commonMain
└── kotlin
└── eu
└── kanade
└── tachiyomi
├── source
├── CatalogueSource.kt
├── ConfigurableSource.kt
├── Source.kt
├── SourceFactory.kt
├── UnmeteredSource.kt
├── model
│ ├── Filter.kt
│ ├── FilterList.kt
│ ├── MangasPage.kt
│ ├── Page.kt
│ ├── SChapter.kt
│ ├── SChapterImpl.kt
│ ├── SManga.kt
│ ├── SMangaImpl.kt
│ └── UpdateStrategy.kt
└── online
│ ├── DelegatedHttpSource.kt
│ ├── HttpSource.kt
│ └── ParsedHttpSource.kt
└── util
├── JsoupExtensions.kt
└── RxExtension.kt
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | * text eol=lf
3 |
4 | # Windows forced line-endings
5 | /.idea/* text eol=crlf
6 |
7 | # Gradle wrapper
8 | *.jar binary
9 |
10 | # Images
11 | *.webp binary
12 | *.png binary
13 | *.jpg binary
14 | *.jpeg binary
15 | *.gif binary
16 | *.ico binary
17 | *.gz binary
18 | *.zip binary
19 | *.7z binary
20 | *.ttf binary
21 | *.eot binary
22 | *.woff binary
23 | *.pyc binary
24 | *.swp binary
25 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [null2264]
2 | ko_fi: ziro2264
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: 🖥️ Mihon website
4 | url: https://mihon.app/help/
5 | about: Guides, troubleshooting, and answers to common questions
6 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | ---
7 |
8 | Add a :+1: [reaction] to [pull requests you find important].
9 |
10 | [reaction]: https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/
11 | [pull requests you find important]: https://github.com/null2264/yokai/pulls?q=is%3Aopen+sort%3Areactions-%2B1-desc
12 |
--------------------------------------------------------------------------------
/.github/readme-images/app-icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/.github/readme-images/app-icon.webp
--------------------------------------------------------------------------------
/.github/readme-images/material snackbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/.github/readme-images/material snackbar.png
--------------------------------------------------------------------------------
/.github/readme-images/screens.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/.github/readme-images/screens.gif
--------------------------------------------------------------------------------
/.github/readme-images/share menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/.github/readme-images/share menu.png
--------------------------------------------------------------------------------
/.github/runner-files/ci-gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.daemon=false
2 | org.gradle.jvmargs=-Xmx5120m
3 | org.gradle.workers.max=2
4 |
5 | kotlin.incremental=false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | .DS_Store
5 | /build
6 | .idea/
7 | *iml
8 | *.iml
9 | */build
10 | */*/build
11 | .kotlin/
12 | kls_database.db
13 | weblate.conf
14 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | *iml
3 | *.iml
4 | custom.gradle
--------------------------------------------------------------------------------
/app/src/debug/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/debug/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/debug/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Yōkai Debug
4 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/null2264/yokai/17879ddc5abb6e2c82a85861cbfa17ffaa32c625/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/annotations/Nsfw.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.annotations
2 |
3 | @Retention(AnnotationRetention.RUNTIME)
4 | @Target(AnnotationTarget.CLASS)
5 | annotation class Nsfw
6 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/appwidget/TachiyomiWidgetManager.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.appwidget
2 |
3 | import android.content.Context
4 | import androidx.glance.appwidget.GlanceAppWidgetManager
5 |
6 | class TachiyomiWidgetManager {
7 |
8 | suspend fun Context.init() {
9 | val manager = GlanceAppWidgetManager(this)
10 | if (manager.getGlanceIds(UpdatesGridGlanceWidget::class.java).isNotEmpty()) {
11 | UpdatesGridGlanceWidget().loadData()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/appwidget/UpdatesGridGlanceReceiver.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.appwidget
2 |
3 | import androidx.glance.appwidget.GlanceAppWidget
4 | import androidx.glance.appwidget.GlanceAppWidgetReceiver
5 |
6 | class UpdatesGridGlanceReceiver : GlanceAppWidgetReceiver() {
7 | override val glanceAppWidget: GlanceAppWidget = UpdatesGridGlanceWidget().apply { loadData() }
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/core/storage/FolderProvider.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.core.storage
2 |
3 | import java.io.File
4 |
5 | interface FolderProvider {
6 |
7 | fun directory(): File
8 |
9 | fun path(): String
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.backup
2 |
3 | import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
4 |
5 | object BackupConst {
6 | private const val NAME = "BackupRestorer"
7 | const val EXTRA_URI = "$ID.$NAME.EXTRA_URI"
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/database/models/SourceIdMangaCount.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.database.models
2 |
3 | data class SourceIdMangaCount(val source: Long, val count: Long)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/dto/ALAddManga.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.anilist.dto
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class ALAddMangaResult(
8 | val data: ALAddMangaData,
9 | )
10 |
11 | @Serializable
12 | data class ALAddMangaData(
13 | @SerialName("SaveMediaListEntry")
14 | val entry: ALAddMangaEntry,
15 | )
16 |
17 | @Serializable
18 | data class ALAddMangaEntry(
19 | val id: Long,
20 | )
21 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/dto/ALOAuth.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.anilist.dto
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class ALOAuth(
8 | @SerialName("access_token")
9 | val accessToken: String,
10 | @SerialName("token_type")
11 | val tokenType: String,
12 | val expires: Long,
13 | @SerialName("expires_in")
14 | val expiresIn: Long,
15 | ) {
16 |
17 | fun isExpired() = System.currentTimeMillis() > expires
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/dto/ALSearch.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.anilist.dto
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class ALSearchResult(
8 | val data: ALSearchPage,
9 | )
10 |
11 | @Serializable
12 | data class ALSearchPage(
13 | @SerialName("Page")
14 | val page: ALSearchMedia,
15 | )
16 |
17 | @Serializable
18 | data class ALSearchMedia(
19 | val media: List,
20 | )
21 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/KitsuUtils.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.kitsu
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Track
4 |
5 | fun Track.toApiStatus() = when (status) {
6 | Kitsu.READING -> "current"
7 | Kitsu.COMPLETED -> "completed"
8 | Kitsu.ON_HOLD -> "on_hold"
9 | Kitsu.DROPPED -> "dropped"
10 | Kitsu.PLAN_TO_READ -> "planned"
11 | else -> throw Exception("Unknown status")
12 | }
13 |
14 | fun Track.toApiScore(): String? {
15 | return if (score > 0) (score * 2).toInt().toString() else null
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/dto/KitsuAddManga.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.kitsu.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class KitsuAddMangaResult(
7 | val data: KitsuAddMangaItem,
8 | )
9 |
10 | @Serializable
11 | data class KitsuAddMangaItem(
12 | val id: Long,
13 | )
14 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/dto/KitsuSearchItemCover.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.kitsu.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class KitsuSearchItemCover(
7 | val original: String?,
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/dto/KitsuUser.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.kitsu.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class KitsuCurrentUserResult(
7 | val data: List,
8 | )
9 |
10 | @Serializable
11 | data class KitsuUser(
12 | val id: String,
13 | )
14 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MUContext.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class MUContext(
8 | @SerialName("session_token")
9 | val sessionToken: String,
10 | val uid: Long,
11 | )
12 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MUImage.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MUImage(
7 | val url: MUUrl? = null,
8 | val height: Int? = null,
9 | val width: Int? = null,
10 | )
11 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MULoginResponse.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MULoginResponse(
7 | val context: MUContext,
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MURating.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Track
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class MURating(
8 | val rating: Float? = null,
9 | )
10 |
11 | fun MURating.copyTo(track: Track): Track {
12 | return track.apply {
13 | this.score = rating ?: 0f
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MUSearch.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MUSearchResult(
7 | val results: List,
8 | )
9 |
10 | @Serializable
11 | data class MUSearchResultItem(
12 | val record: MURecord,
13 | )
14 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MUSeries.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MUSeries(
7 | val id: Long? = null,
8 | val title: String? = null,
9 | )
10 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MUStatus.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MUStatus(
7 | val volume: Int? = null,
8 | val chapter: Int? = null,
9 | )
10 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/dto/MUUrl.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.mangaupdates.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MUUrl(
7 | val original: String? = null,
8 | val thumb: String? = null,
9 | )
10 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/dto/MALSearch.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.myanimelist.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MALSearchResult(
7 | val data: List,
8 | )
9 |
10 | @Serializable
11 | data class MALSearchResultNode(
12 | val node: MALSearchResultItem,
13 | )
14 |
15 | @Serializable
16 | data class MALSearchResultItem(
17 | val id: Int,
18 | )
19 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/dto/MALUser.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.myanimelist.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class MALUser(
7 | val name: String,
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/dto/SMAddMangaResponse.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.shikimori.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class SMAddMangaResponse(
7 | val id: Long,
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/dto/SMUser.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.track.shikimori.dto
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class SMUser(
7 | val id: Int,
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateResult.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.data.updater
2 |
3 | sealed class AppUpdateResult {
4 |
5 | class NewUpdate(val release: GithubRelease) : AppUpdateResult()
6 | object NoNewUpdate : AppUpdateResult()
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/extension/model/InstallStep.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.extension.model
2 |
3 | enum class InstallStep {
4 | Pending, Downloading, Loading, Installing, Installed, Error, Done;
5 |
6 | fun isCompleted(): Boolean {
7 | return this == Installed || this == Error || this == Done
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/extension/model/LoadResult.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.extension.model
2 |
3 | sealed interface LoadResult {
4 |
5 | data class Success(val extension: Extension.Installed) : LoadResult
6 | data class Untrusted(val extension: Extension.Untrusted) : LoadResult
7 | data object Error : LoadResult
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/source/models/SMangaExtensions.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.source.models
2 |
3 | import eu.kanade.tachiyomi.domain.manga.models.Manga
4 | import eu.kanade.tachiyomi.source.model.SManga
5 |
6 | val SManga.originalTitle: String
7 | get() = if (this is Manga) this.originalTitle else title
8 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseCoroutineComposeController.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.base.controller
2 |
3 | import android.os.Bundle
4 | import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
5 |
6 | abstract class BaseCoroutineComposeController>(bundle: Bundle? = null) :
7 | BaseComposeController(bundle) {
8 |
9 | abstract val presenter: PS
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/BaseViewHolder.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.base.holder
2 |
3 | import android.view.View
4 |
5 | abstract class BaseViewHolder(view: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(view)
6 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionViewUtils.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.extension
2 |
3 | import android.content.Context
4 | import android.content.pm.PackageManager
5 | import android.graphics.drawable.Drawable
6 | import eu.kanade.tachiyomi.extension.model.Extension
7 |
8 | fun Extension.getApplicationIcon(context: Context): Drawable? {
9 | return try {
10 | context.packageManager.getApplicationIcon(pkgName)
11 | } catch (e: PackageManager.NameNotFoundException) {
12 | null
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/library/filter/LibraryFilter.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.library.filter
2 |
3 | data class LibraryFilter(
4 | val headerName: String,
5 | val filters: List,
6 | val tagGroup: FilterTagGroup,
7 | var activeFilter: Int,
8 | )
9 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackItem.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.manga.track
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Track
4 | import eu.kanade.tachiyomi.data.track.TrackService
5 |
6 | data class TrackItem(val track: Track?, val service: TrackService)
7 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationPresenter.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.migration
2 |
3 | import kotlinx.coroutines.launch
4 |
5 | class MigrationPresenter : BaseMigrationPresenter() {
6 | override fun onCreate() {
7 | super.onCreate()
8 | presenterScope.launch { firstTimeMigration() }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationProcedureConfig.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.migration.manga.process
2 |
3 | import android.os.Parcelable
4 | import kotlinx.parcelize.Parcelize
5 |
6 | @Parcelize
7 | data class MigrationProcedureConfig(
8 | var mangaIds: List,
9 | val extraSearchParams: String?,
10 | ) : Parcelable
11 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/InsertPage.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.reader.model
2 |
3 | class InsertPage(parent: ReaderPage) : ReaderPage(
4 | parent.index,
5 | parent.url,
6 | parent.imageUrl,
7 | ) {
8 |
9 | override var chapter: ReaderChapter = parent.chapter
10 |
11 | init {
12 | fullPage = true
13 | firstHalf = false
14 | stream = parent.stream
15 | status = State.Ready
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/ReaderItem.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.reader.model
2 |
3 | sealed interface ReaderItem
4 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/SplitPage.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.reader.model
2 |
3 | /**
4 | * Used as placeholder for split page's second page
5 | */
6 | data object SplitPage : ReaderItem
7 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/ViewerChapters.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.reader.model
2 |
3 | data class ViewerChapters(
4 | val currChapter: ReaderChapter,
5 | val prevChapter: ReaderChapter?,
6 | val nextChapter: ReaderChapter?,
7 | ) {
8 |
9 | fun ref() {
10 | currChapter.ref()
11 | prevChapter?.ref()
12 | nextChapter?.ref()
13 | }
14 |
15 | fun unref() {
16 | currChapter.unref()
17 | prevChapter?.unref()
18 | nextChapter?.unref()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/navigation/DisabledNavigation.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.reader.viewer.navigation
2 |
3 | import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
4 |
5 | /**
6 | * Visualization of default state without any inversion
7 | * +---+---+---+
8 | * | M | M | M | P: Previous
9 | * +---+---+---+
10 | * | M | M | M | M: Menu
11 | * +---+---+---+
12 | * | M | M | M | N: Next
13 | * +---+---+---+
14 | */
15 | class DisabledNavigation : ViewerNavigation() {
16 |
17 | override var regions: List = emptyList()
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/setting/controllers/SettingsDataController.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.setting.controllers
2 |
3 | import eu.kanade.tachiyomi.ui.setting.SettingsComposeController
4 | import yokai.presentation.settings.ComposableSettings
5 | import yokai.presentation.settings.screen.SettingsDataScreen
6 |
7 | class SettingsDataController : SettingsComposeController() {
8 | override fun getComposableSettings(): ComposableSettings = SettingsDataScreen
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/LatestUpdatesPager.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.source.browse
2 |
3 | import eu.kanade.tachiyomi.source.CatalogueSource
4 |
5 | /**
6 | * LatestUpdatesPager inherited from the general Pager.
7 | */
8 | class LatestUpdatesPager(val source: CatalogueSource) : Pager() {
9 |
10 | override suspend fun requestNextPage() {
11 | val mangasPage = source.getLatestUpdates(currentPage)
12 | onPageReceived(mangasPage)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/ui/source/browse/NoResultsException.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.ui.source.browse
2 |
3 | class NoResultsException : Exception()
4 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/PkceUtil.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util
2 |
3 | import android.util.Base64
4 | import java.security.SecureRandom
5 |
6 | object PkceUtil {
7 |
8 | private const val PKCE_BASE64_ENCODE_SETTINGS = Base64.NO_WRAP or Base64.NO_PADDING or Base64.URL_SAFE
9 |
10 | fun generateCodeVerifier(): String {
11 | val codeVerifier = ByteArray(50)
12 | SecureRandom().nextBytes(codeVerifier)
13 | return Base64.encodeToString(codeVerifier, PKCE_BASE64_ENCODE_SETTINGS)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/WindowSize.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util
2 |
3 | import androidx.compose.runtime.Composable
4 | import androidx.compose.runtime.ReadOnlyComposable
5 | import androidx.compose.ui.platform.LocalConfiguration
6 | import eu.kanade.tachiyomi.util.system.isTablet
7 |
8 | @Composable
9 | @ReadOnlyComposable
10 | fun isTablet(): Boolean {
11 | return LocalConfiguration.current.isTablet()
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/chapter/NoChaptersException.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.chapter
2 |
3 | class NoChaptersException : Exception()
4 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/compose/ColorSchemeExtensions.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.compose
2 |
3 | import androidx.compose.material3.ColorScheme
4 |
5 | val ColorScheme.textHint get() = onBackground.copy(alpha = 0.35f)
6 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/lang/EnumExtensions.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.lang
2 |
3 | inline fun > T.next(): T {
4 | val values = enumValues()
5 | val nextOrdinal = (ordinal + 1) % values.size
6 | return values[nextOrdinal]
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/system/BooleanExtensions.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.system
2 |
3 | fun Boolean.toInt() = if (this) 1 else 0
4 | fun Int.toBoolean() = this == 1
5 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/system/CoilExtensions.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.system
2 |
3 | import coil3.Extras
4 | import coil3.request.ImageRequest
5 |
6 | fun ImageRequest.Builder.setExtras(extraKey: Extras.Key, value: T): ImageRequest.Builder {
7 | this.extras[extraKey] = value
8 | return this
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/system/HashCode.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.system
2 |
3 | /**Generate a unique hash code*/
4 | class HashCode {
5 | companion object {
6 | fun generate(vararg thingsToHash: T): Int {
7 | var hash = 17
8 | for (t in thingsToHash) {
9 | hash = hash * 31 + t.hashCode()
10 | }
11 | return hash
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/system/NumberExtensions.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.system
2 |
3 | import kotlin.math.roundToLong
4 |
5 | fun Double.roundToTwoDecimal(): Double {
6 | return (this * 100.0).roundToLong() / 100.0
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/util/system/SideNavMode.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.util.system
2 |
3 | import androidx.annotation.StringRes
4 | import dev.icerock.moko.resources.StringResource
5 | import eu.kanade.tachiyomi.R
6 | import yokai.i18n.MR
7 | import yokai.util.lang.getString
8 | import dev.icerock.moko.resources.compose.stringResource
9 |
10 | enum class SideNavMode(val prefValue: Int, val stringRes: StringResource) {
11 | DEFAULT(0, MR.strings.default_behavior),
12 | NEVER(1, MR.strings.never),
13 | ALWAYS(2, MR.strings.always),
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleTextWatcher.kt:
--------------------------------------------------------------------------------
1 | package eu.kanade.tachiyomi.widget
2 |
3 | import android.text.Editable
4 | import android.text.TextWatcher
5 |
6 | open class SimpleTextWatcher : TextWatcher {
7 | override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
8 |
9 | override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
10 |
11 | override fun afterTextChanged(s: Editable) {}
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/core/migration/MigrationCompletedListener.kt:
--------------------------------------------------------------------------------
1 | package yokai.core.migration
2 |
3 | typealias MigrationCompletedListener = () -> Unit
4 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/core/migration/MigrationContext.kt:
--------------------------------------------------------------------------------
1 | package yokai.core.migration
2 |
3 | import uy.kohesive.injekt.Injekt
4 |
5 | class MigrationContext(val dryRun: Boolean) {
6 |
7 | inline fun get(): T? {
8 | return Injekt.getInstanceOrNull(T::class.java)
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/Result.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain
2 |
3 | sealed class Result {
4 | data class Success(val data: T? = null) : Result()
5 | data class Error(val message: String? = null) : Result()
6 | data object Loading : Result()
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/SplashState.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain
2 |
3 | class SplashState {
4 | var shown = false
5 | var ready = false
6 | }
7 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/category/interactor/DeleteCategories.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.category.interactor
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Category
4 | import yokai.domain.category.CategoryRepository
5 | import yokai.domain.category.models.CategoryUpdate
6 |
7 | class DeleteCategories(
8 | private val categoryRepository: CategoryRepository,
9 | ) {
10 | // suspend fun await(updates: List) =
11 | suspend fun awaitOne(id: Long) = categoryRepository.delete(id)
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/category/interactor/GetCategories.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.category.interactor
2 |
3 | import yokai.domain.category.CategoryRepository
4 |
5 | class GetCategories(
6 | private val categoryRepository: CategoryRepository,
7 | ) {
8 | suspend fun await() = categoryRepository.getAll()
9 | suspend fun awaitByMangaId(mangaId: Long?) = mangaId?.let { categoryRepository.getAllByMangaId(it) }.orEmpty()
10 | fun subscribe() = categoryRepository.getAllAsFlow()
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/category/interactor/InsertCategories.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.category.interactor
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Category
4 | import yokai.domain.category.CategoryRepository
5 |
6 | class InsertCategories(
7 | private val categoryRepository: CategoryRepository,
8 | ) {
9 | suspend fun await(categories: List) = categoryRepository.insertBulk(categories)
10 | suspend fun awaitOne(category: Category) = categoryRepository.insert(category)
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/category/interactor/UpdateCategories.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.category.interactor
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Category
4 | import yokai.domain.category.CategoryRepository
5 | import yokai.domain.category.models.CategoryUpdate
6 |
7 | class UpdateCategories(
8 | private val categoryRepository: CategoryRepository,
9 | ) {
10 | suspend fun await(updates: List) = categoryRepository.updateAll(updates)
11 | suspend fun awaitOne(update: CategoryUpdate) = categoryRepository.update(update)
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/chapter/interactor/DeleteChapter.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.chapter.interactor
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Chapter
4 | import yokai.domain.chapter.ChapterRepository
5 |
6 | class DeleteChapter(
7 | private val chapterRepository: ChapterRepository,
8 | ) {
9 | suspend fun await(chapter: Chapter) = chapterRepository.delete(chapter)
10 | suspend fun awaitAllById(chapterIds: List) = chapterRepository.deleteAllById(chapterIds)
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/chapter/interactor/GetAvailableScanlators.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.chapter.interactor
2 |
3 | import yokai.domain.chapter.ChapterRepository
4 |
5 | class GetAvailableScanlators(
6 | private val chapterRepository: ChapterRepository,
7 | ) {
8 | suspend fun await(mangaId: Long) = chapterRepository.getScanlatorsByChapter(mangaId)
9 | fun subscribe(mangaId: Long) = chapterRepository.getScanlatorsByChapterAsFlow(mangaId)
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/chapter/interactor/InsertChapter.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.chapter.interactor
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Chapter
4 | import yokai.domain.chapter.ChapterRepository
5 |
6 | class InsertChapter(
7 | private val chapterRepository: ChapterRepository,
8 | ) {
9 | suspend fun await(chapter: Chapter) = chapterRepository.insert(chapter)
10 |
11 | suspend fun awaitBulk(chapters: List) = chapterRepository.insertBulk(chapters)
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/chapter/interactor/UpdateChapter.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.chapter.interactor
2 |
3 | import yokai.domain.chapter.ChapterRepository
4 | import yokai.domain.chapter.models.ChapterUpdate
5 |
6 | class UpdateChapter(
7 | private val chapterRepository: ChapterRepository,
8 | ) {
9 | suspend fun await(chapter: ChapterUpdate) = chapterRepository.update(chapter)
10 | suspend fun awaitAll(chapters: List) = chapterRepository.updateAll(chapters)
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/download/DownloadPreferences.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.download
2 |
3 | import eu.kanade.tachiyomi.core.preference.PreferenceStore
4 |
5 | class DownloadPreferences(
6 | private val preferenceStore: PreferenceStore,
7 | ) {
8 | fun downloadWithId() = preferenceStore.getBoolean("download_with_id", false)
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/extension/repo/exception/SaveExtensionRepoException.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.extension.repo.exception
2 |
3 | import java.io.IOException
4 |
5 | /**
6 | * Exception to abstract over SQLiteException and SQLiteConstraintException for multiplatform.
7 | *
8 | * @param throwable the source throwable to include for tracing.
9 | */
10 | class SaveExtensionRepoException(throwable: Throwable) : IOException("Error Saving Repository to Database", throwable)
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/extension/repo/interactor/DeleteExtensionRepo.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.extension.repo.interactor
2 |
3 | import yokai.domain.extension.repo.ExtensionRepoRepository
4 |
5 | class DeleteExtensionRepo(
6 | private val extensionRepoRepository: ExtensionRepoRepository
7 | ) {
8 | suspend fun await(baseUrl: String) {
9 | extensionRepoRepository.deleteRepository(baseUrl)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/extension/repo/interactor/GetExtensionRepo.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.extension.repo.interactor
2 |
3 | import kotlinx.coroutines.flow.Flow
4 | import yokai.domain.extension.repo.ExtensionRepoRepository
5 | import yokai.domain.extension.repo.model.ExtensionRepo
6 |
7 | class GetExtensionRepo(
8 | private val extensionRepoRepository: ExtensionRepoRepository
9 | ) {
10 | fun subscribeAll(): Flow> = extensionRepoRepository.subscribeAll()
11 |
12 | suspend fun getAll(): List = extensionRepoRepository.getAll()
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/extension/repo/interactor/GetExtensionRepoCount.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.extension.repo.interactor
2 |
3 | import yokai.domain.extension.repo.ExtensionRepoRepository
4 |
5 | class GetExtensionRepoCount(
6 | private val extensionRepoRepository: ExtensionRepoRepository
7 | ) {
8 | fun subscribe() = extensionRepoRepository.getCount()
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/extension/repo/interactor/ReplaceExtensionRepo.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.extension.repo.interactor
2 |
3 | import yokai.domain.extension.repo.ExtensionRepoRepository
4 | import yokai.domain.extension.repo.model.ExtensionRepo
5 |
6 | class ReplaceExtensionRepo(
7 | private val extensionRepoRepository: ExtensionRepoRepository
8 | ) {
9 | suspend fun await(repo: ExtensionRepo) {
10 | extensionRepoRepository.replaceRepository(repo)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/history/interactor/GetHistory.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.history.interactor
2 |
3 | import yokai.domain.history.HistoryRepository
4 |
5 | class GetHistory(
6 | private val historyRepository: HistoryRepository
7 | ) {
8 | suspend fun awaitByMangaId(mangaId: Long) = historyRepository.getByMangaId(mangaId)
9 | suspend fun awaitAllByMangaId(mangaId: Long) = historyRepository.getAllByMangaId(mangaId)
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/library/custom/exception/SaveCustomMangaException.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.library.custom.exception
2 |
3 | import java.io.IOException
4 |
5 | /**
6 | * Exception to abstract over SQLiteException and SQLiteConstraintException for multiplatform.
7 | *
8 | * @param throwable the source throwable to include for tracing.
9 | */
10 | class SaveCustomMangaException(throwable: Throwable) : IOException("Error Saving Custom Manga Info to Database", throwable)
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/library/custom/interactor/DeleteCustomManga.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.library.custom.interactor
2 |
3 | import yokai.domain.library.custom.CustomMangaRepository
4 |
5 | class DeleteCustomManga(
6 | private val customMangaRepository: CustomMangaRepository,
7 | ) {
8 | suspend fun await(mangaId: Long) = customMangaRepository.deleteCustomManga(mangaId)
9 | suspend fun bulk(mangaIds: List) = customMangaRepository.deleteBulkCustomManga(mangaIds)
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/library/custom/interactor/GetCustomManga.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.library.custom.interactor
2 |
3 | import yokai.domain.library.custom.CustomMangaRepository
4 |
5 | class GetCustomManga(
6 | private val customMangaRepository: CustomMangaRepository,
7 | ) {
8 | fun subscribeAll() = customMangaRepository.subscribeAll()
9 |
10 | suspend fun getAll() = customMangaRepository.getAll()
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/library/custom/interactor/RelinkCustomManga.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.library.custom.interactor
2 |
3 | import yokai.domain.library.custom.CustomMangaRepository
4 |
5 | class RelinkCustomManga(
6 | private val customMangaRepository: CustomMangaRepository,
7 | ) {
8 | suspend fun await(oldId: Long, newId: Long) = customMangaRepository.relinkCustomManga(oldId, newId)
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/manga/interactor/GetLibraryManga.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.manga.interactor
2 |
3 | import eu.kanade.tachiyomi.data.database.models.LibraryManga
4 | import kotlinx.coroutines.flow.Flow
5 | import yokai.domain.manga.MangaRepository
6 |
7 | class GetLibraryManga(
8 | private val mangaRepository: MangaRepository,
9 | ) {
10 | suspend fun await(): List = mangaRepository.getLibraryManga()
11 | fun subscribe(): Flow> = mangaRepository.getLibraryMangaAsFlow()
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/manga/interactor/InsertManga.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.manga.interactor
2 |
3 | import eu.kanade.tachiyomi.domain.manga.models.Manga
4 | import yokai.domain.manga.MangaRepository
5 |
6 | class InsertManga (
7 | private val mangaRepository: MangaRepository,
8 | ) {
9 | suspend fun await(manga: Manga) = mangaRepository.insert(manga)
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/manga/interactor/UpdateManga.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.manga.interactor
2 |
3 | import yokai.domain.manga.MangaRepository
4 | import yokai.domain.manga.models.MangaUpdate
5 |
6 | class UpdateManga (
7 | private val mangaRepository: MangaRepository,
8 | ) {
9 | suspend fun await(update: MangaUpdate) = mangaRepository.update(update)
10 | suspend fun awaitAll(updates: List) = mangaRepository.updateAll(updates)
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/source/SourcePreferences.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.source
2 |
3 | import eu.kanade.tachiyomi.core.preference.PreferenceStore
4 |
5 | class SourcePreferences(private val preferenceStore: PreferenceStore) {
6 | fun trustedExtensions() = preferenceStore.getStringSet("trusted_extensions", emptySet())
7 |
8 | fun externalLocalSource() = preferenceStore.getBoolean("pref_external_local_source", false)
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/source/browse/filter/interactor/DeleteSavedSearch.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.source.browse.filter.interactor
2 |
3 | import yokai.domain.source.browse.filter.SavedSearchRepository
4 |
5 | class DeleteSavedSearch(
6 | private val repository: SavedSearchRepository,
7 | ) {
8 | suspend fun await(searchId: Long) = repository.deleteById(searchId)
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/source/browse/filter/interactor/InsertSavedSearch.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.source.browse.filter.interactor
2 |
3 | import yokai.domain.source.browse.filter.SavedSearchRepository
4 |
5 | class InsertSavedSearch(
6 | private val repository: SavedSearchRepository,
7 | ) {
8 | suspend fun await(sourceId: Long, name: String, query: String?, filtersJson: String?) = repository.insert(sourceId, name, query, filtersJson)
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/source/browse/filter/models/SavedSearch.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.source.browse.filter.models
2 |
3 | import eu.kanade.tachiyomi.source.model.FilterList
4 |
5 | data class SavedSearch(
6 | val id: Long,
7 | val name: String,
8 | val query: String,
9 | val filters: FilterList?,
10 | )
11 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/storage/StoragePreferences.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.storage
2 |
3 | import eu.kanade.tachiyomi.core.preference.Preference
4 | import eu.kanade.tachiyomi.core.preference.PreferenceStore
5 | import eu.kanade.tachiyomi.core.storage.FolderProvider
6 |
7 | class StoragePreferences(
8 | private val folderProvider: FolderProvider,
9 | private val preferenceStore: PreferenceStore,
10 | ) {
11 | fun baseStorageDirectory() = preferenceStore.getString(Preference.appStateKey("storage_dir"), folderProvider.path())
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/yokai/domain/track/TrackRepository.kt:
--------------------------------------------------------------------------------
1 | package yokai.domain.track
2 |
3 | import eu.kanade.tachiyomi.data.database.models.Track
4 |
5 | interface TrackRepository {
6 | suspend fun getAllByMangaId(mangaId: Long): List