0
0
mirror of https://github.com/florisboard/florisboard.git synced 2024-09-20 03:52:18 +02:00

Add barebones implementation for addons screen

This commit is contained in:
Patrick Goldinger 2024-06-03 15:55:59 +02:00
parent e520a9c335
commit f1d60d9958
No known key found for this signature in database
8 changed files with 301 additions and 203 deletions

View File

@ -27,8 +27,11 @@ import dev.patrickgold.florisboard.app.devtools.DevtoolsScreen
import dev.patrickgold.florisboard.app.devtools.ExportDebugLogScreen import dev.patrickgold.florisboard.app.devtools.ExportDebugLogScreen
import dev.patrickgold.florisboard.app.ext.ExtensionEditScreen import dev.patrickgold.florisboard.app.ext.ExtensionEditScreen
import dev.patrickgold.florisboard.app.ext.ExtensionExportScreen import dev.patrickgold.florisboard.app.ext.ExtensionExportScreen
import dev.patrickgold.florisboard.app.ext.ExtensionHomeScreen
import dev.patrickgold.florisboard.app.ext.ExtensionImportScreen import dev.patrickgold.florisboard.app.ext.ExtensionImportScreen
import dev.patrickgold.florisboard.app.ext.ExtensionImportScreenType import dev.patrickgold.florisboard.app.ext.ExtensionImportScreenType
import dev.patrickgold.florisboard.app.ext.ExtensionListScreen
import dev.patrickgold.florisboard.app.ext.ExtensionListScreenType
import dev.patrickgold.florisboard.app.ext.ExtensionViewScreen import dev.patrickgold.florisboard.app.ext.ExtensionViewScreen
import dev.patrickgold.florisboard.app.settings.HomeScreen import dev.patrickgold.florisboard.app.settings.HomeScreen
import dev.patrickgold.florisboard.app.settings.about.AboutScreen import dev.patrickgold.florisboard.app.settings.about.AboutScreen
@ -58,7 +61,7 @@ import dev.patrickgold.florisboard.app.settings.typing.TypingScreen
import dev.patrickgold.florisboard.app.setup.SetupScreen import dev.patrickgold.florisboard.app.setup.SetupScreen
import org.florisboard.lib.kotlin.curlyFormat import org.florisboard.lib.kotlin.curlyFormat
@Suppress("FunctionName") @Suppress("FunctionName", "ConstPropertyName")
object Routes { object Routes {
object Setup { object Setup {
const val Screen = "setup" const val Screen = "setup"
@ -117,6 +120,13 @@ object Routes {
} }
object Ext { object Ext {
const val Home = "ext"
const val List = "ext/list/{type}"
fun List(
type: ExtensionListScreenType,
) = List.curlyFormat("type" to type.id)
const val Edit = "ext/edit/{id}?create={serial_type}" const val Edit = "ext/edit/{id}?create={serial_type}"
fun Edit(id: String, serialType: String? = null): String { fun Edit(id: String, serialType: String? = null): String {
return Edit.curlyFormat("id" to id, "serial_type" to (serialType ?: "")) return Edit.curlyFormat("id" to id, "serial_type" to (serialType ?: ""))
@ -209,12 +219,19 @@ object Routes {
} }
composable(Devtools.ExportDebugLog) { ExportDebugLogScreen() } composable(Devtools.ExportDebugLog) { ExportDebugLogScreen() }
composable(Ext.Home) { ExtensionHomeScreen() }
composable(Ext.List) { navBackStack ->
val type = navBackStack.arguments?.getString("type")?.let { typeId ->
ExtensionListScreenType.entries.firstOrNull { it.id == typeId }
} ?: error("unknown type")
ExtensionListScreen(type)
}
composable(Ext.Edit) { navBackStack -> composable(Ext.Edit) { navBackStack ->
val extensionId = navBackStack.arguments?.getString("id") val extensionId = navBackStack.arguments?.getString("id")
val serialType = navBackStack.arguments?.getString("serial_type") val serialType = navBackStack.arguments?.getString("serial_type")
ExtensionEditScreen( ExtensionEditScreen(
id = extensionId.toString(), id = extensionId.toString(),
createSerialType = serialType.takeIf { it != null && it.isNotBlank() }, createSerialType = serialType.takeIf { !it.isNullOrBlank() },
) )
} }
composable(Ext.Export) { navBackStack -> composable(Ext.Export) { navBackStack ->

View File

@ -0,0 +1,129 @@
package dev.patrickgold.florisboard.app.ext
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Input
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Language
import androidx.compose.material.icons.filled.Palette
import androidx.compose.material.icons.filled.Shop
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.lib.android.launchUrl
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
import dev.patrickgold.florisboard.lib.compose.FlorisTextButton
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.stringRes
import dev.patrickgold.jetpref.datastore.ui.Preference
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
import org.florisboard.lib.kotlin.curlyFormat
@Composable
fun ExtensionHomeScreen() = FlorisScreen {
title = stringRes(R.string.ext__home__title)
previewFieldVisible = false
val context = LocalContext.current
val navController = LocalNavController.current
content {
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
) {
Text(
modifier = Modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 4.dp),
text = "You can download and install extensions from the FlorisBoard Addons Store or import any extension file you have downloaded from the internet.",
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
FlorisTextButton(
onClick = {
//context.launchUrl("https://beta.addons.florisboard.org")
context.launchUrl("https://fladdonstest.patrickgold.dev")
},
icon = Icons.Default.Shop,
text = "Visit Addons Store",//stringRes(R.string.action__edit),
)
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Import(ExtensionImportScreenType.EXT_ANY, null))
},
icon = Icons.AutoMirrored.Filled.Input,
text = stringRes(R.string.action__import),
)
}
}
PreferenceGroup(title = "Manage installed extensions") {
Preference(
icon = Icons.Default.Palette,
title = stringRes(R.string.ext__list__ext_theme),
onClick = {
navController.navigate(Routes.Ext.List(ExtensionListScreenType.EXT_THEME))
},
)
Preference(
icon = Icons.Default.Keyboard,
title = stringRes(R.string.ext__list__ext_keyboard),
onClick = {
navController.navigate(Routes.Ext.List(ExtensionListScreenType.EXT_KEYBOARD))
},
)
Preference(
icon = Icons.Default.Language,
title = stringRes(R.string.ext__list__ext_languagepack),
onClick = {
navController.navigate(Routes.Ext.List(ExtensionListScreenType.EXT_LANGUAGEPACK))
},
)
}
}
}
@Composable
fun AddonManagementReferenceBox() {
val navController = LocalNavController.current
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
title = "Managing extensions"
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
text = "All tasks related to importing, exporting, creating, customizing, and removing extensions can be handled through the centralized addon manager.",
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Home)
},
icon = Icons.Default.Shop,
text = "Go to {ext_home_title}".curlyFormat(
"ext_home_title" to stringRes(R.string.ext__home__title),
),
)
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2021 Patrick Goldinger * Copyright (C) 2024 Patrick Goldinger
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,84 +16,134 @@
package dev.patrickgold.florisboard.app.ext package dev.patrickgold.florisboard.app.ext
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import dev.patrickgold.florisboard.R import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.extensionManager
import dev.patrickgold.florisboard.ime.keyboard.KeyboardExtension
import dev.patrickgold.florisboard.ime.nlp.LanguagePackExtension
import dev.patrickgold.florisboard.ime.theme.ThemeExtension
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.FlorisScreen import dev.patrickgold.florisboard.lib.compose.FlorisScreen
import dev.patrickgold.florisboard.lib.compose.FlorisTextButton
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.stringRes import dev.patrickgold.florisboard.lib.compose.stringRes
import dev.patrickgold.florisboard.lib.ext.ExtensionManager
import dev.patrickgold.florisboard.lib.observeAsNonNullState
enum class ExtensionListScreenType(
val id: String,
@StringRes val titleResId: Int,
val getExtensionIndex: (ExtensionManager) -> ExtensionManager.ExtensionIndex<*>,
val launchExtensionCreate: ((NavController) -> Unit)?,
) {
EXT_THEME(
id = "ext-theme",
titleResId = R.string.ext__list__ext_theme,
getExtensionIndex = { it.themes },
launchExtensionCreate = { it.navigate(Routes.Ext.Edit("null", ThemeExtension.SERIAL_TYPE)) },
),
EXT_KEYBOARD(
id = "ext-keyboard",
titleResId = R.string.ext__list__ext_keyboard,
getExtensionIndex = { it.keyboardExtensions },
launchExtensionCreate = null,//{ it.navigate(Routes.Ext.Edit("null", KeyboardExtension.SERIAL_TYPE)) },
),
EXT_LANGUAGEPACK(
id = "ext-languagepack",
titleResId = R.string.ext__list__ext_languagepack,
getExtensionIndex = { it.languagePacks },
launchExtensionCreate = null,//{ it.navigate(Routes.Ext.Edit("null", LanguagePackExtension.SERIAL_TYPE)) },
);
}
@Composable @Composable
fun ExtensionListScreen() = FlorisScreen { fun ExtensionListScreen(type: ExtensionListScreenType) = FlorisScreen {
title = stringRes(R.string.about__title) title = stringRes(type.titleResId)
previewFieldVisible = false
/*val navController = LocalNavController.current
val context = LocalContext.current val context = LocalContext.current
val extensionManager = ExtensionManager.def val navController = LocalNavController.current
val extensionManager by context.extensionManager()
val extensionIndex by type.getExtensionIndex(extensionManager).observeAsNonNullState()
Column( content {
verticalArrangement = Arrangement.Top, for (ext in extensionIndex) {
horizontalAlignment = Alignment.CenterHorizontally, FlorisOutlinedBox(
modifier = Modifier modifier = Modifier.defaultFlorisOutlinedBox(),
.fillMaxWidth() title = ext.meta.title,
.padding(top = 24.dp, bottom = 32.dp) subtitle = ext.meta.id,
) { ) {
FlorisAppIcon() Text(
Text( modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
text = stringRes(R.string.floris_app_name), text = ext.meta.description ?: "",
fontSize = 24.sp, style = MaterialTheme.typography.bodySmall,
fontWeight = FontWeight.SemiBold, )
modifier = Modifier.padding(top = 16.dp), Row(
) modifier = Modifier
} .fillMaxWidth()
Preference( .padding(horizontal = 6.dp),
icon = R.drawable.ic_info, ) {
title = stringRes(R.string.about__version__title), FlorisTextButton(
summary = appVersion, onClick = {
onClick = { navController.navigate(Routes.Ext.View(ext.meta.id))
try { },
val isImeSelected = InputMethodUtils.checkIsFlorisboardSelected(context) icon = Icons.Outlined.Info,
if (isImeSelected) { text = "View details",//stringRes(R.string.action__add),
FlorisClipboardManager.getInstance().addNewPlaintext(appVersion) colors = ButtonDefaults.textButtonColors(),
} else { )
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager Spacer(modifier = Modifier.weight(1f))
val clip = ClipData.newPlainText("Florisboard version", appVersion) FlorisTextButton(
clipboard.setPrimaryClip(clip) onClick = {
navController.navigate(Routes.Ext.Edit(ext.meta.id))
},
icon = Icons.Default.Edit,
text = stringRes(R.string.action__edit),
enabled = extensionManager.canDelete(ext),
)
} }
Toast.makeText(context, R.string.about__version_copied__title, Toast.LENGTH_SHORT).show()
} catch (e: Throwable) {
Toast.makeText(
context, context.getString(R.string.about__version_copied__error, e.message), Toast.LENGTH_SHORT
).show()
} }
}, }
) }
Preference(
icon = R.drawable.ic_history, if (type.launchExtensionCreate != null) {
title = stringRes(R.string.about__changelog__title), floatingActionButton {
summary = stringRes(R.string.about__changelog__summary), ExtendedFloatingActionButton(
onClick = { launchUrl(context, R.string.florisboard__changelog_url, arrayOf(BuildConfig.VERSION_NAME)) }, icon = {
) Icon(
Preference( imageVector = Icons.Default.Add,
icon = R.drawable.ic_code, contentDescription = "Create extension",
title = stringRes(R.string.about__repository__title), )
summary = stringRes(R.string.about__repository__summary), },
onClick = { launchUrl(context, R.string.florisboard__repo_url) }, text = {
) Text(
Preference( text = "Create extension",
icon = R.drawable.ic_policy, )
title = stringRes(R.string.about__privacy_policy__title), },
summary = stringRes(R.string.about__privacy_policy__summary), shape = FloatingActionButtonDefaults.extendedFabShape,
onClick = { launchUrl(context, R.string.florisboard__privacy_policy_url) }, onClick = { type.launchExtensionCreate.invoke(navController) },
) )
Preference( }
icon = R.drawable.ic_description, }
title = stringRes(R.string.about__project_license__title),
summary = stringRes(R.string.about__project_license__summary, "license_name" to "Apache 2.0"),
onClick = { navController.navigate(Routes.Settings.ProjectLicense) },
)
Preference(
icon = R.drawable.ic_description,
title = stringRes(id = R.string.about__third_party_licenses__title),
summary = stringRes(id = R.string.about__third_party_licenses__summary),
onClick = { navController.navigate(Routes.Settings.ThirdPartyLicenses) },
)*/
} }

View File

@ -18,14 +18,13 @@ package dev.patrickgold.florisboard.app.settings
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Adb import androidx.compose.material.icons.automirrored.outlined.Assignment
import androidx.compose.material.icons.filled.Extension
import androidx.compose.material.icons.filled.Gesture import androidx.compose.material.icons.filled.Gesture
import androidx.compose.material.icons.filled.Language import androidx.compose.material.icons.filled.Language
import androidx.compose.material.icons.filled.LibraryBooks
import androidx.compose.material.icons.filled.SentimentSatisfiedAlt import androidx.compose.material.icons.filled.SentimentSatisfiedAlt
import androidx.compose.material.icons.filled.SmartButton import androidx.compose.material.icons.filled.SmartButton
import androidx.compose.material.icons.filled.Spellcheck import androidx.compose.material.icons.filled.Spellcheck
import androidx.compose.material.icons.outlined.Assignment
import androidx.compose.material.icons.outlined.Build import androidx.compose.material.icons.outlined.Build
import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.Keyboard import androidx.compose.material.icons.outlined.Keyboard
@ -131,18 +130,13 @@ fun HomeScreen() = FlorisScreen {
title = stringRes(R.string.settings__typing__title), title = stringRes(R.string.settings__typing__title),
onClick = { navController.navigate(Routes.Settings.Typing) }, onClick = { navController.navigate(Routes.Settings.Typing) },
) )
Preference(
icon = Icons.Default.LibraryBooks,
title = stringRes(R.string.settings__dictionary__title),
onClick = { navController.navigate(Routes.Settings.Dictionary) },
)
Preference( Preference(
icon = Icons.Default.Gesture, icon = Icons.Default.Gesture,
title = stringRes(R.string.settings__gestures__title), title = stringRes(R.string.settings__gestures__title),
onClick = { navController.navigate(Routes.Settings.Gestures) }, onClick = { navController.navigate(Routes.Settings.Gestures) },
) )
Preference( Preference(
icon = Icons.Outlined.Assignment, icon = Icons.AutoMirrored.Outlined.Assignment,
title = stringRes(R.string.settings__clipboard__title), title = stringRes(R.string.settings__clipboard__title),
onClick = { navController.navigate(Routes.Settings.Clipboard) }, onClick = { navController.navigate(Routes.Settings.Clipboard) },
) )
@ -152,9 +146,9 @@ fun HomeScreen() = FlorisScreen {
onClick = { navController.navigate(Routes.Settings.Media) }, onClick = { navController.navigate(Routes.Settings.Media) },
) )
Preference( Preference(
icon = Icons.Default.Adb, icon = Icons.Default.Extension,
title = stringRes(R.string.devtools__title), title = stringRes(R.string.ext__home__title),
onClick = { navController.navigate(Routes.Devtools.Home) }, onClick = { navController.navigate(Routes.Ext.Home) },
) )
Preference( Preference(
icon = Icons.Outlined.Build, icon = Icons.Outlined.Build,

View File

@ -17,6 +17,7 @@
package dev.patrickgold.florisboard.app.settings.advanced package dev.patrickgold.florisboard.app.settings.advanced
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Adb
import androidx.compose.material.icons.filled.Archive import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.filled.FormatPaint import androidx.compose.material.icons.filled.FormatPaint
import androidx.compose.material.icons.filled.Language import androidx.compose.material.icons.filled.Language
@ -166,6 +167,11 @@ fun AdvancedScreen() = FlorisScreen {
title = stringRes(R.string.pref__advanced__incognito_mode__label), title = stringRes(R.string.pref__advanced__incognito_mode__label),
entries = IncognitoMode.listEntries(), entries = IncognitoMode.listEntries(),
) )
Preference(
icon = Icons.Default.Adb,
title = stringRes(R.string.devtools__title),
onClick = { navController.navigate(Routes.Devtools.Home) },
)
PreferenceGroup(title = stringRes(R.string.backup_and_restore__title)) { PreferenceGroup(title = stringRes(R.string.backup_and_restore__title)) {
Preference( Preference(

View File

@ -16,26 +16,13 @@
package dev.patrickgold.florisboard.app.settings.theme package dev.patrickgold.florisboard.app.settings.theme
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Input
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.BrightnessAuto import androidx.compose.material.icons.filled.BrightnessAuto
import androidx.compose.material.icons.filled.DarkMode import androidx.compose.material.icons.filled.DarkMode
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.LightMode import androidx.compose.material.icons.filled.LightMode
import androidx.compose.material.icons.filled.Shop
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -43,25 +30,17 @@ import androidx.compose.ui.unit.dp
import dev.patrickgold.florisboard.R import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.app.ext.ExtensionImportScreenType import dev.patrickgold.florisboard.app.ext.AddonManagementReferenceBox
import dev.patrickgold.florisboard.extensionManager
import dev.patrickgold.florisboard.ime.theme.ThemeExtension
import dev.patrickgold.florisboard.ime.theme.ThemeManager import dev.patrickgold.florisboard.ime.theme.ThemeManager
import dev.patrickgold.florisboard.ime.theme.ThemeMode import dev.patrickgold.florisboard.ime.theme.ThemeMode
import dev.patrickgold.florisboard.lib.android.launchUrl
import dev.patrickgold.florisboard.lib.compose.FlorisInfoCard import dev.patrickgold.florisboard.lib.compose.FlorisInfoCard
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.FlorisScreen import dev.patrickgold.florisboard.lib.compose.FlorisScreen
import dev.patrickgold.florisboard.lib.compose.FlorisTextButton
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.stringRes import dev.patrickgold.florisboard.lib.compose.stringRes
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
import dev.patrickgold.florisboard.lib.observeAsNonNullState
import dev.patrickgold.florisboard.themeManager import dev.patrickgold.florisboard.themeManager
import dev.patrickgold.jetpref.datastore.model.observeAsState import dev.patrickgold.jetpref.datastore.model.observeAsState
import dev.patrickgold.jetpref.datastore.ui.ListPreference import dev.patrickgold.jetpref.datastore.ui.ListPreference
import dev.patrickgold.jetpref.datastore.ui.Preference import dev.patrickgold.jetpref.datastore.ui.Preference
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
@Composable @Composable
fun ThemeScreen() = FlorisScreen { fun ThemeScreen() = FlorisScreen {
@ -70,7 +49,6 @@ fun ThemeScreen() = FlorisScreen {
val context = LocalContext.current val context = LocalContext.current
val navController = LocalNavController.current val navController = LocalNavController.current
val extensionManager by context.extensionManager()
val themeManager by context.themeManager() val themeManager by context.themeManager()
@Composable @Composable
@ -129,99 +107,6 @@ fun ThemeScreen() = FlorisScreen {
}, },
) )
PreferenceGroup(title = stringRes(R.string.settings__theme_manager__title_manage), iconSpaceReserved = false) { AddonManagementReferenceBox()
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
) {
Text(
modifier = Modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 4.dp),
text = "You can download and install additional themes from the FlorisBoard Addons Store or import any theme extension file you have downloaded from the internet.",
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
FlorisTextButton(
onClick = {
context.launchUrl("https://beta.addons.florisboard.org")
},
icon = Icons.Default.Shop,
text = "Visit Addons Store",//stringRes(R.string.action__edit),
)
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Import(ExtensionImportScreenType.EXT_THEME, null))
},
icon = Icons.AutoMirrored.Filled.Input,
text = stringRes(R.string.action__import),
)
}
}
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
) {
Text(
modifier = Modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 4.dp),
text = "If you are a more advanced user you can also choose to create and share your own theme extension using the stylesheet editor.",
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Edit("null", ThemeExtension.SERIAL_TYPE))
},
icon = Icons.Default.Add,
text = stringRes(R.string.ext__editor__title_create_theme),
)
}
}
}
PreferenceGroup(title = "All installed themes", iconSpaceReserved = false) {
val indexedThemeExtensions by extensionManager.themes.observeAsNonNullState()
for (ext in indexedThemeExtensions) key(ext.meta.id) {
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
title = ext.meta.title,
subtitle = ext.meta.id,
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
text = ext.meta.description ?: "",
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.View(ext.meta.id))
},
icon = Icons.Outlined.Info,
text = "View details",//stringRes(R.string.action__add),
colors = ButtonDefaults.textButtonColors(),
)
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Edit(ext.meta.id))
},
icon = Icons.Default.Edit,
text = stringRes(R.string.action__edit),
enabled = extensionManager.canDelete(ext),
)
}
}
}
}
} }
} }

View File

@ -19,9 +19,9 @@ package dev.patrickgold.florisboard.app.settings.typing
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.LibraryBooks
import androidx.compose.material.icons.filled.Contacts import androidx.compose.material.icons.filled.Contacts
import androidx.compose.material.icons.filled.Language import androidx.compose.material.icons.filled.Language
import androidx.compose.material.icons.filled.LibraryBooks
import androidx.compose.material.icons.filled.SpaceBar import androidx.compose.material.icons.filled.SpaceBar
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -32,6 +32,8 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import dev.patrickgold.florisboard.R import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.ime.nlp.SpellingLanguageMode import dev.patrickgold.florisboard.ime.nlp.SpellingLanguageMode
import dev.patrickgold.florisboard.lib.android.AndroidVersion import dev.patrickgold.florisboard.lib.android.AndroidVersion
import dev.patrickgold.florisboard.lib.compose.FlorisErrorCard import dev.patrickgold.florisboard.lib.compose.FlorisErrorCard
@ -42,6 +44,7 @@ import dev.patrickgold.jetpref.datastore.model.observeAsState
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
import dev.patrickgold.jetpref.datastore.ui.ListPreference import dev.patrickgold.jetpref.datastore.ui.ListPreference
import dev.patrickgold.jetpref.datastore.ui.Preference
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
@ -51,6 +54,8 @@ fun TypingScreen() = FlorisScreen {
title = stringRes(R.string.settings__typing__title) title = stringRes(R.string.settings__typing__title)
previewFieldVisible = true previewFieldVisible = true
val navController = LocalNavController.current
content { content {
// This card is temporary and is therefore not using a string resource // This card is temporary and is therefore not using a string resource
FlorisErrorCard( FlorisErrorCard(
@ -159,12 +164,20 @@ fun TypingScreen() = FlorisScreen {
) )
SwitchPreference( SwitchPreference(
prefs.spelling.useUdmEntries, prefs.spelling.useUdmEntries,
icon = Icons.Default.LibraryBooks, icon = Icons.AutoMirrored.Filled.LibraryBooks,
title = stringRes(R.string.pref__spelling__use_udm_entries__label), title = stringRes(R.string.pref__spelling__use_udm_entries__label),
summary = stringRes(R.string.pref__spelling__use_udm_entries__summary), summary = stringRes(R.string.pref__spelling__use_udm_entries__summary),
enabledIf = { florisSpellCheckerEnabled.value }, enabledIf = { florisSpellCheckerEnabled.value },
visibleIf = { false }, // For now visibleIf = { false }, // For now
) )
} }
PreferenceGroup(title = stringRes(R.string.settings__dictionary__title)) {
Preference(
icon = Icons.AutoMirrored.Filled.LibraryBooks,
title = stringRes(R.string.settings__dictionary__title),
onClick = { navController.navigate(Routes.Settings.Dictionary) },
)
}
} }
} }

View File

@ -616,6 +616,10 @@
<!-- Extension strings --> <!-- Extension strings -->
<string name="ext__home__title">Addons &amp; Extensions</string>
<string name="ext__list__ext_theme">Theme extensions</string>
<string name="ext__list__ext_keyboard">Keyboard extensions</string>
<string name="ext__list__ext_languagepack">Language pack extensions</string>
<string name="ext__meta__authors">Authors</string> <string name="ext__meta__authors">Authors</string>
<string name="ext__meta__components">Bundled components</string> <string name="ext__meta__components">Bundled components</string>
<string name="ext__meta__components_theme">Bundled themes</string> <string name="ext__meta__components_theme">Bundled themes</string>