Refactor navigation
parent
a5199e2f06
commit
f675c606a2
@ -0,0 +1,602 @@
|
||||
package org.koitharu.kotatsu.core.nav
|
||||
|
||||
import android.accounts.Account
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import androidx.annotation.CheckResult
|
||||
import androidx.core.net.toUri
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.findFragment
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.alternatives.ui.AlternativesActivity
|
||||
import org.koitharu.kotatsu.bookmarks.ui.AllBookmarksActivity
|
||||
import org.koitharu.kotatsu.browser.BrowserActivity
|
||||
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity
|
||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.MangaSourceInfo
|
||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaListFilter
|
||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaPage
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.parser.external.ExternalMangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
import org.koitharu.kotatsu.core.ui.dialog.ErrorDetailsDialog
|
||||
import org.koitharu.kotatsu.core.util.ext.findActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.mapToArray
|
||||
import org.koitharu.kotatsu.core.util.ext.toUriOrNull
|
||||
import org.koitharu.kotatsu.core.util.ext.withArgs
|
||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesSheet
|
||||
import org.koitharu.kotatsu.details.ui.related.RelatedMangaActivity
|
||||
import org.koitharu.kotatsu.details.ui.scrobbling.ScrobblingInfoSheet
|
||||
import org.koitharu.kotatsu.download.ui.dialog.DownloadDialogFragment
|
||||
import org.koitharu.kotatsu.download.ui.list.DownloadsActivity
|
||||
import org.koitharu.kotatsu.favourites.ui.FavouritesActivity
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavoriteDialog
|
||||
import org.koitharu.kotatsu.filter.ui.FilterCoordinator
|
||||
import org.koitharu.kotatsu.filter.ui.sheet.FilterSheetFragment
|
||||
import org.koitharu.kotatsu.filter.ui.tags.TagsCatalogSheet
|
||||
import org.koitharu.kotatsu.history.ui.HistoryActivity
|
||||
import org.koitharu.kotatsu.image.ui.ImageActivity
|
||||
import org.koitharu.kotatsu.list.ui.config.ListConfigBottomSheet
|
||||
import org.koitharu.kotatsu.list.ui.config.ListConfigSection
|
||||
import org.koitharu.kotatsu.local.ui.ImportDialogFragment
|
||||
import org.koitharu.kotatsu.local.ui.info.LocalInfoDialog
|
||||
import org.koitharu.kotatsu.main.ui.welcome.WelcomeSheet
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaListFilter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.util.isNullOrEmpty
|
||||
import org.koitharu.kotatsu.reader.ui.colorfilter.ColorFilterConfigActivity
|
||||
import org.koitharu.kotatsu.reader.ui.config.ReaderConfigSheet
|
||||
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService
|
||||
import org.koitharu.kotatsu.scrobbling.common.ui.config.ScrobblerConfigActivity
|
||||
import org.koitharu.kotatsu.scrobbling.common.ui.selector.ScrobblingSelectorSheet
|
||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||
import org.koitharu.kotatsu.search.ui.multi.SearchActivity
|
||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||
import org.koitharu.kotatsu.settings.about.AppUpdateActivity
|
||||
import org.koitharu.kotatsu.settings.backup.BackupDialogFragment
|
||||
import org.koitharu.kotatsu.settings.backup.RestoreDialogFragment
|
||||
import org.koitharu.kotatsu.settings.reader.ReaderTapGridConfigActivity
|
||||
import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity
|
||||
import org.koitharu.kotatsu.settings.sources.catalog.SourcesCatalogActivity
|
||||
import org.koitharu.kotatsu.settings.storage.MangaDirectorySelectDialog
|
||||
import org.koitharu.kotatsu.settings.storage.directories.MangaDirectoriesActivity
|
||||
import org.koitharu.kotatsu.settings.tracker.categories.TrackerCategoriesConfigSheet
|
||||
import org.koitharu.kotatsu.stats.ui.StatsActivity
|
||||
import org.koitharu.kotatsu.stats.ui.sheet.MangaStatsSheet
|
||||
import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity
|
||||
import org.koitharu.kotatsu.tracker.ui.updates.UpdatesActivity
|
||||
|
||||
class AppRouter private constructor(
|
||||
private val activity: FragmentActivity?,
|
||||
private val fragment: Fragment?,
|
||||
) {
|
||||
|
||||
constructor(activity: FragmentActivity) : this(activity, null)
|
||||
|
||||
constructor(fragment: Fragment) : this(null, fragment)
|
||||
|
||||
/** Activities **/
|
||||
|
||||
fun openList(source: MangaSource, filter: MangaListFilter?) {
|
||||
startActivity(listIntent(contextOrNull() ?: return, source, filter))
|
||||
}
|
||||
|
||||
fun openList(tag: MangaTag) = openList(tag.source, MangaListFilter(tags = setOf(tag)))
|
||||
|
||||
fun openSearch(query: String) {
|
||||
startActivity(
|
||||
Intent(contextOrNull() ?: return, SearchActivity::class.java)
|
||||
.putExtra(KEY_QUERY, query),
|
||||
)
|
||||
}
|
||||
|
||||
fun openSearch(source: MangaSource, query: String) = openList(source, MangaListFilter(query = query))
|
||||
|
||||
fun openDetails(manga: Manga) {
|
||||
startActivity(detailsIntent(contextOrNull() ?: return, manga))
|
||||
}
|
||||
|
||||
fun openDetails(mangaId: Long) {
|
||||
startActivity(detailsIntent(contextOrNull() ?: return, mangaId))
|
||||
}
|
||||
|
||||
fun openReader(manga: Manga, anchor: View? = null) {
|
||||
openReader(
|
||||
ReaderIntent.Builder(contextOrNull() ?: return)
|
||||
.manga(manga)
|
||||
.build(),
|
||||
anchor,
|
||||
)
|
||||
}
|
||||
|
||||
fun openReader(intent: ReaderIntent, anchor: View? = null) {
|
||||
startActivity(intent.intent, anchor?.let { view -> scaleUpActivityOptionsOf(view) })
|
||||
}
|
||||
|
||||
fun openAlternatives(manga: Manga) {
|
||||
startActivity(
|
||||
Intent(contextOrNull() ?: return, AlternativesActivity::class.java)
|
||||
.putExtra(KEY_MANGA, ParcelableManga(manga)),
|
||||
)
|
||||
}
|
||||
|
||||
fun openRelated(manga: Manga) {
|
||||
startActivity(
|
||||
Intent(contextOrNull(), RelatedMangaActivity::class.java)
|
||||
.putExtra(KEY_MANGA, ParcelableManga(manga)),
|
||||
)
|
||||
}
|
||||
|
||||
fun openImage(url: String, source: MangaSource?, anchor: View? = null) {
|
||||
startActivity(
|
||||
Intent(contextOrNull(), ImageActivity::class.java)
|
||||
.setData(url.toUri())
|
||||
.putExtra(KEY_SOURCE, source?.name),
|
||||
anchor?.let { scaleUpActivityOptionsOf(it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun openBookmarks() = startActivity(AllBookmarksActivity::class.java)
|
||||
|
||||
fun openAppUpdate() = startActivity(AppUpdateActivity::class.java)
|
||||
|
||||
fun openSuggestions() {
|
||||
startActivity(suggestionsIntent(contextOrNull() ?: return))
|
||||
}
|
||||
|
||||
fun openSourcesCatalog() = startActivity(SourcesCatalogActivity::class.java)
|
||||
|
||||
fun openDownloads() = startActivity(DownloadsActivity::class.java)
|
||||
|
||||
fun openDirectoriesSettings() = startActivity(MangaDirectoriesActivity::class.java)
|
||||
|
||||
fun openBrowser(url: String, source: MangaSource?, title: String?) {
|
||||
startActivity(
|
||||
Intent(contextOrNull() ?: return, BrowserActivity::class.java)
|
||||
.setData(url.toUri())
|
||||
.putExtra(KEY_TITLE, title)
|
||||
.putExtra(KEY_SOURCE, source?.name),
|
||||
)
|
||||
}
|
||||
|
||||
fun openColorFilterConfig(manga: Manga, page: MangaPage) {
|
||||
startActivity(
|
||||
Intent(contextOrNull(), ColorFilterConfigActivity::class.java)
|
||||
.putExtra(KEY_MANGA, ParcelableManga(manga))
|
||||
.putExtra(KEY_PAGES, ParcelableMangaPage(page)),
|
||||
)
|
||||
}
|
||||
|
||||
fun openHistory() = startActivity(HistoryActivity::class.java)
|
||||
|
||||
fun openFavorites() = startActivity(FavouritesActivity::class.java)
|
||||
|
||||
fun openFavorites(category: FavouriteCategory) {
|
||||
startActivity(
|
||||
Intent(contextOrNull() ?: return, FavouritesActivity::class.java)
|
||||
.putExtra(KEY_ID, category.id)
|
||||
.putExtra(KEY_TITLE, category.title),
|
||||
)
|
||||
}
|
||||
|
||||
fun openFavoriteCategories() = startActivity(FavouriteCategoriesActivity::class.java)
|
||||
|
||||
fun openFavoriteCategoryEdit(categoryId: Long) {
|
||||
startActivity(
|
||||
Intent(contextOrNull() ?: return, FavouritesCategoryEditActivity::class.java)
|
||||
.putExtra(KEY_ID, categoryId),
|
||||
)
|
||||
}
|
||||
|
||||
fun openFavoriteCategoryCreate() = openFavoriteCategoryEdit(FavouritesCategoryEditActivity.NO_ID)
|
||||
|
||||
fun openMangaUpdates() {
|
||||
startActivity(mangaUpdatesIntent(contextOrNull() ?: return))
|
||||
}
|
||||
|
||||
fun openSettings() = startActivity(SettingsActivity::class.java)
|
||||
|
||||
fun openReaderSettings() {
|
||||
startActivity(readerSettingsIntent(contextOrNull() ?: return))
|
||||
}
|
||||
|
||||
fun openProxySettings() {
|
||||
startActivity(proxySettingsIntent(contextOrNull() ?: return))
|
||||
}
|
||||
|
||||
fun openDownloadsSetting() {
|
||||
startActivity(downloadsSettingsIntent(contextOrNull() ?: return))
|
||||
}
|
||||
|
||||
fun openSourceSettings(source: MangaSource) {
|
||||
startActivity(sourceSettingsIntent(contextOrNull() ?: return, source))
|
||||
}
|
||||
|
||||
fun openSuggestionsSettings() {
|
||||
startActivity(suggestionsSettingsIntent(contextOrNull() ?: return))
|
||||
}
|
||||
|
||||
fun openSourcesSettings() {
|
||||
startActivity(sourcesSettingsIntent(contextOrNull() ?: return))
|
||||
}
|
||||
|
||||
fun openReaderTapGridSettings() = startActivity(ReaderTapGridConfigActivity::class.java)
|
||||
|
||||
fun openScrobblerSettings(scrobbler: ScrobblerService) {
|
||||
startActivity(
|
||||
Intent(contextOrNull() ?: return, ScrobblerConfigActivity::class.java)
|
||||
.putExtra(KEY_ID, scrobbler.id),
|
||||
)
|
||||
}
|
||||
|
||||
fun openSourceAuth(source: MangaSource) {
|
||||
startActivity(sourceAuthIntent(contextOrNull() ?: return, source))
|
||||
}
|
||||
|
||||
fun openManageSources() {
|
||||
startActivity(
|
||||
manageSourcesIntent(contextOrNull() ?: return),
|
||||
)
|
||||
}
|
||||
|
||||
fun openStatistic() = startActivity(StatsActivity::class.java)
|
||||
|
||||
@CheckResult
|
||||
fun openExternalBrowser(url: String, chooserTitle: CharSequence? = null): Boolean {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.data = url.toUriOrNull() ?: return false
|
||||
return startActivitySafe(
|
||||
if (!chooserTitle.isNullOrEmpty()) {
|
||||
Intent.createChooser(intent, chooserTitle)
|
||||
} else {
|
||||
intent
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
fun openSystemSyncSettings(account: Account): Boolean {
|
||||
val args = Bundle(1)
|
||||
args.putParcelable(ACCOUNT_KEY, account)
|
||||
val intent = Intent(ACTION_ACCOUNT_SYNC_SETTINGS)
|
||||
intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args)
|
||||
return startActivitySafe(intent)
|
||||
}
|
||||
|
||||
/** Dialogs **/
|
||||
|
||||
fun showDownloadDialog(manga: Manga, snackbarHost: View?) = showDownloadDialog(setOf(manga), snackbarHost)
|
||||
|
||||
fun showDownloadDialog(manga: Collection<Manga>, snackbarHost: View?) {
|
||||
if (manga.isEmpty()) {
|
||||
return
|
||||
}
|
||||
val fm = getFragmentManager() ?: return
|
||||
if (snackbarHost != null) {
|
||||
getLifecycleOwner()?.let { lifecycleOwner ->
|
||||
DownloadDialogFragment.registerCallback(fm, lifecycleOwner, snackbarHost)
|
||||
}
|
||||
} else {
|
||||
DownloadDialogFragment.unregisterCallback(fm)
|
||||
}
|
||||
DownloadDialogFragment().withArgs(1) {
|
||||
putParcelableArray(KEY_MANGA, manga.mapToArray { ParcelableManga(it) })
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showLocalInfoDialog(manga: Manga) {
|
||||
LocalInfoDialog().withArgs(1) {
|
||||
putParcelable(KEY_MANGA, ParcelableManga(manga))
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showDirectorySelectDialog() {
|
||||
MangaDirectorySelectDialog().showDistinct()
|
||||
}
|
||||
|
||||
fun showFavoriteDialog(manga: Manga) = showFavoriteDialog(setOf(manga))
|
||||
|
||||
fun showFavoriteDialog(manga: Collection<Manga>) {
|
||||
if (manga.isEmpty()) {
|
||||
return
|
||||
}
|
||||
FavoriteDialog().withArgs(1) {
|
||||
putParcelableArrayList(
|
||||
KEY_MANGA_LIST,
|
||||
manga.mapTo(ArrayList(manga.size), ::ParcelableManga),
|
||||
)
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showErrorDialog(error: Throwable, url: String? = null) {
|
||||
ErrorDetailsDialog().withArgs(2) {
|
||||
putSerializable(KEY_ERROR, error)
|
||||
putString(KEY_URL, url)
|
||||
}.show()
|
||||
}
|
||||
|
||||
fun showBackupRestoreDialog(fileUri: Uri) {
|
||||
RestoreDialogFragment().withArgs(1) {
|
||||
putString(KEY_FILE, fileUri.toString())
|
||||
}.show()
|
||||
}
|
||||
|
||||
fun showBackupCreateDialog() {
|
||||
BackupDialogFragment().show()
|
||||
}
|
||||
|
||||
fun showImportDialog() {
|
||||
ImportDialogFragment().showDistinct()
|
||||
}
|
||||
|
||||
fun showFilterSheet(): Boolean = if (isFilterSupported()) {
|
||||
FilterSheetFragment().showDistinct()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
fun showTagsCatalogSheet(excludeMode: Boolean) {
|
||||
if (!isFilterSupported()) {
|
||||
return
|
||||
}
|
||||
TagsCatalogSheet().withArgs(1) {
|
||||
putBoolean(KEY_EXCLUDE, excludeMode)
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showListConfigSheet(section: ListConfigSection) {
|
||||
ListConfigBottomSheet().withArgs(1) {
|
||||
putParcelable(KEY_LIST_SECTION, section)
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showStatisticSheet(manga: Manga) {
|
||||
MangaStatsSheet().withArgs(1) {
|
||||
putParcelable(KEY_MANGA, ParcelableManga(manga))
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showReaderConfigSheet(mode: ReaderMode) {
|
||||
ReaderConfigSheet().withArgs(1) {
|
||||
putInt(KEY_READER_MODE, mode.id)
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showWelcomeSheet() {
|
||||
WelcomeSheet().showDistinct()
|
||||
}
|
||||
|
||||
fun showChapterPagesSheet() {
|
||||
ChaptersPagesSheet().showDistinct()
|
||||
}
|
||||
|
||||
fun showChapterPagesSheet(defaultTab: Int) {
|
||||
ChaptersPagesSheet().withArgs(1) {
|
||||
putInt(KEY_TAB, defaultTab)
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showScrobblingSelectorSheet(manga: Manga, scrobblerService: ScrobblerService?) {
|
||||
ScrobblingSelectorSheet().withArgs(2) {
|
||||
putParcelable(KEY_MANGA, ParcelableManga(manga))
|
||||
if (scrobblerService != null) {
|
||||
putInt(KEY_ID, scrobblerService.id)
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
||||
fun showScrobblingInfoSheet(index: Int) {
|
||||
ScrobblingInfoSheet().withArgs(1) {
|
||||
putInt(KEY_INDEX, index)
|
||||
}.showDistinct()
|
||||
}
|
||||
|
||||
fun showTrackerCategoriesConfigSheet() {
|
||||
TrackerCategoriesConfigSheet().showDistinct()
|
||||
}
|
||||
|
||||
/** Public utils **/
|
||||
|
||||
fun isFilterSupported(): Boolean = when {
|
||||
fragment != null -> fragment.activity is FilterCoordinator.Owner
|
||||
activity != null -> activity is FilterCoordinator.Owner
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun isChapterPagesSheetShown(): Boolean {
|
||||
val sheet = getFragmentManager()?.findFragmentByTag(fragmentTag<ChaptersPagesSheet>()) as? ChaptersPagesSheet
|
||||
return sheet?.dialog?.isShowing == true
|
||||
}
|
||||
|
||||
fun closeWelcomeSheet(): Boolean {
|
||||
val fm = fragment?.parentFragmentManager ?: activity?.supportFragmentManager ?: return false
|
||||
val sheet = fm.findFragmentByTag(fragmentTag<WelcomeSheet>()) as? WelcomeSheet ?: return false
|
||||
sheet.dismissAllowingStateLoss()
|
||||
return true
|
||||
}
|
||||
|
||||
/** Private utils **/
|
||||
|
||||
private fun startActivity(intent: Intent, options: Bundle? = null) {
|
||||
fragment?.startActivity(intent, options)
|
||||
?: activity?.startActivity(intent, options)
|
||||
}
|
||||
|
||||
private fun startActivitySafe(intent: Intent): Boolean = try {
|
||||
startActivity(intent)
|
||||
true
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
false
|
||||
}
|
||||
|
||||
private fun startActivity(activityClass: Class<out Activity>) {
|
||||
startActivity(Intent(contextOrNull() ?: return, activityClass))
|
||||
}
|
||||
|
||||
private fun getFragmentManager(): FragmentManager? {
|
||||
return fragment?.childFragmentManager ?: activity?.supportFragmentManager
|
||||
}
|
||||
|
||||
private fun contextOrNull(): Context? = activity ?: fragment?.context
|
||||
|
||||
private fun getLifecycleOwner(): LifecycleOwner? = activity ?: fragment?.viewLifecycleOwner
|
||||
|
||||
private fun DialogFragment.showDistinct(): Boolean {
|
||||
val fm = this@AppRouter.getFragmentManager() ?: return false
|
||||
val tag = javaClass.fragmentTag()
|
||||
val existing = fm.findFragmentByTag(tag) as? DialogFragment?
|
||||
if (existing != null && existing.isVisible && existing.arguments == this.arguments) {
|
||||
return false
|
||||
}
|
||||
show(fm, tag)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun DialogFragment.show() {
|
||||
show(
|
||||
this@AppRouter.getFragmentManager() ?: return,
|
||||
javaClass.fragmentTag(),
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun from(view: View): AppRouter? = runCatching {
|
||||
AppRouter(view.findFragment<Fragment>())
|
||||
}.getOrElse {
|
||||
(view.context.findActivity() as? FragmentActivity)?.let(::AppRouter)
|
||||
}
|
||||
|
||||
fun detailsIntent(context: Context, manga: Manga) = Intent(context, DetailsActivity::class.java)
|
||||
.putExtra(KEY_MANGA, ParcelableManga(manga))
|
||||
|
||||
fun detailsIntent(context: Context, mangaId: Long) = Intent(context, DetailsActivity::class.java)
|
||||
.putExtra(KEY_ID, mangaId)
|
||||
|
||||
fun listIntent(context: Context, source: MangaSource, filter: MangaListFilter?): Intent =
|
||||
Intent(context, MangaListActivity::class.java)
|
||||
.setAction(ACTION_MANGA_EXPLORE)
|
||||
.putExtra(KEY_SOURCE, source.name)
|
||||
.apply {
|
||||
if (!filter.isNullOrEmpty()) {
|
||||
putExtra(KEY_FILTER, ParcelableMangaListFilter(filter))
|
||||
}
|
||||
}
|
||||
|
||||
fun cloudFlareResolveIntent(context: Context, exception: CloudFlareProtectedException): Intent =
|
||||
Intent(context, CloudFlareActivity::class.java).apply {
|
||||
data = exception.url.toUri()
|
||||
putExtra(KEY_SOURCE, exception.source?.name)
|
||||
exception.headers.get(CommonHeaders.USER_AGENT)?.let {
|
||||
putExtra(KEY_USER_AGENT, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun suggestionsIntent(context: Context) = Intent(context, SuggestionsActivity::class.java)
|
||||
|
||||
fun mangaUpdatesIntent(context: Context) = Intent(context, UpdatesActivity::class.java)
|
||||
|
||||
fun readerSettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_READER)
|
||||
|
||||
fun suggestionsSettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_SUGGESTIONS)
|
||||
|
||||
fun trackerSettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_TRACKER)
|
||||
|
||||
fun proxySettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_PROXY)
|
||||
|
||||
fun historySettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_HISTORY)
|
||||
|
||||
fun sourcesSettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_SOURCES)
|
||||
|
||||
fun manageSourcesIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_MANAGE_SOURCES)
|
||||
|
||||
fun downloadsSettingsIntent(context: Context) =
|
||||
Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_MANAGE_DOWNLOADS)
|
||||
|
||||
fun sourceSettingsIntent(context: Context, source: MangaSource): Intent = when (source) {
|
||||
is MangaSourceInfo -> sourceSettingsIntent(context, source.mangaSource)
|
||||
is ExternalMangaSource -> Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
.setData(Uri.fromParts("package", source.packageName, null))
|
||||
|
||||
else -> Intent(context, SettingsActivity::class.java)
|
||||
.setAction(ACTION_SOURCE)
|
||||
.putExtra(KEY_SOURCE, source.name)
|
||||
}
|
||||
|
||||
fun sourceAuthIntent(context: Context, source: MangaSource): Intent {
|
||||
return Intent(context, SourceAuthActivity::class.java)
|
||||
.putExtra(KEY_SOURCE, source.name)
|
||||
}
|
||||
|
||||
const val KEY_EXCLUDE = "exclude"
|
||||
const val KEY_FILTER = "filter"
|
||||
const val KEY_ID = "id"
|
||||
const val KEY_LIST_SECTION = "list_section"
|
||||
const val KEY_MANGA = "manga"
|
||||
const val KEY_MANGA_LIST = "manga_list"
|
||||
const val KEY_PAGES = "pages"
|
||||
const val KEY_QUERY = "query"
|
||||
const val KEY_READER_MODE = "reader_mode"
|
||||
const val KEY_SOURCE = "source"
|
||||
const val KEY_TAB = "tab"
|
||||
const val KEY_TITLE = "title"
|
||||
const val KEY_USER_AGENT = "user_agent"
|
||||
const val KEY_URL = "url"
|
||||
const val KEY_ERROR = "error"
|
||||
const val KEY_FILE = "file"
|
||||
const val KEY_INDEX = "index"
|
||||
const val KEY_DATA = "data"
|
||||
|
||||
const val ACTION_HISTORY = "${BuildConfig.APPLICATION_ID}.action.MANAGE_HISTORY"
|
||||
const val ACTION_MANAGE_DOWNLOADS = "${BuildConfig.APPLICATION_ID}.action.MANAGE_DOWNLOADS"
|
||||
const val ACTION_MANAGE_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES_LIST"
|
||||
const val ACTION_MANGA_EXPLORE = "${BuildConfig.APPLICATION_ID}.action.EXPLORE_MANGA"
|
||||
const val ACTION_PROXY = "${BuildConfig.APPLICATION_ID}.action.MANAGE_PROXY"
|
||||
const val ACTION_READER = "${BuildConfig.APPLICATION_ID}.action.MANAGE_READER_SETTINGS"
|
||||
const val ACTION_SOURCE = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCE_SETTINGS"
|
||||
const val ACTION_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES"
|
||||
const val ACTION_SUGGESTIONS = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SUGGESTIONS"
|
||||
const val ACTION_TRACKER = "${BuildConfig.APPLICATION_ID}.action.MANAGE_TRACKER"
|
||||
|
||||
private const val ACCOUNT_KEY = "account"
|
||||
private const val ACTION_ACCOUNT_SYNC_SETTINGS = "android.settings.ACCOUNT_SYNC_SETTINGS"
|
||||
private const val EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args"
|
||||
|
||||
private fun Class<out Fragment>.fragmentTag() = name // TODO
|
||||
|
||||
private inline fun <reified F : Fragment> fragmentTag() = F::class.java.fragmentTag()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package org.koitharu.kotatsu.core.nav
|
||||
|
||||
import android.app.ActivityOptions
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
|
||||
|
||||
inline val FragmentActivity.router: AppRouter
|
||||
get() = AppRouter(this)
|
||||
|
||||
inline val Fragment.router: AppRouter
|
||||
get() = AppRouter(this)
|
||||
|
||||
tailrec fun Fragment.dismissParentDialog(): Boolean {
|
||||
return when (val parent = parentFragment) {
|
||||
null -> return false
|
||||
is DialogFragment -> {
|
||||
parent.dismiss()
|
||||
true
|
||||
}
|
||||
|
||||
else -> parent.dismissParentDialog()
|
||||
}
|
||||
}
|
||||
|
||||
fun scaleUpActivityOptionsOf(view: View): Bundle? = if (view.context.isAnimationsEnabled) {
|
||||
ActivityOptions.makeScaleUpAnimation(
|
||||
view,
|
||||
0,
|
||||
0,
|
||||
view.width,
|
||||
view.height,
|
||||
).toBundle()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package org.koitharu.kotatsu.core.nav
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
|
||||
@JvmInline
|
||||
value class ReaderIntent private constructor(
|
||||
val intent: Intent,
|
||||
) {
|
||||
|
||||
class Builder(context: Context) {
|
||||
|
||||
private val intent = Intent(context, ReaderActivity::class.java)
|
||||
.setAction(ACTION_MANGA_READ)
|
||||
|
||||
fun manga(manga: Manga) = apply {
|
||||
intent.putExtra(AppRouter.KEY_MANGA, ParcelableManga(manga))
|
||||
}
|
||||
|
||||
fun mangaId(mangaId: Long) = apply {
|
||||
intent.putExtra(AppRouter.KEY_ID, mangaId)
|
||||
}
|
||||
|
||||
fun incognito(incognito: Boolean) = apply {
|
||||
intent.putExtra(EXTRA_INCOGNITO, incognito)
|
||||
}
|
||||
|
||||
fun branch(branch: String?) = apply {
|
||||
intent.putExtra(EXTRA_BRANCH, branch)
|
||||
}
|
||||
|
||||
fun state(state: ReaderState?) = apply {
|
||||
intent.putExtra(EXTRA_STATE, state)
|
||||
}
|
||||
|
||||
fun bookmark(bookmark: Bookmark) = manga(
|
||||
bookmark.manga,
|
||||
).state(
|
||||
ReaderState(
|
||||
chapterId = bookmark.chapterId,
|
||||
page = bookmark.page,
|
||||
scroll = bookmark.scroll,
|
||||
),
|
||||
)
|
||||
|
||||
fun build() = ReaderIntent(intent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ACTION_MANGA_READ = "${BuildConfig.APPLICATION_ID}.action.READ_MANGA"
|
||||
const val EXTRA_STATE = "state"
|
||||
const val EXTRA_BRANCH = "branch"
|
||||
const val EXTRA_INCOGNITO = "incognito"
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,18 @@
|
||||
package org.koitharu.kotatsu.details.ui.scrobbling
|
||||
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import coil3.ImageLoader
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.ui.BaseListAdapter
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
|
||||
class ScrollingInfoAdapter(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
coil: ImageLoader,
|
||||
fragmentManager: FragmentManager,
|
||||
router: AppRouter,
|
||||
) : BaseListAdapter<ListModel>() {
|
||||
|
||||
init {
|
||||
delegatesManager.addDelegate(scrobblingInfoAD(lifecycleOwner, coil, fragmentManager))
|
||||
delegatesManager.addDelegate(scrobblingInfoAD(lifecycleOwner, coil, router))
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue