mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-04-30 05:54:26 +02:00
feat: Improve patch bundle screen (#2070)
This commit is contained in:
parent
747017a5f9
commit
edb4e421e2
@ -2,37 +2,33 @@ package app.revanced.manager.ui.component.bundle
|
||||
|
||||
import android.webkit.URLUtil
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ArrowRight
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material.icons.outlined.Extension
|
||||
import androidx.compose.material.icons.outlined.Inventory2
|
||||
import androidx.compose.material.icons.outlined.Sell
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||
import app.revanced.manager.ui.component.TextInputDialog
|
||||
import app.revanced.manager.util.isDebuggable
|
||||
|
||||
@Composable
|
||||
fun BaseBundleDialog(
|
||||
modifier: Modifier = Modifier,
|
||||
isDefault: Boolean,
|
||||
name: String?,
|
||||
onNameChange: ((String) -> Unit)? = null,
|
||||
remoteUrl: String?,
|
||||
onRemoteUrlChange: ((String) -> Unit)? = null,
|
||||
patchCount: Int,
|
||||
@ -40,39 +36,66 @@ fun BaseBundleDialog(
|
||||
autoUpdate: Boolean,
|
||||
onAutoUpdateChange: (Boolean) -> Unit,
|
||||
onPatchesClick: () -> Unit,
|
||||
onBundleTypeClick: () -> Unit = {},
|
||||
extraFields: @Composable ColumnScope.() -> Unit = {}
|
||||
) {
|
||||
ColumnWithScrollbar(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.then(modifier)
|
||||
.then(modifier),
|
||||
) {
|
||||
if (name != null) {
|
||||
var showNameInputDialog by rememberSaveable {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
if (showNameInputDialog) {
|
||||
TextInputDialog(
|
||||
initial = name,
|
||||
title = stringResource(R.string.bundle_input_name),
|
||||
onDismissRequest = {
|
||||
showNameInputDialog = false
|
||||
},
|
||||
onConfirm = {
|
||||
showNameInputDialog = false
|
||||
onNameChange?.invoke(it)
|
||||
},
|
||||
validator = {
|
||||
it.length in 1..19
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.Start),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Inventory2,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
name?.let {
|
||||
Text(
|
||||
text = it,
|
||||
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight(800)),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 2.dp)
|
||||
) {
|
||||
version?.let {
|
||||
Tag(Icons.Outlined.Sell, it)
|
||||
}
|
||||
Tag(Icons.Outlined.Extension, patchCount.toString())
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
color = MaterialTheme.colorScheme.outlineVariant
|
||||
)
|
||||
|
||||
if (remoteUrl != null) {
|
||||
BundleListItem(
|
||||
headlineText = stringResource(R.string.bundle_input_name),
|
||||
supportingText = name.ifEmpty { stringResource(R.string.field_not_set) },
|
||||
modifier = Modifier.clickable(enabled = onNameChange != null) {
|
||||
showNameInputDialog = true
|
||||
headlineText = stringResource(R.string.bundle_auto_update),
|
||||
supportingText = stringResource(R.string.bundle_auto_update_description),
|
||||
trailingContent = {
|
||||
Switch(
|
||||
checked = autoUpdate,
|
||||
onCheckedChange = onAutoUpdateChange
|
||||
)
|
||||
},
|
||||
modifier = Modifier.clickable {
|
||||
onAutoUpdateChange(!autoUpdate)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -99,81 +122,59 @@ fun BaseBundleDialog(
|
||||
}
|
||||
|
||||
BundleListItem(
|
||||
modifier = Modifier.clickable(enabled = onRemoteUrlChange != null) {
|
||||
showUrlInputDialog = true
|
||||
},
|
||||
headlineText = stringResource(R.string.bundle_input_source_url),
|
||||
supportingText = url.ifEmpty { stringResource(R.string.field_not_set) }
|
||||
)
|
||||
}
|
||||
|
||||
extraFields()
|
||||
|
||||
if (remoteUrl != null) {
|
||||
BundleListItem(
|
||||
headlineText = stringResource(R.string.bundle_auto_update),
|
||||
supportingText = stringResource(R.string.bundle_auto_update_description),
|
||||
trailingContent = {
|
||||
Switch(
|
||||
checked = autoUpdate,
|
||||
onCheckedChange = onAutoUpdateChange
|
||||
)
|
||||
},
|
||||
modifier = Modifier.clickable {
|
||||
onAutoUpdateChange(!autoUpdate)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
BundleListItem(
|
||||
headlineText = stringResource(R.string.bundle_type),
|
||||
supportingText = stringResource(R.string.bundle_type_description),
|
||||
modifier = Modifier.clickable {
|
||||
onBundleTypeClick()
|
||||
}
|
||||
) {
|
||||
FilledTonalButton(
|
||||
onClick = onBundleTypeClick,
|
||||
content = {
|
||||
if (remoteUrl == null) {
|
||||
Text(stringResource(R.string.local))
|
||||
} else {
|
||||
Text(stringResource(R.string.remote))
|
||||
modifier = Modifier.clickable(
|
||||
enabled = onRemoteUrlChange != null,
|
||||
onClick = {
|
||||
showUrlInputDialog = true
|
||||
}
|
||||
),
|
||||
headlineText = stringResource(R.string.bundle_input_source_url),
|
||||
supportingText = url.ifEmpty {
|
||||
stringResource(R.string.field_not_set)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (version != null || patchCount > 0) {
|
||||
Text(
|
||||
text = stringResource(R.string.information),
|
||||
modifier = Modifier.padding(
|
||||
horizontal = 16.dp,
|
||||
vertical = 12.dp
|
||||
),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
||||
val patchesClickable = LocalContext.current.isDebuggable && patchCount > 0
|
||||
val patchesClickable = patchCount > 0
|
||||
BundleListItem(
|
||||
headlineText = stringResource(R.string.patches),
|
||||
supportingText = pluralStringResource(R.plurals.bundle_patches_available, patchCount, patchCount),
|
||||
modifier = Modifier.clickable(enabled = patchesClickable, onClick = onPatchesClick)
|
||||
supportingText = stringResource(R.string.bundle_view_patches),
|
||||
modifier = Modifier.clickable(
|
||||
enabled = patchesClickable,
|
||||
onClick = onPatchesClick
|
||||
)
|
||||
) {
|
||||
if (patchesClickable)
|
||||
if (patchesClickable) {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Outlined.ArrowRight,
|
||||
stringResource(R.string.patches)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
version?.let {
|
||||
BundleListItem(
|
||||
headlineText = stringResource(R.string.version),
|
||||
supportingText = it,
|
||||
)
|
||||
}
|
||||
extraFields()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Tag(
|
||||
icon: ImageVector,
|
||||
text: String
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = MaterialTheme.colorScheme.outline,
|
||||
)
|
||||
Text(
|
||||
text,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
)
|
||||
}
|
||||
}
|
@ -11,18 +11,9 @@ 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.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
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
|
||||
@ -78,7 +69,7 @@ fun BundleInformationDialog(
|
||||
Scaffold(
|
||||
topBar = {
|
||||
BundleTopBar(
|
||||
title = bundleName,
|
||||
title = stringResource(R.string.patch_bundle_field),
|
||||
onBackClick = onDismissRequest,
|
||||
backIcon = {
|
||||
Icon(
|
||||
@ -111,7 +102,6 @@ fun BundleInformationDialog(
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
isDefault = bundle.isDefault,
|
||||
name = bundleName,
|
||||
onNameChange = { composableScope.launch { bundle.setName(it) } },
|
||||
remoteUrl = bundle.asRemoteOrNull?.endpoint,
|
||||
patchCount = patchCount,
|
||||
version = props?.versionInfo?.patches,
|
||||
|
@ -11,8 +11,4 @@
|
||||
<plurals name="selected_count">
|
||||
<item quantity="other">%d selected</item>
|
||||
</plurals>
|
||||
<plurals name="bundle_patches_available">
|
||||
<item quantity="one">%d patch available</item>
|
||||
<item quantity="other">%d patches available</item>
|
||||
</plurals>
|
||||
</resources>
|
@ -145,7 +145,6 @@
|
||||
<string name="close">Close</string>
|
||||
<string name="system">System</string>
|
||||
<string name="light">Light</string>
|
||||
<string name="information">Information</string>
|
||||
<string name="dark">Dark</string>
|
||||
<string name="appearance">Appearance</string>
|
||||
<string name="downloaded_apps">Downloaded apps</string>
|
||||
@ -181,8 +180,6 @@
|
||||
<string name="tab_bundles">Patch bundles</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="refresh">Refresh</string>
|
||||
<string name="remote">Remote</string>
|
||||
<string name="local">Local</string>
|
||||
<string name="continue_anyways">Continue anyways</string>
|
||||
<string name="download_another_version">Download another version</string>
|
||||
<string name="download_app">Download app</string>
|
||||
@ -302,14 +299,12 @@
|
||||
<string name="submit_feedback_description">Help us improve this application</string>
|
||||
<string name="developer_options">Developer options</string>
|
||||
<string name="developer_options_description">Options for debugging issues</string>
|
||||
<string name="bundle_input_name">Name</string>
|
||||
<string name="bundle_input_source_url">Source URL</string>
|
||||
<string name="bundle_update_success">Successfully updated %s</string>
|
||||
<string name="bundle_update_unavailable">No update available for %s</string>
|
||||
<string name="bundle_auto_update">Auto update</string>
|
||||
<string name="bundle_auto_update_description">Automatically update this bundle when ReVanced starts</string>
|
||||
<string name="bundle_type">Bundle type</string>
|
||||
<string name="bundle_type_description">Choose the type of bundle you want</string>
|
||||
<string name="bundle_view_patches">View patches</string>
|
||||
<string name="about_revanced_manager">About ReVanced Manager</string>
|
||||
<string name="revanced_manager_description">ReVanced Manager is an application designed to work with ReVanced Patcher, which allows for long-lasting patches to be created for Android apps. The patching system is designed to automatically work with new versions of apps with minimal maintenance.</string>
|
||||
<string name="update_available">An update is available</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user