From 6135798471e1fbd91453775a8e8ce1f0fd04c03d Mon Sep 17 00:00:00 2001 From: arkon Date: Mon, 11 Dec 2023 22:24:33 -0500 Subject: [PATCH] feat(app): Add ability to open available extension websites in WebView Closes #8628 --- .../browse/anime/AnimeExtensionsScreen.kt | 110 +++++++++++++----- .../browse/manga/MangaExtensionsScreen.kt | 109 ++++++++++++----- .../anime/extension/AnimeExtensionsTab.kt | 12 ++ .../manga/extension/MangaExtensionsTab.kt | 12 ++ 4 files changed, 183 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt index cc0fdfdde..f760ad865 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt @@ -14,6 +14,11 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Close +import androidx.compose.material.icons.outlined.GetApp +import androidx.compose.material.icons.outlined.Public +import androidx.compose.material.icons.outlined.Refresh +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material.icons.outlined.VerifiedUser import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon @@ -61,6 +66,7 @@ fun AnimeExtensionScreen( searchQuery: String?, onLongClickItem: (AnimeExtension) -> Unit, onClickItemCancel: (AnimeExtension) -> Unit, + onClickItemWebView: (AnimeExtension.Available) -> Unit, onInstallExtension: (AnimeExtension.Available) -> Unit, onUninstallExtension: (AnimeExtension) -> Unit, onUpdateExtension: (AnimeExtension.Installed) -> Unit, @@ -93,6 +99,7 @@ fun AnimeExtensionScreen( contentPadding = contentPadding, onLongClickItem = onLongClickItem, onClickItemCancel = onClickItemCancel, + onClickItemWebView = onClickItemWebView, onInstallExtension = onInstallExtension, onUninstallExtension = onUninstallExtension, onUpdateExtension = onUpdateExtension, @@ -110,6 +117,7 @@ private fun AnimeExtensionContent( state: AnimeExtensionsScreenModel.State, contentPadding: PaddingValues, onLongClickItem: (AnimeExtension) -> Unit, + onClickItemWebView: (AnimeExtension.Available) -> Unit, onClickItemCancel: (AnimeExtension) -> Unit, onInstallExtension: (AnimeExtension.Available) -> Unit, onUninstallExtension: (AnimeExtension) -> Unit, @@ -177,6 +185,7 @@ private fun AnimeExtensionContent( }, onLongClickItem = onLongClickItem, onClickItemCancel = onClickItemCancel, + onClickItemWebView = onClickItemWebView, onClickItemAction = { when (it) { is AnimeExtension.Available -> onInstallExtension(it) @@ -219,6 +228,7 @@ private fun AnimeExtensionItem( item: AnimeExtensionUiModel.Item, onClickItem: (AnimeExtension) -> Unit, onLongClickItem: (AnimeExtension) -> Unit, + onClickItemWebView: (AnimeExtension.Available) -> Unit, onClickItemCancel: (AnimeExtension) -> Unit, onClickItemAction: (AnimeExtension) -> Unit, modifier: Modifier = Modifier, @@ -262,6 +272,7 @@ private fun AnimeExtensionItem( AnimeExtensionItemActions( extension = extension, installStep = installStep, + onClickItemWebView = onClickItemWebView, onClickItemCancel = onClickItemCancel, onClickItemAction = onClickItemAction, ) @@ -348,43 +359,82 @@ private fun AnimeExtensionItemActions( extension: AnimeExtension, installStep: InstallStep, modifier: Modifier = Modifier, + onClickItemWebView: (AnimeExtension.Available) -> Unit = {}, onClickItemCancel: (AnimeExtension) -> Unit = {}, onClickItemAction: (AnimeExtension) -> Unit = {}, ) { val isIdle = installStep.isCompleted() - Row(modifier = modifier) { - if (isIdle) { - TextButton( - onClick = { onClickItemAction(extension) }, - ) { - Text( - text = when (installStep) { - InstallStep.Installed -> stringResource(MR.strings.ext_installed) - InstallStep.Error -> stringResource(MR.strings.action_retry) - InstallStep.Idle -> { - when (extension) { - is AnimeExtension.Installed -> { - if (extension.hasUpdate) { - stringResource(MR.strings.ext_update) - } else { - stringResource(MR.strings.action_settings) - } - } - is AnimeExtension.Untrusted -> stringResource(MR.strings.ext_trust) - is AnimeExtension.Available -> stringResource(MR.strings.ext_install) + + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + when { + !isIdle -> { + IconButton(onClick = { onClickItemCancel(extension) }) { + Icon( + imageVector = Icons.Outlined.Close, + contentDescription = stringResource(MR.strings.action_cancel), + ) + } + } + installStep == InstallStep.Error -> { + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.Refresh, + contentDescription = stringResource(MR.strings.action_retry), + ) + } + } + installStep == InstallStep.Idle -> { + when (extension) { + is AnimeExtension.Installed -> { + if (extension.hasUpdate) { + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.GetApp, + contentDescription = stringResource(MR.strings.ext_update), + ) } } - else -> error("Must not show install process text") - }, - ) - } - } else { - IconButton(onClick = { onClickItemCancel(extension) }) { - Icon( - imageVector = Icons.Outlined.Close, - contentDescription = stringResource(MR.strings.action_cancel), - ) + + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.Settings, + contentDescription = stringResource(MR.strings.action_settings), + ) + } + } + is AnimeExtension.Untrusted -> { + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.VerifiedUser, + contentDescription = stringResource(MR.strings.ext_trust), + ) + } + } + is AnimeExtension.Available -> { + if (extension.sources.isNotEmpty()) { + IconButton( + onClick = { onClickItemWebView(extension) }, + ) { + Icon( + imageVector = Icons.Outlined.Public, + contentDescription = stringResource(MR.strings.action_open_in_web_view), + ) + } + } + + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.GetApp, + contentDescription = stringResource(MR.strings.ext_install), + ) + } + } + } } } } } + diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt index 74c8d2223..797b6c560 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt @@ -14,6 +14,11 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Close +import androidx.compose.material.icons.outlined.GetApp +import androidx.compose.material.icons.outlined.Public +import androidx.compose.material.icons.outlined.Refresh +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material.icons.outlined.VerifiedUser import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator @@ -62,6 +67,7 @@ fun MangaExtensionScreen( searchQuery: String?, onLongClickItem: (MangaExtension) -> Unit, onClickItemCancel: (MangaExtension) -> Unit, + onClickItemWebView: (MangaExtension.Available) -> Unit, onInstallExtension: (MangaExtension.Available) -> Unit, onUninstallExtension: (MangaExtension) -> Unit, onUpdateExtension: (MangaExtension.Installed) -> Unit, @@ -94,6 +100,7 @@ fun MangaExtensionScreen( contentPadding = contentPadding, onLongClickItem = onLongClickItem, onClickItemCancel = onClickItemCancel, + onClickItemWebView = onClickItemWebView, onInstallExtension = onInstallExtension, onUninstallExtension = onUninstallExtension, onUpdateExtension = onUpdateExtension, @@ -111,6 +118,7 @@ private fun ExtensionContent( state: MangaExtensionsScreenModel.State, contentPadding: PaddingValues, onLongClickItem: (MangaExtension) -> Unit, + onClickItemWebView: (MangaExtension.Available) -> Unit, onClickItemCancel: (MangaExtension) -> Unit, onInstallExtension: (MangaExtension.Available) -> Unit, onUninstallExtension: (MangaExtension) -> Unit, @@ -177,6 +185,7 @@ private fun ExtensionContent( } }, onLongClickItem = onLongClickItem, + onClickItemWebView = onClickItemWebView, onClickItemCancel = onClickItemCancel, onClickItemAction = { when (it) { @@ -220,6 +229,7 @@ private fun ExtensionItem( item: MangaExtensionUiModel.Item, onClickItem: (MangaExtension) -> Unit, onLongClickItem: (MangaExtension) -> Unit, + onClickItemWebView: (MangaExtension.Available) -> Unit, onClickItemCancel: (MangaExtension) -> Unit, onClickItemAction: (MangaExtension) -> Unit, modifier: Modifier = Modifier, @@ -263,6 +273,7 @@ private fun ExtensionItem( ExtensionItemActions( extension = extension, installStep = installStep, + onClickItemWebView = onClickItemWebView, onClickItemCancel = onClickItemCancel, onClickItemAction = onClickItemAction, ) @@ -349,42 +360,80 @@ private fun ExtensionItemActions( extension: MangaExtension, installStep: InstallStep, modifier: Modifier = Modifier, + onClickItemWebView: (MangaExtension.Available) -> Unit = {}, onClickItemCancel: (MangaExtension) -> Unit = {}, onClickItemAction: (MangaExtension) -> Unit = {}, ) { val isIdle = installStep.isCompleted() - Row(modifier = modifier) { - if (isIdle) { - TextButton( - onClick = { onClickItemAction(extension) }, - ) { - Text( - text = when (installStep) { - InstallStep.Installed -> stringResource(MR.strings.ext_installed) - InstallStep.Error -> stringResource(MR.strings.action_retry) - InstallStep.Idle -> { - when (extension) { - is MangaExtension.Installed -> { - if (extension.hasUpdate) { - stringResource(MR.strings.ext_update) - } else { - stringResource(MR.strings.action_settings) - } - } - is MangaExtension.Untrusted -> stringResource(MR.strings.ext_trust) - is MangaExtension.Available -> stringResource(MR.strings.ext_install) + + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + when { + !isIdle -> { + IconButton(onClick = { onClickItemCancel(extension) }) { + Icon( + imageVector = Icons.Outlined.Close, + contentDescription = stringResource(MR.strings.action_cancel), + ) + } + } + installStep == InstallStep.Error -> { + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.Refresh, + contentDescription = stringResource(MR.strings.action_retry), + ) + } + } + installStep == InstallStep.Idle -> { + when (extension) { + is MangaExtension.Installed -> { + if (extension.hasUpdate) { + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.GetApp, + contentDescription = stringResource(MR.strings.ext_update), + ) } } - else -> error("Must not show install process text") - }, - ) - } - } else { - IconButton(onClick = { onClickItemCancel(extension) }) { - Icon( - imageVector = Icons.Outlined.Close, - contentDescription = stringResource(MR.strings.action_cancel), - ) + + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.Settings, + contentDescription = stringResource(MR.strings.action_settings), + ) + } + } + is MangaExtension.Untrusted -> { + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.VerifiedUser, + contentDescription = stringResource(MR.strings.ext_trust), + ) + } + } + is MangaExtension.Available -> { + if (extension.sources.isNotEmpty()) { + IconButton( + onClick = { onClickItemWebView(extension) }, + ) { + Icon( + imageVector = Icons.Outlined.Public, + contentDescription = stringResource(MR.strings.action_open_in_web_view), + ) + } + } + + IconButton(onClick = { onClickItemAction(extension) }) { + Icon( + imageVector = Icons.Outlined.GetApp, + contentDescription = stringResource(MR.strings.ext_install), + ) + } + } + } } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsTab.kt index ee8dc560a..3a83ee44d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsTab.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.ui.browse.anime.extension +import eu.kanade.tachiyomi.ui.webview.WebViewScreen import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Translate import androidx.compose.runtime.Composable @@ -53,6 +54,17 @@ fun animeExtensionsTab( }, onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension, onClickUpdateAll = extensionsScreenModel::updateAllExtensions, + onClickItemWebView = { extension -> + extension.sources.getOrNull(0)?.let { + navigator.push( + WebViewScreen( + url = it.baseUrl, + initialTitle = it.name, + sourceId = it.id, + ), + ) + } + }, onInstallExtension = extensionsScreenModel::installExtension, onOpenExtension = { navigator.push(AnimeExtensionDetailsScreen(it.pkgName)) }, onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) }, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsTab.kt index 443eb798d..2119e3c81 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsTab.kt @@ -12,6 +12,7 @@ import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.TabContent import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.ui.browse.manga.extension.details.MangaExtensionDetailsScreen +import eu.kanade.tachiyomi.ui.webview.WebViewScreen import kotlinx.collections.immutable.persistentListOf import tachiyomi.i18n.MR import tachiyomi.presentation.core.i18n.stringResource @@ -49,6 +50,17 @@ fun mangaExtensionsTab( }, onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension, onClickUpdateAll = extensionsScreenModel::updateAllExtensions, + onClickItemWebView = { extension -> + extension.sources.getOrNull(0)?.let { + navigator.push( + WebViewScreen( + url = it.baseUrl, + initialTitle = it.name, + sourceId = it.id, + ), + ) + } + }, onInstallExtension = extensionsScreenModel::installExtension, onOpenExtension = { navigator.push(MangaExtensionDetailsScreen(it.pkgName)) }, onTrustExtension = { extensionsScreenModel.trustSignature(it.signatureHash) },