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:
parent
e520a9c335
commit
f1d60d9958
@ -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 ->
|
||||||
|
@ -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),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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) },
|
|
||||||
)*/
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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(
|
||||||
|
@ -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),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -616,6 +616,10 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- Extension strings -->
|
<!-- Extension strings -->
|
||||||
|
<string name="ext__home__title">Addons & 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>
|
||||||
|
Loading…
Reference in New Issue
Block a user