diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt index 2ff13e69c..3381d6dd6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsTab.kt @@ -2,11 +2,18 @@ package eu.kanade.tachiyomi.ui.browse.extension import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined._18UpRating +import androidx.compose.material3.AlertDialog import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.LocalContext import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.ExtensionScreen @@ -16,6 +23,7 @@ import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreen import eu.kanade.tachiyomi.ui.webview.WebViewScreen +import eu.kanade.tachiyomi.util.system.isPackageInstalled import kotlinx.collections.immutable.persistentListOf import tachiyomi.i18n.MR import tachiyomi.i18n.kmk.KMR @@ -26,7 +34,10 @@ fun extensionsTab( extensionsScreenModel: ExtensionsScreenModel, ): TabContent { val navigator = LocalNavigator.currentOrThrow + val context = LocalContext.current + val state by extensionsScreenModel.state.collectAsState() + var privateExtensionToUninstall by remember { mutableStateOf(null) } return TabContent( titleRes = MR.strings.label_extensions, @@ -62,7 +73,13 @@ fun extensionsTab( onLongClickItem = { extension -> when (extension) { is Extension.Available -> extensionsScreenModel.installExtension(extension) - else -> extensionsScreenModel.uninstallExtension(extension) + else -> { + if (context.isPackageInstalled(extension.pkgName)) { + extensionsScreenModel.uninstallExtension(extension) + } else { + privateExtensionToUninstall = extension + } + } } }, onClickItemCancel = extensionsScreenModel::cancelInstallUpdateExtension, @@ -85,6 +102,50 @@ fun extensionsTab( onUpdateExtension = extensionsScreenModel::updateExtension, onRefresh = extensionsScreenModel::findAvailableExtensions, ) + + privateExtensionToUninstall?.let { extension -> + ExtensionUninstallConfirmation( + extensionName = extension.name, + onClickConfirm = { + extensionsScreenModel.uninstallExtension(extension) + }, + onDismissRequest = { + privateExtensionToUninstall = null + }, + ) + } }, ) } + +@Composable +private fun ExtensionUninstallConfirmation( + extensionName: String, + onClickConfirm: () -> Unit, + onDismissRequest: () -> Unit, +) { + AlertDialog( + title = { + Text(text = stringResource(MR.strings.ext_confirm_remove)) + }, + text = { + Text(text = stringResource(MR.strings.remove_private_extension_message, extensionName)) + }, + confirmButton = { + TextButton( + onClick = { + onClickConfirm() + onDismissRequest() + }, + ) { + Text(text = stringResource(MR.strings.ext_remove)) + } + }, + dismissButton = { + TextButton(onClick = onDismissRequest) { + Text(text = stringResource(MR.strings.action_cancel)) + } + }, + onDismissRequest = onDismissRequest, + ) +} diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index 45a5f4bcc..fa04016bc 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -320,10 +320,13 @@ Trust Untrusted Uninstall + Remove + Remove Extension? App info Untrusted extension Malicious extensions can read any stored login credentials or execute arbitrary code.\n\nBy trusting this extension, you accept these risks. This extension is no longer available. It may not function properly and can cause issues with the app. Uninstalling it is recommended. + Do you really want to remove \"%s\" extension? Failed to fetch available extensions Version Language