fix: display plugins + settings screens properly
This commit is contained in:
parent
9635e4aaee
commit
f314283b8e
5 changed files with 221 additions and 184 deletions
|
|
@ -26,6 +26,8 @@ import com.aliucord.manager.ui.components.dialogs.InstallerDialog
|
||||||
import com.aliucord.manager.ui.components.home.InfoCard
|
import com.aliucord.manager.ui.components.home.InfoCard
|
||||||
import com.aliucord.manager.ui.screens.about.AboutScreen
|
import com.aliucord.manager.ui.screens.about.AboutScreen
|
||||||
import com.aliucord.manager.ui.screens.install.InstallScreen
|
import com.aliucord.manager.ui.screens.install.InstallScreen
|
||||||
|
import com.aliucord.manager.ui.screens.plugins.PluginsScreen
|
||||||
|
import com.aliucord.manager.ui.screens.settings.SettingsScreen
|
||||||
|
|
||||||
class HomeScreen : Screen {
|
class HomeScreen : Screen {
|
||||||
override val key = "Home"
|
override val key = "Home"
|
||||||
|
|
@ -51,8 +53,6 @@ class HomeScreen : Screen {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add a way to open plugins and settings
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { HomeAppBar() },
|
topBar = { HomeAppBar() },
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
|
@ -102,6 +102,20 @@ private fun HomeAppBar() {
|
||||||
contentDescription = stringResource(R.string.navigation_about)
|
contentDescription = stringResource(R.string.navigation_about)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IconButton(onClick = { navigator.push(PluginsScreen()) }) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_extension),
|
||||||
|
contentDescription = stringResource(R.string.navigation_about)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(onClick = { navigator.push(SettingsScreen()) }) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_settings),
|
||||||
|
contentDescription = stringResource(R.string.navigation_settings)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ class InstallModel(
|
||||||
|
|
||||||
fun copyDebugToClipboard() {
|
fun copyDebugToClipboard() {
|
||||||
val text = "$debugInfo\n\n$stacktrace"
|
val text = "$debugInfo\n\n$stacktrace"
|
||||||
|
// TODO: remove this useless replace
|
||||||
.replace("(\\\\*~_)".toRegex(), "\\$1")
|
.replace("(\\\\*~_)".toRegex(), "\\$1")
|
||||||
|
|
||||||
application.copyToClipboard(text)
|
application.copyToClipboard(text)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.koin.getScreenModel
|
import cafe.adriel.voyager.koin.getScreenModel
|
||||||
import com.aliucord.manager.R
|
import com.aliucord.manager.R
|
||||||
|
import com.aliucord.manager.ui.components.BackButton
|
||||||
import com.aliucord.manager.ui.components.plugins.Changelog
|
import com.aliucord.manager.ui.components.plugins.Changelog
|
||||||
import com.aliucord.manager.ui.components.plugins.PluginCard
|
import com.aliucord.manager.ui.components.plugins.PluginCard
|
||||||
|
|
||||||
|
|
@ -52,75 +53,85 @@ class PluginsScreen : Screen {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
Scaffold(
|
||||||
modifier = Modifier
|
topBar = {
|
||||||
.fillMaxSize()
|
TopAppBar(
|
||||||
.padding(horizontal = 16.dp),
|
title = { Text(stringResource(R.string.plugins_title)) },
|
||||||
verticalArrangement = Arrangement.spacedBy(14.dp)
|
navigationIcon = { BackButton() },
|
||||||
) {
|
)
|
||||||
PluginSearch(
|
}
|
||||||
currentFilter = model.search,
|
) { paddingValues ->
|
||||||
onFilterChange = model::search,
|
Column(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
)
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(14.dp)
|
||||||
|
) {
|
||||||
|
PluginSearch(
|
||||||
|
currentFilter = model.search,
|
||||||
|
onFilterChange = model::search,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
|
||||||
if (model.error) {
|
if (model.error) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Column(
|
||||||
imageVector = Icons.Default.Warning,
|
modifier = Modifier.align(Alignment.Center),
|
||||||
contentDescription = null,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
tint = MaterialTheme.colorScheme.error,
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
)
|
) {
|
||||||
Text(
|
Icon(
|
||||||
text = stringResource(R.string.plugins_error),
|
imageVector = Icons.Default.Warning,
|
||||||
color = MaterialTheme.colorScheme.error,
|
contentDescription = null,
|
||||||
)
|
tint = MaterialTheme.colorScheme.error,
|
||||||
}
|
)
|
||||||
}
|
Text(
|
||||||
} else if (model.plugins.isNotEmpty()) {
|
text = stringResource(R.string.plugins_error),
|
||||||
LazyColumn(
|
color = MaterialTheme.colorScheme.error,
|
||||||
contentPadding = PaddingValues(bottom = 15.dp, top = 6.dp),
|
)
|
||||||
verticalArrangement = Arrangement.spacedBy(14.dp)
|
|
||||||
) {
|
|
||||||
items(
|
|
||||||
// TODO: remember {} this
|
|
||||||
model.plugins.filter { plugin ->
|
|
||||||
plugin.manifest.run {
|
|
||||||
name.contains(model.search, true)
|
|
||||||
|| description.contains(model.search, true)
|
|
||||||
|| authors.any { (name) -> name.contains(model.search, true) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
) { plugin ->
|
|
||||||
PluginCard(
|
|
||||||
plugin = plugin,
|
|
||||||
enabled = model.enabled[plugin.manifest.name] ?: true,
|
|
||||||
onClickDelete = { model.showUninstallDialog(plugin) },
|
|
||||||
onClickShowChangelog = { model.showChangelogDialog(plugin) },
|
|
||||||
onSetEnabled = { model.setPluginEnabled(plugin.manifest.name, it) }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
} else if (model.plugins.isNotEmpty()) {
|
||||||
} else {
|
LazyColumn(
|
||||||
Box(
|
contentPadding = PaddingValues(bottom = 15.dp, top = 6.dp),
|
||||||
modifier = Modifier.fillMaxSize()
|
verticalArrangement = Arrangement.spacedBy(14.dp)
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
items(
|
||||||
painter = painterResource(R.drawable.ic_extension_off),
|
// TODO: remember {} this
|
||||||
contentDescription = null
|
model.plugins.filter { plugin ->
|
||||||
)
|
plugin.manifest.run {
|
||||||
Text(stringResource(R.string.plugins_none_installed))
|
name.contains(model.search, true)
|
||||||
|
|| description.contains(model.search, true)
|
||||||
|
|| authors.any { (name) -> name.contains(model.search, true) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) { plugin ->
|
||||||
|
PluginCard(
|
||||||
|
plugin = plugin,
|
||||||
|
enabled = model.enabled[plugin.manifest.name] ?: true,
|
||||||
|
onClickDelete = { model.showUninstallDialog(plugin) },
|
||||||
|
onClickShowChangelog = { model.showChangelogDialog(plugin) },
|
||||||
|
onSetEnabled = { model.setPluginEnabled(plugin.manifest.name, it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_extension_off),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
Text(stringResource(R.string.plugins_none_installed))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.koin.getScreenModel
|
import cafe.adriel.voyager.koin.getScreenModel
|
||||||
import com.aliucord.manager.R
|
import com.aliucord.manager.R
|
||||||
|
import com.aliucord.manager.ui.components.BackButton
|
||||||
import com.aliucord.manager.ui.components.Theme
|
import com.aliucord.manager.ui.components.Theme
|
||||||
import com.aliucord.manager.ui.components.settings.*
|
import com.aliucord.manager.ui.components.settings.*
|
||||||
|
|
||||||
|
|
@ -30,126 +31,136 @@ class SettingsScreen : Screen {
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<SettingsModel>()
|
val model = getScreenModel<SettingsModel>()
|
||||||
|
|
||||||
Column(
|
Scaffold(
|
||||||
modifier = Modifier
|
topBar = {
|
||||||
.verticalScroll(state = rememberScrollState())
|
TopAppBar(
|
||||||
) {
|
title = { Text(stringResource(R.string.navigation_settings)) },
|
||||||
val preferences = model.preferences
|
navigationIcon = { BackButton() },
|
||||||
|
|
||||||
if (model.showThemeDialog) {
|
|
||||||
ThemeDialog(
|
|
||||||
currentTheme = preferences.theme,
|
|
||||||
onDismissRequest = model::hideThemeDialog,
|
|
||||||
onConfirm = model::setTheme
|
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
) { paddingValues ->
|
||||||
SettingsHeader(stringResource(R.string.settings_appearance))
|
Column(
|
||||||
|
|
||||||
SettingsItem(
|
|
||||||
modifier = Modifier.clickable(onClick = model::showThemeDialog),
|
|
||||||
icon = { Icon(painterResource(R.drawable.ic_brush), null) },
|
|
||||||
text = { Text(stringResource(R.string.settings_theme)) }
|
|
||||||
) {
|
|
||||||
FilledTonalButton(onClick = model::showThemeDialog) {
|
|
||||||
Text(preferences.theme.toDisplayName())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsSwitch(
|
|
||||||
label = stringResource(R.string.setting_dynamic_color),
|
|
||||||
pref = preferences.dynamicColor,
|
|
||||||
icon = { Icon(painterResource(R.drawable.ic_palette), null) }
|
|
||||||
) {
|
|
||||||
preferences.dynamicColor = it
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsHeader(stringResource(R.string.settings_advanced))
|
|
||||||
|
|
||||||
SettingsTextField(
|
|
||||||
label = stringResource(R.string.setting_app_name),
|
|
||||||
pref = preferences.appName,
|
|
||||||
onPrefChange = model::setAppName
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
|
|
||||||
SettingsSwitch(
|
|
||||||
label = stringResource(R.string.setting_replace_icon),
|
|
||||||
secondaryLabel = stringResource(R.string.setting_replace_icon_desc),
|
|
||||||
pref = preferences.replaceIcon,
|
|
||||||
icon = { Icon(painterResource(R.drawable.ic_app_shortcut), null) }
|
|
||||||
) {
|
|
||||||
preferences.replaceIcon = it
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsSwitch(
|
|
||||||
label = stringResource(R.string.setting_keep_patched_apks),
|
|
||||||
secondaryLabel = stringResource(R.string.setting_keep_patched_apks_desc),
|
|
||||||
icon = { Icon(painterResource(R.drawable.ic_delete_forever), null) },
|
|
||||||
pref = preferences.keepPatchedApks,
|
|
||||||
onPrefChange = { preferences.keepPatchedApks = it },
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(14.dp))
|
|
||||||
|
|
||||||
SettingsSwitch(
|
|
||||||
label = stringResource(R.string.settings_developer_options),
|
|
||||||
pref = preferences.devMode,
|
|
||||||
icon = { Icon(painterResource(R.drawable.ic_code), null) }
|
|
||||||
) {
|
|
||||||
preferences.devMode = it
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = preferences.devMode,
|
|
||||||
enter = expandVertically(),
|
|
||||||
exit = shrinkVertically()
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.spacedBy(6.dp)
|
|
||||||
) {
|
|
||||||
SettingsTextField(
|
|
||||||
label = stringResource(R.string.setting_package_name),
|
|
||||||
pref = preferences.packageName,
|
|
||||||
onPrefChange = model::setPackageName,
|
|
||||||
error = model.packageNameError
|
|
||||||
)
|
|
||||||
|
|
||||||
SettingsTextField(
|
|
||||||
label = stringResource(R.string.setting_target_version),
|
|
||||||
pref = preferences.version,
|
|
||||||
onPrefChange = model::setVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
SettingsSwitch(
|
|
||||||
label = stringResource(R.string.setting_debuggable),
|
|
||||||
secondaryLabel = stringResource(R.string.setting_debuggable_desc),
|
|
||||||
pref = preferences.debuggable,
|
|
||||||
icon = { Icon(painterResource(R.drawable.ic_bug), null) },
|
|
||||||
onPrefChange = { preferences.debuggable = it },
|
|
||||||
)
|
|
||||||
|
|
||||||
SettingsSwitch(
|
|
||||||
label = stringResource(R.string.setting_hermes_replace_libcpp),
|
|
||||||
secondaryLabel = stringResource(R.string.setting_hermes_replace_libcpp_desc),
|
|
||||||
icon = { Icon(painterResource(R.drawable.ic_copy_file), null) },
|
|
||||||
pref = preferences.hermesReplaceLibCpp,
|
|
||||||
onPrefChange = { preferences.hermesReplaceLibCpp = it },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.padding(paddingValues)
|
||||||
.padding(18.dp),
|
.verticalScroll(state = rememberScrollState())
|
||||||
shape = ShapeDefaults.Large,
|
|
||||||
onClick = model::clearCacheDir
|
|
||||||
) {
|
) {
|
||||||
Text(
|
val preferences = model.preferences
|
||||||
text = stringResource(R.string.setting_clear_cache),
|
|
||||||
textAlign = TextAlign.Center
|
if (model.showThemeDialog) {
|
||||||
|
ThemeDialog(
|
||||||
|
currentTheme = preferences.theme,
|
||||||
|
onDismissRequest = model::hideThemeDialog,
|
||||||
|
onConfirm = model::setTheme
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsHeader(stringResource(R.string.settings_appearance))
|
||||||
|
|
||||||
|
SettingsItem(
|
||||||
|
modifier = Modifier.clickable(onClick = model::showThemeDialog),
|
||||||
|
icon = { Icon(painterResource(R.drawable.ic_brush), null) },
|
||||||
|
text = { Text(stringResource(R.string.settings_theme)) }
|
||||||
|
) {
|
||||||
|
FilledTonalButton(onClick = model::showThemeDialog) {
|
||||||
|
Text(preferences.theme.toDisplayName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSwitch(
|
||||||
|
label = stringResource(R.string.setting_dynamic_color),
|
||||||
|
pref = preferences.dynamicColor,
|
||||||
|
icon = { Icon(painterResource(R.drawable.ic_palette), null) }
|
||||||
|
) {
|
||||||
|
preferences.dynamicColor = it
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsHeader(stringResource(R.string.settings_advanced))
|
||||||
|
|
||||||
|
SettingsTextField(
|
||||||
|
label = stringResource(R.string.setting_app_name),
|
||||||
|
pref = preferences.appName,
|
||||||
|
onPrefChange = model::setAppName
|
||||||
)
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
|
SettingsSwitch(
|
||||||
|
label = stringResource(R.string.setting_replace_icon),
|
||||||
|
secondaryLabel = stringResource(R.string.setting_replace_icon_desc),
|
||||||
|
pref = preferences.replaceIcon,
|
||||||
|
icon = { Icon(painterResource(R.drawable.ic_app_shortcut), null) }
|
||||||
|
) {
|
||||||
|
preferences.replaceIcon = it
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSwitch(
|
||||||
|
label = stringResource(R.string.setting_keep_patched_apks),
|
||||||
|
secondaryLabel = stringResource(R.string.setting_keep_patched_apks_desc),
|
||||||
|
icon = { Icon(painterResource(R.drawable.ic_delete_forever), null) },
|
||||||
|
pref = preferences.keepPatchedApks,
|
||||||
|
onPrefChange = { preferences.keepPatchedApks = it },
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(14.dp))
|
||||||
|
|
||||||
|
SettingsSwitch(
|
||||||
|
label = stringResource(R.string.settings_developer_options),
|
||||||
|
pref = preferences.devMode,
|
||||||
|
icon = { Icon(painterResource(R.drawable.ic_code), null) }
|
||||||
|
) {
|
||||||
|
preferences.devMode = it
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = preferences.devMode,
|
||||||
|
enter = expandVertically(),
|
||||||
|
exit = shrinkVertically()
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(6.dp)
|
||||||
|
) {
|
||||||
|
SettingsTextField(
|
||||||
|
label = stringResource(R.string.setting_package_name),
|
||||||
|
pref = preferences.packageName,
|
||||||
|
onPrefChange = model::setPackageName,
|
||||||
|
error = model.packageNameError
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingsTextField(
|
||||||
|
label = stringResource(R.string.setting_target_version),
|
||||||
|
pref = preferences.version,
|
||||||
|
onPrefChange = model::setVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingsSwitch(
|
||||||
|
label = stringResource(R.string.setting_debuggable),
|
||||||
|
secondaryLabel = stringResource(R.string.setting_debuggable_desc),
|
||||||
|
pref = preferences.debuggable,
|
||||||
|
icon = { Icon(painterResource(R.drawable.ic_bug), null) },
|
||||||
|
onPrefChange = { preferences.debuggable = it },
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingsSwitch(
|
||||||
|
label = stringResource(R.string.setting_hermes_replace_libcpp),
|
||||||
|
secondaryLabel = stringResource(R.string.setting_hermes_replace_libcpp_desc),
|
||||||
|
icon = { Icon(painterResource(R.drawable.ic_copy_file), null) },
|
||||||
|
pref = preferences.hermesReplaceLibCpp,
|
||||||
|
onPrefChange = { preferences.hermesReplaceLibCpp = it },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(18.dp),
|
||||||
|
shape = ShapeDefaults.Large,
|
||||||
|
onClick = model::clearCacheDir
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.setting_clear_cache),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.aliucord.manager.R
|
import com.aliucord.manager.R
|
||||||
import org.koin.androidx.compose.getViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UpdaterDialog(
|
fun UpdaterDialog(
|
||||||
viewModel: UpdaterViewModel = getViewModel(),
|
viewModel: UpdaterViewModel = koinViewModel(),
|
||||||
) {
|
) {
|
||||||
if (!viewModel.showDialog) return
|
if (!viewModel.showDialog) return
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue