fix: display plugins + settings screens properly

This commit is contained in:
rushiiMachine 2024-01-24 12:29:50 -08:00
parent 9635e4aaee
commit f314283b8e
No known key found for this signature in database
GPG key ID: DCBE5952BB3B6420
5 changed files with 221 additions and 184 deletions

View file

@ -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)
)
}
} }
) )
} }

View file

@ -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)

View file

@ -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))
}
} }
} }
} }

View file

@ -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
)
}
} }
} }
} }

View file

@ -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