Skip to content

Commit

Permalink
feat: improve bundle dialog UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Axelen123 committed Aug 4, 2023
1 parent 379ce91 commit 1707a96
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 123 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package app.revanced.manager.ui.component

import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R

@Composable
fun TextInputDialog(
initial: String,
title: String,
onDismissRequest: () -> Unit,
onConfirm: (String) -> Unit,
validator: (String) -> Boolean = String::isNotEmpty,
) {
val (value, setValue) = rememberSaveable(initial) {
mutableStateOf(initial)
}
val valid = remember(value, validator) {
validator(value)
}

AlertDialog(
onDismissRequest = onDismissRequest,
confirmButton = {
TextButton(
onClick = { onConfirm(value) },
enabled = valid
) {
Text(stringResource(R.string.ok))
}
},
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(stringResource(R.string.cancel))
}
},
title = {
Text(title)
},
text = {
TextField(value = value, onValueChange = setValue)
}
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package app.revanced.manager.ui.component.bundle

import android.webkit.URLUtil
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
Expand All @@ -12,23 +14,27 @@ import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
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.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.ui.component.TextInputDialog

@Composable
fun BaseBundleDialog(
modifier: Modifier = Modifier,
isDefault: Boolean,
name: String,
onNameChange: (String) -> Unit = {},
onNameChange: ((String) -> Unit)? = null,
remoteUrl: String?,
onRemoteUrlChange: (String) -> Unit = {},
onRemoteUrlChange: ((String) -> Unit)? = null,
patchCount: Int,
version: String?,
autoUpdate: Boolean,
Expand All @@ -40,79 +46,108 @@ fun BaseBundleDialog(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
.padding(
start = 8.dp,
top = 8.dp,
end = 4.dp,
)
.then(modifier)
) {
Column(
modifier = Modifier.padding(
start = 24.dp,
top = 16.dp,
end = 24.dp,
)
) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp),
value = name,
onValueChange = onNameChange,
label = {
Text(stringResource(R.string.bundle_input_name))
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
}
)
remoteUrl?.takeUnless { isDefault }?.let {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp),
value = it,
onValueChange = onRemoteUrlChange,
label = {
Text(stringResource(R.string.bundle_input_source_url))
}
)
}
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
}
)

extraFields()
}
remoteUrl?.takeUnless { isDefault }?.let { url ->
var showUrlInputDialog by rememberSaveable {
mutableStateOf(false)
}
if (showUrlInputDialog) {
TextInputDialog(
initial = url,
title = stringResource(R.string.bundle_input_source_url),
onDismissRequest = { showUrlInputDialog = false },
onConfirm = {
showUrlInputDialog = false
onRemoteUrlChange?.invoke(it)
},
validator = {
if (it.isEmpty()) return@TextInputDialog false

Column(
Modifier.padding(
start = 8.dp,
top = 8.dp,
end = 4.dp,
)
) Info@{
if (remoteUrl != null) {
BundleListItem(
headlineText = stringResource(R.string.automatically_update),
supportingText = stringResource(R.string.automatically_update_description),
trailingContent = {
Switch(
checked = autoUpdate,
onCheckedChange = onAutoUpdateChange
)
URLUtil.isValidUrl(it)
}
)
}

BundleListItem(
headlineText = stringResource(R.string.bundle_type),
supportingText = stringResource(R.string.bundle_type_description)
) {
FilledTonalButton(
onClick = onBundleTypeClick,
content = {
if (remoteUrl == null) {
Text(stringResource(R.string.local))
} else {
Text(stringResource(R.string.remote))
}
}
)
}
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) }
)
}

if (version == null && patchCount < 1) return@Info
extraFields()

if (remoteUrl != null) {
BundleListItem(
headlineText = stringResource(R.string.automatically_update),
supportingText = stringResource(R.string.automatically_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))
}
}
)
}

if (version != null || patchCount > 0) {
Text(
text = stringResource(R.string.information),
modifier = Modifier.padding(
Expand All @@ -122,7 +157,9 @@ fun BaseBundleDialog(
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary,
)
}

if (patchCount > 0) {
BundleListItem(
headlineText = stringResource(R.string.patches),
supportingText = if (patchCount == 0) stringResource(R.string.no_patches)
Expand All @@ -138,12 +175,12 @@ fun BaseBundleDialog(
}
}
)
}

if (version == null) return@Info

version?.let {
BundleListItem(
headlineText = stringResource(R.string.version),
supportingText = version,
supportingText = it,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fun BundleInformationDialog(
Scaffold(
topBar = {
BundleTopBar(
title = stringResource(R.string.bundle_information),
title = bundle.name,
onBackClick = onDismissRequest,
onBackIcon = {
Icon(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier

@Composable
fun BundleListItem(
modifier: Modifier = Modifier,
headlineText: String,
supportingText: String = "",
trailingContent: @Composable (() -> Unit)? = null,
Expand All @@ -26,5 +28,6 @@ fun BundleListItem(
)
},
trailingContent = trailingContent,
modifier = modifier
)
}
Loading

0 comments on commit 1707a96

Please sign in to comment.