mirror of
https://github.com/mihonapp/mihon.git
synced 2026-10-16 13:48:09 -07:00
Use plain icon buttons for extension actions
This commit is contained in:
@@ -15,10 +15,10 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
import androidx.compose.material3.FilledTonalIconButton
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Switch
|
||||
@@ -336,7 +336,7 @@ private fun DetailsHeader(
|
||||
}
|
||||
|
||||
if (onClickAppInfo != null) {
|
||||
FilledTonalButton(
|
||||
Button(
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = onClickAppInfo,
|
||||
) {
|
||||
@@ -434,10 +434,11 @@ private fun SourceSwitchPreference(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (source.source is ConfigurableSource) {
|
||||
FilledTonalIconButton(onClick = { onClickSourcePreferences(source.source.id) }) {
|
||||
IconButton(onClick = { onClickSourcePreferences(source.source.id) }) {
|
||||
Icon(
|
||||
imageVector = MaterialSymbols.Rounded.Settings,
|
||||
contentDescription = stringResource(MR.strings.label_settings),
|
||||
tint = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.items
|
||||
@@ -18,14 +17,10 @@ import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.FilledTonalIconButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SplitButtonDefaults
|
||||
import androidx.compose.material3.SplitButtonLayout
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -36,11 +31,9 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
@@ -49,7 +42,6 @@ import eu.kanade.presentation.browse.components.BaseBrowseItem
|
||||
import eu.kanade.presentation.browse.components.ExtensionIcon
|
||||
import eu.kanade.presentation.browse.components.ExtensionPill
|
||||
import eu.kanade.presentation.browse.components.label
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.presentation.components.WarningBanner
|
||||
import eu.kanade.presentation.more.settings.screen.browse.ExtensionStoresScreen
|
||||
import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState
|
||||
@@ -65,7 +57,7 @@ import mihon.icons.materialsymbols.MaterialSymbols
|
||||
import mihon.icons.materialsymbols.rounded.Close
|
||||
import mihon.icons.materialsymbols.rounded.Download
|
||||
import mihon.icons.materialsymbols.rounded.Info
|
||||
import mihon.icons.materialsymbols.rounded.KeyboardArrowDown
|
||||
import mihon.icons.materialsymbols.rounded.Public
|
||||
import mihon.icons.materialsymbols.rounded.Refresh
|
||||
import mihon.icons.materialsymbols.rounded.Settings
|
||||
import mihon.icons.materialsymbols.rounded.VerifiedUser
|
||||
@@ -160,7 +152,6 @@ private fun ExtensionContent(
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var notLoadedState by remember { mutableStateOf<Extension.NotLoaded?>(null) }
|
||||
var installErrorState by remember { mutableStateOf<InstallStep.Error?>(null) }
|
||||
val installGranted = rememberRequestPackageInstallsPermissionState(initialValue = true)
|
||||
|
||||
FastScrollLazyColumn(
|
||||
@@ -248,7 +239,6 @@ private fun ExtensionContent(
|
||||
}
|
||||
},
|
||||
onClickItemCancel = onClickItemCancel,
|
||||
onClickItemError = { installErrorState = it },
|
||||
onClickItemAction = {
|
||||
when (it) {
|
||||
is Extension.Available -> onInstallExtension(it)
|
||||
@@ -297,55 +287,6 @@ private fun ExtensionContent(
|
||||
)
|
||||
}
|
||||
}
|
||||
installErrorState?.let { error ->
|
||||
ExtensionInstallErrorDialog(
|
||||
error = error,
|
||||
onDismissRequest = { installErrorState = null },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ExtensionInstallErrorDialog(
|
||||
error: InstallStep.Error,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
AlertDialog(
|
||||
title = {
|
||||
Text(text = stringResource(MR.strings.ext_install_error))
|
||||
},
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small)) {
|
||||
Text(
|
||||
text = error.message,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
|
||||
error.stackTrace?.let { stackTrace ->
|
||||
val context = LocalContext.current
|
||||
TextButton(
|
||||
onClick = {
|
||||
context.copyToClipboard(
|
||||
label = context.stringResource(MR.strings.ext_copy_stacktrace),
|
||||
content = stackTrace,
|
||||
)
|
||||
},
|
||||
contentPadding = PaddingValues(0.dp),
|
||||
) {
|
||||
Text(text = stringResource(MR.strings.ext_copy_stacktrace))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
onDismissRequest = onDismissRequest,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -354,7 +295,6 @@ private fun ExtensionItem(
|
||||
onClickItem: (Extension) -> Unit,
|
||||
onLongClickItem: (Extension) -> Unit,
|
||||
onClickItemCancel: (Extension) -> Unit,
|
||||
onClickItemError: (InstallStep.Error) -> Unit,
|
||||
onClickItemAction: (Extension) -> Unit,
|
||||
onClickItemSecondaryAction: (Extension) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -377,7 +317,6 @@ private fun ExtensionItem(
|
||||
extension = extension,
|
||||
installStep = installStep,
|
||||
onClickItemCancel = onClickItemCancel,
|
||||
onClickItemError = onClickItemError,
|
||||
onClickItemAction = onClickItemAction,
|
||||
onClickItemSecondaryAction = onClickItemSecondaryAction,
|
||||
)
|
||||
@@ -518,152 +457,56 @@ private fun ExtensionItemActions(
|
||||
installStep: InstallStep,
|
||||
modifier: Modifier = Modifier,
|
||||
onClickItemCancel: (Extension) -> Unit = {},
|
||||
onClickItemError: (InstallStep.Error) -> Unit = {},
|
||||
onClickItemAction: (Extension) -> Unit = {},
|
||||
onClickItemSecondaryAction: (Extension) -> Unit = {},
|
||||
) {
|
||||
val isUntrusted = (extension as? Extension.NotLoaded)?.reason is Extension.NotLoaded.Reason.Untrusted
|
||||
val secondaryAction = when (extension) {
|
||||
is Extension.Available -> extension.sources.takeIf { it.isNotEmpty() }
|
||||
?.let { stringResource(MR.strings.action_open_in_web_view) }
|
||||
is Extension.Loaded -> stringResource(MR.strings.action_settings)
|
||||
is Extension.NotLoaded -> if (isUntrusted) {
|
||||
stringResource(MR.strings.ext_trust)
|
||||
} else {
|
||||
stringResource(MR.strings.ext_not_loaded_details)
|
||||
}
|
||||
}
|
||||
?.let { it to { onClickItemSecondaryAction(extension) } }
|
||||
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
when {
|
||||
!installStep.isCompleted() -> {
|
||||
if (!installStep.isCompleted()) {
|
||||
IconButton(onClick = { onClickItemCancel(extension) }) {
|
||||
Icon(
|
||||
imageVector = MaterialSymbols.Rounded.Close,
|
||||
contentDescription = stringResource(MR.strings.action_cancel),
|
||||
)
|
||||
}
|
||||
return@Row
|
||||
}
|
||||
installStep is InstallStep.Error -> {
|
||||
ExtensionSplitButton(
|
||||
icon = MaterialSymbols.Rounded.Refresh,
|
||||
contentDescription = stringResource(MR.strings.action_retry),
|
||||
onClick = { onClickItemAction(extension) },
|
||||
menuItems = listOfNotNull(
|
||||
stringResource(MR.strings.ext_install_error_details) to { onClickItemError(installStep) },
|
||||
secondaryAction,
|
||||
),
|
||||
)
|
||||
|
||||
val secondaryAction = when (extension) {
|
||||
is Extension.Available -> {
|
||||
(MaterialSymbols.Rounded.Public to MR.strings.action_open_in_web_view)
|
||||
.takeIf { extension.sources.isNotEmpty() }
|
||||
}
|
||||
extension is Extension.Available -> {
|
||||
ExtensionSplitButton(
|
||||
icon = MaterialSymbols.Rounded.Download,
|
||||
contentDescription = stringResource(MR.strings.ext_install),
|
||||
onClick = { onClickItemAction(extension) },
|
||||
menuItems = listOfNotNull(secondaryAction),
|
||||
)
|
||||
}
|
||||
extension is Extension.Installed && extension.hasUpdate -> {
|
||||
ExtensionSplitButton(
|
||||
icon = MaterialSymbols.Rounded.Download,
|
||||
contentDescription = stringResource(MR.strings.ext_update),
|
||||
onClick = { onClickItemAction(extension) },
|
||||
menuItems = listOfNotNull(secondaryAction),
|
||||
)
|
||||
}
|
||||
extension is Extension.Loaded -> {
|
||||
FilledTonalIconButton(onClick = { onClickItemSecondaryAction(extension) }) {
|
||||
Icon(
|
||||
imageVector = MaterialSymbols.Rounded.Settings,
|
||||
contentDescription = stringResource(MR.strings.action_settings),
|
||||
)
|
||||
}
|
||||
}
|
||||
extension is Extension.NotLoaded -> {
|
||||
IconButton(onClick = { onClickItemSecondaryAction(extension) }) {
|
||||
Icon(
|
||||
imageVector = if (isUntrusted) {
|
||||
MaterialSymbols.Rounded.VerifiedUser
|
||||
is Extension.Loaded -> MaterialSymbols.Rounded.Settings to MR.strings.action_settings
|
||||
is Extension.NotLoaded -> if (extension.reason is Extension.NotLoaded.Reason.Untrusted) {
|
||||
MaterialSymbols.Rounded.VerifiedUser to MR.strings.ext_trust
|
||||
} else {
|
||||
MaterialSymbols.Rounded.Info
|
||||
},
|
||||
contentDescription = secondaryAction?.first,
|
||||
)
|
||||
MaterialSymbols.Rounded.Info to MR.strings.ext_not_loaded_details
|
||||
}
|
||||
}
|
||||
secondaryAction?.let { (icon, label) ->
|
||||
IconButton(onClick = { onClickItemSecondaryAction(extension) }) {
|
||||
Icon(imageVector = icon, contentDescription = stringResource(label))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ExtensionSplitButton(
|
||||
icon: ImageVector,
|
||||
contentDescription: String,
|
||||
onClick: () -> Unit,
|
||||
menuItems: List<Pair<String, () -> Unit>>,
|
||||
) {
|
||||
if (menuItems.isEmpty()) {
|
||||
FilledTonalIconButton(onClick = onClick) {
|
||||
Icon(imageVector = icon, contentDescription = contentDescription)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val size = SplitButtonDefaults.ExtraSmallContainerHeight
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
SplitButtonLayout(
|
||||
leadingButton = {
|
||||
SplitButtonDefaults.TonalLeadingButton(
|
||||
onClick = onClick,
|
||||
modifier = Modifier.height(size),
|
||||
shapes = SplitButtonDefaults.leadingButtonShapesFor(size),
|
||||
contentPadding = SplitButtonDefaults.leadingButtonContentPaddingFor(size),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = contentDescription,
|
||||
modifier = Modifier.size(SplitButtonDefaults.leadingButtonIconSizeFor(size)),
|
||||
)
|
||||
val action = when {
|
||||
installStep == InstallStep.Error -> MaterialSymbols.Rounded.Refresh to MR.strings.action_retry
|
||||
extension is Extension.Available -> MaterialSymbols.Rounded.Download to MR.strings.ext_install
|
||||
extension is Extension.Installed && extension.hasUpdate -> {
|
||||
MaterialSymbols.Rounded.Download to MR.strings.ext_update
|
||||
}
|
||||
},
|
||||
trailingButton = {
|
||||
Box {
|
||||
SplitButtonDefaults.TonalTrailingButton(
|
||||
checked = expanded,
|
||||
onCheckedChange = { expanded = it },
|
||||
modifier = Modifier.height(size),
|
||||
shapes = SplitButtonDefaults.trailingButtonShapesFor(size),
|
||||
contentPadding = SplitButtonDefaults.trailingButtonContentPaddingFor(size),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = MaterialSymbols.Rounded.KeyboardArrowDown,
|
||||
contentDescription = stringResource(MR.strings.action_menu),
|
||||
modifier = Modifier.size(SplitButtonDefaults.trailingButtonIconSizeFor(size)),
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
offset = DpOffset.Zero,
|
||||
) {
|
||||
menuItems.forEach { (text, action) ->
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = text) },
|
||||
onClick = {
|
||||
expanded = false
|
||||
action()
|
||||
},
|
||||
)
|
||||
action?.let { (icon, label) ->
|
||||
IconButton(onClick = { onClickItemAction(extension) }) {
|
||||
Icon(imageVector = icon, contentDescription = stringResource(label))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -5,7 +5,9 @@ import android.net.Uri
|
||||
import androidx.annotation.CallSuper
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.model.InstallStep
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import java.util.Collections
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
import kotlin.concurrent.atomics.AtomicReference
|
||||
@@ -107,10 +109,8 @@ abstract class Installer(private val service: Service) {
|
||||
open fun onDestroy() {
|
||||
cancelListeners -= cancelListener
|
||||
queue.forEach {
|
||||
extensionManager.updateInstallStep(
|
||||
it.downloadId,
|
||||
InstallStep.Error("The installer stopped before it got to this one"),
|
||||
)
|
||||
logcat(LogPriority.INFO) { "The installer stopped before installing ${it.downloadId}" }
|
||||
extensionManager.updateInstallStep(it.downloadId, InstallStep.Error)
|
||||
}
|
||||
queue.clear()
|
||||
waitingInstall.store(null)
|
||||
|
||||
+14
-10
@@ -43,8 +43,10 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
|
||||
.sanitizeByFiltering(this)
|
||||
}
|
||||
if (userAction == null) {
|
||||
logcat(LogPriority.ERROR) { "Fatal error for $intent" }
|
||||
continueQueue(InstallStep.Error("The system installer asked for an action it didn't provide"))
|
||||
logcat(LogPriority.INFO) {
|
||||
"The system installer asked for an action it didn't provide: $intent"
|
||||
}
|
||||
continueQueue(InstallStep.Error)
|
||||
return
|
||||
}
|
||||
userAction.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
@@ -54,12 +56,14 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
|
||||
continueQueue(InstallStep.Idle)
|
||||
}
|
||||
PackageInstaller.STATUS_SUCCESS -> continueQueue(InstallStep.Installed)
|
||||
else -> continueQueue(
|
||||
InstallStep.Error(
|
||||
intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)
|
||||
?: "The system installer failed ($status)",
|
||||
),
|
||||
)
|
||||
else -> {
|
||||
logcat(LogPriority.INFO) {
|
||||
"The system installer failed ($status): ${intent.getStringExtra(
|
||||
PackageInstaller.EXTRA_STATUS_MESSAGE,
|
||||
)}"
|
||||
}
|
||||
continueQueue(InstallStep.Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,11 +105,11 @@ class PackageInstallerInstaller(private val service: Service) : Installer(servic
|
||||
session.commit(intentSender)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
|
||||
logcat(LogPriority.INFO, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
|
||||
activeSession?.let { (_, sessionId) ->
|
||||
packageInstaller.abandonSession(sessionId)
|
||||
}
|
||||
continueQueue(InstallStep.Error.from(e))
|
||||
continueQueue(InstallStep.Error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,8 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
|
||||
if (status == PackageInstaller.STATUS_SUCCESS) {
|
||||
continueQueue(InstallStep.Installed)
|
||||
} else {
|
||||
logcat(LogPriority.ERROR) { "Failed to install extension $packageName: $message" }
|
||||
continueQueue(InstallStep.Error(message ?: "Shizuku failed to install it ($status)"))
|
||||
logcat(LogPriority.INFO) { "Shizuku failed to install $packageName ($status): $message" }
|
||||
continueQueue(InstallStep.Error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,8 +123,8 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
|
||||
}
|
||||
service.contentResolver.delete(entry.uri, null, null)
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
|
||||
continueQueue(InstallStep.Error.from(e))
|
||||
logcat(LogPriority.INFO, e) { "Failed to install extension ${entry.downloadId} ${entry.uri}" }
|
||||
continueQueue(InstallStep.Error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,23 +6,9 @@ sealed interface InstallStep {
|
||||
data object Downloading : InstallStep
|
||||
data object Installing : InstallStep
|
||||
data object Installed : InstallStep
|
||||
|
||||
/**
|
||||
* [message] says what went wrong; [stackTrace] is there when an exception did.
|
||||
*/
|
||||
data class Error(val message: String, val stackTrace: String? = null) : InstallStep {
|
||||
companion object {
|
||||
fun from(e: Throwable): Error {
|
||||
val root = generateSequence(e) { it.cause }.last()
|
||||
return Error(
|
||||
message = root.message ?: root::class.simpleName.orEmpty(),
|
||||
stackTrace = e.stackTraceToString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
data object Error : InstallStep
|
||||
|
||||
fun isCompleted(): Boolean {
|
||||
return this == Installed || this is Error || this == Idle
|
||||
return this == Installed || this == Error || this == Idle
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.model.InstallStep
|
||||
import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import logcat.LogPriority
|
||||
import mihon.app.di.appGraph
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
@@ -77,7 +79,10 @@ class ExtensionInstallActivity : Activity() {
|
||||
val newStep = when (resultCode) {
|
||||
RESULT_OK -> InstallStep.Installed
|
||||
RESULT_CANCELED -> InstallStep.Idle
|
||||
else -> InstallStep.Error("The installer reported a failure")
|
||||
else -> {
|
||||
logcat(LogPriority.INFO) { "The installer reported a failure ($resultCode)" }
|
||||
InstallStep.Error
|
||||
}
|
||||
}
|
||||
extensionManager.updateInstallStep(downloadId, newStep)
|
||||
}
|
||||
|
||||
@@ -93,8 +93,8 @@ class ExtensionInstaller(
|
||||
if (e is InterruptedException) {
|
||||
// Canceled
|
||||
} else {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
step.value = InstallStep.Error.from(e)
|
||||
logcat(LogPriority.INFO, e)
|
||||
step.value = InstallStep.Error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,8 +158,8 @@ class ExtensionInstaller(
|
||||
ExtensionLoader.installPrivateExtensionFile(context, tempFile, packageInfo)
|
||||
updateInstallStep(downloadId, InstallStep.Installed)
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e) { "Failed to install extension privately" }
|
||||
updateInstallStep(downloadId, InstallStep.Error.from(e))
|
||||
logcat(LogPriority.INFO, e) { "Failed to install extension privately" }
|
||||
updateInstallStep(downloadId, InstallStep.Error)
|
||||
}
|
||||
|
||||
tempFile.delete()
|
||||
|
||||
@@ -347,8 +347,6 @@
|
||||
<string name="ext_filtered">Filtered</string>
|
||||
<string name="ext_not_loaded">Not loaded</string>
|
||||
<string name="ext_not_loaded_dialog">Couldn\'t load</string>
|
||||
<string name="ext_install_error">Couldn\'t install</string>
|
||||
<string name="ext_install_error_details">Why it failed</string>
|
||||
<string name="ext_not_loaded_details">Why it isn\'t loaded</string>
|
||||
<string name="ext_copy_stacktrace">Copy stack trace</string>
|
||||
<string name="ext_filtered_message">This extension\'s content warning isn\'t one you chose to load, so its sources aren\'t available.</string>
|
||||
|
||||
Reference in New Issue
Block a user