diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt
index 1c67f360..9a9573a5 100644
--- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt
+++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleInformationDialog.kt
@@ -1,21 +1,30 @@
package app.revanced.manager.ui.component.bundle
+import android.content.Intent
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
+import androidx.compose.material.icons.automirrored.outlined.ArrowRight
import androidx.compose.material.icons.outlined.DeleteOutline
+import androidx.compose.material.icons.outlined.Share
import androidx.compose.material.icons.outlined.Update
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
@@ -26,7 +35,7 @@ import app.revanced.manager.domain.bundles.PatchBundleSource
import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.asRemoteOrNull
import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.isDefault
import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState
-import kotlinx.coroutines.flow.map
+import app.revanced.manager.ui.component.ColumnWithScrollbar
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@@ -35,17 +44,18 @@ fun BundleInformationDialog(
onDismissRequest: () -> Unit,
onDeleteRequest: () -> Unit,
bundle: PatchBundleSource,
- onRefreshButton: () -> Unit,
+ onUpdate: () -> Unit,
) {
val composableScope = rememberCoroutineScope()
var viewCurrentBundlePatches by remember { mutableStateOf(false) }
val isLocal = bundle is LocalPatchBundle
- val patchCount by remember(bundle) {
- bundle.state.map { it.patchBundleOrNull()?.patches?.size ?: 0 }
- }.collectAsStateWithLifecycle(0)
+ val state by bundle.state.collectAsStateWithLifecycle()
val props by remember(bundle) {
bundle.propsFlow()
}.collectAsStateWithLifecycle(null)
+ val patchCount = remember(state) {
+ state.patchBundleOrNull()?.patches?.size ?: 0
+ }
if (viewCurrentBundlePatches) {
BundlePatchesDialog(
@@ -70,7 +80,7 @@ fun BundleInformationDialog(
BundleTopBar(
title = bundleName,
onBackClick = onDismissRequest,
- onBackIcon = {
+ backIcon = {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back)
@@ -86,7 +96,7 @@ fun BundleInformationDialog(
}
}
if (!isLocal) {
- IconButton(onClick = onRefreshButton) {
+ IconButton(onClick = onUpdate) {
Icon(
Icons.Outlined.Update,
stringResource(R.string.refresh)
@@ -114,7 +124,95 @@ fun BundleInformationDialog(
onPatchesClick = {
viewCurrentBundlePatches = true
},
+ extraFields = {
+ (state as? PatchBundleSource.State.Failed)?.throwable?.let {
+ var showDialog by rememberSaveable {
+ mutableStateOf(false)
+ }
+ if (showDialog) BundleErrorViewerDialog(
+ onDismiss = { showDialog = false },
+ text = remember(it) { it.stackTraceToString() }
+ )
+
+ BundleListItem(
+ headlineText = stringResource(R.string.bundle_error),
+ supportingText = stringResource(R.string.bundle_error_description),
+ trailingContent = {
+ Icon(
+ Icons.AutoMirrored.Outlined.ArrowRight,
+ null
+ )
+ },
+ modifier = Modifier.clickable { showDialog = true }
+ )
+ }
+
+ if (state is PatchBundleSource.State.Missing && !isLocal) {
+ BundleListItem(
+ headlineText = stringResource(R.string.bundle_error),
+ supportingText = stringResource(R.string.bundle_not_downloaded),
+ modifier = Modifier.clickable(onClick = onUpdate)
+ )
+ }
+ }
)
}
}
}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+private fun BundleErrorViewerDialog(onDismiss: () -> Unit, text: String) {
+ val context = LocalContext.current
+
+ Dialog(
+ onDismissRequest = onDismiss,
+ properties = DialogProperties(
+ usePlatformDefaultWidth = false,
+ dismissOnBackPress = true
+ )
+ ) {
+ Scaffold(
+ topBar = {
+ BundleTopBar(
+ title = stringResource(R.string.bundle_error),
+ onBackClick = onDismiss,
+ backIcon = {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+ contentDescription = stringResource(R.string.back)
+ )
+ },
+ actions = {
+ IconButton(
+ onClick = {
+ val sendIntent: Intent = Intent().apply {
+ action = Intent.ACTION_SEND
+ putExtra(
+ Intent.EXTRA_TEXT,
+ text
+ )
+ type = "text/plain"
+ }
+
+ val shareIntent = Intent.createChooser(sendIntent, null)
+ context.startActivity(shareIntent)
+ }
+ ) {
+ Icon(
+ Icons.Outlined.Share,
+ contentDescription = stringResource(R.string.share)
+ )
+ }
+ }
+ )
+ }
+ ) { paddingValues ->
+ ColumnWithScrollbar(
+ modifier = Modifier.padding(paddingValues)
+ ) {
+ Text(text, modifier = Modifier.horizontalScroll(rememberScrollState()))
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt
index 31f4fef6..617c384f 100644
--- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt
+++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleItem.kt
@@ -57,7 +57,7 @@ fun BundleItem(
onDelete()
},
bundle = bundle,
- onRefreshButton = onUpdate,
+ onUpdate = onUpdate,
)
}
diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt
index df2e8e67..a4fbce81 100644
--- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt
+++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt
@@ -50,7 +50,7 @@ fun BundlePatchesDialog(
BundleTopBar(
title = stringResource(R.string.bundle_patches),
onBackClick = onDismissRequest,
- onBackIcon = {
+ backIcon = {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back)
diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleTopBar.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleTopBar.kt
index 7f98f014..543d2d34 100644
--- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleTopBar.kt
+++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundleTopBar.kt
@@ -19,7 +19,7 @@ fun BundleTopBar(
onBackClick: (() -> Unit)? = null,
actions: @Composable (RowScope.() -> Unit) = {},
scrollBehavior: TopAppBarScrollBehavior? = null,
- onBackIcon: @Composable () -> Unit,
+ backIcon: @Composable () -> Unit,
) {
val containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
@@ -34,7 +34,7 @@ fun BundleTopBar(
navigationIcon = {
if (onBackClick != null) {
IconButton(onClick = onBackClick) {
- onBackIcon()
+ backIcon()
}
}
},
diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt
index 481056df..cb23a36a 100644
--- a/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt
+++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/ImportBundleDialog.kt
@@ -81,7 +81,7 @@ fun ImportBundleDialog(
BundleTopBar(
title = stringResource(R.string.import_bundle),
onBackClick = onDismissRequest,
- onBackIcon = {
+ backIcon = {
Icon(
imageVector = Icons.Default.Close,
contentDescription = stringResource(R.string.close)
diff --git a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt
index 59ed6f4e..5f5ff1fa 100644
--- a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt
+++ b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt
@@ -131,7 +131,7 @@ fun DashboardScreen(
BundleTopBar(
title = stringResource(R.string.bundles_selected, vm.selectedSources.size),
onBackClick = vm::cancelSourceSelection,
- onBackIcon = {
+ backIcon = {
Icon(
imageVector = Icons.Default.Close,
contentDescription = stringResource(R.string.back)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 41bdfa16..95ca818b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -25,6 +25,8 @@
Missing
Error
+ Bundle could not be loaded. Click to view the error
+ Bundle has not been downloaded. Click here to download it
Default
Unnamed
@@ -121,6 +123,7 @@
Edit
Value
Reset
+ Share
Patch
Select from storage
Select an APK file from storage using file picker