├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── source_issue.md ├── readme-images │ ├── app-icon.png │ └── screens.png └── workflows │ └── build.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── debug │ └── res │ │ ├── drawable │ │ └── ic_launcher_foreground.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ ├── eu │ │ │ └── kanade │ │ │ │ └── tachiyomi │ │ │ │ ├── App.kt │ │ │ │ ├── AppInfo.kt │ │ │ │ ├── AppModule.kt │ │ │ │ ├── Migrations.kt │ │ │ │ ├── annotations │ │ │ │ └── Nsfw.kt │ │ │ │ ├── data │ │ │ │ ├── backup │ │ │ │ │ ├── AbstractBackupManager.kt │ │ │ │ │ ├── AbstractBackupRestore.kt │ │ │ │ │ ├── AbstractBackupRestoreValidator.kt │ │ │ │ │ ├── BackupConst.kt │ │ │ │ │ ├── BackupCreateService.kt │ │ │ │ │ ├── BackupCreatorJob.kt │ │ │ │ │ ├── BackupNotifier.kt │ │ │ │ │ ├── BackupRestoreService.kt │ │ │ │ │ ├── full │ │ │ │ │ │ ├── FullBackupManager.kt │ │ │ │ │ │ ├── FullBackupRestore.kt │ │ │ │ │ │ ├── FullBackupRestoreValidator.kt │ │ │ │ │ │ └── models │ │ │ │ │ │ │ ├── Backup.kt │ │ │ │ │ │ │ ├── BackupCategory.kt │ │ │ │ │ │ │ ├── BackupChapter.kt │ │ │ │ │ │ │ ├── BackupFlatMetadata.kt │ │ │ │ │ │ │ ├── BackupFull.kt │ │ │ │ │ │ │ ├── BackupHistory.kt │ │ │ │ │ │ │ ├── BackupManga.kt │ │ │ │ │ │ │ ├── BackupSavedSearch.kt │ │ │ │ │ │ │ ├── BackupSerializer.kt │ │ │ │ │ │ │ ├── BackupSource.kt │ │ │ │ │ │ │ ├── BackupTracking.kt │ │ │ │ │ │ │ └── metadata │ │ │ │ │ │ │ ├── BackupSearchMetadata.kt │ │ │ │ │ │ │ ├── BackupSearchTag.kt │ │ │ │ │ │ │ └── BackupSearchTitle.kt │ │ │ │ │ └── legacy │ │ │ │ │ │ ├── LegacyBackupManager.kt │ │ │ │ │ │ ├── LegacyBackupRestore.kt │ │ │ │ │ │ ├── LegacyBackupRestoreValidator.kt │ │ │ │ │ │ ├── models │ │ │ │ │ │ ├── Backup.kt │ │ │ │ │ │ └── DHistory.kt │ │ │ │ │ │ └── serializer │ │ │ │ │ │ ├── CategoryTypeAdapter.kt │ │ │ │ │ │ ├── ChapterTypeAdapter.kt │ │ │ │ │ │ ├── HistoryTypeAdapter.kt │ │ │ │ │ │ ├── MangaTypeAdapter.kt │ │ │ │ │ │ └── TrackTypeAdapter.kt │ │ │ │ ├── cache │ │ │ │ │ ├── ChapterCache.kt │ │ │ │ │ └── CoverCache.kt │ │ │ │ ├── database │ │ │ │ │ ├── DatabaseAdapter.kt │ │ │ │ │ ├── DatabaseHelper.kt │ │ │ │ │ ├── DbExtensions.kt │ │ │ │ │ ├── DbOpenCallback.kt │ │ │ │ │ ├── DbProvider.kt │ │ │ │ │ ├── mappers │ │ │ │ │ │ ├── CategoryTypeMapping.kt │ │ │ │ │ │ ├── ChapterTypeMapping.kt │ │ │ │ │ │ ├── HistoryTypeMapping.kt │ │ │ │ │ │ ├── MangaCategoryTypeMapping.kt │ │ │ │ │ │ ├── MangaTypeMapping.kt │ │ │ │ │ │ └── TrackTypeMapping.kt │ │ │ │ │ ├── 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 │ │ │ │ │ │ ├── Track.kt │ │ │ │ │ │ └── TrackImpl.kt │ │ │ │ │ ├── queries │ │ │ │ │ │ ├── CategoryQueries.kt │ │ │ │ │ │ ├── ChapterQueries.kt │ │ │ │ │ │ ├── HistoryQueries.kt │ │ │ │ │ │ ├── MangaCategoryQueries.kt │ │ │ │ │ │ ├── MangaQueries.kt │ │ │ │ │ │ ├── RawQueries.kt │ │ │ │ │ │ └── TrackQueries.kt │ │ │ │ │ ├── resolvers │ │ │ │ │ │ ├── ChapterBackupPutResolver.kt │ │ │ │ │ │ ├── ChapterProgressPutResolver.kt │ │ │ │ │ │ ├── ChapterSourceOrderPutResolver.kt │ │ │ │ │ │ ├── HistoryLastReadPutResolver.kt │ │ │ │ │ │ ├── LibraryMangaGetResolver.kt │ │ │ │ │ │ ├── MangaChapterGetResolver.kt │ │ │ │ │ │ ├── MangaChapterHistoryGetResolver.kt │ │ │ │ │ │ ├── MangaCoverLastModifiedPutResolver.kt │ │ │ │ │ │ ├── MangaFavoritePutResolver.kt │ │ │ │ │ │ ├── MangaFlagsPutResolver.kt │ │ │ │ │ │ ├── MangaLastUpdatedPutResolver.kt │ │ │ │ │ │ ├── MangaTitlePutResolver.kt │ │ │ │ │ │ ├── MangaUrlPutResolver.kt │ │ │ │ │ │ └── MangaViewerPutResolver.kt │ │ │ │ │ └── tables │ │ │ │ │ │ ├── CategoryTable.kt │ │ │ │ │ │ ├── ChapterTable.kt │ │ │ │ │ │ ├── HistoryTable.kt │ │ │ │ │ │ ├── MangaCategoryTable.kt │ │ │ │ │ │ ├── MangaTable.kt │ │ │ │ │ │ ├── MergedTable.kt │ │ │ │ │ │ └── TrackTable.kt │ │ │ │ ├── download │ │ │ │ │ ├── DownloadCache.kt │ │ │ │ │ ├── DownloadManager.kt │ │ │ │ │ ├── DownloadNotifier.kt │ │ │ │ │ ├── DownloadPendingDeleter.kt │ │ │ │ │ ├── DownloadProvider.kt │ │ │ │ │ ├── DownloadService.kt │ │ │ │ │ ├── DownloadStore.kt │ │ │ │ │ ├── Downloader.kt │ │ │ │ │ └── model │ │ │ │ │ │ ├── Download.kt │ │ │ │ │ │ └── DownloadQueue.kt │ │ │ │ ├── glide │ │ │ │ │ ├── FileFetcher.kt │ │ │ │ │ ├── LibraryMangaCustomCoverFetcher.kt │ │ │ │ │ ├── LibraryMangaUrlFetcher.kt │ │ │ │ │ ├── MangaThumbnail.kt │ │ │ │ │ ├── MangaThumbnailModelLoader.kt │ │ │ │ │ ├── PassthroughModelLoader.kt │ │ │ │ │ ├── TachiGlideModule.kt │ │ │ │ │ └── TachiyomiImageDecoderGlideWrapper.kt │ │ │ │ ├── library │ │ │ │ │ ├── LibraryUpdateJob.kt │ │ │ │ │ ├── LibraryUpdateNotifier.kt │ │ │ │ │ ├── LibraryUpdateRanker.kt │ │ │ │ │ └── LibraryUpdateService.kt │ │ │ │ ├── notification │ │ │ │ │ ├── NotificationHandler.kt │ │ │ │ │ ├── NotificationReceiver.kt │ │ │ │ │ └── Notifications.kt │ │ │ │ ├── preference │ │ │ │ │ ├── EmptyPreferenceDataStore.kt │ │ │ │ │ ├── PreferenceKeys.kt │ │ │ │ │ ├── PreferenceValues.kt │ │ │ │ │ ├── PreferencesHelper.kt │ │ │ │ │ └── SharedPreferencesDataStore.kt │ │ │ │ ├── track │ │ │ │ │ ├── TrackManager.kt │ │ │ │ │ ├── TrackService.kt │ │ │ │ │ ├── anilist │ │ │ │ │ │ ├── Anilist.kt │ │ │ │ │ │ ├── AnilistApi.kt │ │ │ │ │ │ ├── AnilistInterceptor.kt │ │ │ │ │ │ ├── AnilistModels.kt │ │ │ │ │ │ └── OAuth.kt │ │ │ │ │ ├── bangumi │ │ │ │ │ │ ├── Avatar.kt │ │ │ │ │ │ ├── Bangumi.kt │ │ │ │ │ │ ├── BangumiApi.kt │ │ │ │ │ │ ├── BangumiInterceptor.kt │ │ │ │ │ │ ├── BangumiModels.kt │ │ │ │ │ │ ├── Collection.kt │ │ │ │ │ │ ├── OAuth.kt │ │ │ │ │ │ ├── Status.kt │ │ │ │ │ │ └── User.kt │ │ │ │ │ ├── job │ │ │ │ │ │ ├── DelayedTrackingStore.kt │ │ │ │ │ │ └── DelayedTrackingUpdateJob.kt │ │ │ │ │ ├── kitsu │ │ │ │ │ │ ├── Kitsu.kt │ │ │ │ │ │ ├── KitsuApi.kt │ │ │ │ │ │ ├── KitsuInterceptor.kt │ │ │ │ │ │ ├── KitsuModels.kt │ │ │ │ │ │ └── OAuth.kt │ │ │ │ │ ├── model │ │ │ │ │ │ └── TrackSearch.kt │ │ │ │ │ ├── myanimelist │ │ │ │ │ │ ├── MyAnimeList.kt │ │ │ │ │ │ ├── MyAnimeListApi.kt │ │ │ │ │ │ └── MyAnimeListInterceptor.kt │ │ │ │ │ └── shikimori │ │ │ │ │ │ ├── OAuth.kt │ │ │ │ │ │ ├── Shikimori.kt │ │ │ │ │ │ ├── ShikimoriApi.kt │ │ │ │ │ │ ├── ShikimoriInterceptor.kt │ │ │ │ │ │ └── ShikimoriModels.kt │ │ │ │ └── updater │ │ │ │ │ ├── Release.kt │ │ │ │ │ ├── UpdateChecker.kt │ │ │ │ │ ├── UpdateResult.kt │ │ │ │ │ ├── UpdaterJob.kt │ │ │ │ │ ├── UpdaterNotifier.kt │ │ │ │ │ ├── UpdaterService.kt │ │ │ │ │ ├── devrepo │ │ │ │ │ ├── DevRepoRelease.kt │ │ │ │ │ ├── DevRepoUpdateChecker.kt │ │ │ │ │ └── DevRepoUpdateResult.kt │ │ │ │ │ └── github │ │ │ │ │ ├── GithubRelease.kt │ │ │ │ │ ├── GithubService.kt │ │ │ │ │ ├── GithubUpdateChecker.kt │ │ │ │ │ └── GithubUpdateResult.kt │ │ │ │ ├── extension │ │ │ │ ├── ExtensionManager.kt │ │ │ │ ├── ExtensionUpdateJob.kt │ │ │ │ ├── api │ │ │ │ │ ├── ExtensionGithubApi.kt │ │ │ │ │ └── ExtensionGithubService.kt │ │ │ │ ├── installer │ │ │ │ │ ├── Installer.kt │ │ │ │ │ ├── PackageInstallerInstaller.kt │ │ │ │ │ └── ShizukuInstaller.kt │ │ │ │ ├── model │ │ │ │ │ ├── Extension.kt │ │ │ │ │ ├── InstallStep.kt │ │ │ │ │ └── LoadResult.kt │ │ │ │ └── util │ │ │ │ │ ├── ExtensionInstallActivity.kt │ │ │ │ │ ├── ExtensionInstallReceiver.kt │ │ │ │ │ ├── ExtensionInstallService.kt │ │ │ │ │ ├── ExtensionInstaller.kt │ │ │ │ │ └── ExtensionLoader.kt │ │ │ │ ├── network │ │ │ │ ├── AndroidCookieJar.kt │ │ │ │ ├── JavaScriptEngine.kt │ │ │ │ ├── NetworkHelper.kt │ │ │ │ ├── OkHttpExtensions.kt │ │ │ │ ├── ProgressListener.kt │ │ │ │ ├── ProgressResponseBody.kt │ │ │ │ ├── Requests.kt │ │ │ │ └── interceptor │ │ │ │ │ ├── CloudflareInterceptor.kt │ │ │ │ │ ├── IgnoreGzipInterceptor.kt │ │ │ │ │ ├── RateLimitInterceptor.kt │ │ │ │ │ ├── SpecificHostRateLimitInterceptor.kt │ │ │ │ │ └── UserAgentInterceptor.kt │ │ │ │ ├── source │ │ │ │ ├── CatalogueSource.kt │ │ │ │ ├── ConfigurableSource.kt │ │ │ │ ├── LocalSource.kt │ │ │ │ ├── Source.kt │ │ │ │ ├── SourceFactory.kt │ │ │ │ ├── SourceManager.kt │ │ │ │ ├── UnmeteredSource.kt │ │ │ │ ├── model │ │ │ │ │ ├── Filter.kt │ │ │ │ │ ├── FilterList.kt │ │ │ │ │ ├── MangasPage.kt │ │ │ │ │ ├── Page.kt │ │ │ │ │ ├── SChapter.kt │ │ │ │ │ ├── SChapterImpl.kt │ │ │ │ │ ├── SManga.kt │ │ │ │ │ ├── SMangaImpl.kt │ │ │ │ │ └── UpdateStrategy.kt │ │ │ │ └── online │ │ │ │ │ ├── AnimeSource.kt │ │ │ │ │ ├── HttpSource.kt │ │ │ │ │ ├── HttpSourceFetcher.kt │ │ │ │ │ ├── LewdSource.kt │ │ │ │ │ ├── ParsedHttpSource.kt │ │ │ │ │ ├── UrlImportableSource.kt │ │ │ │ │ ├── all │ │ │ │ │ ├── EHentai.kt │ │ │ │ │ ├── MergedSource.kt │ │ │ │ │ └── NHentai.kt │ │ │ │ │ └── english │ │ │ │ │ ├── HentaiCafe.kt │ │ │ │ │ ├── Pururin.kt │ │ │ │ │ └── Tsumino.kt │ │ │ │ ├── ui │ │ │ │ ├── base │ │ │ │ │ ├── activity │ │ │ │ │ │ ├── BaseActivity.kt │ │ │ │ │ │ └── BaseRxActivity.kt │ │ │ │ │ ├── controller │ │ │ │ │ │ ├── BaseController.kt │ │ │ │ │ │ ├── ConductorExtensions.kt │ │ │ │ │ │ ├── DialogController.kt │ │ │ │ │ │ ├── NoToolbarElevationController.kt │ │ │ │ │ │ ├── NucleusController.kt │ │ │ │ │ │ ├── RootController.kt │ │ │ │ │ │ ├── RxController.kt │ │ │ │ │ │ ├── SecondaryDrawerController.kt │ │ │ │ │ │ └── TabbedController.kt │ │ │ │ │ ├── holder │ │ │ │ │ │ ├── BaseFlexibleViewHolder.kt │ │ │ │ │ │ ├── BaseViewHolder.kt │ │ │ │ │ │ └── SlicedHolder.kt │ │ │ │ │ └── presenter │ │ │ │ │ │ ├── BasePresenter.kt │ │ │ │ │ │ ├── NucleusConductorDelegate.kt │ │ │ │ │ │ └── NucleusConductorLifecycleListener.kt │ │ │ │ ├── category │ │ │ │ │ ├── CategoryAdapter.kt │ │ │ │ │ ├── CategoryController.kt │ │ │ │ │ ├── CategoryCreateDialog.kt │ │ │ │ │ ├── CategoryHolder.kt │ │ │ │ │ ├── CategoryItem.kt │ │ │ │ │ ├── CategoryPresenter.kt │ │ │ │ │ └── CategoryRenameDialog.kt │ │ │ │ ├── download │ │ │ │ │ ├── DownloadAdapter.kt │ │ │ │ │ ├── DownloadController.kt │ │ │ │ │ ├── DownloadHolder.kt │ │ │ │ │ ├── DownloadItem.kt │ │ │ │ │ └── DownloadPresenter.kt │ │ │ │ ├── extension │ │ │ │ │ ├── ExtensionAdapter.kt │ │ │ │ │ ├── ExtensionController.kt │ │ │ │ │ ├── ExtensionDetailsController.kt │ │ │ │ │ ├── ExtensionDetailsPrefsButtonAdapter.kt │ │ │ │ │ ├── ExtensionDetailsPrefsButtonHolder.kt │ │ │ │ │ ├── ExtensionDetailsPrefsButtonItem.kt │ │ │ │ │ ├── ExtensionDetailsPresenter.kt │ │ │ │ │ ├── ExtensionDividerItemDecoration.kt │ │ │ │ │ ├── ExtensionFilterController.kt │ │ │ │ │ ├── ExtensionGroupHolder.kt │ │ │ │ │ ├── ExtensionGroupItem.kt │ │ │ │ │ ├── ExtensionHolder.kt │ │ │ │ │ ├── ExtensionItem.kt │ │ │ │ │ ├── ExtensionPreferencesController.kt │ │ │ │ │ ├── ExtensionPreferencesPresenter.kt │ │ │ │ │ ├── ExtensionPresenter.kt │ │ │ │ │ ├── ExtensionTrustDialog.kt │ │ │ │ │ ├── ExtensionViewUtils.kt │ │ │ │ │ └── repos │ │ │ │ │ │ ├── RepoAdapter.kt │ │ │ │ │ │ ├── RepoController.kt │ │ │ │ │ │ ├── RepoCreateDialog.kt │ │ │ │ │ │ ├── RepoHolder.kt │ │ │ │ │ │ ├── RepoItem.kt │ │ │ │ │ │ └── RepoPresenter.kt │ │ │ │ ├── library │ │ │ │ │ ├── ChangeMangaCategoriesDialog.kt │ │ │ │ │ ├── ChangeMangaCoverDialog.kt │ │ │ │ │ ├── DeleteLibraryMangasDialog.kt │ │ │ │ │ ├── LibraryAdapter.kt │ │ │ │ │ ├── LibraryCategoryAdapter.kt │ │ │ │ │ ├── LibraryCategoryView.kt │ │ │ │ │ ├── LibraryComfortableGridHolder.kt │ │ │ │ │ ├── LibraryController.kt │ │ │ │ │ ├── LibraryGridHolder.kt │ │ │ │ │ ├── LibraryHolder.kt │ │ │ │ │ ├── LibraryItem.kt │ │ │ │ │ ├── LibraryListHolder.kt │ │ │ │ │ ├── LibraryMangaEvent.kt │ │ │ │ │ ├── LibraryNavigationView.kt │ │ │ │ │ ├── LibraryPresenter.kt │ │ │ │ │ ├── LibrarySelectionEvent.kt │ │ │ │ │ └── LibrarySort.kt │ │ │ │ ├── main │ │ │ │ │ ├── ChangelogDialogController.kt │ │ │ │ │ ├── DeepLinkActivity.kt │ │ │ │ │ ├── ForceCloseActivity.kt │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ └── TabsAnimator.kt │ │ │ │ ├── manga │ │ │ │ │ ├── MangaController.kt │ │ │ │ │ ├── chapter │ │ │ │ │ │ ├── ChapterHolder.kt │ │ │ │ │ │ ├── ChapterItem.kt │ │ │ │ │ │ ├── ChaptersAdapter.kt │ │ │ │ │ │ ├── ChaptersController.kt │ │ │ │ │ │ ├── ChaptersPresenter.kt │ │ │ │ │ │ ├── DeleteChaptersDialog.kt │ │ │ │ │ │ └── DownloadCustomChaptersDialog.kt │ │ │ │ │ ├── info │ │ │ │ │ │ ├── MangaInfoController.kt │ │ │ │ │ │ └── MangaInfoPresenter.kt │ │ │ │ │ └── track │ │ │ │ │ │ ├── SetTrackChaptersDialog.kt │ │ │ │ │ │ ├── SetTrackReadingDatesDialog.kt │ │ │ │ │ │ ├── SetTrackScoreDialog.kt │ │ │ │ │ │ ├── SetTrackStatusDialog.kt │ │ │ │ │ │ ├── TrackAdapter.kt │ │ │ │ │ │ ├── TrackController.kt │ │ │ │ │ │ ├── TrackHolder.kt │ │ │ │ │ │ ├── TrackItem.kt │ │ │ │ │ │ ├── TrackPresenter.kt │ │ │ │ │ │ ├── TrackSearchAdapter.kt │ │ │ │ │ │ └── TrackSearchDialog.kt │ │ │ │ ├── migration │ │ │ │ │ ├── MangaAdapter.kt │ │ │ │ │ ├── MangaHolder.kt │ │ │ │ │ ├── MangaItem.kt │ │ │ │ │ ├── MigrationController.kt │ │ │ │ │ ├── MigrationFlags.kt │ │ │ │ │ ├── MigrationMangaDialog.kt │ │ │ │ │ ├── MigrationPresenter.kt │ │ │ │ │ ├── SearchController.kt │ │ │ │ │ ├── SearchPresenter.kt │ │ │ │ │ ├── SelectionHeader.kt │ │ │ │ │ ├── SourceAdapter.kt │ │ │ │ │ ├── SourceHolder.kt │ │ │ │ │ ├── SourceItem.kt │ │ │ │ │ ├── ViewState.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 │ │ │ │ ├── reader │ │ │ │ │ ├── ChapterLoadStrategy.kt │ │ │ │ │ ├── PageIndicatorTextView.kt │ │ │ │ │ ├── ReaderActivity.kt │ │ │ │ │ ├── ReaderColorFilterSheet.kt │ │ │ │ │ ├── ReaderColorFilterView.kt │ │ │ │ │ ├── ReaderPageSheet.kt │ │ │ │ │ ├── ReaderPresenter.kt │ │ │ │ │ ├── ReaderSeekBar.kt │ │ │ │ │ ├── ReaderSettingsSheet.kt │ │ │ │ │ ├── SaveImageNotifier.kt │ │ │ │ │ ├── loader │ │ │ │ │ │ ├── ChapterLoader.kt │ │ │ │ │ │ ├── DirectoryPageLoader.kt │ │ │ │ │ │ ├── DownloadPageLoader.kt │ │ │ │ │ │ ├── EpubPageLoader.kt │ │ │ │ │ │ ├── EpubPageLoaderCompat.kt │ │ │ │ │ │ ├── HttpPageLoader.kt │ │ │ │ │ │ ├── PageLoader.kt │ │ │ │ │ │ ├── RarPageLoader.kt │ │ │ │ │ │ ├── ZipPageLoader.kt │ │ │ │ │ │ └── ZipPageLoaderCompat.kt │ │ │ │ │ ├── model │ │ │ │ │ │ ├── ChapterTransition.kt │ │ │ │ │ │ ├── ReaderChapter.kt │ │ │ │ │ │ ├── ReaderPage.kt │ │ │ │ │ │ └── ViewerChapters.kt │ │ │ │ │ └── viewer │ │ │ │ │ │ ├── BaseViewer.kt │ │ │ │ │ │ ├── GestureDetectorWithLongTap.kt │ │ │ │ │ │ ├── MissingChapters.kt │ │ │ │ │ │ ├── ReaderProgressBar.kt │ │ │ │ │ │ ├── ReaderTransitionView.kt │ │ │ │ │ │ ├── ViewerConfig.kt │ │ │ │ │ │ ├── pager │ │ │ │ │ │ ├── Pager.kt │ │ │ │ │ │ ├── PagerButton.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 │ │ │ │ ├── recent │ │ │ │ │ ├── DateSectionItem.kt │ │ │ │ │ ├── history │ │ │ │ │ │ ├── HistoryAdapter.kt │ │ │ │ │ │ ├── HistoryController.kt │ │ │ │ │ │ ├── HistoryHolder.kt │ │ │ │ │ │ ├── HistoryItem.kt │ │ │ │ │ │ ├── HistoryPresenter.kt │ │ │ │ │ │ └── RemoveHistoryDialog.kt │ │ │ │ │ └── updates │ │ │ │ │ │ ├── ConfirmDeleteChaptersDialog.kt │ │ │ │ │ │ ├── UpdatesAdapter.kt │ │ │ │ │ │ ├── UpdatesController.kt │ │ │ │ │ │ ├── UpdatesHolder.kt │ │ │ │ │ │ ├── UpdatesItem.kt │ │ │ │ │ │ └── UpdatesPresenter.kt │ │ │ │ ├── setting │ │ │ │ │ ├── SettingsAboutController.kt │ │ │ │ │ ├── SettingsAdvancedController.kt │ │ │ │ │ ├── SettingsBackupController.kt │ │ │ │ │ ├── SettingsBrowseController.kt │ │ │ │ │ ├── SettingsController.kt │ │ │ │ │ ├── SettingsDownloadController.kt │ │ │ │ │ ├── SettingsEhController.kt │ │ │ │ │ ├── SettingsGeneralController.kt │ │ │ │ │ ├── SettingsLibraryController.kt │ │ │ │ │ ├── SettingsMainController.kt │ │ │ │ │ ├── SettingsNhController.kt │ │ │ │ │ ├── SettingsReaderController.kt │ │ │ │ │ ├── SettingsSourcesController.kt │ │ │ │ │ ├── SettingsStatisticsController.kt │ │ │ │ │ ├── SettingsTrackingController.kt │ │ │ │ │ └── track │ │ │ │ │ │ ├── AnilistLoginActivity.kt │ │ │ │ │ │ ├── BangumiLoginActivity.kt │ │ │ │ │ │ ├── MyAnimeListLoginActivity.kt │ │ │ │ │ │ └── ShikimoriLoginActivity.kt │ │ │ │ ├── source │ │ │ │ │ ├── LangHolder.kt │ │ │ │ │ ├── LangItem.kt │ │ │ │ │ ├── SourceAdapter.kt │ │ │ │ │ ├── SourceController.kt │ │ │ │ │ ├── SourceDividerItemDecoration.kt │ │ │ │ │ ├── SourceHolder.kt │ │ │ │ │ ├── SourceItem.kt │ │ │ │ │ ├── SourcePresenter.kt │ │ │ │ │ ├── browse │ │ │ │ │ │ ├── BrowseSourceController.kt │ │ │ │ │ │ ├── BrowseSourcePresenter.kt │ │ │ │ │ │ ├── ExhPager.kt │ │ │ │ │ │ ├── NoResultsException.kt │ │ │ │ │ │ ├── Pager.kt │ │ │ │ │ │ ├── ProgressItem.kt │ │ │ │ │ │ ├── RecommendsPager.kt │ │ │ │ │ │ ├── SourceComfortableGridHolder.kt │ │ │ │ │ │ ├── SourceFilterSheet.kt │ │ │ │ │ │ ├── SourceGridHolder.kt │ │ │ │ │ │ ├── SourceHolder.kt │ │ │ │ │ │ ├── SourceItem.kt │ │ │ │ │ │ ├── SourceListHolder.kt │ │ │ │ │ │ └── SourcePager.kt │ │ │ │ │ ├── filter │ │ │ │ │ │ ├── CheckboxItem.kt │ │ │ │ │ │ ├── GroupItem.kt │ │ │ │ │ │ ├── HeaderItem.kt │ │ │ │ │ │ ├── HelpDialogItem.kt │ │ │ │ │ │ ├── SectionItems.kt │ │ │ │ │ │ ├── SelectItem.kt │ │ │ │ │ │ ├── SeparatorItem.kt │ │ │ │ │ │ ├── SortGroup.kt │ │ │ │ │ │ ├── SortItem.kt │ │ │ │ │ │ ├── TextItem.kt │ │ │ │ │ │ └── TriStateItem.kt │ │ │ │ │ ├── globalsearch │ │ │ │ │ │ ├── GlobalSearchAdapter.kt │ │ │ │ │ │ ├── GlobalSearchCardAdapter.kt │ │ │ │ │ │ ├── GlobalSearchCardHolder.kt │ │ │ │ │ │ ├── GlobalSearchCardItem.kt │ │ │ │ │ │ ├── GlobalSearchController.kt │ │ │ │ │ │ ├── GlobalSearchHolder.kt │ │ │ │ │ │ ├── GlobalSearchItem.kt │ │ │ │ │ │ └── GlobalSearchPresenter.kt │ │ │ │ │ └── latest │ │ │ │ │ │ ├── ExhLatestUpdatesPager.kt │ │ │ │ │ │ ├── LatestUpdatesController.kt │ │ │ │ │ │ ├── LatestUpdatesPager.kt │ │ │ │ │ │ └── LatestUpdatesPresenter.kt │ │ │ │ ├── video │ │ │ │ │ ├── VideoActivity.kt │ │ │ │ │ └── VideoPresenter.kt │ │ │ │ └── webview │ │ │ │ │ ├── BaseWebViewActivity.kt │ │ │ │ │ └── WebViewActivity.kt │ │ │ │ ├── util │ │ │ │ ├── CrashLogUtil.kt │ │ │ │ ├── DeferredField.kt │ │ │ │ ├── JsoupExtensions.kt │ │ │ │ ├── MangaExtensions.kt │ │ │ │ ├── chapter │ │ │ │ │ ├── ChapterRecognition.kt │ │ │ │ │ ├── ChapterSourceSync.kt │ │ │ │ │ └── NoChaptersException.kt │ │ │ │ ├── lang │ │ │ │ │ ├── CloseableExtensions.kt │ │ │ │ │ ├── CoroutinesExtensions.kt │ │ │ │ │ ├── DateExtensions.kt │ │ │ │ │ ├── Hash.kt │ │ │ │ │ ├── RetryWithDelay.kt │ │ │ │ │ ├── RxCoroutineBridge.kt │ │ │ │ │ ├── RxExtensions.kt │ │ │ │ │ └── StringExtensions.kt │ │ │ │ ├── preference │ │ │ │ │ └── PreferenceDSL.kt │ │ │ │ ├── storage │ │ │ │ │ ├── DiskUtil.kt │ │ │ │ │ ├── EpubFile.kt │ │ │ │ │ ├── EpubFileCompat.kt │ │ │ │ │ ├── FileExtensions.kt │ │ │ │ │ └── OkioExtensions.kt │ │ │ │ ├── system │ │ │ │ │ ├── ChildFirstPathClassLoader.kt │ │ │ │ │ ├── ContextExtensions.kt │ │ │ │ │ ├── CoroutinesExtensions.kt │ │ │ │ │ ├── GLUtil.kt │ │ │ │ │ ├── ImageUtil.kt │ │ │ │ │ ├── LocaleHelper.kt │ │ │ │ │ ├── MiuiUtil.kt │ │ │ │ │ ├── WebViewClientCompat.kt │ │ │ │ │ └── WebViewUtil.kt │ │ │ │ └── view │ │ │ │ │ ├── ImageViewExtensions.kt │ │ │ │ │ ├── ViewExtensions.kt │ │ │ │ │ ├── ViewGroupExtensions.kt │ │ │ │ │ └── WindowExtensions.kt │ │ │ │ └── widget │ │ │ │ ├── AutofitRecyclerView.kt │ │ │ │ ├── DialogCheckboxView.kt │ │ │ │ ├── DialogCustomDownloadView.kt │ │ │ │ ├── DrawerSwipeCloseListener.kt │ │ │ │ ├── ElevationAppBarLayout.kt │ │ │ │ ├── EmptyView.kt │ │ │ │ ├── ExtendedNavigationView.kt │ │ │ │ ├── IgnoreFirstSpinnerListener.kt │ │ │ │ ├── LimitedScrollView.kt │ │ │ │ ├── MinMaxNumberPicker.kt │ │ │ │ ├── NegativeSeekBar.kt │ │ │ │ ├── OutlineSpan.kt │ │ │ │ ├── RecyclerViewPagerAdapter.kt │ │ │ │ ├── RevealAnimationView.kt │ │ │ │ ├── SimpleAnimationListener.kt │ │ │ │ ├── SimpleNavigationView.kt │ │ │ │ ├── SimpleSeekBarListener.kt │ │ │ │ ├── StateImageViewTarget.kt │ │ │ │ ├── ThemedSwipeRefreshLayout.kt │ │ │ │ ├── ViewPagerAdapter.kt │ │ │ │ └── preference │ │ │ │ ├── BadgePreference.kt │ │ │ │ ├── IntListPreference.kt │ │ │ │ ├── LoginDialogPreference.kt │ │ │ │ ├── LoginPreference.kt │ │ │ │ ├── SwitchPreferenceCategory.kt │ │ │ │ ├── TrackLoginDialog.kt │ │ │ │ └── TrackLogoutDialog.kt │ │ ├── exh │ │ │ ├── EHSourceHelpers.kt │ │ │ ├── EXHMigrations.kt │ │ │ ├── GalleryAdder.kt │ │ │ ├── StringBuilderExtensions.kt │ │ │ ├── debug │ │ │ │ ├── DebugFunctions.kt │ │ │ │ ├── DebugToggles.kt │ │ │ │ ├── SettingsDebugController.kt │ │ │ │ └── StatisticsInfoClass.kt │ │ │ ├── eh │ │ │ │ ├── EHentaiThrottleManager.kt │ │ │ │ ├── EHentaiUpdateHelper.kt │ │ │ │ ├── EHentaiUpdateWorker.kt │ │ │ │ ├── EHentaiUpdaterStats.kt │ │ │ │ ├── GalleryNotUpdatedException.kt │ │ │ │ └── MemAutoFlushingLookupTable.kt │ │ │ ├── favorites │ │ │ │ ├── FavoriteEntry.kt │ │ │ │ ├── FavoritesIntroDialog.kt │ │ │ │ ├── FavoritesSyncHelper.kt │ │ │ │ └── LocalFavoritesStorage.kt │ │ │ ├── log │ │ │ │ ├── CrashlyticsPrinter.kt │ │ │ │ ├── EHDebugModeOverlay.kt │ │ │ │ ├── EHLogLevel.kt │ │ │ │ └── EHNetworkLogging.kt │ │ │ ├── metadata │ │ │ │ ├── MetadataUtil.kt │ │ │ │ ├── metadata │ │ │ │ │ ├── EHentaiSearchMetadata.kt │ │ │ │ │ ├── HentaiCafeSearchMetadata.kt │ │ │ │ │ ├── NHentaiSearchMetadata.kt │ │ │ │ │ ├── PururinSearchMetadata.kt │ │ │ │ │ ├── RaisedSearchMetadata.kt │ │ │ │ │ ├── TsuminoSearchMetadata.kt │ │ │ │ │ └── base │ │ │ │ │ │ ├── FlatMetadata.kt │ │ │ │ │ │ ├── RaisedTag.kt │ │ │ │ │ │ └── RaisedTitle.kt │ │ │ │ └── sql │ │ │ │ │ ├── mappers │ │ │ │ │ ├── SearchMetadataTypeMapping.kt │ │ │ │ │ ├── SearchTagTypeMapping.kt │ │ │ │ │ └── SearchTitleTypeMapping.kt │ │ │ │ │ ├── models │ │ │ │ │ ├── SearchMetadata.kt │ │ │ │ │ ├── SearchTag.kt │ │ │ │ │ └── SearchTitle.kt │ │ │ │ │ ├── queries │ │ │ │ │ ├── SearchMetadataQueries.kt │ │ │ │ │ ├── SearchTagQueries.kt │ │ │ │ │ └── SearchTitleQueries.kt │ │ │ │ │ └── tables │ │ │ │ │ ├── SearchMetadataTable.kt │ │ │ │ │ ├── SearchTagTable.kt │ │ │ │ │ └── SearchTitleTable.kt │ │ │ ├── patch │ │ │ │ ├── MangaDexLogin.kt │ │ │ │ ├── NetworkPatches.kt │ │ │ │ └── UniversalCaptchaDetection.kt │ │ │ ├── savedsearches │ │ │ │ ├── EXHSavedSearch.kt │ │ │ │ └── JsonSavedSearch.kt │ │ │ ├── search │ │ │ │ ├── MultiWildcard.kt │ │ │ │ ├── Namespace.kt │ │ │ │ ├── QueryComponent.kt │ │ │ │ ├── SearchEngine.kt │ │ │ │ ├── SingleWildcard.kt │ │ │ │ ├── StringTextComponent.kt │ │ │ │ ├── Text.kt │ │ │ │ └── TextComponent.kt │ │ │ ├── smartsearch │ │ │ │ └── SmartSearchEngine.kt │ │ │ ├── source │ │ │ │ ├── BlacklistedSources.kt │ │ │ │ ├── DelegatedHttpSource.kt │ │ │ │ └── EnhancedHttpSource.kt │ │ │ ├── uconfig │ │ │ │ ├── ConfiguringDialogController.kt │ │ │ │ ├── EHConfigurator.kt │ │ │ │ ├── EHHathPerksResponse.kt │ │ │ │ ├── EhUConfigBuilder.kt │ │ │ │ └── WarnConfigureDialogController.kt │ │ │ ├── ui │ │ │ │ ├── LoaderManager.kt │ │ │ │ ├── base │ │ │ │ │ └── BaseExhController.kt │ │ │ │ ├── batchadd │ │ │ │ │ ├── BatchAddController.kt │ │ │ │ │ └── BatchAddPresenter.kt │ │ │ │ ├── captcha │ │ │ │ │ ├── AutoSolvingWebViewClient.kt │ │ │ │ │ ├── BasicWebViewClient.kt │ │ │ │ │ ├── BrowserActionActivity.kt │ │ │ │ │ ├── HeadersInjectingWebViewClient.kt │ │ │ │ │ └── WebViewUtil.kt │ │ │ │ ├── intercept │ │ │ │ │ └── InterceptActivity.kt │ │ │ │ ├── lock │ │ │ │ │ ├── FingerLockPreference.kt │ │ │ │ │ ├── LockActivityDelegate.kt │ │ │ │ │ ├── LockChangeHandler.kt │ │ │ │ │ ├── LockController.kt │ │ │ │ │ ├── LockPreference.kt │ │ │ │ │ ├── LockPresenter.kt │ │ │ │ │ └── LockUtils.kt │ │ │ │ ├── login │ │ │ │ │ ├── LoginController.kt │ │ │ │ │ └── LoginPresenter.kt │ │ │ │ └── smartsearch │ │ │ │ │ ├── SmartSearchController.kt │ │ │ │ │ └── SmartSearchPresenter.kt │ │ │ └── util │ │ │ │ ├── CachedField.kt │ │ │ │ ├── ContextExtensions.kt │ │ │ │ ├── CoroutineUtil.kt │ │ │ │ ├── DatabaseExtensions.kt │ │ │ │ ├── DeferredField.kt │ │ │ │ ├── ExceptionUtil.kt │ │ │ │ ├── FakeMutables.kt │ │ │ │ ├── JsonReaderObjectReader.kt │ │ │ │ ├── LewdMangaChecker.kt │ │ │ │ ├── LoggingRealmQuery.kt │ │ │ │ ├── MangaType.kt │ │ │ │ ├── NakedTrie.kt │ │ │ │ ├── OkHttpUtil.kt │ │ │ │ ├── RealmUtil.kt │ │ │ │ ├── RxUtil.kt │ │ │ │ ├── SearchOverride.kt │ │ │ │ ├── SourceTagsUtil.kt │ │ │ │ ├── SparseArrayCollection.kt │ │ │ │ ├── StringUtil.kt │ │ │ │ ├── UriFilter.kt │ │ │ │ ├── UriGroup.kt │ │ │ │ ├── ViewExtensions.kt │ │ │ │ └── ViewUtil.kt │ │ ├── org │ │ │ └── vepta │ │ │ │ └── vdm │ │ │ │ └── ByteCursor.kt │ │ └── xyz │ │ │ └── nulldev │ │ │ └── ts │ │ │ └── api │ │ │ └── http │ │ │ └── serializer │ │ │ ├── FilterSerializer.kt │ │ │ └── FilterSerializerModels.kt │ └── res │ │ ├── anim │ │ ├── enter_from_bottom.xml │ │ ├── enter_from_top.xml │ │ ├── exit_to_bottom.xml │ │ ├── exit_to_top.xml │ │ └── fade_in_long.xml │ │ ├── color │ │ └── text_input_stroke.xml │ │ ├── drawable-anydpi │ │ ├── ic_copy.xml │ │ ├── ic_done.xml │ │ └── ic_done_all.xml │ │ ├── drawable-hdpi │ │ ├── ic_copy.png │ │ ├── ic_done.png │ │ ├── ic_done_all.png │ │ ├── ic_extension_update.png │ │ └── tachiyomi_circle.webp │ │ ├── drawable-mdpi │ │ ├── ic_copy.png │ │ ├── ic_done.png │ │ ├── ic_done_all.png │ │ ├── ic_extension_update.png │ │ └── tachiyomi_circle.webp │ │ ├── drawable-nodpi │ │ ├── filter_mock.webp │ │ ├── ic_tracker_anilist.webp │ │ ├── ic_tracker_bangumi.webp │ │ ├── ic_tracker_kitsu.webp │ │ ├── ic_tracker_mal.webp │ │ └── ic_tracker_shikimori.webp │ │ ├── drawable-v21 │ │ └── lock_dot_empty.xml │ │ ├── drawable-xhdpi │ │ ├── ic_copy.png │ │ ├── ic_done.png │ │ ├── ic_done_all.png │ │ ├── ic_extension_update.png │ │ └── tachiyomi_circle.webp │ │ ├── drawable-xxhdpi │ │ ├── ic_copy.png │ │ ├── ic_done.png │ │ ├── ic_done_all.png │ │ ├── ic_extension_update.png │ │ └── tachiyomi_circle.webp │ │ ├── drawable-xxxhdpi │ │ ├── ic_extension_update.png │ │ └── tachiyomi_circle.webp │ │ ├── drawable │ │ ├── baseline_swap_calls_24.xml │ │ ├── dialog_rounded_background.xml │ │ ├── eh_ic_arrow_drop_down_white_100dp.xml │ │ ├── eh_ic_check_white_24dp.xml │ │ ├── eh_ic_clear_white_24dp.xml │ │ ├── eh_ic_ehlogo_red_24dp.xml │ │ ├── eh_ic_find_replace_white_24dp.xml │ │ ├── eh_ic_nhlogo_color.xml │ │ ├── eh_migration_backup.png │ │ ├── eh_migration_backup_button.png │ │ ├── eh_migration_hamburgers.png │ │ ├── eh_migration_share_icon.png │ │ ├── empty_divider.xml │ │ ├── empty_drawable_32dp.xml │ │ ├── fumo.jpg │ │ ├── gradient_shape.xml │ │ ├── ic_add_24dp.xml │ │ ├── ic_add_to_library_24dp.xml │ │ ├── ic_arrow_back_24dp.xml │ │ ├── ic_arrow_down_white_32dp.xml │ │ ├── ic_arrow_forward_24dp.xml │ │ ├── ic_arrow_up_white_32dp.xml │ │ ├── ic_backup_24dp.xml │ │ ├── ic_book_24dp.xml │ │ ├── ic_bookmark_24dp.xml │ │ ├── ic_bookmark_border_24dp.xml │ │ ├── ic_brightness_4_24dp.xml │ │ ├── ic_brightness_5_24dp.xml │ │ ├── ic_broken_image_grey_24dp.xml │ │ ├── ic_check_box_24dp.xml │ │ ├── ic_check_box_outline_blank_24dp.xml │ │ ├── ic_check_box_x_24dp.xml │ │ ├── ic_chevron_left_black_24dp.xml │ │ ├── ic_chevron_left_double_black_24dp.xml │ │ ├── ic_chevron_right_black_24dp.xml │ │ ├── ic_chevron_right_double_black_24dp.xml │ │ ├── ic_chevron_right_white_24dp.xml │ │ ├── ic_chrome_reader_mode_24dp.xml │ │ ├── ic_clear_grey.xml │ │ ├── ic_close_24dp.xml │ │ ├── ic_cloud_download_white_24dp.xml │ │ ├── ic_cloud_off_24dp.xml │ │ ├── ic_cloud_white_24dp.xml │ │ ├── ic_code_24dp.xml │ │ ├── ic_collections_bookmark_24dp.xml │ │ ├── ic_collections_bookmark_outline_24dp.xml │ │ ├── ic_collections_bookmark_state.xml │ │ ├── ic_copy_24dp.xml │ │ ├── ic_delete_24dp.xml │ │ ├── ic_desktop_windows_black_24dp.xml │ │ ├── ic_done_24dp.xml │ │ ├── ic_done_all_24dp.xml │ │ ├── ic_done_green_24dp.xml │ │ ├── ic_done_outline_24dp.xml │ │ ├── ic_done_prev_24dp.xml │ │ ├── ic_done_white_18dp.xml │ │ ├── ic_drag_pill_24dp.xml │ │ ├── ic_edit_24dp.xml │ │ ├── ic_error_grey.xml │ │ ├── ic_expand_more_white_24dp.xml │ │ ├── ic_explore_24dp.xml │ │ ├── ic_explore_outline_24dp.xml │ │ ├── ic_explore_state.xml │ │ ├── ic_extension_24dp.xml │ │ ├── ic_file_download_black_24dp.xml │ │ ├── ic_filter_list_24dp.xml │ │ ├── ic_flip_to_back_24dp.xml │ │ ├── ic_folder_24dp.xml │ │ ├── ic_get_app_24dp.xml │ │ ├── ic_glasses_black_128dp.xml │ │ ├── ic_glasses_black_24dp.xml │ │ ├── ic_help_24dp.xml │ │ ├── ic_help_white_24dp.xml │ │ ├── ic_history_24dp.xml │ │ ├── ic_in_library_24dp.xml │ │ ├── ic_info_24dp.xml │ │ ├── ic_keyboard_arrow_down_black_32dp.xml │ │ ├── ic_keyboard_arrow_down_white_32dp.xml │ │ ├── ic_keyboard_arrow_right_black_24dp.xml │ │ ├── ic_keyboard_arrow_up_black_32dp.xml │ │ ├── ic_keyboard_arrow_up_white_32dp.xml │ │ ├── ic_label_24dp.xml │ │ ├── ic_language_black_24dp.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_menu_white_24dp.xml │ │ ├── ic_migrate_direction.xml │ │ ├── ic_more_horiz_24dp.xml │ │ ├── ic_more_vert_24dp.xml │ │ ├── ic_more_vert_black_24dp.xml │ │ ├── ic_new_releases_24dp.xml │ │ ├── ic_new_releases_outline_24dp.xml │ │ ├── ic_new_releases_state.xml │ │ ├── ic_pause_24dp.xml │ │ ├── ic_photo_24dp.xml │ │ ├── ic_pin_24dp.xml │ │ ├── ic_play_arrow_24dp.xml │ │ ├── ic_playlist_add_black_24dp.xml │ │ ├── ic_public_24dp.xml │ │ ├── ic_query_stats_24dp.xml │ │ ├── ic_refresh_24dp.xml │ │ ├── ic_reorder_grey_24dp.xml │ │ ├── ic_save_black_24dp.xml │ │ ├── ic_search_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_skip_next_24dp.xml │ │ ├── ic_skip_previous_24dp.xml │ │ ├── ic_sort_by_numeric_white_24dp.xml │ │ ├── ic_sort_white_24dp.xml │ │ ├── ic_start_reading_24dp.xml │ │ ├── ic_sync_24dp.xml │ │ ├── ic_system_update_alt_white_24dp.xml │ │ ├── ic_tachi.xml │ │ ├── ic_tune_24dp.xml │ │ ├── ic_update_black_128dp.xml │ │ ├── ic_update_black_24dp.xml │ │ ├── ic_view_module_24dp.xml │ │ ├── ic_warning_white_24dp.xml │ │ ├── ic_watch_later_black_24dp.xml │ │ ├── library_item_selector.xml │ │ ├── line_divider.xml │ │ ├── list_item_selector.xml │ │ ├── lock_dot_empty.xml │ │ ├── lock_dot_filled.xml │ │ ├── round_play_background.xml │ │ ├── round_textview_background.xml │ │ ├── rounded_rectangle.xml │ │ ├── sc_book_48dp.xml │ │ ├── sc_explore_48dp.xml │ │ ├── sc_glasses_48dp.xml │ │ ├── sc_update_48dp.xml │ │ ├── snackbar_bg.xml │ │ ├── splash_background.xml │ │ ├── tab_indicator.xml │ │ └── text_button.xml │ │ ├── font │ │ └── ptsans_narrow_bold.ttf │ │ ├── layout-land │ │ └── reader_color_filter_sheet.xml │ │ ├── layout │ │ ├── activity_lock.xml │ │ ├── activity_webview.xml │ │ ├── categories_controller.xml │ │ ├── categories_item.xml │ │ ├── changelog_header_layout.xml │ │ ├── changelog_row_layout.xml │ │ ├── chapters_controller.xml │ │ ├── chapters_item.xml │ │ ├── common_dialog_with_checkbox.xml │ │ ├── common_spinner_item.xml │ │ ├── common_view_empty.xml │ │ ├── download_controller.xml │ │ ├── download_custom_amount.xml │ │ ├── download_item.xml │ │ ├── eh_activity_captcha.xml │ │ ├── eh_activity_intercept.xml │ │ ├── eh_activity_login.xml │ │ ├── eh_dialog_categories.xml │ │ ├── eh_dialog_languages.xml │ │ ├── eh_fragment_batch_add.xml │ │ ├── extension_card_header.xml │ │ ├── extension_card_item.xml │ │ ├── extension_controller.xml │ │ ├── extension_detail_controller.xml │ │ ├── extension_detail_item.xml │ │ ├── extension_preferences_controller.xml │ │ ├── global_search_controller.xml │ │ ├── global_search_controller_card.xml │ │ ├── global_search_controller_card_item.xml │ │ ├── history_controller.xml │ │ ├── history_item.xml │ │ ├── library_category.xml │ │ ├── library_controller.xml │ │ ├── library_drawer.xml │ │ ├── library_grid_recycler.xml │ │ ├── library_list_recycler.xml │ │ ├── main_activity.xml │ │ ├── manga_controller.xml │ │ ├── manga_info_controller.xml │ │ ├── manga_info_web_controller.xml │ │ ├── migration_bottom_sheet.xml │ │ ├── migration_controller.xml │ │ ├── migration_list_controller.xml │ │ ├── migration_manga_card.xml │ │ ├── migration_process_item.xml │ │ ├── migration_source_item.xml │ │ ├── navigation_header.xml │ │ ├── navigation_view_checkbox.xml │ │ ├── navigation_view_checkedtext.xml │ │ ├── navigation_view_group.xml │ │ ├── navigation_view_help_dialog.xml │ │ ├── navigation_view_radio.xml │ │ ├── navigation_view_spinner.xml │ │ ├── navigation_view_text.xml │ │ ├── pre_migration_controller.xml │ │ ├── pref_account_login.xml │ │ ├── pref_badge.xml │ │ ├── pref_library_columns.xml │ │ ├── pref_widget_imageview.xml │ │ ├── reader_activity.xml │ │ ├── reader_color_filter.xml │ │ ├── reader_color_filter_sheet.xml │ │ ├── reader_page_sheet.xml │ │ ├── reader_settings_sheet.xml │ │ ├── reader_transition_view.xml │ │ ├── recent_section_item.xml │ │ ├── recycler_view_item.xml │ │ ├── recycler_view_item_1.xml │ │ ├── smart_search.xml │ │ ├── source_comfortable_grid_item.xml │ │ ├── source_compact_grid_item.xml │ │ ├── source_controller.xml │ │ ├── source_drawer.xml │ │ ├── source_filter_sheet.xml │ │ ├── source_list_item.xml │ │ ├── source_main_controller.xml │ │ ├── source_main_controller_card.xml │ │ ├── source_main_controller_card_item.xml │ │ ├── source_progress_item.xml │ │ ├── source_recycler_autofit.xml │ │ ├── track_chapters_dialog.xml │ │ ├── track_controller.xml │ │ ├── track_item.xml │ │ ├── track_score_dialog.xml │ │ ├── track_search_dialog.xml │ │ ├── track_search_item.xml │ │ ├── updates_controller.xml │ │ ├── updates_item.xml │ │ ├── video_activity.xml │ │ └── webview_activity.xml │ │ ├── menu │ │ ├── category_selection.xml │ │ ├── chapter_recent.xml │ │ ├── chapter_selection.xml │ │ ├── chapter_single.xml │ │ ├── chapters.xml │ │ ├── download_queue.xml │ │ ├── download_single.xml │ │ ├── extension_main.xml │ │ ├── global_search.xml │ │ ├── library.xml │ │ ├── library_selection.xml │ │ ├── manga_info.xml │ │ ├── menu_navigation.xml │ │ ├── menu_webview.xml │ │ ├── migration.xml │ │ ├── migration_list.xml │ │ ├── migration_single.xml │ │ ├── pre_migration.xml │ │ ├── reader.xml │ │ ├── recently_read.xml │ │ ├── settings.xml │ │ ├── settings_sources.xml │ │ ├── source_browse.xml │ │ ├── source_main.xml │ │ ├── updates.xml │ │ ├── updates_chapter_selection.xml │ │ └── webview.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_ehentai_source.png │ │ ├── ic_exhentai_source.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_local_source.webp │ │ ├── ic_merged_source.png │ │ └── ic_nhentai_source.png │ │ ├── mipmap-mdpi │ │ ├── ic_ehentai_source.png │ │ ├── ic_exhentai_source.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_local_source.webp │ │ ├── ic_merged_source.png │ │ └── ic_nhentai_source.png │ │ ├── mipmap-xhdpi │ │ ├── ic_ehentai_source.png │ │ ├── ic_exhentai_source.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_local_source.webp │ │ ├── ic_merged_source.png │ │ └── ic_nhentai_source.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_ehentai_source.png │ │ ├── ic_exhentai_source.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_local_source.webp │ │ ├── ic_merged_source.png │ │ └── ic_nhentai_source.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_ehentai_source.png │ │ ├── ic_exhentai_source.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_local_source.webp │ │ ├── ic_merged_source.png │ │ └── ic_nhentai_source.png │ │ ├── raw │ │ ├── changelog_debug.xml │ │ └── changelog_release.xml │ │ ├── values-ar │ │ └── strings.xml │ │ ├── values-b+es+419 │ │ └── strings.xml │ │ ├── values-bg │ │ └── strings.xml │ │ ├── values-bn │ │ └── strings.xml │ │ ├── values-ca │ │ └── strings.xml │ │ ├── values-cs │ │ └── strings.xml │ │ ├── values-de │ │ └── strings.xml │ │ ├── values-el │ │ └── strings.xml │ │ ├── values-es │ │ └── strings.xml │ │ ├── values-fi │ │ └── strings.xml │ │ ├── values-fr │ │ └── strings.xml │ │ ├── values-he │ │ └── strings.xml │ │ ├── values-hi │ │ └── strings.xml │ │ ├── values-hr │ │ └── strings.xml │ │ ├── values-hu │ │ └── strings.xml │ │ ├── values-in │ │ └── strings.xml │ │ ├── values-it │ │ └── strings.xml │ │ ├── values-ja │ │ └── strings.xml │ │ ├── values-kn │ │ └── strings.xml │ │ ├── values-ko │ │ └── strings.xml │ │ ├── values-land │ │ └── dimens.xml │ │ ├── values-lv │ │ └── strings.xml │ │ ├── values-mr │ │ └── strings.xml │ │ ├── values-ms │ │ └── strings.xml │ │ ├── values-nb-rNO │ │ └── strings.xml │ │ ├── values-night │ │ └── themes.xml │ │ ├── values-nl │ │ └── strings.xml │ │ ├── values-pl │ │ └── strings.xml │ │ ├── values-pt-rBR │ │ └── strings.xml │ │ ├── values-pt │ │ └── strings.xml │ │ ├── values-ro │ │ └── strings.xml │ │ ├── values-ru │ │ └── strings.xml │ │ ├── values-sc │ │ └── strings.xml │ │ ├── values-sk │ │ └── strings.xml │ │ ├── values-sr │ │ └── strings.xml │ │ ├── values-sv │ │ └── strings.xml │ │ ├── values-sw360dp-v13 │ │ └── values-preference.xml │ │ ├── values-sw600dp │ │ └── dimens.xml │ │ ├── values-th │ │ └── strings.xml │ │ ├── values-tl │ │ └── strings.xml │ │ ├── values-tr │ │ └── strings.xml │ │ ├── values-uk │ │ └── strings.xml │ │ ├── values-ur-rPK │ │ └── strings.xml │ │ ├── values-v23 │ │ └── themes.xml │ │ ├── values-v26 │ │ └── colors.xml │ │ ├── values-v27 │ │ └── themes.xml │ │ ├── values-v28 │ │ └── arrays.xml │ │ ├── values-vi │ │ └── strings.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values-zh-rCN │ │ └── strings.xml │ │ ├── values-zh-rTW │ │ └── strings.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ ├── network_security_config.xml │ │ ├── provider_paths.xml │ │ ├── searchable.xml │ │ └── shortcuts.xml │ └── test │ └── java │ └── eu │ └── kanade │ └── tachiyomi │ ├── CustomRobolectricGradleTestRunner.kt │ └── data │ ├── backup │ └── BackupTest.kt │ └── library │ └── LibraryUpdateServiceTest.kt ├── branding └── teh-banner.png ├── build.gradle.kts ├── buildSrc ├── .gitignore ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── Dependencies.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── ktlintCodeStyle.xml ├── settings.gradle.kts └── update-frequency.patch /.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 | 26 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: inorichi 2 | ko_fi: inorichi 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **PLEASE READ THIS** 2 | 3 | I acknowledge that: 4 | 5 | - I have updated to the latest version of the app (stable is v0.8.5) 6 | - I have updated all extensions 7 | - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions 8 | 9 | **DELETE THIS SECTION IF YOU HAVE READ AND ACKNOWLEDGED IT** 10 | 11 | --- 12 | 13 | ### Device information 14 | * Tachiyomi version: ? 15 | * Android version: ? 16 | * Device: ? 17 | 18 | ## Steps to reproduce 19 | 1. First step 20 | 2. Second step 21 | 22 | ## Issue/Request 23 | ? 24 | 25 | ## Other details 26 | Additional details and attachments. 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🐞 Bug report" 3 | about: Report a bug 4 | title: "[Bug] Write short description here" 5 | labels: "bug" 6 | --- 7 | 8 | **PLEASE READ THIS** 9 | 10 | I acknowledge that: 11 | 12 | - I have updated to the latest version of the app (stable is v8.7.0) 13 | - I have updated all extensions 14 | - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions 15 | 16 | **DELETE THIS SECTION IF YOU HAVE READ AND ACKNOWLEDGED IT** 17 | 18 | --- 19 | 20 | ### Device information 21 | * Tachiyomi version: ? 22 | * Android version: ? 23 | * Device: ? 24 | 25 | ## Steps to reproduce 26 | 1. First step 27 | 2. Second step 28 | 29 | ### Expected behavior 30 | This should happen. 31 | 32 | ### Actual behavior 33 | This happened instead. 34 | 35 | ### Other details 36 | Additional details and attachments. 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🌟 Feature request" 3 | about: Suggest a feature to improve Tachiyomi 4 | title: "[Feature Request] Write short description here" 5 | labels: "feature" 6 | --- 7 | 8 | **PLEASE READ THIS** 9 | 10 | I acknowledge that: 11 | 12 | - I have updated to the latest version of the app (stable is v8.7.0) 13 | - I have updated all extensions 14 | - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions 15 | 16 | **DELETE THIS SECTION IF YOU HAVE READ AND ACKNOWLEDGED IT** 17 | 18 | --- 19 | 20 | ### Why/User Benefit/User Problem 21 | (explain why this feature should be added) 22 | 23 | ### What/Requirements 24 | (explain how this feature would behave) 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/source_issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Extension/source/catalogue issue" 3 | about: "Do not open an issue here. See https://github.com/inorichi/tachiyomi-extensions" 4 | title: "THIS ISSUE IS IN THE WRONG REPO; SEE https://github.com/inorichi/tachiyomi-extensions" 5 | labels: "catalog" 6 | --- 7 | 8 | DO NOT OPEN AN ISSUE IN THIS REPO. SEE https://github.com/inorichi/tachiyomi-extensions -------------------------------------------------------------------------------- /.github/readme-images/app-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/.github/readme-images/app-icon.png -------------------------------------------------------------------------------- /.github/readme-images/screens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/.github/readme-images/screens.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | .DS_Store 5 | .idea/ 6 | *iml 7 | *.iml 8 | /mainframer 9 | /.mainframer 10 | TODO.md 11 | CHANGELOG.md 12 | /captures 13 | build.sh 14 | test.sh 15 | 16 | # Built files 17 | */build 18 | /build 19 | *.apk 20 | *.idsig 21 | app/**/output.json 22 | 23 | 24 | # Hebrew assets are copied on build 25 | app/src/main/res/values-iw/ 26 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *iml 3 | *.iml 4 | custom.gradle 5 | google-services.json 6 | output.json -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/AppInfo.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi 2 | 3 | import eu.kanade.tachiyomi.util.system.ImageUtil 4 | 5 | /** 6 | * Used by extensions. 7 | * 8 | * @since extension-lib 1.3 9 | */ 10 | object AppInfo { 11 | fun getVersionCode() = BuildConfig.VERSION_CODE 12 | 13 | fun getVersionName() = BuildConfig.VERSION_NAME 14 | 15 | // @since extension-lib 1.5 16 | fun getSupportedImageMimeTypes() = ImageUtil.ImageType.entries.map { it.mime } 17 | } 18 | -------------------------------------------------------------------------------- /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/data/backup/AbstractBackupRestoreValidator.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup 2 | 3 | import android.content.Context 4 | import android.net.Uri 5 | import eu.kanade.tachiyomi.data.track.TrackManager 6 | import eu.kanade.tachiyomi.source.SourceManager 7 | import uy.kohesive.injekt.injectLazy 8 | 9 | abstract class AbstractBackupRestoreValidator { 10 | protected val sourceManager: SourceManager by injectLazy() 11 | protected val trackManager: TrackManager by injectLazy() 12 | 13 | abstract fun validate( 14 | context: Context, 15 | uri: Uri 16 | ): Results 17 | 18 | data class Results(val missingSources: List, val missingTrackers: List) 19 | } 20 | -------------------------------------------------------------------------------- /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 = "BackupRestoreServices" 7 | const val EXTRA_URI = "$ID.$NAME.EXTRA_URI" 8 | const val EXTRA_FLAGS = "$ID.$NAME.EXTRA_FLAGS" 9 | const val EXTRA_MODE = "$ID.$NAME.EXTRA_MODE" 10 | const val EXTRA_TYPE = "$ID.$NAME.EXTRA_TYPE" 11 | 12 | const val BACKUP_TYPE_LEGACY = 0 13 | const val BACKUP_TYPE_FULL = 1 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/full/models/Backup.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.full.models 2 | 3 | import kotlinx.serialization.ExperimentalSerializationApi 4 | import kotlinx.serialization.Serializable 5 | import kotlinx.serialization.protobuf.ProtoNumber 6 | 7 | /** 8 | * Backup json model 9 | */ 10 | @ExperimentalSerializationApi 11 | @Serializable 12 | data class Backup( 13 | @ProtoNumber(1) val backupManga: List, 14 | @ProtoNumber(2) var backupCategories: List = emptyList(), 15 | // Bump by 100 to specify this is a 0.x value 16 | @ProtoNumber(100) var backupSources: List = emptyList(), 17 | // SY specific values 18 | @ProtoNumber(600) var backupSavedSearches: List = emptyList() 19 | ) 20 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/full/models/BackupFull.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.full.models 2 | 3 | import java.text.SimpleDateFormat 4 | import java.util.Date 5 | import java.util.Locale 6 | 7 | object BackupFull { 8 | fun getDefaultFilename(): String { 9 | val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.getDefault()).format(Date()) 10 | return "tachiyomi_full_$date.tachibk" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/full/models/BackupHistory.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.full.models 2 | 3 | import kotlinx.serialization.ExperimentalSerializationApi 4 | import kotlinx.serialization.Serializable 5 | import kotlinx.serialization.protobuf.ProtoNumber 6 | 7 | @ExperimentalSerializationApi 8 | @Serializable 9 | data class BackupHistory( 10 | @ProtoNumber(0) var url: String, 11 | @ProtoNumber(1) var lastRead: Long 12 | ) 13 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/full/models/BackupSavedSearch.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.full.models 2 | 3 | import kotlinx.serialization.ExperimentalSerializationApi 4 | import kotlinx.serialization.Serializable 5 | import kotlinx.serialization.protobuf.ProtoNumber 6 | 7 | /* 8 | * SY saved searches class 9 | */ 10 | @ExperimentalSerializationApi 11 | @Serializable 12 | data class BackupSavedSearch( 13 | @ProtoNumber(1) val name: String, 14 | @ProtoNumber(2) val query: String = "", 15 | @ProtoNumber(3) val filterList: String = "", 16 | @ProtoNumber(4) val source: Long = 0 17 | ) 18 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/full/models/BackupSerializer.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.full.models 2 | 3 | import kotlinx.serialization.ExperimentalSerializationApi 4 | import kotlinx.serialization.Serializer 5 | 6 | @ExperimentalSerializationApi 7 | @Serializer(forClass = Backup::class) 8 | object BackupSerializer 9 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/full/models/BackupSource.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.full.models 2 | 3 | import eu.kanade.tachiyomi.source.Source 4 | import kotlinx.serialization.ExperimentalSerializationApi 5 | import kotlinx.serialization.Serializable 6 | import kotlinx.serialization.protobuf.ProtoNumber 7 | 8 | @ExperimentalSerializationApi 9 | @Serializable 10 | data class BackupSource( 11 | @ProtoNumber(0) var name: String = "", 12 | @ProtoNumber(1) var sourceId: Long 13 | ) { 14 | companion object { 15 | fun copyFrom(source: Source): BackupSource { 16 | return BackupSource( 17 | name = source.name, 18 | sourceId = source.id 19 | ) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/models/Backup.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.legacy.models 2 | 3 | import java.text.SimpleDateFormat 4 | import java.util.Date 5 | import java.util.Locale 6 | 7 | /** 8 | * Json values 9 | */ 10 | object Backup { 11 | const val CURRENT_VERSION = 2 12 | const val MANGA = "manga" 13 | const val MANGAS = "mangas" 14 | const val TRACK = "track" 15 | const val CHAPTERS = "chapters" 16 | const val CATEGORIES = "categories" 17 | const val EXTENSIONS = "extensions" 18 | const val HISTORY = "history" 19 | const val VERSION = "version" 20 | const val SAVEDSEARCHES = "savedsearches" 21 | 22 | fun getDefaultFilename(): String { 23 | val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.getDefault()).format(Date()) 24 | return "tachiyomi_$date.json" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/backup/legacy/models/DHistory.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.backup.legacy.models 2 | 3 | data class DHistory(val url: String, val lastRead: Long) 4 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/DbExtensions.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database 2 | 3 | import com.pushtorefresh.storio.sqlite.StorIOSQLite 4 | 5 | inline fun StorIOSQLite.inTransaction(block: () -> Unit) { 6 | lowLevel().beginTransaction() 7 | try { 8 | block() 9 | lowLevel().setTransactionSuccessful() 10 | } finally { 11 | lowLevel().endTransaction() 12 | } 13 | } 14 | 15 | inline fun StorIOSQLite.inTransactionReturn(block: () -> T): T { 16 | lowLevel().beginTransaction() 17 | try { 18 | val result = block() 19 | lowLevel().setTransactionSuccessful() 20 | return result 21 | } finally { 22 | lowLevel().endTransaction() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/DbProvider.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database 2 | 3 | import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite 4 | 5 | interface DbProvider { 6 | val db: DefaultStorIOSQLite 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | import java.io.Serializable 4 | 5 | interface Category : Serializable { 6 | var id: Int? 7 | 8 | var name: String 9 | 10 | var order: Int 11 | 12 | var flags: Int 13 | 14 | var mangaOrder: List 15 | 16 | companion object { 17 | fun create(name: String): Category = 18 | CategoryImpl().apply { 19 | this.name = name 20 | } 21 | 22 | fun createDefault(): Category = create("Default").apply { id = 0 } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | class CategoryImpl : Category { 4 | override var id: Int? = null 5 | 6 | override lateinit var name: String 7 | 8 | override var order: Int = 0 9 | 10 | override var flags: Int = 0 11 | 12 | override var mangaOrder: List = emptyList() 13 | 14 | override fun equals(other: Any?): Boolean { 15 | if (this === other) return true 16 | if (other == null || javaClass != other.javaClass) return false 17 | 18 | val category = other as Category 19 | return name == category.name 20 | } 21 | 22 | override fun hashCode(): Int { 23 | return name.hashCode() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/Chapter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | import eu.kanade.tachiyomi.source.model.SChapter 4 | import java.io.Serializable 5 | 6 | interface Chapter : SChapter, Serializable { 7 | var id: Long? 8 | 9 | var manga_id: Long? 10 | 11 | var read: Boolean 12 | 13 | var bookmark: Boolean 14 | 15 | var last_page_read: Int 16 | 17 | var date_fetch: Long 18 | 19 | var source_order: Int 20 | 21 | val isRecognizedNumber: Boolean 22 | get() = chapter_number >= 0f 23 | 24 | companion object { 25 | fun create(): Chapter = 26 | ChapterImpl().apply { 27 | chapter_number = -1f 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/HistoryImpl.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | /** 4 | * Object containing the history statistics of a chapter 5 | */ 6 | class HistoryImpl : History { 7 | /** 8 | * Id of history object. 9 | */ 10 | override var id: Long? = null 11 | 12 | /** 13 | * Chapter id of history object. 14 | */ 15 | override var chapter_id: Long = 0 16 | 17 | /** 18 | * Last time chapter was read in time long format 19 | */ 20 | override var last_read: Long = 0 21 | 22 | /** 23 | * Total time chapter was read - todo not yet implemented 24 | */ 25 | override var time_read: Long = 0 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | class LibraryManga : MangaImpl() { 4 | var unread: Int = 0 5 | 6 | var category: Int = 0 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaCategory.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | class MangaCategory { 4 | var id: Long? = null 5 | 6 | var manga_id: Long = 0 7 | 8 | var category_id: Int = 0 9 | 10 | companion object { 11 | fun create( 12 | manga: Manga, 13 | category: Category 14 | ): MangaCategory { 15 | val mc = MangaCategory() 16 | mc.manga_id = manga.id!! 17 | mc.category_id = category.id!! 18 | return mc 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaChapter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | class MangaChapter(val manga: Manga, val chapter: Chapter) 4 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaChapterHistory.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.models 2 | 3 | /** 4 | * Object containing manga, chapter and history 5 | * 6 | * @param manga object containing manga 7 | * @param chapter object containing chater 8 | * @param history object containing history 9 | */ 10 | data class MangaChapterHistory(val manga: Manga, val chapter: Chapter, val history: History) 11 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.tables 2 | 3 | object CategoryTable { 4 | const val TABLE = "categories" 5 | 6 | const val COL_ID = "_id" 7 | 8 | const val COL_NAME = "name" 9 | 10 | const val COL_ORDER = "sort" 11 | 12 | const val COL_FLAGS = "flags" 13 | 14 | const val COL_MANGA_ORDER = "manga_order" 15 | 16 | val createTableQuery: String 17 | get() = 18 | """CREATE TABLE $TABLE( 19 | $COL_ID INTEGER NOT NULL PRIMARY KEY, 20 | $COL_NAME TEXT NOT NULL, 21 | $COL_ORDER INTEGER NOT NULL, 22 | $COL_FLAGS INTEGER NOT NULL, 23 | $COL_MANGA_ORDER TEXT NOT NULL 24 | )""" 25 | 26 | val addMangaOrder: String 27 | get() = "ALTER TABLE $TABLE ADD COLUMN $COL_MANGA_ORDER TEXT" 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.tables 2 | 3 | object MangaCategoryTable { 4 | const val TABLE = "mangas_categories" 5 | 6 | const val COL_ID = "_id" 7 | 8 | const val COL_MANGA_ID = "manga_id" 9 | 10 | const val COL_CATEGORY_ID = "category_id" 11 | 12 | val createTableQuery: String 13 | get() = 14 | """CREATE TABLE $TABLE( 15 | $COL_ID INTEGER NOT NULL PRIMARY KEY, 16 | $COL_MANGA_ID INTEGER NOT NULL, 17 | $COL_CATEGORY_ID INTEGER NOT NULL, 18 | FOREIGN KEY($COL_CATEGORY_ID) REFERENCES ${CategoryTable.TABLE} (${CategoryTable.COL_ID}) 19 | ON DELETE CASCADE, 20 | FOREIGN KEY($COL_MANGA_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID}) 21 | ON DELETE CASCADE 22 | )""" 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MergedTable.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.database.tables 2 | 3 | object MergedTable { 4 | const val TABLE = "merged" 5 | 6 | const val COL_MERGE_ID = "mergeID" 7 | 8 | const val COL_MANGA_ID = "mangaID" 9 | 10 | val createTableQuery: String 11 | get() = 12 | """CREATE TABLE $TABLE( 13 | $COL_MERGE_ID INTEGER NOT NULL, 14 | $COL_MANGA_ID INTEGER NOT NULL 15 | )""" 16 | 17 | val createIndexQuery: String 18 | get() = "CREATE INDEX ${TABLE}_${COL_MERGE_ID}_index ON $TABLE($COL_MERGE_ID)" 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaThumbnail.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.glide 2 | 3 | import com.bumptech.glide.load.Key 4 | import eu.kanade.tachiyomi.data.database.models.Manga 5 | import java.security.MessageDigest 6 | 7 | data class MangaThumbnail(val manga: Manga, val coverLastModified: Long) : Key { 8 | val key = manga.url + coverLastModified 9 | 10 | override fun updateDiskCacheKey(messageDigest: MessageDigest) { 11 | messageDigest.update(key.toByteArray(Key.CHARSET)) 12 | } 13 | } 14 | 15 | fun Manga.toMangaThumbnail() = MangaThumbnail(this, cover_last_modified) 16 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/OAuth.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.anilist 2 | 3 | data class OAuth( 4 | val access_token: String, 5 | val token_type: String, 6 | val expires: Long, 7 | val expires_in: Long 8 | ) { 9 | fun isExpired() = System.currentTimeMillis() > expires 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Avatar.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.bangumi 2 | 3 | data class Avatar( 4 | val large: String? = "", 5 | val medium: String? = "", 6 | val small: String? = "" 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiModels.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.bangumi 2 | 3 | import eu.kanade.tachiyomi.data.database.models.Track 4 | 5 | fun Track.toBangumiStatus() = 6 | when (status) { 7 | Bangumi.READING -> "do" 8 | Bangumi.COMPLETED -> "collect" 9 | Bangumi.ON_HOLD -> "on_hold" 10 | Bangumi.DROPPED -> "dropped" 11 | Bangumi.PLANNING -> "wish" 12 | else -> throw NotImplementedError("Unknown status: $status") 13 | } 14 | 15 | fun toTrackStatus(status: String) = 16 | when (status) { 17 | "do" -> Bangumi.READING 18 | "collect" -> Bangumi.COMPLETED 19 | "on_hold" -> Bangumi.ON_HOLD 20 | "dropped" -> Bangumi.DROPPED 21 | "wish" -> Bangumi.PLANNING 22 | else -> throw NotImplementedError("Unknown status: $status") 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Collection.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.bangumi 2 | 3 | data class Collection( 4 | val `private`: Int? = 0, 5 | val comment: String? = "", 6 | val ep_status: Int? = 0, 7 | val lasttouch: Int? = 0, 8 | val rating: Int? = 0, 9 | val status: Status? = Status(), 10 | val tag: List? = listOf(), 11 | val user: User? = User(), 12 | val vol_status: Int? = 0 13 | ) 14 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/OAuth.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.bangumi 2 | 3 | data class OAuth( 4 | val access_token: String, 5 | val token_type: String, 6 | val created_at: Long, 7 | val expires_in: Long, 8 | val refresh_token: String?, 9 | val user_id: Long? 10 | ) { 11 | // Access token refresh before expired 12 | fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600) 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Status.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.bangumi 2 | 3 | data class Status( 4 | val id: Int? = 0, 5 | val name: String? = "", 6 | val type: String? = "" 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/User.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.bangumi 2 | 3 | data class User( 4 | val avatar: Avatar? = Avatar(), 5 | val id: Int? = 0, 6 | val nickname: String? = "", 7 | val sign: String? = "", 8 | val url: String? = "", 9 | val usergroup: Int? = 0, 10 | val username: String? = "" 11 | ) 12 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/OAuth.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.kitsu 2 | 3 | data class OAuth( 4 | val access_token: String, 5 | val token_type: String, 6 | val created_at: Long, 7 | val expires_in: Long, 8 | val refresh_token: String? 9 | ) { 10 | fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600) 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/OAuth.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.track.shikimori 2 | 3 | data class OAuth( 4 | val access_token: String, 5 | val token_type: String, 6 | val created_at: Long, 7 | val expires_in: Long, 8 | val refresh_token: String? 9 | ) { 10 | // Access token lives 1 day 11 | fun isExpired() = (System.currentTimeMillis() / 1000) > (created_at + expires_in - 3600) 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/updater/Release.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.updater 2 | 3 | interface Release { 4 | val info: String 5 | 6 | /** 7 | * Get download link of latest release. 8 | * @return download link of latest release. 9 | */ 10 | val downloadLink: String 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateChecker.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.updater 2 | 3 | import eu.kanade.tachiyomi.BuildConfig 4 | import eu.kanade.tachiyomi.data.updater.devrepo.DevRepoUpdateChecker 5 | import eu.kanade.tachiyomi.data.updater.github.GithubUpdateChecker 6 | 7 | abstract class UpdateChecker { 8 | companion object { 9 | fun getUpdateChecker(): UpdateChecker { 10 | return if (BuildConfig.DEBUG) { 11 | DevRepoUpdateChecker() 12 | } else { 13 | GithubUpdateChecker() 14 | } 15 | } 16 | } 17 | 18 | /** 19 | * Returns observable containing release information 20 | */ 21 | abstract suspend fun checkForUpdate(): UpdateResult 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateResult.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.updater 2 | 3 | abstract class UpdateResult { 4 | open class NewUpdate(val release: T) : UpdateResult() 5 | 6 | open class NoNewUpdate : UpdateResult() 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoRelease.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.updater.devrepo 2 | 3 | import eu.kanade.tachiyomi.data.updater.Release 4 | 5 | class DevRepoRelease(override val info: String) : Release { 6 | override val downloadLink: String 7 | get() = LATEST_URL 8 | 9 | companion object { 10 | const val LATEST_URL = "https://tachiyomi.kanade.eu/latest" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoUpdateResult.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.updater.devrepo 2 | 3 | import eu.kanade.tachiyomi.data.updater.UpdateResult 4 | 5 | sealed class DevRepoUpdateResult : UpdateResult() { 6 | class NewUpdate(release: DevRepoRelease) : UpdateResult.NewUpdate(release) 7 | 8 | class NoNewUpdate : UpdateResult.NoNewUpdate() 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubUpdateChecker.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.updater.github 2 | 3 | import eu.kanade.tachiyomi.BuildConfig 4 | import eu.kanade.tachiyomi.data.updater.UpdateChecker 5 | import eu.kanade.tachiyomi.data.updater.UpdateResult 6 | 7 | class GithubUpdateChecker : UpdateChecker() { 8 | private val service: GithubService = GithubService.create() 9 | 10 | override suspend fun checkForUpdate(): UpdateResult { 11 | val release = service.getLatestVersion() 12 | 13 | val newVersion = release.version 14 | // Check if latest version is different from current version 15 | return if (newVersion != BuildConfig.VERSION_NAME) { 16 | GithubUpdateResult.NewUpdate(release) 17 | } else { 18 | GithubUpdateResult.NoNewUpdate() 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubUpdateResult.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.data.updater.github 2 | 3 | import eu.kanade.tachiyomi.data.updater.UpdateResult 4 | 5 | sealed class GithubUpdateResult : UpdateResult() { 6 | class NewUpdate(release: GithubRelease) : UpdateResult.NewUpdate(release) 7 | 8 | class NoNewUpdate : UpdateResult.NoNewUpdate() 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/extension/model/InstallStep.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.extension.model 2 | 3 | enum class InstallStep { 4 | Idle, 5 | Pending, 6 | Downloading, 7 | Installing, 8 | Installed, 9 | Error 10 | ; 11 | 12 | fun isCompleted(): Boolean { 13 | return this == Installed || this == Error || this == Idle 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/extension/model/LoadResult.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.extension.model 2 | 3 | sealed class LoadResult { 4 | class Success(val extension: Extension.Installed) : LoadResult() 5 | 6 | class Untrusted(val extension: Extension.Untrusted) : LoadResult() 7 | 8 | class Error(val message: String? = null) : LoadResult() { 9 | constructor(exception: Throwable) : this(exception.message) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/network/JavaScriptEngine.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.network 2 | 3 | import android.content.Context 4 | import app.cash.quickjs.QuickJs 5 | import eu.kanade.tachiyomi.util.system.withIOContext 6 | 7 | /** 8 | * Util for evaluating JavaScript in sources. 9 | */ 10 | class JavaScriptEngine(context: Context) { 11 | /** 12 | * Evaluate arbitrary JavaScript code and get the result as a primtive type 13 | * (e.g., String, Int). 14 | * 15 | * @since extensions-lib 1.4 16 | * @param script JavaScript to execute. 17 | * @return Result of JavaScript code as a primitive type. 18 | */ 19 | @Suppress("UNUSED", "UNCHECKED_CAST") 20 | suspend fun evaluate(script: String): T = 21 | withIOContext { 22 | QuickJs.create().use { 23 | it.evaluate(script) as T 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/network/ProgressListener.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.network 2 | 3 | interface ProgressListener { 4 | fun update( 5 | bytesRead: Long, 6 | contentLength: Long, 7 | done: Boolean 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/ConfigurableSource.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import android.content.SharedPreferences 6 | import androidx.preference.PreferenceScreen 7 | import uy.kohesive.injekt.Injekt 8 | import uy.kohesive.injekt.api.get 9 | 10 | interface ConfigurableSource : Source { 11 | fun setupPreferenceScreen(screen: PreferenceScreen) 12 | } 13 | 14 | fun ConfigurableSource.preferenceKey(): String = "source_$id" 15 | 16 | fun sourcePreferences(key: String): SharedPreferences = Injekt.get().getSharedPreferences(key, Context.MODE_PRIVATE) 17 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source 2 | 3 | /** 4 | * A factory for creating sources at runtime. 5 | */ 6 | interface SourceFactory { 7 | /** 8 | * Create a new copy of the sources 9 | * @return The created sources 10 | */ 11 | fun createSources(): List 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/UnmeteredSource.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source 2 | 3 | /** 4 | * A source that explicitly doesn't require traffic considerations. 5 | * 6 | * This typically applies for self-hosted sources. 7 | */ 8 | interface UnmeteredSource 9 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/model/FilterList.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source.model 2 | 3 | data class FilterList(val list: List>) : List> by list { 4 | constructor(vararg fs: Filter<*>) : this(if (fs.isNotEmpty()) fs.asList() else emptyList()) 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/model/MangasPage.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source.model 2 | 3 | data class MangasPage(val mangas: List, val hasNextPage: Boolean) 4 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/model/SChapterImpl.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source.model 2 | 3 | class SChapterImpl : SChapter { 4 | override lateinit var url: String 5 | 6 | override lateinit var name: String 7 | 8 | override var date_upload: Long = 0 9 | 10 | override var chapter_number: Float = -1f 11 | 12 | override var scanlator: String? = null 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaImpl.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source.model 2 | 3 | class SMangaImpl : SManga { 4 | override lateinit var url: String 5 | 6 | override var title: String = "" 7 | 8 | override var artist: String? = null 9 | 10 | override var author: String? = null 11 | 12 | override var description: String? = null 13 | 14 | override var genre: String? = null 15 | 16 | override var status: Int = 0 17 | 18 | override var thumbnail_url: String? = null 19 | 20 | override var update_strategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE 21 | 22 | override var initialized: Boolean = false 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/model/UpdateStrategy.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source.model 2 | 3 | /** 4 | * Define the update strategy for a single [SManga]. 5 | * The strategy used will only take effect on the library update. 6 | * 7 | * @since extensions-lib 1.4 8 | */ 9 | enum class UpdateStrategy { 10 | /** 11 | * Series marked as always update will be included in the library 12 | * update if they aren't excluded by additional restrictions. 13 | */ 14 | ALWAYS_UPDATE, 15 | 16 | /** 17 | * Series marked as only fetch once will be automatically skipped 18 | * during library updates. Useful for cases where the series is previously 19 | * known to be finished and have only a single chapter, for example. 20 | */ 21 | ONLY_FETCH_ONCE 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/source/online/AnimeSource.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.source.online 2 | 3 | /** 4 | * A source that will return anime instead of manga. 5 | * Chapters are episodes, pages are videos, page numbers are video quality 6 | * The rest works the same as a standard HttpSource 7 | */ 8 | interface AnimeSource 9 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/NoToolbarElevationController.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.base.controller 2 | 3 | interface NoToolbarElevationController 4 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RootController.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.base.controller 2 | 3 | interface RootController 4 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/SecondaryDrawerController.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.base.controller 2 | 3 | import android.view.ViewGroup 4 | 5 | interface SecondaryDrawerController { 6 | fun createSecondaryDrawer(drawer: androidx.drawerlayout.widget.DrawerLayout): ViewGroup? 7 | 8 | fun cleanupSecondaryDrawer(drawer: androidx.drawerlayout.widget.DrawerLayout) 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/TabbedController.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.base.controller 2 | 3 | import com.google.android.material.tabs.TabLayout 4 | 5 | interface TabbedController { 6 | fun configureTabs(tabs: TabLayout) {} 7 | 8 | fun cleanupTabs(tabs: TabLayout) {} 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/BaseFlexibleViewHolder.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.base.holder 2 | 3 | import android.view.View 4 | import eu.davidea.flexibleadapter.FlexibleAdapter 5 | import eu.davidea.viewholders.FlexibleViewHolder 6 | import kotlinx.android.extensions.LayoutContainer 7 | 8 | abstract class BaseFlexibleViewHolder( 9 | view: View, 10 | adapter: FlexibleAdapter<*>, 11 | stickyHeader: Boolean = false 12 | ) : FlexibleViewHolder(view, adapter, stickyHeader), LayoutContainer { 13 | override val containerView: View? 14 | get() = itemView 15 | } 16 | -------------------------------------------------------------------------------- /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 | import kotlinx.android.extensions.LayoutContainer 5 | 6 | abstract class BaseViewHolder(view: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(view), LayoutContainer { 7 | override val containerView: View? 8 | get() = itemView 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadAdapter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.download 2 | 3 | import android.view.MenuItem 4 | import eu.davidea.flexibleadapter.FlexibleAdapter 5 | 6 | /** 7 | * Adapter storing a list of downloads. 8 | * 9 | * @param context the context of the fragment containing this adapter. 10 | */ 11 | class DownloadAdapter(controller: DownloadController) : FlexibleAdapter( 12 | null, 13 | controller, 14 | true 15 | ) { 16 | /** 17 | * Listener called when an item of the list is released. 18 | */ 19 | val downloadItemListener: DownloadItemListener = controller 20 | 21 | interface DownloadItemListener { 22 | fun onItemReleased(position: Int) 23 | 24 | fun onMenuItemClick( 25 | position: Int, 26 | menuItem: MenuItem 27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionDetailsPrefsButtonAdapter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.extension 2 | 3 | import eu.davidea.flexibleadapter.FlexibleAdapter 4 | 5 | /** 6 | * Custom adapter for repos. 7 | * 8 | * @param controller The containing controller. 9 | */ 10 | class ExtensionDetailsPrefsButtonAdapter(controller: ExtensionDetailsController) : 11 | FlexibleAdapter(null, controller, true) 12 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/extension/ExtensionPreferencesPresenter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.extension 2 | 3 | import eu.kanade.tachiyomi.source.SourceManager 4 | import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter 5 | import uy.kohesive.injekt.Injekt 6 | import uy.kohesive.injekt.api.get 7 | 8 | class ExtensionPreferencesPresenter( 9 | val sourceId: Long 10 | ) : BasePresenter() { 11 | private val sourceManager: SourceManager = Injekt.get() 12 | 13 | val source = sourceManager.get(sourceId) 14 | } 15 | -------------------------------------------------------------------------------- /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/LibraryMangaEvent.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.library 2 | 3 | import eu.kanade.tachiyomi.data.database.models.Category 4 | 5 | class LibraryMangaEvent(val mangas: Map>) { 6 | fun getMangaForCategory(category: Category): List? { 7 | return mangas[category.id] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySelectionEvent.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.library 2 | 3 | import eu.kanade.tachiyomi.data.database.models.Manga 4 | 5 | sealed class LibrarySelectionEvent { 6 | class Selected(val manga: Manga) : LibrarySelectionEvent() 7 | 8 | class Unselected(val manga: Manga) : LibrarySelectionEvent() 9 | 10 | class Cleared : LibrarySelectionEvent() 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySort.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.library 2 | 3 | object LibrarySort { 4 | const val ALPHA = 0 5 | const val LAST_READ = 1 6 | const val LAST_CHECKED = 2 7 | const val UNREAD = 3 8 | const val TOTAL = 4 9 | const val SOURCE = 5 10 | const val DRAG_AND_DROP = 6 11 | const val LATEST_CHAPTER = 7 12 | const val DATE_ADDED = 8 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/main/DeepLinkActivity.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.main 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import android.os.Bundle 6 | 7 | class DeepLinkActivity : Activity() { 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | 11 | intent.apply { 12 | flags = flags or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK 13 | setClass(applicationContext, MainActivity::class.java) 14 | } 15 | startActivity(intent) 16 | finish() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /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/MangaAdapter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.migration 2 | 3 | import eu.davidea.flexibleadapter.FlexibleAdapter 4 | import eu.davidea.flexibleadapter.items.IFlexible 5 | 6 | class MangaAdapter(controller: MigrationController) : 7 | FlexibleAdapter>(null, controller) { 8 | private var items: List>? = null 9 | 10 | override fun updateDataSet(items: MutableList>?) { 11 | if (this.items !== items) { 12 | this.items = items 13 | super.updateDataSet(items) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/migration/ViewState.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.migration 2 | 3 | import eu.kanade.tachiyomi.source.Source 4 | 5 | data class ViewState( 6 | val selectedSource: Source? = null, 7 | val mangaForSource: List = emptyList(), 8 | val sourcesWithManga: List = emptyList(), 9 | val isReplacingManga: Boolean = false 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/ReaderPage.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.reader.model 2 | 3 | import android.graphics.drawable.Drawable 4 | import eu.kanade.tachiyomi.source.model.Page 5 | import java.io.InputStream 6 | 7 | class ReaderPage( 8 | index: Int, 9 | url: String = "", 10 | imageUrl: String? = null, 11 | // SY --> 12 | var bg: Drawable? = null, 13 | var bgType: Int? = null, 14 | // SY <-- 15 | var stream: (() -> InputStream)? = null 16 | ) : Page(index, url, imageUrl, null) { 17 | lateinit var chapter: ReaderChapter 18 | } 19 | -------------------------------------------------------------------------------- /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 | fun ref() { 9 | currChapter.ref() 10 | prevChapter?.ref() 11 | nextChapter?.ref() 12 | } 13 | 14 | fun unref() { 15 | currChapter.unref() 16 | prevChapter?.unref() 17 | nextChapter?.unref() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonSubsamplingImageView.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.reader.viewer.webtoon 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.MotionEvent 6 | import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView 7 | 8 | /** 9 | * Implementation of subsampling scale image view that ignores all touch events, because the 10 | * webtoon viewer handles all the gestures. 11 | */ 12 | class WebtoonSubsamplingImageView 13 | @JvmOverloads 14 | constructor( 15 | context: Context, 16 | attrs: AttributeSet? = null 17 | ) : SubsamplingScaleImageView(context, attrs) { 18 | override fun onTouchEvent(event: MotionEvent): Boolean { 19 | return false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesAdapter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.recent.updates 2 | 3 | import eu.davidea.flexibleadapter.FlexibleAdapter 4 | import eu.davidea.flexibleadapter.items.IFlexible 5 | 6 | class UpdatesAdapter(val controller: UpdatesController) : 7 | FlexibleAdapter>(null, controller, true) { 8 | val coverClickListener: OnCoverClickListener = controller 9 | 10 | init { 11 | setDisplayHeadersAtStartUp(true) 12 | setStickyHeaders(true) 13 | } 14 | 15 | interface OnCoverClickListener { 16 | fun onCoverClick(position: Int) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsNhController.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.setting 2 | 3 | import androidx.preference.PreferenceScreen 4 | import eu.kanade.tachiyomi.data.preference.PreferenceKeys 5 | import eu.kanade.tachiyomi.util.preference.defaultValue 6 | import eu.kanade.tachiyomi.util.preference.switchPreference 7 | 8 | /** 9 | * nhentai Settings fragment 10 | */ 11 | 12 | class SettingsNhController : SettingsController() { 13 | override fun setupPreferenceScreen(screen: PreferenceScreen) = 14 | with(screen) { 15 | title = "nhentai" 16 | 17 | switchPreference { 18 | title = "Use high-quality thumbnails" 19 | summary = "May slow down search results" 20 | key = PreferenceKeys.eh_nh_useHighQualityThumbs 21 | defaultValue = false 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/source/LangHolder.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.source 2 | 3 | import android.view.View 4 | import eu.davidea.flexibleadapter.FlexibleAdapter 5 | import eu.kanade.tachiyomi.databinding.SourceMainControllerCardBinding 6 | import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder 7 | import eu.kanade.tachiyomi.util.system.LocaleHelper 8 | 9 | class LangHolder(view: View, adapter: FlexibleAdapter<*>) : 10 | BaseFlexibleViewHolder(view, adapter) { 11 | private val binding = SourceMainControllerCardBinding.bind(view) 12 | 13 | fun bind(item: LangItem) { 14 | binding.title.text = LocaleHelper.getSourceDisplayName(item.code, itemView.context) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /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/ui/source/latest/LatestUpdatesPager.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.source.latest 2 | 3 | import eu.kanade.tachiyomi.source.CatalogueSource 4 | import eu.kanade.tachiyomi.ui.source.browse.Pager 5 | import eu.kanade.tachiyomi.util.lang.awaitSingle 6 | 7 | /** 8 | * LatestUpdatesPager inherited from the general Pager. 9 | */ 10 | class LatestUpdatesPager(val source: CatalogueSource) : Pager() { 11 | override suspend fun requestNextPage() { 12 | val mangasPage = source.fetchLatestUpdates(currentPage).awaitSingle() 13 | onPageReceived(mangasPage) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/ui/source/latest/LatestUpdatesPresenter.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.ui.source.latest 2 | 3 | import eu.kanade.tachiyomi.source.model.FilterList 4 | import eu.kanade.tachiyomi.ui.source.browse.BrowseSourcePresenter 5 | import eu.kanade.tachiyomi.ui.source.browse.Pager 6 | import exh.isEhBasedSource 7 | 8 | /** 9 | * Presenter of [LatestUpdatesController]. Inherit BrowseCataloguePresenter. 10 | */ 11 | class LatestUpdatesPresenter(sourceId: Long) : BrowseSourcePresenter(sourceId) { 12 | override fun createPager( 13 | query: String, 14 | filters: FilterList 15 | ): Pager { 16 | return if (source.isEhBasedSource()) { 17 | ExhLatestUpdatesPager(source) 18 | } else { 19 | LatestUpdatesPager(source) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /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/lang/CoroutinesExtensions.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.util.lang 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlinx.coroutines.CoroutineStart 5 | import kotlinx.coroutines.Dispatchers 6 | import kotlinx.coroutines.ExperimentalCoroutinesApi 7 | import kotlinx.coroutines.GlobalScope 8 | import kotlinx.coroutines.Job 9 | import kotlinx.coroutines.launch 10 | 11 | fun launchUI(block: suspend CoroutineScope.() -> Unit): Job = GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT, block) 12 | 13 | fun launchIO(block: suspend CoroutineScope.() -> Unit): Job = GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT, block) 14 | 15 | @OptIn(ExperimentalCoroutinesApi::class) 16 | fun launchNow(block: suspend CoroutineScope.() -> Unit): Job = GlobalScope.launch(Dispatchers.Main, CoroutineStart.UNDISPATCHED, block) 17 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/util/lang/RxExtensions.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.util.lang 2 | 3 | import rx.Observable 4 | import rx.Subscription 5 | import rx.subscriptions.CompositeSubscription 6 | 7 | fun Subscription?.isNullOrUnsubscribed() = this == null || isUnsubscribed 8 | 9 | operator fun CompositeSubscription.plusAssign(subscription: Subscription) = add(subscription) 10 | 11 | fun Observable.combineLatest( 12 | o2: Observable, 13 | combineFn: (T, U) -> R 14 | ): Observable { 15 | return Observable.combineLatest(this, o2, combineFn) 16 | } 17 | 18 | fun Subscription.addTo(subscriptions: CompositeSubscription) { 19 | subscriptions.add(this) 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.util.view 2 | 3 | import android.widget.ImageView 4 | import androidx.annotation.DrawableRes 5 | import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat 6 | 7 | /** 8 | * Set a vector on a [ImageView]. 9 | * 10 | * @param drawable id of drawable resource 11 | */ 12 | fun ImageView.setVectorCompat( 13 | @DrawableRes drawable: Int, 14 | tint: Int? = null 15 | ) { 16 | val vector = VectorDrawableCompat.create(resources, drawable, context.theme) 17 | if (tint != null) { 18 | vector?.mutate() 19 | vector?.setTint(tint) 20 | } 21 | setImageDrawable(vector) 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/util/view/ViewGroupExtensions.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.util.view 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.annotation.LayoutRes 7 | 8 | /** 9 | * Extension method to inflate a view directly from its parent. 10 | * @param layout the layout to inflate. 11 | * @param attachToRoot whether to attach the view to the root or not. Defaults to false. 12 | */ 13 | fun ViewGroup.inflate( 14 | @LayoutRes layout: Int, 15 | attachToRoot: Boolean = false 16 | ): View { 17 | return LayoutInflater.from(context).inflate(layout, this, attachToRoot) 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/widget/IgnoreFirstSpinnerListener.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.widget 2 | 3 | import android.view.View 4 | import android.widget.AdapterView 5 | import android.widget.AdapterView.OnItemSelectedListener 6 | 7 | class IgnoreFirstSpinnerListener(private val block: (Int) -> Unit) : OnItemSelectedListener { 8 | private var firstEvent = true 9 | 10 | override fun onItemSelected( 11 | parent: AdapterView<*>?, 12 | view: View?, 13 | position: Int, 14 | id: Long 15 | ) { 16 | if (!firstEvent) { 17 | block(position) 18 | } else { 19 | firstEvent = false 20 | } 21 | } 22 | 23 | override fun onNothingSelected(parent: AdapterView<*>?) { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/widget/MinMaxNumberPicker.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.widget 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.widget.NumberPicker 6 | import eu.kanade.tachiyomi.R 7 | 8 | class MinMaxNumberPicker 9 | @JvmOverloads 10 | constructor(context: Context, attrs: AttributeSet? = null) : 11 | NumberPicker(context, attrs) { 12 | init { 13 | if (attrs != null) { 14 | val ta = context.obtainStyledAttributes(attrs, R.styleable.MinMaxNumberPicker, 0, 0) 15 | try { 16 | minValue = ta.getInt(R.styleable.MinMaxNumberPicker_min, 0) 17 | maxValue = ta.getInt(R.styleable.MinMaxNumberPicker_max, 0) 18 | } finally { 19 | ta.recycle() 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/widget/SimpleAnimationListener.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.widget 2 | 3 | import android.view.animation.Animation 4 | 5 | open class SimpleAnimationListener : Animation.AnimationListener { 6 | override fun onAnimationRepeat(animation: Animation) {} 7 | 8 | override fun onAnimationEnd(animation: Animation) {} 9 | 10 | override fun onAnimationStart(animation: Animation) {} 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/eu/kanade/tachiyomi/widget/SimpleSeekBarListener.kt: -------------------------------------------------------------------------------- 1 | package eu.kanade.tachiyomi.widget 2 | 3 | import android.widget.SeekBar 4 | 5 | open class SimpleSeekBarListener : SeekBar.OnSeekBarChangeListener { 6 | override fun onProgressChanged( 7 | seekBar: SeekBar, 8 | value: Int, 9 | fromUser: Boolean 10 | ) { 11 | } 12 | 13 | override fun onStartTrackingTouch(seekBar: SeekBar) { 14 | } 15 | 16 | override fun onStopTrackingTouch(seekBar: SeekBar) { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/exh/StringBuilderExtensions.kt: -------------------------------------------------------------------------------- 1 | package exh 2 | 3 | operator fun StringBuilder.plusAssign(other: String) { 4 | append(other) 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/exh/debug/StatisticsInfoClass.kt: -------------------------------------------------------------------------------- 1 | package exh.debug 2 | 3 | data class StatisticsInfoClass( 4 | var mangaCount: Int = 0, 5 | var completedMangaCount: Int = 0, 6 | var startedMangaCount: Int = 0, 7 | var localMangaCount: Int = 0, 8 | var totalChapterCount: Int = 0, 9 | var readChapterCount: Int = 0, 10 | var downloadedChapterCount: Int = 0, 11 | var trackedMangaCount: Int = 0, 12 | var meanMangaScore: Double = Double.NaN 13 | ) 14 | -------------------------------------------------------------------------------- /app/src/main/java/exh/eh/EHentaiUpdaterStats.kt: -------------------------------------------------------------------------------- 1 | package exh.eh 2 | 3 | data class EHentaiUpdaterStats( 4 | val startTime: Long, 5 | val possibleUpdates: Int, 6 | val updateCount: Int 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/exh/eh/GalleryNotUpdatedException.kt: -------------------------------------------------------------------------------- 1 | package exh.eh 2 | 3 | class GalleryNotUpdatedException(val network: Boolean, cause: Throwable) : RuntimeException(cause) 4 | -------------------------------------------------------------------------------- /app/src/main/java/exh/favorites/FavoriteEntry.kt: -------------------------------------------------------------------------------- 1 | package exh.favorites 2 | 3 | import exh.metadata.metadata.EHentaiSearchMetadata 4 | import io.realm.RealmObject 5 | import io.realm.annotations.Index 6 | import io.realm.annotations.PrimaryKey 7 | import io.realm.annotations.RealmClass 8 | import java.util.UUID 9 | 10 | @RealmClass 11 | open class FavoriteEntry : RealmObject() { 12 | @PrimaryKey var id: String = UUID.randomUUID().toString() 13 | 14 | var title: String? = null 15 | 16 | @Index lateinit var gid: String 17 | 18 | @Index lateinit var token: String 19 | 20 | @Index var category: Int = -1 21 | 22 | fun getUrl() = EHentaiSearchMetadata.idAndTokenToUrl(gid, token) 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/exh/metadata/metadata/base/RaisedTag.kt: -------------------------------------------------------------------------------- 1 | package exh.metadata.metadata.base 2 | import kotlinx.serialization.Serializable 3 | 4 | @Serializable 5 | data class RaisedTag( 6 | val namespace: String?, 7 | val name: String, 8 | val type: Int 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/exh/metadata/metadata/base/RaisedTitle.kt: -------------------------------------------------------------------------------- 1 | package exh.metadata.metadata.base 2 | import kotlinx.serialization.Serializable 3 | 4 | @Serializable 5 | data class RaisedTitle( 6 | val title: String, 7 | val type: Int = 0 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/exh/metadata/sql/models/SearchMetadata.kt: -------------------------------------------------------------------------------- 1 | package exh.metadata.sql.models 2 | import kotlinx.serialization.Contextual 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | data class SearchMetadata( 7 | // Manga ID this gallery is linked to 8 | val mangaId: Long, 9 | // Gallery uploader 10 | val uploader: String?, 11 | // Extra data attached to this metadata, in JSON format 12 | val extra: String, 13 | // Indexed extra data attached to this metadata 14 | val indexedExtra: String?, 15 | // The version of this metadata's extra. Used to track changes to the 'extra' field's schema 16 | val extraVersion: Int 17 | ) { 18 | // Transient information attached to this piece of metadata, useful for caching 19 | var transientCache: Map? = null 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/exh/metadata/sql/models/SearchTag.kt: -------------------------------------------------------------------------------- 1 | package exh.metadata.sql.models 2 | import kotlinx.serialization.Serializable 3 | 4 | @Serializable 5 | data class SearchTag( 6 | // Tag identifier, unique 7 | val id: Long?, 8 | // Metadata this tag is attached to 9 | val mangaId: Long, 10 | // Tag namespace 11 | val namespace: String?, 12 | // Tag name 13 | val name: String, 14 | // Tag type 15 | val type: Int 16 | ) 17 | -------------------------------------------------------------------------------- /app/src/main/java/exh/metadata/sql/models/SearchTitle.kt: -------------------------------------------------------------------------------- 1 | package exh.metadata.sql.models 2 | import kotlinx.serialization.Serializable 3 | 4 | @Serializable 5 | data class SearchTitle( 6 | // Title identifier, unique 7 | val id: Long?, 8 | // Metadata this title is attached to 9 | val mangaId: Long, 10 | // Title 11 | val title: String, 12 | // Title type, useful for distinguishing between main/alt titles 13 | val type: Int 14 | ) 15 | -------------------------------------------------------------------------------- /app/src/main/java/exh/savedsearches/EXHSavedSearch.kt: -------------------------------------------------------------------------------- 1 | package exh.savedsearches 2 | 3 | import eu.kanade.tachiyomi.source.model.FilterList 4 | 5 | data class EXHSavedSearch( 6 | val name: String, 7 | val query: String, 8 | val filterList: FilterList 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/exh/savedsearches/JsonSavedSearch.kt: -------------------------------------------------------------------------------- 1 | package exh.savedsearches 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.json.JsonArray 5 | import kotlinx.serialization.json.JsonObject 6 | import kotlinx.serialization.json.jsonArray 7 | import kotlinx.serialization.json.jsonPrimitive 8 | 9 | @Serializable 10 | data class JsonSavedSearch( 11 | val name: String, 12 | val query: String, 13 | val filters: JsonArray 14 | ) { 15 | companion object { 16 | fun fromJsonObject(json: JsonObject): JsonSavedSearch { 17 | return JsonSavedSearch( 18 | json["name"]!!.jsonPrimitive.content, 19 | json["query"]!!.jsonPrimitive.content, 20 | json["filters"]!!.jsonArray 21 | ) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/exh/search/MultiWildcard.kt: -------------------------------------------------------------------------------- 1 | package exh.search 2 | 3 | class MultiWildcard(rawText: String) : TextComponent(rawText) 4 | -------------------------------------------------------------------------------- /app/src/main/java/exh/search/Namespace.kt: -------------------------------------------------------------------------------- 1 | package exh.search 2 | 3 | class Namespace( 4 | var namespace: String, 5 | var tag: Text? = null 6 | ) : QueryComponent() 7 | -------------------------------------------------------------------------------- /app/src/main/java/exh/search/QueryComponent.kt: -------------------------------------------------------------------------------- 1 | package exh.search 2 | 3 | open class QueryComponent { 4 | var excluded = false 5 | var exact = false 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/exh/search/SingleWildcard.kt: -------------------------------------------------------------------------------- 1 | package exh.search 2 | 3 | class SingleWildcard(rawText: String) : TextComponent(rawText) 4 | -------------------------------------------------------------------------------- /app/src/main/java/exh/search/StringTextComponent.kt: -------------------------------------------------------------------------------- 1 | package exh.search 2 | 3 | class StringTextComponent(val value: String) : TextComponent(value) 4 | -------------------------------------------------------------------------------- /app/src/main/java/exh/search/TextComponent.kt: -------------------------------------------------------------------------------- 1 | package exh.search 2 | 3 | open class TextComponent(val rawText: String) 4 | -------------------------------------------------------------------------------- /app/src/main/java/exh/uconfig/EHHathPerksResponse.kt: -------------------------------------------------------------------------------- 1 | package exh.uconfig 2 | 3 | class EHHathPerksResponse { 4 | var moreThumbs = false 5 | var thumbsUp = false 6 | var allThumbs = false 7 | 8 | var pagingEnlargementI = false 9 | var pagingEnlargementII = false 10 | var pagingEnlargementIII = false 11 | 12 | override fun toString() = 13 | "EHHathPerksResponse(moreThumbs=$moreThumbs, thumbsUp=$thumbsUp, allThumbs=$allThumbs, pagingEnlargementI=$pagingEnlargementI, pagingEnlargementII=$pagingEnlargementII, pagingEnlargementIII=$pagingEnlargementIII)" 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/exh/ui/captcha/BasicWebViewClient.kt: -------------------------------------------------------------------------------- 1 | package exh.ui.captcha 2 | 3 | import android.webkit.WebView 4 | import android.webkit.WebViewClient 5 | 6 | open class BasicWebViewClient( 7 | protected val activity: BrowserActionActivity, 8 | protected val verifyComplete: (String) -> Boolean, 9 | private val injectScript: String? 10 | ) : WebViewClient() { 11 | override fun onPageFinished( 12 | view: WebView, 13 | url: String 14 | ) { 15 | super.onPageFinished(view, url) 16 | 17 | if (verifyComplete(url)) { 18 | activity.finish() 19 | } else { 20 | if (injectScript != null) { 21 | view.evaluateJavascript("(function() {$injectScript})();", null) 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/exh/ui/captcha/WebViewUtil.kt: -------------------------------------------------------------------------------- 1 | package exh.ui.captcha 2 | 3 | import android.webkit.WebResourceRequest 4 | import okhttp3.Request 5 | 6 | fun WebResourceRequest.toOkHttpRequest(): Request { 7 | val request = 8 | Request.Builder() 9 | .url(url.toString()) 10 | .method(method, null) 11 | 12 | requestHeaders.entries.forEach { (t, u) -> 13 | request.addHeader(t, u) 14 | } 15 | 16 | return request.build() 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/exh/ui/lock/LockPresenter.kt: -------------------------------------------------------------------------------- 1 | package exh.ui.lock 2 | 3 | import android.os.Build 4 | import com.github.ajalt.reprint.core.Reprint 5 | import eu.kanade.tachiyomi.data.preference.PreferencesHelper 6 | import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter 7 | import uy.kohesive.injekt.injectLazy 8 | 9 | class LockPresenter : BasePresenter() { 10 | val prefs: PreferencesHelper by injectLazy() 11 | 12 | val useFingerprint 13 | get() = 14 | Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 15 | Reprint.isHardwarePresent() && 16 | Reprint.hasFingerprintRegistered() && 17 | prefs.eh_lockUseFingerprint().get() 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/exh/ui/login/LoginPresenter.kt: -------------------------------------------------------------------------------- 1 | package exh.ui.login 2 | 3 | import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter 4 | 5 | class LoginPresenter : BasePresenter() 6 | -------------------------------------------------------------------------------- /app/src/main/java/exh/util/CachedField.kt: -------------------------------------------------------------------------------- 1 | package exh.util 2 | 3 | import kotlinx.coroutines.sync.Mutex 4 | import kotlinx.coroutines.sync.withLock 5 | 6 | class CachedField(private val expiresAfterMs: Long) { 7 | @Volatile 8 | private var initTime: Long = -1 9 | 10 | @Volatile 11 | private var content: T? = null 12 | 13 | private val mutex = Mutex() 14 | 15 | suspend fun obtain(producer: suspend () -> T): T { 16 | return mutex.withLock { 17 | if (initTime < 0 || System.currentTimeMillis() - initTime > expiresAfterMs) { 18 | content = producer() 19 | } 20 | 21 | content!! 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/exh/util/CoroutineUtil.kt: -------------------------------------------------------------------------------- 1 | package exh.util 2 | 3 | import kotlinx.coroutines.FlowPreview 4 | import kotlinx.coroutines.ensureActive 5 | import kotlinx.coroutines.flow.Flow 6 | import kotlinx.coroutines.flow.onEach 7 | import kotlin.coroutines.coroutineContext 8 | 9 | @FlowPreview 10 | fun Flow.cancellable() = 11 | onEach { 12 | coroutineContext.ensureActive() 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/exh/util/ExceptionUtil.kt: -------------------------------------------------------------------------------- 1 | package exh.util 2 | 3 | inline fun ignore(expr: () -> T): T? { 4 | return try { 5 | expr() 6 | } catch (t: Throwable) { 7 | null 8 | } 9 | } 10 | 11 | fun T.withRootCause(cause: Throwable): T { 12 | val curCause = this.cause 13 | 14 | if (curCause == null) { 15 | this.initCause(cause) 16 | } else { 17 | curCause.withRootCause(cause) 18 | } 19 | 20 | return this 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/exh/util/StringUtil.kt: -------------------------------------------------------------------------------- 1 | package exh.util 2 | 3 | fun List.trimAll() = map { it.trim() } 4 | 5 | fun List.dropBlank() = filter { it.isNotBlank() } 6 | 7 | fun List.dropEmpty() = filter { it.isNotEmpty() } 8 | -------------------------------------------------------------------------------- /app/src/main/java/exh/util/UriFilter.kt: -------------------------------------------------------------------------------- 1 | package exh.util 2 | 3 | import android.net.Uri 4 | 5 | /** 6 | * Uri filter 7 | */ 8 | interface UriFilter { 9 | fun addToUri(builder: Uri.Builder) 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/exh/util/UriGroup.kt: -------------------------------------------------------------------------------- 1 | package exh.util 2 | 3 | import android.net.Uri 4 | import eu.kanade.tachiyomi.source.model.Filter 5 | 6 | /** 7 | * UriGroup 8 | */ 9 | open class UriGroup(name: String, state: List) : Filter.Group(name, state), UriFilter { 10 | override fun addToUri(builder: Uri.Builder) { 11 | state.forEach { 12 | if (it is UriFilter) it.addToUri(builder) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/exh/util/ViewUtil.kt: -------------------------------------------------------------------------------- 1 | package exh.util 2 | 3 | import android.content.Context 4 | 5 | fun dpToPx( 6 | context: Context, 7 | dp: Int 8 | ): Int { 9 | val scale = context.resources.displayMetrics.density 10 | return (dp * scale + 0.5f).toInt() 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/enter_from_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/enter_from_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/exit_to_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/exit_to_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in_long.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/color/text_input_stroke.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_copy.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_done.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_done_all.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-hdpi/ic_copy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-hdpi/ic_done.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_done_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-hdpi/ic_done_all.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_extension_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-hdpi/ic_extension_update.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/tachiyomi_circle.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-hdpi/tachiyomi_circle.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-mdpi/ic_copy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-mdpi/ic_done.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_done_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-mdpi/ic_done_all.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_extension_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-mdpi/ic_extension_update.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/tachiyomi_circle.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-mdpi/tachiyomi_circle.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/filter_mock.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-nodpi/filter_mock.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_tracker_anilist.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-nodpi/ic_tracker_anilist.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_tracker_bangumi.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-nodpi/ic_tracker_bangumi.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_tracker_kitsu.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-nodpi/ic_tracker_kitsu.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_tracker_mal.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-nodpi/ic_tracker_mal.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_tracker_shikimori.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-nodpi/ic_tracker_shikimori.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/lock_dot_empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xhdpi/ic_copy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xhdpi/ic_done.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_done_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xhdpi/ic_done_all.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_extension_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xhdpi/ic_extension_update.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/tachiyomi_circle.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xhdpi/tachiyomi_circle.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xxhdpi/ic_copy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xxhdpi/ic_done.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_done_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xxhdpi/ic_done_all.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_extension_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xxhdpi/ic_extension_update.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/tachiyomi_circle.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xxhdpi/tachiyomi_circle.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_extension_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xxxhdpi/ic_extension_update.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/tachiyomi_circle.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable-xxxhdpi/tachiyomi_circle.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_swap_calls_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog_rounded_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_ic_arrow_drop_down_white_100dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_ic_check_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_ic_clear_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_ic_find_replace_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_migration_backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable/eh_migration_backup.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_migration_backup_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable/eh_migration_backup_button.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_migration_hamburgers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable/eh_migration_hamburgers.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/eh_migration_share_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable/eh_migration_share_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/empty_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/empty_drawable_32dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fumo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/drawable/fumo.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/gradient_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_to_library_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_down_white_32dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_forward_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_up_white_32dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_backup_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_book_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bookmark_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bookmark_border_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_brightness_4_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_brightness_5_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_broken_image_grey_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check_box_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check_box_outline_blank_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check_box_x_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chevron_left_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chevron_left_double_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chevron_right_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chevron_right_double_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chevron_right_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chrome_reader_mode_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clear_grey.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cloud_download_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cloud_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cloud_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_code_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_collections_bookmark_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_collections_bookmark_state.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_copy_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_desktop_windows_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_all_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_green_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_outline_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_prev_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_done_white_18dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_drag_pill_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_edit_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_error_grey.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_more_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_explore_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_explore_outline_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_explore_state.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_extension_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_file_download_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_filter_list_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_flip_to_back_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_folder_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_get_app_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_help_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_help_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_history_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_in_library_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_arrow_down_black_32dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_arrow_down_white_32dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_arrow_right_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_arrow_up_black_32dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_arrow_up_white_32dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_label_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_migrate_direction.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_horiz_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_vert_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_vert_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_new_releases_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_new_releases_outline_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_new_releases_state.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pause_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_photo_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pin_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_play_arrow_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_playlist_add_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_public_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_query_stats_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_reorder_grey_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_save_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_security_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_select_all_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_select_none_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_share_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_skip_next_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_skip_previous_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sort_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_start_reading_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sync_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_system_update_alt_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tune_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_update_black_128dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_update_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_view_module_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_warning_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_watch_later_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/library_item_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/line_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_item_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/lock_dot_empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/lock_dot_filled.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_textview_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_rectangle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sc_book_48dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sc_explore_48dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/snackbar_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/text_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/font/ptsans_narrow_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/az4521/TachiyomiAZ/85b7d54325f6f9a1c1f71a430eb493793630c180/app/src/main/res/font/ptsans_narrow_bold.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/common_spinner_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/download_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/extension_detail_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/extension_preferences_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/global_search_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/library_category.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/library_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/library_grid_recycler.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/library_list_recycler.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/manga_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/manga_info_web_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/migration_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/migration_list_controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/navigation_view_help_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 |