Compare commits
29 Commits
test/inlin
...
v0.5.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d9bacbefd | ||
|
|
a1031acd8e | ||
|
|
7a3af3eb54 | ||
|
|
7a433e9860 | ||
|
|
f687873cc5 | ||
|
|
c6a84fd324 | ||
|
|
dcc490cc9d | ||
|
|
d7b52cd489 | ||
|
|
fc7700395c | ||
|
|
9f07702852 | ||
|
|
f111544d81 | ||
|
|
fc09bb74c0 | ||
|
|
674bdccc40 | ||
|
|
3e69dddaa9 | ||
|
|
3c175bc60d | ||
|
|
83150e17ab | ||
|
|
2d6646e674 | ||
|
|
cc9511edca | ||
|
|
f25df31147 | ||
|
|
0ccb0c33b4 | ||
|
|
7ea4e8c827 | ||
|
|
93c76640f4 | ||
|
|
c2c874a9e0 | ||
|
|
b14877da8c | ||
|
|
2fb1fdb281 | ||
|
|
52646ecba1 | ||
|
|
7905dae807 | ||
|
|
e73ac5f96f | ||
|
|
15039fb020 |
20
README.md
20
README.md
@@ -29,7 +29,7 @@ fully respecting your privacy. Currently in early-beta state.
|
||||
<p><a href="https://f-droid.org/packages/dev.patrickgold.florisboard"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="64" alt="F-Droid badge"></a></p>
|
||||
<p>
|
||||
|
||||
**Google Play**: Join the [FlorisBoard Test Group](https://groups.google.com/g/florisboard-public-alpha-test), then visit the [testing page](https://play.google.com/apps/testing/dev.patrickgold.florisboard). Once joined and installed, updates will be delivered like for any other app. ([Store entry](https://play.google.com/store/apps/details?id=dev.patrickgold.florisboard))
|
||||
**Google Play**: Join the [FlorisBoard Test Group](https://groups.google.com/g/florisboard-closed-beta-test), then visit the [testing page](https://play.google.com/apps/testing/dev.patrickgold.florisboard). Once joined and installed, updates will be delivered like for any other app. ([Store entry](https://play.google.com/store/apps/details?id=dev.patrickgold.florisboard))
|
||||
|
||||
</p>
|
||||
<p>
|
||||
@@ -47,7 +47,7 @@ fully respecting your privacy. Currently in early-beta state.
|
||||
<p><a href="https://apt.izzysoft.de/fdroid/index/apk/dev.patrickgold.florisboard.beta"><img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png" height="64" alt="IzzySoft repo badge"></a></p>
|
||||
<p>
|
||||
|
||||
**Google Play**: Join the [FlorisBoard Test Group](https://groups.google.com/g/florisboard-public-alpha-test), then visit the [preview testing page](https://play.google.com/apps/testing/dev.patrickgold.florisboard.beta). Once joined and installed, updates will be delivered like for any other app. ([Store entry](https://play.google.com/store/apps/details?id=dev.patrickgold.florisboard.beta))
|
||||
**Google Play**: Join the [FlorisBoard Test Group](https://groups.google.com/g/florisboard-closed-beta-test), then visit the [preview testing page](https://play.google.com/apps/testing/dev.patrickgold.florisboard.beta). Once joined and installed, updates will be delivered like for any other app. ([Store entry](https://play.google.com/store/apps/details?id=dev.patrickgold.florisboard.beta))
|
||||
|
||||
</p>
|
||||
<p>
|
||||
@@ -96,6 +96,22 @@ Many thanks to Ali ([@4H1R](https://github.com/4H1R)) for implementing the store
|
||||
Please refer to this [page](https://github.com/florisboard/florisboard/wiki/List-of-permissions-FlorisBoard-requests)
|
||||
to get more information on this topic.
|
||||
|
||||
## APK signing certificate hashes
|
||||
|
||||
The package names and SHA-256 hashes of the signature certificate are listed below, so you can verify both FlorisBoard variants with apksigner by using `apksigner verify --print-certs florisboard-<version>-<track>.apk` when you download the APK.
|
||||
If you have [AppVerifier](https://github.com/soupslurpr/AppVerifier) installed, you can alternatively copy both the package name and the hash of the corresponding track and share them to AppVerifier.
|
||||
|
||||
##### Stable track:
|
||||
|
||||
dev.patrickgold.florisboard<br>
|
||||
0B:80:71:64:50:8E:AF:EB:1F:BB:81:5B:E7:A2:3C:77:FE:68:9D:94:B1:43:75:C9:9B:DA:A9:B6:57:7F:D6:D6
|
||||
|
||||
##### Preview track:
|
||||
|
||||
dev.patrickgold.florisboard.beta<br>
|
||||
0B:80:71:64:50:8E:AF:EB:1F:BB:81:5B:E7:A2:3C:77:FE:68:9D:94:B1:43:75:C9:9B:DA:A9:B6:57:7F:D6:D6
|
||||
|
||||
|
||||
## Used libraries, components and icons
|
||||
* [AndroidX libraries](https://github.com/androidx/androidx) by
|
||||
[Android Jetpack](https://github.com/androidx)
|
||||
|
||||
@@ -200,6 +200,7 @@ dependencies {
|
||||
ksp(libs.androidx.room.compiler)
|
||||
implementation(libs.androidx.room.runtime)
|
||||
implementation(libs.cache4k)
|
||||
implementation(libs.kotlin.reflect)
|
||||
implementation(libs.kotlinx.coroutines)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
implementation(libs.mikepenz.aboutlibraries.core)
|
||||
@@ -212,6 +213,7 @@ dependencies {
|
||||
|
||||
implementation(project(":lib:android"))
|
||||
implementation(project(":lib:color"))
|
||||
implementation(project(":lib:compose"))
|
||||
implementation(project(":lib:kotlin"))
|
||||
implementation(project(":lib:native"))
|
||||
implementation(project(":lib:snygg"))
|
||||
|
||||
@@ -608,6 +608,12 @@
|
||||
"authors": [ "waelwindows" ],
|
||||
"direction": "ltr"
|
||||
},
|
||||
{
|
||||
"id": "czech",
|
||||
"label": "Czech",
|
||||
"authors": [ "bmondream" ],
|
||||
"direction": "ltr"
|
||||
},
|
||||
{
|
||||
"id": "devanagari",
|
||||
"label": "Devanagari",
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
[
|
||||
[
|
||||
{ "$": "shift_state_selector",
|
||||
"default": {
|
||||
"code": 43, "label": "+", "type": "numeric", "popup": {
|
||||
"main": { "code": 49, "label": "1" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 282, "label": "Ě", "type": "numeric", "popup": {
|
||||
"main": { "code": 50, "label": "2" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 283, "label": "ě", "type": "numeric", "popup": {
|
||||
"main": { "code": 50, "label": "2" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 352, "label": "Š", "type": "numeric", "popup": {
|
||||
"main": { "code": 51, "label": "3" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 353, "label": "š", "type": "numeric", "popup": {
|
||||
"main": { "code": 51, "label": "3" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 268, "label": "Č", "type": "numeric", "popup": {
|
||||
"main": { "code": 52, "label": "4" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 269, "label": "č", "type": "numeric", "popup": {
|
||||
"main": { "code": 52, "label": "4" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 344, "label": "Ř", "type": "numeric", "popup": {
|
||||
"main": { "code": 53, "label": "5" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 345, "label": "ř", "type": "numeric", "popup": {
|
||||
"main": { "code": 53, "label": "5" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 381, "label": "Ž", "type": "numeric", "popup": {
|
||||
"main": { "code": 54, "label": "6" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 382, "label": "ž", "type": "numeric", "popup": {
|
||||
"main": { "code": 54, "label": "6" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 221, "label": "Ý", "type": "numeric", "popup": {
|
||||
"main": { "code": 55, "label": "7" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 253, "label": "ý", "type": "numeric", "popup": {
|
||||
"main": { "code": 55, "label": "7" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 193, "label": "Á", "type": "numeric", "popup": {
|
||||
"main": { "code": 56, "label": "8" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 225, "label": "á", "type": "numeric", "popup": {
|
||||
"main": { "code": 56, "label": "8" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 205, "label": "Í", "type": "numeric", "popup": {
|
||||
"main": { "code": 57, "label": "9" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 237, "label": "í", "type": "numeric", "popup": {
|
||||
"main": { "code": 57, "label": "9" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "$": "shift_state_selector",
|
||||
"shiftedManual": {
|
||||
"code": 201, "label": "É", "type": "numeric", "popup": {
|
||||
"main": { "code": 48, "label": "0" }
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"code": 233, "label": "é", "type": "numeric", "popup": {
|
||||
"main": { "code": 48, "label": "0" }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -34,9 +34,7 @@
|
||||
]
|
||||
},
|
||||
"h": {
|
||||
"relevant": [
|
||||
{ "$": "auto_text_key", "code": 7717, "label": "ḥ" }
|
||||
]
|
||||
"main": { "$": "auto_text_key", "code": 7717, "label": "ḥ" }
|
||||
},
|
||||
"i": {
|
||||
"main": { "$": "auto_text_key", "code": 237, "label": "í" },
|
||||
@@ -49,13 +47,11 @@
|
||||
]
|
||||
},
|
||||
"l": {
|
||||
"relevant": [
|
||||
{ "$": "auto_text_key", "code": 7735, "label": "ḷ" }
|
||||
]
|
||||
"main": { "$": "auto_text_key", "code": 7735, "label": "ḷ" }
|
||||
},
|
||||
"n": {
|
||||
"main": { "$": "auto_text_key", "code": 241, "label": "ñ" },
|
||||
"relevant": [
|
||||
{ "$": "auto_text_key", "code": 241, "label": "ñ" },
|
||||
{ "$": "auto_text_key", "code": 324, "label": "ń" }
|
||||
]
|
||||
},
|
||||
@@ -73,9 +69,7 @@
|
||||
]
|
||||
},
|
||||
"r": {
|
||||
"relevant": [
|
||||
{ "$": "auto_text_key", "code": 691, "label": "ʳ" }
|
||||
]
|
||||
"main": { "$": "auto_text_key", "code": 691, "label": "ʳ" }
|
||||
},
|
||||
"s": {
|
||||
"relevant": [
|
||||
@@ -112,4 +106,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +102,6 @@ import dev.patrickgold.florisboard.ime.text.TextInputLayout
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeTheme
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.ime.theme.WallpaperChangeReceiver
|
||||
import dev.patrickgold.florisboard.lib.compose.ProvideLocalizedResources
|
||||
import dev.patrickgold.florisboard.lib.compose.SystemUiIme
|
||||
import dev.patrickgold.florisboard.lib.devtools.LogTopic
|
||||
import dev.patrickgold.florisboard.lib.devtools.flogError
|
||||
@@ -118,13 +117,14 @@ import org.florisboard.lib.android.AndroidInternalR
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.android.isOrientationLandscape
|
||||
import org.florisboard.lib.android.isOrientationPortrait
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
import org.florisboard.lib.android.systemServiceOrNull
|
||||
import org.florisboard.lib.compose.ProvideLocalizedResources
|
||||
import org.florisboard.lib.kotlin.collectIn
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggButton
|
||||
import org.florisboard.lib.snygg.ui.SnyggRow
|
||||
import org.florisboard.lib.snygg.ui.SnyggSurfaceView
|
||||
import org.florisboard.lib.snygg.ui.SnyggText
|
||||
import org.florisboard.lib.snygg.ui.rememberSnyggThemeQuery
|
||||
|
||||
@@ -572,7 +572,10 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
|
||||
@Composable
|
||||
private fun ImeUiWrapper() {
|
||||
ProvideLocalizedResources(resourcesContext) {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
) {
|
||||
ProvideKeyboardRowBaseHeight {
|
||||
CompositionLocalProvider(LocalInputFeedbackController provides inputFeedbackController) {
|
||||
FlorisImeTheme {
|
||||
@@ -617,9 +620,14 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
clickAndSemanticsModifier = Modifier
|
||||
// Do not remove below line or touch input may get stuck
|
||||
.pointerInteropFilter { false },
|
||||
supportsBackgroundImage = true,
|
||||
supportsBackgroundImage = false,
|
||||
allowClip = false,
|
||||
) {
|
||||
SnyggSurfaceView(
|
||||
elementName = FlorisImeUi.Window.elementName,
|
||||
attributes = attributes,
|
||||
modifier = Modifier.matchParentSize(),
|
||||
)
|
||||
val configuration = LocalConfiguration.current
|
||||
val bottomOffset by if (configuration.isOrientationPortrait()) {
|
||||
prefs.keyboard.bottomOffsetPortrait
|
||||
@@ -671,10 +679,13 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean =
|
||||
if (keyboardManager.onHardwareKeyDown(keyCode, event)) true
|
||||
else super.onKeyDown(keyCode, event)
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return keyboardManager.onHardwareKeyDown(keyCode, event) || super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return keyboardManager.onHardwareKeyUp(keyCode, event) || super.onKeyUp(keyCode, event)
|
||||
}
|
||||
|
||||
private inner class ComposeInputView : AbstractComposeView(this) {
|
||||
init {
|
||||
@@ -709,7 +720,11 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
val keyboardManager by context.keyboardManager()
|
||||
val state by keyboardManager.activeState.collectAsState()
|
||||
|
||||
ProvideLocalizedResources(resourcesContext, forceLayoutDirection = LayoutDirection.Ltr) {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
forceLayoutDirection = LayoutDirection.Ltr,
|
||||
) {
|
||||
FlorisImeTheme {
|
||||
BottomSheetHostUi(
|
||||
isShowing = state.isBottomSheetShowing() || state.isSubtypeSelectionShowing(),
|
||||
@@ -761,7 +776,11 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
|
||||
@Composable
|
||||
fun Content() {
|
||||
ProvideLocalizedResources(resourcesContext, forceLayoutDirection = LayoutDirection.Ltr) {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
forceLayoutDirection = LayoutDirection.Ltr,
|
||||
) {
|
||||
FlorisImeTheme {
|
||||
val activeEditorInfo by editorInstance.activeInfoFlow.collectAsState()
|
||||
SnyggBox(FlorisImeUi.ExtractedLandscapeInputLayout.elementName) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import dev.patrickgold.florisboard.app.settings.theme.ColorPreferenceSerializer
|
||||
import dev.patrickgold.florisboard.app.settings.theme.DisplayKbdAfterDialogs
|
||||
import dev.patrickgold.florisboard.app.settings.theme.SnyggLevel
|
||||
import dev.patrickgold.florisboard.app.setup.NotificationPermissionState
|
||||
@@ -53,7 +54,6 @@ import dev.patrickgold.florisboard.ime.text.key.UtilityKeyAction
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeMode
|
||||
import dev.patrickgold.florisboard.ime.theme.extCoreTheme
|
||||
import dev.patrickgold.florisboard.lib.compose.ColorPreferenceSerializer
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
|
||||
import dev.patrickgold.florisboard.lib.observeAsTransformingState
|
||||
import dev.patrickgold.florisboard.lib.util.VersionName
|
||||
@@ -860,6 +860,11 @@ abstract class FlorisPreferenceModel : PreferenceModel() {
|
||||
dynamicActions = newArrangement.dynamicActions.plus(QuickAction.InsertKey(TextKeyData.LANGUAGE_SWITCH))
|
||||
)
|
||||
}
|
||||
if (QuickAction.InsertKey(TextKeyData.FORWARD_DELETE) !in newArrangement) {
|
||||
newArrangement = newArrangement.copy(
|
||||
dynamicActions = newArrangement.dynamicActions.plus(QuickAction.InsertKey(TextKeyData.FORWARD_DELETE))
|
||||
)
|
||||
}
|
||||
val json = QuickActionJsonConfig.encodeToString(newArrangement.distinct())
|
||||
entry.transform(rawValue = json)
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ import dev.patrickgold.florisboard.ime.text.gestures.SwipeAction
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyHintMode
|
||||
import dev.patrickgold.florisboard.ime.text.key.UtilityKeyAction
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeMode
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.ListPreferenceEntry
|
||||
import dev.patrickgold.jetpref.datastore.ui.listPrefEntries
|
||||
import dev.patrickgold.jetpref.material.ui.ColorRepresentation
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
@@ -51,16 +51,16 @@ import dev.patrickgold.florisboard.cacheManager
|
||||
import dev.patrickgold.florisboard.lib.FlorisLocale
|
||||
import dev.patrickgold.florisboard.lib.compose.LocalPreviewFieldController
|
||||
import dev.patrickgold.florisboard.lib.compose.PreviewKeyboardField
|
||||
import dev.patrickgold.florisboard.lib.compose.ProvideLocalizedResources
|
||||
import dev.patrickgold.florisboard.lib.compose.conditional
|
||||
import dev.patrickgold.florisboard.lib.compose.rememberPreviewFieldController
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.util.AppVersionUtils
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.datastore.ui.ProvideDefaultDialogPrefStrings
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.android.hideAppIcon
|
||||
import org.florisboard.lib.android.showAppIcon
|
||||
import org.florisboard.lib.compose.ProvideLocalizedResources
|
||||
import org.florisboard.lib.compose.conditional
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.collectIn
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
@@ -121,7 +121,10 @@ class FlorisAppActivity : ComponentActivity() {
|
||||
}
|
||||
AppVersionUtils.updateVersionOnInstallAndLastUse(this, prefs)
|
||||
setContent {
|
||||
ProvideLocalizedResources(resourcesContext) {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
) {
|
||||
FlorisAppTheme(theme = appTheme) {
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
AppContent()
|
||||
@@ -194,7 +197,7 @@ class FlorisAppActivity : ComponentActivity() {
|
||||
Routes.AppNavHost(
|
||||
modifier = Modifier.weight(1.0f),
|
||||
navController = navController,
|
||||
startDestination = if (isImeSetUp) Routes.Settings.Home else Routes.Setup.Screen,
|
||||
startDestination = if (isImeSetUp) Routes.Settings.Home::class else Routes.Setup.Screen::class,
|
||||
)
|
||||
PreviewKeyboardField(previewFieldController)
|
||||
}
|
||||
|
||||
@@ -17,12 +17,17 @@
|
||||
package dev.patrickgold.florisboard.app
|
||||
|
||||
import androidx.compose.animation.AnimatedContentScope
|
||||
import androidx.compose.animation.EnterTransition
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.scaleOut
|
||||
import androidx.compose.animation.slideIn
|
||||
import androidx.compose.animation.slideOut
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
@@ -30,6 +35,7 @@ import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navDeepLink
|
||||
import androidx.navigation.toRoute
|
||||
import dev.patrickgold.florisboard.app.devtools.AndroidLocalesScreen
|
||||
import dev.patrickgold.florisboard.app.devtools.AndroidSettingsScreen
|
||||
import dev.patrickgold.florisboard.app.devtools.DevtoolsScreen
|
||||
@@ -70,113 +76,185 @@ import dev.patrickgold.florisboard.app.settings.theme.ThemeManagerScreenAction
|
||||
import dev.patrickgold.florisboard.app.settings.theme.ThemeScreen
|
||||
import dev.patrickgold.florisboard.app.settings.typing.TypingScreen
|
||||
import dev.patrickgold.florisboard.app.setup.SetupScreen
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class Deeplink(val path: String)
|
||||
|
||||
inline fun <reified T : Any> NavGraphBuilder.composableWithDeepLink(
|
||||
kClass: KClass<T>,
|
||||
noinline content: @Composable (AnimatedContentScope.(NavBackStackEntry) -> Unit),
|
||||
) {
|
||||
val deeplink = requireNotNull(kClass.annotations.firstOrNull { it is Deeplink } as? Deeplink) {
|
||||
"faulty class: $kClass with annotations ${kClass.annotations}"
|
||||
}
|
||||
composable<T>(
|
||||
deepLinks = listOf(navDeepLink<T>(basePath = "ui://florisboard/${deeplink.path}")),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "ConstPropertyName")
|
||||
object Routes {
|
||||
object Setup {
|
||||
const val Screen = "setup"
|
||||
@Serializable
|
||||
object Screen
|
||||
}
|
||||
|
||||
object Settings {
|
||||
const val Home = "settings"
|
||||
@Serializable
|
||||
@Deeplink("settings/home")
|
||||
object Home
|
||||
|
||||
const val Localization = "settings/localization"
|
||||
const val SelectLocale = "settings/localization/select-locale"
|
||||
const val LanguagePackManager = "settings/localization/language-pack-manage/{action}"
|
||||
fun LanguagePackManager(action: LanguagePackManagerScreenAction) =
|
||||
LanguagePackManager.curlyFormat("action" to action.id)
|
||||
const val SubtypeAdd = "settings/localization/subtype/add"
|
||||
const val SubtypeEdit = "settings/localization/subtype/edit/{id}"
|
||||
fun SubtypeEdit(id: Long) = SubtypeEdit.curlyFormat("id" to id)
|
||||
@Serializable
|
||||
@Deeplink("settings/localization")
|
||||
object Localization
|
||||
|
||||
const val Theme = "settings/theme"
|
||||
const val ThemeManager = "settings/theme/manage/{action}"
|
||||
fun ThemeManager(action: ThemeManagerScreenAction) = ThemeManager.curlyFormat("action" to action.id)
|
||||
@Serializable
|
||||
@Deeplink("settings/localization/select-locale")
|
||||
object SelectLocale
|
||||
|
||||
const val Keyboard = "settings/keyboard"
|
||||
const val InputFeedback = "settings/keyboard/input-feedback"
|
||||
@Serializable
|
||||
@Deeplink("settings/localization/language-pack-manage")
|
||||
data class LanguagePackManager(val action: LanguagePackManagerScreenAction)
|
||||
|
||||
const val Smartbar = "settings/smartbar"
|
||||
@Serializable
|
||||
@Deeplink("settings/localization/subtype/add")
|
||||
object SubtypeAdd
|
||||
|
||||
const val Typing = "settings/typing"
|
||||
@Serializable
|
||||
@Deeplink("settings/localization/subtype/edit")
|
||||
data class SubtypeEdit(val id: Long)
|
||||
|
||||
const val Dictionary = "settings/dictionary"
|
||||
const val UserDictionary = "settings/dictionary/user-dictionary/{type}"
|
||||
fun UserDictionary(type: UserDictionaryType) = UserDictionary.curlyFormat("type" to type.id)
|
||||
@Serializable
|
||||
@Deeplink("settings/theme")
|
||||
object Theme
|
||||
|
||||
const val Gestures = "settings/gestures"
|
||||
@Serializable
|
||||
@Deeplink("settings/theme/manage")
|
||||
data class ThemeManager(val action: ThemeManagerScreenAction)
|
||||
|
||||
const val Clipboard = "settings/clipboard"
|
||||
@Serializable
|
||||
@Deeplink("settings/keyboard")
|
||||
object Keyboard
|
||||
|
||||
const val Media = "settings/media"
|
||||
@Serializable
|
||||
@Deeplink("settings/keyboard/input-feedback")
|
||||
object InputFeedback
|
||||
|
||||
const val Other = "settings/other"
|
||||
const val PhysicalKeyboard = "settings/other/physical-keyboard"
|
||||
const val Backup = "settings/other/backup"
|
||||
const val Restore = "settings/other/restore"
|
||||
@Serializable
|
||||
@Deeplink("settings/smartbar")
|
||||
object Smartbar
|
||||
|
||||
const val About = "settings/about"
|
||||
const val ProjectLicense = "settings/about/project-license"
|
||||
const val ThirdPartyLicenses = "settings/about/third-party-licenses"
|
||||
@Serializable
|
||||
@Deeplink("settings/typing")
|
||||
object Typing
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/dictionary")
|
||||
object Dictionary
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/dictionary/user-dictionary")
|
||||
data class UserDictionary(val type: UserDictionaryType)
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/gestures")
|
||||
object Gestures
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/clipboard")
|
||||
object Clipboard
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/media")
|
||||
object Media
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/other")
|
||||
object Other
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/other/physical-keyboard")
|
||||
object PhysicalKeyboard
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/other/backup")
|
||||
object Backup
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/other/restore")
|
||||
object Restore
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/about")
|
||||
object About
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/about/project-license")
|
||||
object ProjectLicense
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/about/third-party-licenses")
|
||||
object ThirdPartyLicenses
|
||||
}
|
||||
|
||||
object Devtools {
|
||||
const val Home = "devtools"
|
||||
@Serializable
|
||||
@Deeplink("devtools")
|
||||
object Home
|
||||
|
||||
const val AndroidLocales = "devtools/android/locales"
|
||||
const val AndroidSettings = "devtools/android/settings/{name}"
|
||||
fun AndroidSettings(name: String) = AndroidSettings.curlyFormat("name" to name)
|
||||
@Serializable
|
||||
@Deeplink("devtools/android/locales")
|
||||
object AndroidLocales
|
||||
|
||||
const val ExportDebugLog = "export-debug-log"
|
||||
@Serializable
|
||||
@Deeplink("devtools/android/settings")
|
||||
data class AndroidSettings(val name: String)
|
||||
|
||||
@Serializable
|
||||
@Deeplink("export-debug-log")
|
||||
object ExportDebugLog
|
||||
}
|
||||
|
||||
object Ext {
|
||||
const val Home = "ext"
|
||||
@Serializable
|
||||
@Deeplink("ext")
|
||||
object Home
|
||||
|
||||
const val List = "ext/list/{type}?showUpdate={showUpdate}"
|
||||
fun List(
|
||||
type: ExtensionListScreenType,
|
||||
showUpdate: Boolean
|
||||
) = List.curlyFormat("type" to type.id, "showUpdate" to showUpdate)
|
||||
@Serializable
|
||||
@Deeplink("ext/list")
|
||||
data class List(val type: ExtensionListScreenType, val showUpdate: Boolean? = null)
|
||||
|
||||
const val Edit = "ext/edit/{id}?create={serial_type}"
|
||||
fun Edit(id: String, serialType: String? = null): String {
|
||||
return Edit.curlyFormat("id" to id, "serial_type" to (serialType ?: ""))
|
||||
}
|
||||
@Serializable
|
||||
@Deeplink("ext/edit")
|
||||
data class Edit(val id: String, @SerialName("create") val serialType: String? = null)
|
||||
|
||||
const val Export = "ext/export/{id}"
|
||||
fun Export(id: String) = Export.curlyFormat("id" to id)
|
||||
@Serializable
|
||||
@Deeplink("ext/export")
|
||||
data class Export(val id: String)
|
||||
|
||||
const val Import = "ext/import/{type}?uuid={uuid}"
|
||||
fun Import(
|
||||
type: ExtensionImportScreenType,
|
||||
uuid: String?,
|
||||
) = Import.curlyFormat("type" to type.id, "uuid" to uuid.toString())
|
||||
@Serializable
|
||||
@Deeplink("ext/import")
|
||||
data class Import(val type: ExtensionImportScreenType, val uuid: String? = null)
|
||||
|
||||
const val View = "ext/view/{id}"
|
||||
fun View(id: String) = View.curlyFormat("id" to id)
|
||||
@Serializable
|
||||
@Deeplink("ext/view")
|
||||
data class View(val id: String)
|
||||
|
||||
const val CheckUpdates = "ext/check-updates"
|
||||
@Serializable
|
||||
@Deeplink("ext/check-updates")
|
||||
object CheckUpdates
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppNavHost(
|
||||
modifier: Modifier,
|
||||
navController: NavHostController,
|
||||
startDestination: String,
|
||||
startDestination: KClass<*>,
|
||||
) {
|
||||
fun NavGraphBuilder.composableWithDeepLink(
|
||||
route: String,
|
||||
content: @Composable (AnimatedContentScope.(NavBackStackEntry) -> Unit),
|
||||
) {
|
||||
composable(
|
||||
route = route,
|
||||
deepLinks = listOf(navDeepLink { uriPattern = "ui://florisboard/$route" }),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
NavHost(
|
||||
modifier = modifier,
|
||||
navController = navController,
|
||||
@@ -187,109 +265,103 @@ object Routes {
|
||||
exitTransition = {
|
||||
slideOut { IntOffset(-it.width, 0) } + fadeOut()
|
||||
},
|
||||
popEnterTransition = {
|
||||
slideIn { IntOffset(-it.width, 0) } + fadeIn()
|
||||
},
|
||||
popEnterTransition = { EnterTransition.None },
|
||||
popExitTransition = {
|
||||
slideOut { IntOffset(it.width, 0) } + fadeOut()
|
||||
}
|
||||
scaleOut(
|
||||
targetScale = 0.85F,
|
||||
transformOrigin = TransformOrigin(pivotFractionX = 0.8f, pivotFractionY = 0.5f)
|
||||
) + fadeOut(spring(stiffness = Spring.StiffnessMedium))
|
||||
},
|
||||
) {
|
||||
composable(Setup.Screen) { SetupScreen() }
|
||||
composable<Setup.Screen> { SetupScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Home) { HomeScreen() }
|
||||
composableWithDeepLink(Settings.Home::class) { HomeScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Localization) { LocalizationScreen() }
|
||||
composableWithDeepLink(Settings.SelectLocale) { SelectLocaleScreen() }
|
||||
composableWithDeepLink(Settings.LanguagePackManager) { navBackStack ->
|
||||
val action = navBackStack.arguments?.getString("action")?.let { actionId ->
|
||||
LanguagePackManagerScreenAction.entries.firstOrNull { it.id == actionId }
|
||||
}
|
||||
LanguagePackManagerScreen(action)
|
||||
composableWithDeepLink(Settings.Localization::class) { LocalizationScreen() }
|
||||
composableWithDeepLink(Settings.SelectLocale::class) { SelectLocaleScreen() }
|
||||
composableWithDeepLink(Settings.LanguagePackManager::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Settings.LanguagePackManager>()
|
||||
LanguagePackManagerScreen(payload.action)
|
||||
}
|
||||
composableWithDeepLink(Settings.SubtypeAdd) { SubtypeEditorScreen(null) }
|
||||
composableWithDeepLink(Settings.SubtypeEdit) { navBackStack ->
|
||||
val id = navBackStack.arguments?.getString("id")?.toLongOrNull()
|
||||
SubtypeEditorScreen(id)
|
||||
composableWithDeepLink(Settings.SubtypeAdd::class) { SubtypeEditorScreen(null) }
|
||||
composableWithDeepLink(Settings.SubtypeEdit::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Settings.SubtypeEdit>()
|
||||
SubtypeEditorScreen(payload.id)
|
||||
}
|
||||
|
||||
composableWithDeepLink(Settings.Theme) { ThemeScreen() }
|
||||
composableWithDeepLink(Settings.ThemeManager) { navBackStack ->
|
||||
val action = navBackStack.arguments?.getString("action")?.let { actionId ->
|
||||
ThemeManagerScreenAction.entries.firstOrNull { it.id == actionId }
|
||||
}
|
||||
ThemeManagerScreen(action)
|
||||
composableWithDeepLink(Settings.Theme::class) { ThemeScreen() }
|
||||
composableWithDeepLink(Settings.ThemeManager::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Settings.ThemeManager>()
|
||||
ThemeManagerScreen(payload.action)
|
||||
}
|
||||
|
||||
composableWithDeepLink(Settings.Keyboard) { KeyboardScreen() }
|
||||
composableWithDeepLink(Settings.InputFeedback) { InputFeedbackScreen() }
|
||||
composableWithDeepLink(Settings.Keyboard::class) { KeyboardScreen() }
|
||||
composableWithDeepLink(Settings.InputFeedback::class) { InputFeedbackScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Smartbar) { SmartbarScreen() }
|
||||
composableWithDeepLink(Settings.Smartbar::class) { SmartbarScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Typing) { TypingScreen() }
|
||||
composableWithDeepLink(Settings.Typing::class) { TypingScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Dictionary) { DictionaryScreen() }
|
||||
composableWithDeepLink(Settings.UserDictionary) { navBackStack ->
|
||||
val type = navBackStack.arguments?.getString("type")?.let { typeId ->
|
||||
UserDictionaryType.entries.firstOrNull { it.id == typeId }
|
||||
}
|
||||
UserDictionaryScreen(type!!)
|
||||
composableWithDeepLink(Settings.Dictionary::class) { DictionaryScreen() }
|
||||
composableWithDeepLink(Settings.UserDictionary::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Settings.UserDictionary>()
|
||||
UserDictionaryScreen(payload.type)
|
||||
}
|
||||
|
||||
composableWithDeepLink(Settings.Gestures) { GesturesScreen() }
|
||||
composableWithDeepLink(Settings.Gestures::class) { GesturesScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Clipboard) { ClipboardScreen() }
|
||||
composableWithDeepLink(Settings.Clipboard::class) { ClipboardScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Media) { MediaScreen() }
|
||||
composableWithDeepLink(Settings.Media::class) { MediaScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Other) { OtherScreen() }
|
||||
composableWithDeepLink(Settings.PhysicalKeyboard) { PhysicalKeyboardScreen() }
|
||||
composableWithDeepLink(Settings.Backup) { BackupScreen() }
|
||||
composableWithDeepLink(Settings.Restore) { RestoreScreen() }
|
||||
composableWithDeepLink(Settings.Other::class) { OtherScreen() }
|
||||
composableWithDeepLink(Settings.PhysicalKeyboard::class) { PhysicalKeyboardScreen() }
|
||||
composableWithDeepLink(Settings.Backup::class) { BackupScreen() }
|
||||
composableWithDeepLink(Settings.Restore::class) { RestoreScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.About) { AboutScreen() }
|
||||
composableWithDeepLink(Settings.ProjectLicense) { ProjectLicenseScreen() }
|
||||
composableWithDeepLink(Settings.ThirdPartyLicenses) { ThirdPartyLicensesScreen() }
|
||||
composableWithDeepLink(Settings.About::class) { AboutScreen() }
|
||||
composableWithDeepLink(Settings.ProjectLicense::class) { ProjectLicenseScreen() }
|
||||
composableWithDeepLink(Settings.ThirdPartyLicenses::class) { ThirdPartyLicensesScreen() }
|
||||
|
||||
composableWithDeepLink(Devtools.Home) { DevtoolsScreen() }
|
||||
composableWithDeepLink(Devtools.AndroidLocales) { AndroidLocalesScreen() }
|
||||
composableWithDeepLink(Devtools.AndroidSettings) { navBackStack ->
|
||||
val name = navBackStack.arguments?.getString("name")
|
||||
AndroidSettingsScreen(name)
|
||||
composableWithDeepLink(Devtools.Home::class) { DevtoolsScreen() }
|
||||
composableWithDeepLink(Devtools.AndroidLocales::class) { AndroidLocalesScreen() }
|
||||
composableWithDeepLink(Devtools.AndroidSettings::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Devtools.AndroidSettings>()
|
||||
AndroidSettingsScreen(payload.name)
|
||||
}
|
||||
composableWithDeepLink(Devtools.ExportDebugLog) { ExportDebugLogScreen() }
|
||||
composableWithDeepLink(Devtools.ExportDebugLog::class) { ExportDebugLogScreen() }
|
||||
|
||||
composableWithDeepLink(Ext.Home) { ExtensionHomeScreen() }
|
||||
composableWithDeepLink(Ext.List) { navBackStack ->
|
||||
val type = navBackStack.arguments?.getString("type")?.let { typeId ->
|
||||
ExtensionListScreenType.entries.firstOrNull { it.id == typeId }
|
||||
} ?: error("unknown type")
|
||||
val showUpdate = navBackStack.arguments?.getString("showUpdate")
|
||||
ExtensionListScreen(type, showUpdate == "true")
|
||||
composableWithDeepLink(Ext.Home::class) { ExtensionHomeScreen() }
|
||||
composableWithDeepLink(Ext.List::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.List>()
|
||||
val showUpdate = payload.showUpdate != null && payload.showUpdate
|
||||
ExtensionListScreen(payload.type, showUpdate)
|
||||
}
|
||||
composableWithDeepLink(Ext.Edit) { navBackStack ->
|
||||
val extensionId = navBackStack.arguments?.getString("id")
|
||||
val serialType = navBackStack.arguments?.getString("serial_type")
|
||||
composableWithDeepLink(Ext.Edit::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.Edit>()
|
||||
val extensionId = payload.id
|
||||
val serialType = payload.serialType
|
||||
ExtensionEditScreen(
|
||||
id = extensionId.toString(),
|
||||
id = extensionId,
|
||||
createSerialType = serialType.takeIf { !it.isNullOrBlank() },
|
||||
)
|
||||
}
|
||||
composableWithDeepLink(Ext.Export) { navBackStack ->
|
||||
val extensionId = navBackStack.arguments?.getString("id")
|
||||
ExtensionExportScreen(id = extensionId.toString())
|
||||
composableWithDeepLink(Ext.Export::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.Export>()
|
||||
val extensionId = payload.id
|
||||
ExtensionExportScreen(id = extensionId)
|
||||
}
|
||||
composableWithDeepLink(Ext.Import) { navBackStack ->
|
||||
val type = navBackStack.arguments?.getString("type")?.let { typeId ->
|
||||
ExtensionImportScreenType.entries.firstOrNull { it.id == typeId }
|
||||
} ?: ExtensionImportScreenType.EXT_ANY
|
||||
val uuid = navBackStack.arguments?.getString("uuid")?.takeIf { it != "null" }
|
||||
ExtensionImportScreen(type, uuid)
|
||||
composableWithDeepLink(Ext.Import::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.Import>()
|
||||
val uuid = payload.uuid
|
||||
ExtensionImportScreen(payload.type, uuid)
|
||||
}
|
||||
composableWithDeepLink(Ext.View) { navBackStack ->
|
||||
val extensionId = navBackStack.arguments?.getString("id")
|
||||
ExtensionViewScreen(id = extensionId.toString())
|
||||
composableWithDeepLink(Ext.View::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.View>()
|
||||
val extensionId = payload.id
|
||||
ExtensionViewScreen(id = extensionId)
|
||||
}
|
||||
composableWithDeepLink(Ext.CheckUpdates) {
|
||||
composableWithDeepLink(Ext.CheckUpdates::class) {
|
||||
CheckUpdatesScreen()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,11 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.io.subDir
|
||||
import org.florisboard.lib.kotlin.io.subFile
|
||||
import java.util.Locale
|
||||
|
||||
@@ -27,11 +27,11 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import dev.patrickgold.florisboard.R
|
||||
import org.florisboard.lib.android.AndroidSettings
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import org.florisboard.lib.android.AndroidSettings
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun AndroidSettingsScreen(name: String?) = FlorisScreen {
|
||||
|
||||
@@ -40,6 +40,7 @@ import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.appContext
|
||||
import dev.patrickgold.florisboard.clipboardManager
|
||||
import dev.patrickgold.florisboard.editorInstance
|
||||
import dev.patrickgold.florisboard.ime.keyboard.CachedLayout
|
||||
@@ -52,10 +53,10 @@ import dev.patrickgold.florisboard.lib.observeAsNonNullState
|
||||
import dev.patrickgold.florisboard.nlpManager
|
||||
import dev.patrickgold.florisboard.themeManager
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.snygg.SnyggMissingSchemaException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.snygg.SnyggMissingSchemaException
|
||||
|
||||
private val CardBackground = Color.Black.copy(0.6f)
|
||||
private val DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", FlorisLocale.default().base)
|
||||
@@ -64,6 +65,7 @@ private val DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", FlorisLocale.
|
||||
fun DevtoolsOverlay(modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
val prefs by FlorisPreferenceStore
|
||||
val appContext by context.appContext()
|
||||
val keyboardManager by context.keyboardManager()
|
||||
val themeManager by context.themeManager()
|
||||
|
||||
@@ -72,6 +74,7 @@ fun DevtoolsOverlay(modifier: Modifier = Modifier) {
|
||||
val showInputStateOverlay by prefs.devtools.showInputStateOverlay.observeAsState()
|
||||
val showSpellingOverlay by prefs.devtools.showSpellingOverlay.observeAsState()
|
||||
val showInlineAutofillOverlay by prefs.devtools.showInlineAutofillOverlay.observeAsState()
|
||||
val prefsLoaded by appContext.preferenceStoreLoaded.collectAsState()
|
||||
|
||||
val debugLayoutResult by keyboardManager.layoutManager.debugLayoutComputationResultFlow.collectAsState()
|
||||
val themeInfo by themeManager.activeThemeInfo.collectAsState()
|
||||
@@ -97,7 +100,7 @@ fun DevtoolsOverlay(modifier: Modifier = Modifier) {
|
||||
DevtoolsInlineAutofillOverlay()
|
||||
}
|
||||
val loadFailure = themeInfo.loadFailure
|
||||
if (loadFailure != null) {
|
||||
if (loadFailure != null && prefsLoaded) {
|
||||
DevtoolsStylesheetFailedToLoadOverlay(loadFailure)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,18 +29,17 @@ import dev.patrickgold.florisboard.extensionManager
|
||||
import dev.patrickgold.florisboard.ime.dictionary.DictionaryManager
|
||||
import dev.patrickgold.florisboard.ime.dictionary.FlorisUserDictionaryDatabase
|
||||
import dev.patrickgold.florisboard.ime.smartbar.quickaction.QuickActionArrangement
|
||||
import dev.patrickgold.florisboard.ime.smartbar.quickaction.QuickActionJsonConfig
|
||||
import org.florisboard.lib.android.AndroidSettings
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisConfirmDeleteDialog
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import org.florisboard.lib.android.AndroidSettings
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
|
||||
class DebugOnPurposeCrashException : Exception(
|
||||
|
||||
@@ -40,13 +40,13 @@ import androidx.compose.ui.unit.sp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.clipboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.florisHorizontalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.florisScrollbar
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.devtools.Devtools
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.compose.FlorisButton
|
||||
import org.florisboard.lib.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.compose.florisScrollbar
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
|
||||
// TODO: This screen is just a quick thrown-together thing and needs further enhancing in the UI
|
||||
|
||||
@@ -35,13 +35,13 @@ import dev.patrickgold.florisboard.BuildConfig
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
|
||||
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.ext.Extension
|
||||
import dev.patrickgold.florisboard.lib.ext.generateUpdateUrl
|
||||
import dev.patrickgold.florisboard.lib.util.launchUrl
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.FlorisTextButton
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -21,7 +21,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.extensionManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun CheckUpdatesScreen() = FlorisScreen {
|
||||
|
||||
@@ -40,13 +40,13 @@ import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.nlp.LanguagePackComponent
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeExtensionComponent
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisTextButton
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponent
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionMeta
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.FlorisTextButton
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun ExtensionComponentNoneFoundView() {
|
||||
|
||||
@@ -48,9 +48,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.lib.cache.CacheManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefTextField
|
||||
@@ -62,6 +60,8 @@ import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.io.parentDir
|
||||
import org.florisboard.lib.kotlin.io.subDir
|
||||
import org.florisboard.lib.kotlin.io.subFile
|
||||
|
||||
@@ -42,7 +42,9 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.LocalNavController
|
||||
@@ -60,15 +62,9 @@ import dev.patrickgold.florisboard.ime.theme.ThemeExtensionComponentImpl
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeExtensionEditor
|
||||
import dev.patrickgold.florisboard.lib.ValidationResult
|
||||
import dev.patrickgold.florisboard.lib.cache.CacheManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisButtonBar
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
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.FlorisUnsavedChangesDialog
|
||||
import dev.patrickgold.florisboard.lib.compose.Validation
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.Extension
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponent
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
|
||||
@@ -85,11 +81,15 @@ import dev.patrickgold.florisboard.lib.io.ZipUtils
|
||||
import dev.patrickgold.florisboard.lib.rememberValidationResult
|
||||
import dev.patrickgold.florisboard.themeManager
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.datastore.ui.vectorResource
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefTextField
|
||||
import java.util.*
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.compose.FlorisButtonBar
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.FlorisInfoCard
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.kotlin.io.deleteContentsRecursively
|
||||
import org.florisboard.lib.kotlin.io.subDir
|
||||
@@ -353,7 +353,7 @@ private fun EditScreen(
|
||||
)
|
||||
Preference(
|
||||
onClick = { workspace.currentAction = EditorAction.ManageFiles },
|
||||
icon = vectorResource(R.drawable.ic_file_blank),
|
||||
icon = ImageVector.vectorResource(R.drawable.ic_file_blank),
|
||||
title = stringRes(R.string.ext__editor__files__title),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.extensionManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun ExtensionHomeScreen() = FlorisScreen {
|
||||
|
||||
@@ -50,17 +50,16 @@ 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.NATIVE_NULLPTR
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import dev.patrickgold.florisboard.lib.cache.CacheManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisBulletSpacer
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisButtonBar
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.florisHorizontalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.io.FileRegistry
|
||||
import org.florisboard.lib.compose.FlorisBulletSpacer
|
||||
import org.florisboard.lib.compose.FlorisButtonBar
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.FlorisOutlinedButton
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.kotlin.resultOk
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisChip
|
||||
import org.florisboard.lib.compose.FlorisChip
|
||||
|
||||
@Composable
|
||||
fun ExtensionKeywordChip(
|
||||
|
||||
@@ -52,14 +52,14 @@ import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.extensionManager
|
||||
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.FlorisTextButton
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.florisScrollbar
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionManager
|
||||
import dev.patrickgold.florisboard.lib.observeAsNonNullState
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.FlorisTextButton
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.florisScrollbar
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
enum class ExtensionListScreenType(
|
||||
val id: String,
|
||||
|
||||
@@ -30,10 +30,10 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisChip
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionMaintainer
|
||||
import dev.patrickgold.florisboard.lib.util.launchUrl
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import org.florisboard.lib.compose.FlorisChip
|
||||
|
||||
@Composable
|
||||
fun ExtensionMaintainerChip(
|
||||
|
||||
@@ -24,7 +24,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
internal fun ExtensionNotFoundScreen(id: String) = FlorisScreen {
|
||||
|
||||
@@ -51,18 +51,17 @@ import dev.patrickgold.florisboard.extensionManager
|
||||
import dev.patrickgold.florisboard.ime.nlp.LanguagePackExtension
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeExtension
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeExtensionComponentImpl
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisConfirmDeleteDialog
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisHyperlinkText
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.Extension
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionMaintainer
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionMeta
|
||||
import dev.patrickgold.florisboard.lib.io.FlorisRef
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.compose.FlorisOutlinedButton
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun ExtensionViewScreen(id: String) {
|
||||
|
||||
@@ -37,13 +37,13 @@ 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.compose.FlorisErrorCard
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisWarningCard
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.util.InputMethodUtils
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import org.florisboard.lib.compose.FlorisErrorCard
|
||||
import org.florisboard.lib.compose.FlorisWarningCard
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun HomeScreen() = FlorisScreen {
|
||||
|
||||
@@ -41,12 +41,12 @@ import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.clipboardManager
|
||||
import dev.patrickgold.florisboard.lib.util.launchUrl
|
||||
import org.florisboard.lib.android.stringRes
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisCanvasIcon
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.util.launchUrl
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import org.florisboard.lib.android.stringRes
|
||||
import org.florisboard.lib.compose.FlorisCanvasIcon
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun AboutScreen() = FlorisScreen {
|
||||
|
||||
@@ -29,11 +29,11 @@ import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.sp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.florisHorizontalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.florisVerticalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.io.FlorisRef
|
||||
import dev.patrickgold.florisboard.lib.io.loadTextAsset
|
||||
import org.florisboard.lib.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.compose.florisVerticalScroll
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun ProjectLicenseScreen() = FlorisScreen {
|
||||
|
||||
@@ -26,8 +26,8 @@ import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
|
||||
import com.mikepenz.aboutlibraries.ui.compose.m3.libraryColors
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.florisScrollbar
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.compose.florisScrollbar
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun ThirdPartyLicensesScreen() = FlorisScreen {
|
||||
|
||||
@@ -50,12 +50,7 @@ import dev.patrickgold.florisboard.clipboardManager
|
||||
import dev.patrickgold.florisboard.ime.clipboard.provider.ClipboardFileStorage
|
||||
import dev.patrickgold.florisboard.ime.clipboard.provider.ItemType
|
||||
import dev.patrickgold.florisboard.lib.cache.CacheManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisButtonBar
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.rippleClickable
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.devtools.flogError
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionManager
|
||||
import dev.patrickgold.florisboard.lib.io.FileRegistry
|
||||
@@ -69,6 +64,11 @@ import kotlinx.serialization.Serializable
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.android.writeFromFile
|
||||
import org.florisboard.lib.compose.FlorisButtonBar
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.rippleClickable
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.io.subDir
|
||||
import org.florisboard.lib.kotlin.io.subFile
|
||||
import org.florisboard.lib.kotlin.io.writeJson
|
||||
|
||||
@@ -27,7 +27,9 @@ import androidx.compose.material.icons.filled.SettingsBackupRestore
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.AppTheme
|
||||
import dev.patrickgold.florisboard.app.LocalNavController
|
||||
@@ -36,7 +38,6 @@ import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
|
||||
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
|
||||
import dev.patrickgold.florisboard.lib.FlorisLocale
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.datastore.ui.ColorPickerPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.ListPreference
|
||||
@@ -45,9 +46,9 @@ import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.isMaterialYou
|
||||
import dev.patrickgold.jetpref.datastore.ui.listPrefEntries
|
||||
import dev.patrickgold.jetpref.datastore.ui.vectorResource
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.color.ColorMappings
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
|
||||
@Composable
|
||||
@@ -156,7 +157,7 @@ fun OtherScreen() = FlorisScreen {
|
||||
enabledIf = { AndroidVersion.ATMOST_API28_P },
|
||||
)
|
||||
Preference(
|
||||
icon = vectorResource(R.drawable.ic_keyboard_keys),
|
||||
icon = ImageVector.vectorResource(R.drawable.ic_keyboard_keys),
|
||||
title = stringRes(R.string.physical_keyboard__title),
|
||||
onClick = { navController.navigate(Routes.Settings.PhysicalKeyboard) },
|
||||
)
|
||||
|
||||
@@ -28,9 +28,9 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun PhysicalKeyboardScreen() = FlorisScreen {
|
||||
|
||||
@@ -52,32 +52,32 @@ import dev.patrickgold.florisboard.ime.clipboard.provider.ClipboardFileStorage
|
||||
import dev.patrickgold.florisboard.ime.clipboard.provider.ClipboardItem
|
||||
import dev.patrickgold.florisboard.ime.clipboard.provider.ItemType
|
||||
import dev.patrickgold.florisboard.lib.cache.CacheManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisButtonBar
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisCardDefaults
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionManager
|
||||
import dev.patrickgold.florisboard.lib.io.ZipUtils
|
||||
import dev.patrickgold.jetpref.datastore.runtime.AndroidAppDataStorage
|
||||
import dev.patrickgold.jetpref.datastore.runtime.FileBasedStorage
|
||||
import dev.patrickgold.jetpref.datastore.runtime.ImportStrategy
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import java.io.FileNotFoundException
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.readToFile
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.compose.FlorisButtonBar
|
||||
import org.florisboard.lib.compose.FlorisCardDefaults
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.FlorisOutlinedButton
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.io.deleteContentsRecursively
|
||||
import org.florisboard.lib.kotlin.io.readJson
|
||||
import org.florisboard.lib.kotlin.io.subDir
|
||||
import org.florisboard.lib.kotlin.io.subFile
|
||||
import java.io.FileNotFoundException
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
object Restore {
|
||||
const val MIN_VERSION_CODE = 64
|
||||
|
||||
@@ -20,13 +20,13 @@ import androidx.compose.runtime.Composable
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.clipboard.CLIPBOARD_HISTORY_NUM_GRID_COLUMNS_AUTO
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.pluralsRes
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.compose.pluralsRes
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@OptIn(ExperimentalJetPrefDatastoreUi::class)
|
||||
@Composable
|
||||
|
||||
@@ -21,9 +21,9 @@ import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun DictionaryScreen() = FlorisScreen {
|
||||
|
||||
@@ -55,11 +55,8 @@ import dev.patrickgold.florisboard.ime.dictionary.UserDictionaryDao
|
||||
import dev.patrickgold.florisboard.ime.dictionary.UserDictionaryEntry
|
||||
import dev.patrickgold.florisboard.ime.dictionary.UserDictionaryValidation
|
||||
import dev.patrickgold.florisboard.lib.FlorisLocale
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.Validation
|
||||
import dev.patrickgold.florisboard.lib.compose.rippleClickable
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.rememberValidationResult
|
||||
import dev.patrickgold.florisboard.lib.util.launchActivity
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
@@ -70,6 +67,9 @@ import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.android.stringRes
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.rippleClickable
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
private val AllLanguagesLocale = FlorisLocale.from(language = "zz")
|
||||
private val UserDictionaryEntryToAdd = UserDictionaryEntry(id = 0, "", 255, null, null)
|
||||
|
||||
@@ -23,14 +23,13 @@ import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
|
||||
import dev.patrickgold.florisboard.ime.text.gestures.SwipeAction
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisInfoCard
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
|
||||
import dev.patrickgold.jetpref.datastore.ui.ListPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import org.florisboard.lib.compose.FlorisInfoCard
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@OptIn(ExperimentalJetPrefDatastoreUi::class)
|
||||
@Composable
|
||||
|
||||
@@ -23,7 +23,6 @@ import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
|
||||
import dev.patrickgold.florisboard.ime.input.HapticVibrationMode
|
||||
import dev.patrickgold.florisboard.ime.input.InputFeedbackActivationMode
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
|
||||
import dev.patrickgold.jetpref.datastore.ui.ListPreference
|
||||
@@ -31,6 +30,7 @@ import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import org.florisboard.lib.android.systemVibratorOrNull
|
||||
import org.florisboard.lib.android.vibrate
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@OptIn(ExperimentalJetPrefDatastoreUi::class)
|
||||
@Composable
|
||||
|
||||
@@ -29,13 +29,13 @@ import dev.patrickgold.florisboard.ime.smartbar.IncognitoDisplayMode
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyHintMode
|
||||
import dev.patrickgold.florisboard.ime.text.key.UtilityKeyAction
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
|
||||
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.SwitchPreference
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@OptIn(ExperimentalJetPrefDatastoreUi::class)
|
||||
@Composable
|
||||
|
||||
@@ -47,20 +47,20 @@ import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.app.ext.ExtensionImportScreenType
|
||||
import dev.patrickgold.florisboard.extensionManager
|
||||
import dev.patrickgold.florisboard.ime.nlp.LanguagePackComponent
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisConfirmDeleteDialog
|
||||
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.rippleClickable
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.Extension
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
|
||||
import dev.patrickgold.florisboard.lib.observeAsNonNullState
|
||||
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefListItem
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.FlorisTextButton
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.rippleClickable
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
|
||||
enum class LanguagePackManagerScreenAction(val id: String) {
|
||||
|
||||
@@ -45,8 +45,6 @@ import dev.patrickgold.florisboard.ime.core.Subtype
|
||||
import dev.patrickgold.florisboard.ime.keyboard.LayoutType
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisWarningCard
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.observeAsNonNullState
|
||||
import dev.patrickgold.florisboard.subtypeManager
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
@@ -55,8 +53,9 @@ import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.florisboard.lib.compose.FlorisWarningCard
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
internal val SubtypeSaver = Saver<MutableState<Subtype?>, String>(
|
||||
save = {
|
||||
|
||||
@@ -49,10 +49,10 @@ import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
|
||||
import dev.patrickgold.florisboard.lib.FlorisLocale
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.florisScrollbar
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefListItem
|
||||
import org.florisboard.lib.compose.florisScrollbar
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
const val SelectLocaleScreenResultLanguageTag = "SelectLocaleScreen.languageTag"
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.ListItemDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ShapeDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
@@ -74,18 +75,20 @@ import dev.patrickgold.florisboard.ime.nlp.han.HanShapeBasedLanguageProvider
|
||||
import dev.patrickgold.florisboard.ime.nlp.latin.LatinLanguageProvider
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.FlorisLocale
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisButtonBar
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisDropdownLikeButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisDropdownMenu
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.florisScrollbar
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
|
||||
import dev.patrickgold.florisboard.lib.observeAsNonNullState
|
||||
import dev.patrickgold.florisboard.subtypeManager
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefDropdown
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefDropdownMenuDefaults
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefListItem
|
||||
import org.florisboard.lib.compose.FlorisButtonBar
|
||||
import org.florisboard.lib.compose.FlorisDropdownLikeButton
|
||||
import org.florisboard.lib.compose.florisScrollbar
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
|
||||
private val SelectComponentName = ExtensionComponentName("00", "00")
|
||||
private val SelectNlpProviderId = SelectComponentName.toString()
|
||||
@@ -365,6 +368,7 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
onClick = {
|
||||
navController.navigate(Routes.Settings.SelectLocale)
|
||||
},
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
)
|
||||
}
|
||||
SubtypeProperty(stringRes(R.string.settings__localization__subtype_popup_mapping)) {
|
||||
@@ -374,16 +378,15 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val popupMappingLabels = remember(popupMappings) {
|
||||
selectListValues + popupMappings.values.map { it.label }
|
||||
}
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
val selectedIndex = popupMappingIds.indexOf(popupMapping).coerceAtLeast(0)
|
||||
FlorisDropdownMenu(
|
||||
items = popupMappingLabels,
|
||||
JetPrefDropdown(
|
||||
options = popupMappingLabels,
|
||||
expanded = expanded,
|
||||
selectedIndex = selectedIndex,
|
||||
selectedOptionIndex = selectedIndex,
|
||||
isError = showSelectAsError && selectedIndex == 0,
|
||||
onSelectItem = { popupMapping = popupMappingIds[it] },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
onSelectOption = { popupMapping = popupMappingIds[it] },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
)
|
||||
}
|
||||
SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_characters_layout), LayoutType.CHARACTERS)
|
||||
@@ -404,19 +407,18 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val nlpProviderMappingLabels = remember(nlpProviderMappings) {
|
||||
selectListValues + nlpProviderMappings.values.map { it }
|
||||
}
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
val selectedIndex = nlpProviderMappingIds.indexOf(nlpProviders.suggestion).coerceAtLeast(0)
|
||||
FlorisDropdownMenu(
|
||||
items = nlpProviderMappingLabels,
|
||||
JetPrefDropdown(
|
||||
options = nlpProviderMappingLabels,
|
||||
expanded = expanded,
|
||||
selectedIndex = selectedIndex,
|
||||
selectedOptionIndex = selectedIndex,
|
||||
isError = showSelectAsError && selectedIndex == 0,
|
||||
onSelectItem = { nlpProviders = SubtypeNlpProviderMap(
|
||||
onSelectOption = { nlpProviders = SubtypeNlpProviderMap(
|
||||
suggestion = nlpProviderMappingIds[it],
|
||||
spelling = nlpProviderMappingIds[it]
|
||||
) },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -432,15 +434,14 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val composerNames = remember(composers) {
|
||||
selectListValues + composers.values.map { it.label }
|
||||
}
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
FlorisDropdownMenu(
|
||||
items = composerNames,
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
JetPrefDropdown(
|
||||
options = composerNames,
|
||||
expanded = expanded,
|
||||
selectedIndex = composerIds.indexOf(composer).coerceAtLeast(0),
|
||||
selectedOptionIndex = composerIds.indexOf(composer).coerceAtLeast(0),
|
||||
isError = showSelectAsError && composer == SelectComponentName,
|
||||
onSelectItem = { composer = composerIds[it] },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
onSelectOption = { composer = composerIds[it] },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
)
|
||||
}
|
||||
SubtypeProperty(stringRes(R.string.settings__localization__subtype_currency_set)) {
|
||||
@@ -450,15 +451,14 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val currencySetNames = remember(currencySets) {
|
||||
selectListValues + currencySets.values.map { it.label }
|
||||
}
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
FlorisDropdownMenu(
|
||||
items = currencySetNames,
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
JetPrefDropdown(
|
||||
options = currencySetNames,
|
||||
expanded = expanded,
|
||||
selectedIndex = currencySetIds.indexOf(currencySet).coerceAtLeast(0),
|
||||
selectedOptionIndex = currencySetIds.indexOf(currencySet).coerceAtLeast(0),
|
||||
isError = showSelectAsError && currencySet == SelectComponentName,
|
||||
onSelectItem = { currencySet = currencySetIds[it] },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
onSelectOption = { currencySet = currencySetIds[it] },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -556,16 +556,15 @@ private fun SubtypeLayoutDropdown(
|
||||
val layoutIds = remember(layouts) { SelectListKeys + layouts.keys.toList() }
|
||||
val layoutLabels = remember(layouts) { selectListValues + layouts.values.map { it.label } }
|
||||
val layoutId = remember(layoutMap) { layoutMap[layoutType] }
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
val selectedIndex = layoutIds.indexOf(layoutId).coerceAtLeast(0)
|
||||
FlorisDropdownMenu(
|
||||
items = layoutLabels,
|
||||
JetPrefDropdown(
|
||||
options = layoutLabels,
|
||||
expanded = expanded,
|
||||
selectedIndex = selectedIndex,
|
||||
selectedOptionIndex = selectedIndex,
|
||||
isError = showSelectAsError && selectedIndex == 0,
|
||||
onSelectItem = { onLayoutMapChanged(layoutMap.copy(layoutType, layoutIds[it])!!) },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
onSelectOption = { onLayoutMapChanged(layoutMap.copy(layoutType = layoutType, componentName = layoutIds[it])!!) },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ import dev.patrickgold.florisboard.ime.media.emoji.EmojiHistoryHelper
|
||||
import dev.patrickgold.florisboard.ime.media.emoji.EmojiSkinTone
|
||||
import dev.patrickgold.florisboard.ime.media.emoji.EmojiSuggestionType
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.pluralsRes
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
|
||||
import dev.patrickgold.jetpref.datastore.ui.ListPreference
|
||||
@@ -44,6 +42,8 @@ import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.compose.pluralsRes
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@OptIn(ExperimentalJetPrefDatastoreUi::class)
|
||||
@Composable
|
||||
|
||||
@@ -24,10 +24,10 @@ import dev.patrickgold.florisboard.ime.smartbar.CandidatesDisplayMode
|
||||
import dev.patrickgold.florisboard.ime.smartbar.ExtendedActionsPlacement
|
||||
import dev.patrickgold.florisboard.ime.smartbar.SmartbarLayout
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.ListPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun SmartbarScreen() = FlorisScreen {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.app.settings.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import dev.patrickgold.jetpref.datastore.model.PreferenceSerializer
|
||||
@@ -77,13 +77,7 @@ import dev.patrickgold.florisboard.app.ext.FONTS
|
||||
import dev.patrickgold.florisboard.app.ext.IMAGES
|
||||
import dev.patrickgold.florisboard.lib.ValidationResult
|
||||
import dev.patrickgold.florisboard.lib.cache.CacheManager
|
||||
import dev.patrickgold.florisboard.lib.compose.DpSizeSaver
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisChip
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisTextButton
|
||||
import dev.patrickgold.florisboard.lib.compose.Validation
|
||||
import dev.patrickgold.florisboard.lib.compose.florisVerticalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionValidation
|
||||
import dev.patrickgold.florisboard.lib.rememberValidationResult
|
||||
import dev.patrickgold.jetpref.material.ui.ColorRepresentation
|
||||
@@ -94,7 +88,14 @@ import dev.patrickgold.jetpref.material.ui.JetPrefDropdown
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefListItem
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefTextField
|
||||
import dev.patrickgold.jetpref.material.ui.rememberJetPrefColorPickerState
|
||||
import java.io.File
|
||||
import org.florisboard.lib.color.ColorPalette
|
||||
import org.florisboard.lib.compose.DpSizeSaver
|
||||
import org.florisboard.lib.compose.FlorisChip
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.FlorisTextButton
|
||||
import org.florisboard.lib.compose.florisVerticalScroll
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
import org.florisboard.lib.kotlin.io.subDir
|
||||
import org.florisboard.lib.kotlin.toStringWithoutDotZero
|
||||
@@ -131,7 +132,6 @@ import org.florisboard.lib.snygg.value.SnyggUndefinedValue
|
||||
import org.florisboard.lib.snygg.value.SnyggUriValue
|
||||
import org.florisboard.lib.snygg.value.SnyggValue
|
||||
import org.florisboard.lib.snygg.value.SnyggValueEncoder
|
||||
import java.io.File
|
||||
|
||||
internal val SnyggEmptyPropertyInfoForAdding = PropertyInfo(
|
||||
rule = SnyggEmptyRuleForAdding,
|
||||
|
||||
@@ -85,11 +85,7 @@ import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.NATIVE_NULLPTR
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisChip
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisHyperlinkText
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
import dev.patrickgold.florisboard.lib.compose.florisHorizontalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.util.InputMethodUtils
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefDropdown
|
||||
@@ -98,6 +94,10 @@ import dev.patrickgold.jetpref.material.ui.JetPrefTextFieldDefaults
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
import org.florisboard.lib.android.stringRes
|
||||
import org.florisboard.lib.compose.FlorisChip
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
import org.florisboard.lib.snygg.SnyggAnnotationRule
|
||||
import org.florisboard.lib.snygg.SnyggAttributes
|
||||
|
||||
@@ -22,11 +22,11 @@ import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.ListPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceLayout
|
||||
import dev.patrickgold.jetpref.material.ui.ColorRepresentation
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
private val FineTuneContentPadding = PaddingValues(horizontal = 8.dp)
|
||||
|
||||
|
||||
@@ -80,16 +80,10 @@ import dev.patrickgold.florisboard.ime.theme.ThemeExtensionEditor
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeManager
|
||||
import dev.patrickgold.florisboard.ime.theme.extPreviewTheme
|
||||
import dev.patrickgold.florisboard.lib.cache.CacheManager
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisIconButton
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.PreviewKeyboardField
|
||||
import dev.patrickgold.florisboard.lib.compose.Validation
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.florisVerticalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.rememberPreviewFieldController
|
||||
import dev.patrickgold.florisboard.lib.compose.rippleClickable
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionValidation
|
||||
import dev.patrickgold.florisboard.lib.rememberValidationResult
|
||||
import dev.patrickgold.florisboard.themeManager
|
||||
@@ -100,7 +94,13 @@ import dev.patrickgold.jetpref.material.ui.JetPrefTextField
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.florisVerticalScroll
|
||||
import org.florisboard.lib.compose.rippleClickable
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.io.subFile
|
||||
import org.florisboard.lib.snygg.SnyggAnnotationRule
|
||||
import org.florisboard.lib.snygg.SnyggElementRule
|
||||
|
||||
@@ -36,16 +36,16 @@ import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.extensionManager
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeExtensionComponent
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import dev.patrickgold.florisboard.lib.compose.rippleClickable
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
|
||||
import dev.patrickgold.florisboard.lib.observeAsNonNullState
|
||||
import dev.patrickgold.florisboard.themeManager
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefListItem
|
||||
import org.florisboard.lib.compose.FlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.defaultFlorisOutlinedBox
|
||||
import org.florisboard.lib.compose.rippleClickable
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
enum class ThemeManagerScreenAction(val id: String) {
|
||||
|
||||
@@ -37,7 +37,6 @@ import dev.patrickgold.florisboard.app.ext.ExtensionListScreenType
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeManager
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeMode
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
|
||||
import dev.patrickgold.florisboard.themeManager
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
@@ -47,6 +46,7 @@ import dev.patrickgold.jetpref.datastore.ui.LocalTimePickerPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
import dev.patrickgold.jetpref.datastore.ui.isMaterialYou
|
||||
import org.florisboard.lib.color.ColorMappings
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun ThemeScreen() = FlorisScreen {
|
||||
|
||||
@@ -34,14 +34,14 @@ 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.lib.compose.FlorisCanvasIcon
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisErrorCard
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisSimpleCard
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisWarningCard
|
||||
import dev.patrickgold.florisboard.lib.compose.observeAsState
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.util.launchActivity
|
||||
import org.florisboard.lib.android.AndroidSettings
|
||||
import org.florisboard.lib.compose.FlorisCanvasIcon
|
||||
import org.florisboard.lib.compose.FlorisErrorCard
|
||||
import org.florisboard.lib.compose.FlorisSimpleCard
|
||||
import org.florisboard.lib.compose.FlorisWarningCard
|
||||
import org.florisboard.lib.compose.observeAsState
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun SpellCheckerServiceSelector(florisSpellCheckerEnabled: MutableState<Boolean>) {
|
||||
|
||||
@@ -30,6 +30,8 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.LocalNavController
|
||||
@@ -37,19 +39,17 @@ import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
|
||||
import dev.patrickgold.florisboard.ime.keyboard.IncognitoMode
|
||||
import dev.patrickgold.florisboard.ime.nlp.SpellingLanguageMode
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisErrorCard
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisHyperlinkText
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
|
||||
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.SwitchPreference
|
||||
import dev.patrickgold.jetpref.datastore.ui.vectorResource
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.compose.FlorisErrorCard
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@OptIn(ExperimentalJetPrefDatastoreUi::class)
|
||||
@Composable
|
||||
@@ -89,7 +89,7 @@ fun TypingScreen() = FlorisScreen {
|
||||
)
|
||||
ListPreference(
|
||||
prefs.suggestion.incognitoMode,
|
||||
icon = vectorResource(id = R.drawable.ic_incognito),
|
||||
icon = ImageVector.vectorResource(id = R.drawable.ic_incognito),
|
||||
title = stringRes(R.string.pref__suggestion__incognito_mode__label),
|
||||
entries = enumDisplayEntriesOf(IncognitoMode::class),
|
||||
)
|
||||
|
||||
@@ -46,13 +46,8 @@ import dev.patrickgold.florisboard.app.FlorisPreferenceModel
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.florisboard.app.Routes
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisBulletSpacer
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreenScope
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisStep
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisStepLayout
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisStepState
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.util.InputMethodUtils
|
||||
import dev.patrickgold.florisboard.lib.util.launchActivity
|
||||
import dev.patrickgold.florisboard.lib.util.launchUrl
|
||||
@@ -62,6 +57,11 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.compose.FlorisBulletSpacer
|
||||
import org.florisboard.lib.compose.FlorisStep
|
||||
import org.florisboard.lib.compose.FlorisStepLayout
|
||||
import org.florisboard.lib.compose.FlorisStepState
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun SetupScreen() = FlorisScreen {
|
||||
|
||||
@@ -102,16 +102,11 @@ import dev.patrickgold.florisboard.ime.smartbar.VerticalExitTransition
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.LocalLocalizedDateTimeFormatter
|
||||
import dev.patrickgold.florisboard.lib.compose.autoMirrorForRtl
|
||||
import dev.patrickgold.florisboard.lib.compose.florisHorizontalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.florisVerticalScroll
|
||||
import dev.patrickgold.florisboard.lib.compose.rippleClickable
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.observeAsNonNullState
|
||||
import dev.patrickgold.florisboard.lib.observeAsTransformingState
|
||||
import dev.patrickgold.florisboard.lib.util.NetworkUtils
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import java.time.Instant
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.AndroidKeyguardManager
|
||||
@@ -119,6 +114,12 @@ import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
import org.florisboard.lib.android.systemService
|
||||
import org.florisboard.lib.compose.LocalLocalizedDateTimeFormatter
|
||||
import org.florisboard.lib.compose.autoMirrorForRtl
|
||||
import org.florisboard.lib.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.compose.florisVerticalScroll
|
||||
import org.florisboard.lib.compose.rippleClickable
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.snygg.SnyggQueryAttributes
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggButton
|
||||
@@ -128,7 +129,6 @@ import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
import org.florisboard.lib.snygg.ui.SnyggIconButton
|
||||
import org.florisboard.lib.snygg.ui.SnyggRow
|
||||
import org.florisboard.lib.snygg.ui.SnyggText
|
||||
import java.time.Instant
|
||||
|
||||
private val ItemWidth = 200.dp
|
||||
private val DialogWidth = 240.dp
|
||||
|
||||
@@ -49,13 +49,13 @@ import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.app.apptheme.FlorisAppTheme
|
||||
import dev.patrickgold.florisboard.lib.compose.ProvideLocalizedResources
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import org.florisboard.lib.android.AndroidClipboardManager
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.android.stringRes
|
||||
import org.florisboard.lib.android.systemService
|
||||
import org.florisboard.lib.compose.ProvideLocalizedResources
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.mimeTypeFilterOf
|
||||
|
||||
class FlorisCopyToClipboardActivity : ComponentActivity() {
|
||||
@@ -136,7 +136,11 @@ class FlorisCopyToClipboardActivity : ComponentActivity() {
|
||||
@Composable
|
||||
private fun Content() {
|
||||
val prefs by FlorisPreferenceStore
|
||||
ProvideLocalizedResources(this, forceLayoutDirection = LayoutDirection.Ltr) {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext = this,
|
||||
appName = R.string.app_name,
|
||||
forceLayoutDirection = LayoutDirection.Ltr,
|
||||
) {
|
||||
val theme by prefs.other.settingsTheme.observeAsState()
|
||||
FlorisAppTheme(theme) {
|
||||
BottomSheet {
|
||||
|
||||
@@ -35,8 +35,8 @@ import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.keyboard.KeyboardState
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.subtypeManager
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggColumn
|
||||
import org.florisboard.lib.snygg.ui.SnyggListItem
|
||||
|
||||
@@ -40,6 +40,16 @@ import org.florisboard.lib.kotlin.guardedByLock
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
enum class OperationUnit {
|
||||
CHARACTERS,
|
||||
WORDS;
|
||||
}
|
||||
|
||||
enum class OperationScope {
|
||||
BEFORE_CURSOR,
|
||||
AFTER_CURSOR;
|
||||
}
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
abstract class AbstractEditorInstance(context: Context) {
|
||||
companion object {
|
||||
@@ -428,41 +438,69 @@ abstract class AbstractEditorInstance(context: Context) {
|
||||
return true
|
||||
}
|
||||
|
||||
protected fun deleteBeforeCursor(type: TextType, n: Int): Boolean {
|
||||
protected suspend fun deleteAroundCursor(unit: OperationUnit, scope: OperationScope, n: Int = 0): Boolean {
|
||||
val ic = currentInputConnection()
|
||||
if (ic == null || n < 1) return false
|
||||
val content = activeContent
|
||||
// Cannot perform below check due to editors which lie about their correct selection
|
||||
//if (content.selection.isValid && content.selection.start == 0) return true
|
||||
val oldTextBeforeSelection = content.textBeforeSelection
|
||||
return (if (activeInfo.isRawInputEditor || oldTextBeforeSelection.isEmpty()) {
|
||||
val scopeText = when (scope) {
|
||||
OperationScope.BEFORE_CURSOR -> content.textBeforeSelection
|
||||
OperationScope.AFTER_CURSOR -> content.textAfterSelection
|
||||
}
|
||||
return (if (activeInfo.isRawInputEditor || scopeText.isEmpty()) {
|
||||
// If editor is rich and text before selection is empty we seem to have an invalid state here, so we fall
|
||||
// back to emulating a hardware backspace.
|
||||
when (type) {
|
||||
TextType.CHARACTERS -> sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL, count = n)
|
||||
TextType.WORDS -> sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL, meta(ctrl = true), count = n)
|
||||
// back to emulating a hardware backspace/forward delete.
|
||||
val keyEventCode = when (scope) {
|
||||
OperationScope.BEFORE_CURSOR -> KeyEvent.KEYCODE_DEL
|
||||
OperationScope.AFTER_CURSOR -> KeyEvent.KEYCODE_FORWARD_DEL
|
||||
}
|
||||
val metaState = when (unit) {
|
||||
OperationUnit.CHARACTERS -> meta()
|
||||
OperationUnit.WORDS -> meta(ctrl = true)
|
||||
}
|
||||
sendDownUpKeyEvent(keyEventCode, metaState, count = n)
|
||||
} else {
|
||||
runBlocking {
|
||||
val locale = subtypeManager.activeSubtype.primaryLocale
|
||||
val length = when (type) {
|
||||
TextType.CHARACTERS -> breakIterators.measureLastUChars(oldTextBeforeSelection, n, locale)
|
||||
TextType.WORDS -> breakIterators.measureLastUWords(oldTextBeforeSelection, n, locale)
|
||||
val locale = subtypeManager.activeSubtype.primaryLocale
|
||||
when (scope) {
|
||||
OperationScope.BEFORE_CURSOR -> {
|
||||
val length = when (unit) {
|
||||
OperationUnit.CHARACTERS -> breakIterators.measureLastUChars(scopeText, n, locale)
|
||||
OperationUnit.WORDS -> breakIterators.measureLastUWords(scopeText, n, locale)
|
||||
}
|
||||
val selection = content.selection
|
||||
val newSelection = selection.translatedBy(-length)
|
||||
val newContent = content.generateCopy(
|
||||
selection = newSelection,
|
||||
textBeforeSelection = scopeText.dropLast(length),
|
||||
)
|
||||
expectedContentQueue.push(newContent)
|
||||
ic.beginBatchEdit()
|
||||
ic.finishComposingText()
|
||||
ic.deleteSurroundingText(length, 0)
|
||||
ic.setComposingRegion(newContent.composing)
|
||||
ic.endBatchEdit()
|
||||
}
|
||||
OperationScope.AFTER_CURSOR -> {
|
||||
val length = when (unit) {
|
||||
OperationUnit.CHARACTERS -> breakIterators.measureUChars(scopeText, n, locale)
|
||||
OperationUnit.WORDS -> breakIterators.measureUWords(scopeText, n, locale)
|
||||
}
|
||||
val selection = content.selection
|
||||
val newSelection = selection.translatedBy(length)
|
||||
val newContent = content.generateCopy(
|
||||
selection = newSelection,
|
||||
textAfterSelection = scopeText.drop(length),
|
||||
)
|
||||
expectedContentQueue.push(newContent)
|
||||
ic.beginBatchEdit()
|
||||
ic.finishComposingText()
|
||||
ic.deleteSurroundingText(0, length)
|
||||
ic.setComposingRegion(newContent.composing)
|
||||
ic.endBatchEdit()
|
||||
}
|
||||
val selection = content.selection
|
||||
val newSelection = selection.translatedBy(-length)
|
||||
val newContent = content.generateCopy(
|
||||
selection = newSelection,
|
||||
textBeforeSelection = oldTextBeforeSelection.dropLast(length),
|
||||
)
|
||||
expectedContentQueue.push(newContent)
|
||||
ic.beginBatchEdit()
|
||||
ic.finishComposingText()
|
||||
ic.deleteSurroundingText(length, 0)
|
||||
ic.setComposingRegion(newContent.composing)
|
||||
ic.endBatchEdit()
|
||||
true
|
||||
}
|
||||
true
|
||||
}).also {
|
||||
deleteMoveLastCommitPosition()
|
||||
}
|
||||
@@ -623,11 +661,6 @@ abstract class AbstractEditorInstance(context: Context) {
|
||||
return true
|
||||
}
|
||||
|
||||
protected enum class TextType {
|
||||
CHARACTERS,
|
||||
WORDS;
|
||||
}
|
||||
|
||||
private class ExpectedContentQueue {
|
||||
private val list = guardedByLock { mutableListOf<EditorContent>() }
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ import dev.patrickgold.florisboard.nlpManager
|
||||
import dev.patrickgold.florisboard.subtypeManager
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
|
||||
class EditorInstance(context: Context) : AbstractEditorInstance(context) {
|
||||
@@ -336,34 +335,37 @@ class EditorInstance(context: Context) : AbstractEditorInstance(context) {
|
||||
*
|
||||
* @return True on success, false if an error occurred or the input connection is invalid.
|
||||
*/
|
||||
fun deleteBackwards(): Boolean {
|
||||
fun deleteBackwards(unit: OperationUnit): Boolean {
|
||||
val content = activeContent
|
||||
if (phantomSpace.isActive && content.currentWord.isValid && prefs.glide.immediateBackspaceDeletesWord.get()) {
|
||||
return deleteWordBackwards()
|
||||
if (unit == OperationUnit.CHARACTERS) {
|
||||
if (phantomSpace.isActive && content.currentWord.isValid && prefs.glide.immediateBackspaceDeletesWord.get()) {
|
||||
return deleteBackwards(OperationUnit.WORDS)
|
||||
}
|
||||
}
|
||||
autoSpace.setInactive()
|
||||
phantomSpace.setInactive()
|
||||
return if (content.selection.isSelectionMode) {
|
||||
commitText("")
|
||||
} else {
|
||||
deleteBeforeCursor(TextType.CHARACTERS, 1)
|
||||
} else runBlocking {
|
||||
deleteAroundCursor(unit, OperationScope.BEFORE_CURSOR, n = 1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a backward delete on this editor's text. If a text selection is active, all
|
||||
* characters inside this selection will be removed, else only the left-most word from
|
||||
* characters inside this selection will be removed, else only the left-most character from
|
||||
* the cursor's position.
|
||||
*
|
||||
* @return True on success, false if an error occurred or the input connection is invalid.
|
||||
*/
|
||||
fun deleteWordBackwards(): Boolean {
|
||||
fun deleteForwards(unit: OperationUnit): Boolean {
|
||||
val content = activeContent
|
||||
autoSpace.setInactive()
|
||||
phantomSpace.setInactive()
|
||||
return if (activeContent.selection.isSelectionMode) {
|
||||
return if (content.selection.isSelectionMode) {
|
||||
commitText("")
|
||||
} else {
|
||||
deleteBeforeCursor(TextType.WORDS, 1)
|
||||
} else runBlocking {
|
||||
deleteAroundCursor(unit, OperationScope.AFTER_CURSOR, n = 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +398,7 @@ class EditorInstance(context: Context) : AbstractEditorInstance(context) {
|
||||
} else {
|
||||
appContext.showShortToastSync("Failed to retrieve selected text requested to cut: Eiter selection state is invalid or an error occurred within the input connection.")
|
||||
}
|
||||
return deleteBackwards()
|
||||
return deleteBackwards(OperationUnit.CHARACTERS)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,8 +19,10 @@ package dev.patrickgold.florisboard.ime.keyboard
|
||||
import android.content.Context
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowRightAlt
|
||||
import androidx.compose.material.icons.automirrored.filled.Backspace
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardBackspace
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardReturn
|
||||
import androidx.compose.material.icons.automirrored.filled.Redo
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
@@ -55,7 +57,8 @@ import dev.patrickgold.florisboard.ime.input.InputShiftState
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyType
|
||||
import dev.patrickgold.florisboard.lib.FlorisLocale
|
||||
import dev.patrickgold.jetpref.datastore.ui.vectorResource
|
||||
import dev.patrickgold.florisboard.lib.compose.vectorResource
|
||||
import org.florisboard.lib.compose.icons.ForwardDelete
|
||||
|
||||
interface ComputingEvaluator {
|
||||
val version: Int
|
||||
@@ -234,6 +237,9 @@ fun ComputingEvaluator.computeImageVector(data: KeyData): ImageVector? {
|
||||
}
|
||||
}
|
||||
}
|
||||
KeyCode.FORWARD_DELETE -> {
|
||||
Icons.AutoMirrored.Default.ForwardDelete
|
||||
}
|
||||
KeyCode.IME_UI_MODE_MEDIA -> {
|
||||
Icons.Default.SentimentSatisfiedAlt
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import dev.patrickgold.florisboard.ime.editor.EditorContent
|
||||
import dev.patrickgold.florisboard.ime.editor.FlorisEditorInfo
|
||||
import dev.patrickgold.florisboard.ime.editor.ImeOptions
|
||||
import dev.patrickgold.florisboard.ime.editor.InputAttributes
|
||||
import dev.patrickgold.florisboard.ime.editor.OperationUnit
|
||||
import dev.patrickgold.florisboard.ime.input.CapitalizationBehavior
|
||||
import dev.patrickgold.florisboard.ime.input.InputEventDispatcher
|
||||
import dev.patrickgold.florisboard.ime.input.InputKeyEventReceiver
|
||||
@@ -75,7 +76,6 @@ import kotlinx.coroutines.sync.withLock
|
||||
import org.florisboard.lib.android.AndroidKeyguardManager
|
||||
import org.florisboard.lib.android.showLongToast
|
||||
import org.florisboard.lib.android.showLongToastSync
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
import org.florisboard.lib.android.systemService
|
||||
import org.florisboard.lib.kotlin.collectIn
|
||||
@@ -417,27 +417,30 @@ class KeyboardManager(context: Context) : InputKeyEventReceiver {
|
||||
/**
|
||||
* Handles a [KeyCode.DELETE] event.
|
||||
*/
|
||||
private fun handleDelete() {
|
||||
private fun handleBackwardDelete(unit: OperationUnit) {
|
||||
if (inputEventDispatcher.isPressed(KeyCode.SHIFT)) {
|
||||
return handleForwardDelete(unit)
|
||||
}
|
||||
activeState.batchEdit {
|
||||
it.isManualSelectionMode = false
|
||||
it.isManualSelectionModeStart = false
|
||||
it.isManualSelectionModeEnd = false
|
||||
}
|
||||
revertPreviouslyAcceptedCandidate()
|
||||
editorInstance.deleteBackwards()
|
||||
editorInstance.deleteBackwards(unit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a [KeyCode.DELETE_WORD] event.
|
||||
* Handles a [KeyCode.FORWARD_DELETE] event.
|
||||
*/
|
||||
private fun handleDeleteWord() {
|
||||
private fun handleForwardDelete(unit: OperationUnit) {
|
||||
activeState.batchEdit {
|
||||
it.isManualSelectionMode = false
|
||||
it.isManualSelectionModeStart = false
|
||||
it.isManualSelectionModeEnd = false
|
||||
}
|
||||
revertPreviouslyAcceptedCandidate()
|
||||
editorInstance.deleteWordBackwards()
|
||||
editorInstance.deleteForwards(unit)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -566,7 +569,7 @@ class KeyboardManager(context: Context) : InputKeyEventReceiver {
|
||||
if (inputEventDispatcher.isConsecutiveUp(data)) {
|
||||
val text = editorInstance.run { activeContent.getTextBeforeCursor(2) }
|
||||
if (text.length == 2 && DoubleSpacePeriodMatcher.matches(text)) {
|
||||
editorInstance.deleteBackwards()
|
||||
editorInstance.deleteBackwards(OperationUnit.CHARACTERS)
|
||||
editorInstance.commitText(". ")
|
||||
return
|
||||
}
|
||||
@@ -729,9 +732,11 @@ class KeyboardManager(context: Context) : InputKeyEventReceiver {
|
||||
prefs.keyboard.oneHandedMode.set(OneHandedMode.END)
|
||||
toggleOneHandedMode()
|
||||
}
|
||||
KeyCode.DELETE -> handleDelete()
|
||||
KeyCode.DELETE_WORD -> handleDeleteWord()
|
||||
KeyCode.DELETE -> handleBackwardDelete(OperationUnit.CHARACTERS)
|
||||
KeyCode.DELETE_WORD -> handleBackwardDelete(OperationUnit.WORDS)
|
||||
KeyCode.ENTER -> handleEnter()
|
||||
KeyCode.FORWARD_DELETE -> handleForwardDelete(OperationUnit.CHARACTERS)
|
||||
KeyCode.FORWARD_DELETE_WORD -> handleForwardDelete(OperationUnit.WORDS)
|
||||
KeyCode.IME_SHOW_UI -> FlorisImeService.showUi()
|
||||
KeyCode.IME_HIDE_UI -> FlorisImeService.hideUi()
|
||||
KeyCode.IME_PREV_SUBTYPE -> subtypeManager.switchToPrevSubtype()
|
||||
@@ -866,6 +871,20 @@ class KeyboardManager(context: Context) : InputKeyEventReceiver {
|
||||
handleEnter()
|
||||
return true
|
||||
}
|
||||
KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SHIFT_RIGHT -> {
|
||||
inputEventDispatcher.sendDown(TextKeyData.SHIFT)
|
||||
return true
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
||||
fun onHardwareKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SHIFT_RIGHT -> {
|
||||
inputEventDispatcher.sendUp(TextKeyData.SHIFT)
|
||||
return true
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.shape.GenericShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
|
||||
@@ -52,6 +54,7 @@ import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
@@ -60,6 +63,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -87,14 +91,14 @@ import dev.patrickgold.florisboard.ime.keyboard.FlorisImeSizing
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.florisScrollbar
|
||||
import dev.patrickgold.florisboard.lib.compose.header
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.AndroidKeyguardManager
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.android.systemService
|
||||
import org.florisboard.lib.compose.florisScrollbar
|
||||
import org.florisboard.lib.compose.header
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.snygg.SnyggSelector
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
@@ -169,7 +173,6 @@ fun EmojiPaletteView(
|
||||
}
|
||||
}
|
||||
var recentlyUsedVersion by remember { mutableIntStateOf(0) }
|
||||
val lazyListState = rememberLazyGridState()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
@Composable
|
||||
@@ -204,22 +207,111 @@ fun EmojiPaletteView(
|
||||
)
|
||||
}
|
||||
|
||||
Column(modifier = modifier) {
|
||||
fun calculatePageNumbers(): Int {
|
||||
return when {
|
||||
!emojiHistoryEnabled -> EmojiCategoryValues.size - 1
|
||||
else -> EmojiCategoryValues.size
|
||||
}
|
||||
}
|
||||
|
||||
fun pageNumberToCategory(pageNumber: Int): EmojiCategory {
|
||||
return when {
|
||||
!emojiHistoryEnabled -> EmojiCategoryValues[pageNumber + 1]
|
||||
else -> EmojiCategoryValues[pageNumber]
|
||||
}
|
||||
}
|
||||
|
||||
fun categoryToPageNumber(category: EmojiCategory): Int {
|
||||
return if (emojiHistoryEnabled) {
|
||||
EmojiCategoryValues.indexOf(category)
|
||||
} else {
|
||||
EmojiCategoryValues.indexOf(category) - 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun EmojiCategoriesTabRow(
|
||||
activeCategory: EmojiCategory,
|
||||
onCategoryChange: (EmojiCategory) -> Unit,
|
||||
) {
|
||||
val inputFeedbackController = LocalInputFeedbackController.current
|
||||
val selectedTabIndex = categoryToPageNumber(activeCategory)
|
||||
val style = rememberSnyggThemeQuery(FlorisImeUi.MediaEmojiTab.elementName)
|
||||
TabRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(FlorisImeSizing.smartbarHeight),
|
||||
selectedTabIndex = selectedTabIndex,
|
||||
containerColor = Color.Transparent,
|
||||
contentColor = style.foreground(),
|
||||
indicator = { tabPositions ->
|
||||
val style = rememberSnyggThemeQuery(
|
||||
elementName = FlorisImeUi.MediaEmojiTab.elementName,
|
||||
selector = SnyggSelector.FOCUS,
|
||||
)
|
||||
TabRowDefaults.PrimaryIndicator(
|
||||
Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]),
|
||||
height = 4.dp,
|
||||
color = style.foreground(),
|
||||
)
|
||||
},
|
||||
) {
|
||||
for (category in EmojiCategoryValues) {
|
||||
if (category == EmojiCategory.RECENTLY_USED && !emojiHistoryEnabled) {
|
||||
continue
|
||||
}
|
||||
Tab(
|
||||
onClick = {
|
||||
inputFeedbackController.keyPress(TextKeyData.UNSPECIFIED)
|
||||
onCategoryChange(category)
|
||||
},
|
||||
selected = activeCategory == category,
|
||||
icon = { SnyggIcon(
|
||||
elementName = FlorisImeUi.MediaEmojiTab.elementName,
|
||||
selector = if (activeCategory == category) SnyggSelector.FOCUS else SnyggSelector.NONE,
|
||||
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||
imageVector = category.icon(),
|
||||
) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
) {
|
||||
val pagerState = rememberPagerState(
|
||||
pageCount = { calculatePageNumbers() }
|
||||
)
|
||||
|
||||
// Reset the pager to the first page when emojiHistory is enabled
|
||||
LaunchedEffect(emojiHistoryEnabled) {
|
||||
pagerState.animateScrollToPage(0)
|
||||
}
|
||||
|
||||
EmojiCategoriesTabRow(
|
||||
activeCategory = activeCategory,
|
||||
onCategoryChange = { category ->
|
||||
scope.launch { lazyListState.scrollToItem(0) }
|
||||
activeCategory = category
|
||||
scope.launch { pagerState.animateScrollToPage(categoryToPageNumber(activeCategory)) }
|
||||
},
|
||||
emojiHistoryEnabled = emojiHistoryEnabled,
|
||||
)
|
||||
HorizontalPager(pagerState, beyondViewportPageCount = 1) { page ->
|
||||
// Every page needs its own lazyGridState in order to scroll correctly
|
||||
val lazyGridState = rememberLazyGridState()
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
) {
|
||||
val emojiMapping = if (activeCategory == EmojiCategory.RECENTLY_USED) {
|
||||
// Update the lazyGridState and active category on scroll
|
||||
LaunchedEffect(pagerState) {
|
||||
snapshotFlow { pagerState.currentPage }.collect { page ->
|
||||
lazyGridState.scrollToItem(0)
|
||||
activeCategory = pageNumberToCategory(page)
|
||||
recentlyUsedVersion++
|
||||
}
|
||||
}
|
||||
|
||||
val category = pageNumberToCategory(page)
|
||||
val emojiMapping = if (category == EmojiCategory.RECENTLY_USED) {
|
||||
// Purposely using remember here to prevent recomposition, as this would cause rapid
|
||||
// emoji changes for the user when in recently used category.
|
||||
remember(recentlyUsedVersion) {
|
||||
@@ -234,63 +326,68 @@ fun EmojiPaletteView(
|
||||
EmojiMappingForView(
|
||||
pinned = emptyList(),
|
||||
recent = emptyList(),
|
||||
simple = emojiMappings[activeCategory]!!,
|
||||
simple = emojiMappings[category]!!,
|
||||
)
|
||||
}
|
||||
|
||||
val isEmojiHistoryEmpty = emojiMapping.pinned.isEmpty() && emojiMapping.recent.isEmpty()
|
||||
if (activeCategory == EmojiCategory.RECENTLY_USED && deviceLocked) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(all = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.emoji__history__phone_locked_message),
|
||||
)
|
||||
}
|
||||
} else if (activeCategory == EmojiCategory.RECENTLY_USED && isEmojiHistoryEmpty) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(all = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.emoji__history__empty_message),
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
text = stringRes(R.string.emoji__history__usage_tip),
|
||||
fontStyle = FontStyle.Italic,
|
||||
)
|
||||
}
|
||||
} else key(emojiMapping) {
|
||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
||||
LazyVerticalGrid(
|
||||
when (category) {
|
||||
EmojiCategory.RECENTLY_USED if deviceLocked -> {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.florisScrollbar(lazyListState),
|
||||
columns = GridCells.Adaptive(minSize = EmojiBaseWidth),
|
||||
state = lazyListState,
|
||||
.padding(all = 8.dp),
|
||||
) {
|
||||
if (emojiMapping.pinned.isNotEmpty()) {
|
||||
header("header_pinned") {
|
||||
GridHeader(text = stringRes(R.string.emoji__history__pinned))
|
||||
Text(
|
||||
text = stringRes(R.string.emoji__history__phone_locked_message),
|
||||
)
|
||||
}
|
||||
}
|
||||
EmojiCategory.RECENTLY_USED if isEmojiHistoryEmpty -> {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(all = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.emoji__history__empty_message),
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
text = stringRes(R.string.emoji__history__usage_tip),
|
||||
fontStyle = FontStyle.Italic,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> key(emojiMapping) {
|
||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
||||
LazyVerticalGrid(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.florisScrollbar(lazyGridState),
|
||||
columns = GridCells.Adaptive(minSize = EmojiBaseWidth),
|
||||
state = lazyGridState,
|
||||
) {
|
||||
if (emojiMapping.pinned.isNotEmpty()) {
|
||||
header("header_pinned") {
|
||||
GridHeader(text = stringRes(R.string.emoji__history__pinned))
|
||||
}
|
||||
items(emojiMapping.pinned) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet, isPinned = true)
|
||||
}
|
||||
}
|
||||
items(emojiMapping.pinned) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet, isPinned = true)
|
||||
if (emojiMapping.recent.isNotEmpty()) {
|
||||
header("header_recent") {
|
||||
GridHeader(text = stringRes(R.string.emoji__history__recent))
|
||||
}
|
||||
items(emojiMapping.recent) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet, isRecent = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (emojiMapping.recent.isNotEmpty()) {
|
||||
header("header_recent") {
|
||||
GridHeader(text = stringRes(R.string.emoji__history__recent))
|
||||
}
|
||||
items(emojiMapping.recent) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet, isRecent = true)
|
||||
}
|
||||
}
|
||||
if (emojiMapping.simple.isNotEmpty()) {
|
||||
items(emojiMapping.simple) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet)
|
||||
if (emojiMapping.simple.isNotEmpty()) {
|
||||
items(emojiMapping.simple) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,59 +397,6 @@ fun EmojiPaletteView(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EmojiCategoriesTabRow(
|
||||
activeCategory: EmojiCategory,
|
||||
onCategoryChange: (EmojiCategory) -> Unit,
|
||||
emojiHistoryEnabled: Boolean,
|
||||
) {
|
||||
val inputFeedbackController = LocalInputFeedbackController.current
|
||||
val selectedTabIndex = if (emojiHistoryEnabled) {
|
||||
EmojiCategoryValues.indexOf(activeCategory)
|
||||
} else {
|
||||
EmojiCategoryValues.indexOf(activeCategory) - 1
|
||||
}
|
||||
val style = rememberSnyggThemeQuery(FlorisImeUi.MediaEmojiTab.elementName)
|
||||
TabRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(FlorisImeSizing.smartbarHeight),
|
||||
selectedTabIndex = selectedTabIndex,
|
||||
containerColor = Color.Transparent,
|
||||
contentColor = style.foreground(),
|
||||
indicator = { tabPositions ->
|
||||
val style = rememberSnyggThemeQuery(
|
||||
elementName = FlorisImeUi.MediaEmojiTab.elementName,
|
||||
selector = SnyggSelector.FOCUS,
|
||||
)
|
||||
TabRowDefaults.PrimaryIndicator(
|
||||
Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]),
|
||||
height = 4.dp,
|
||||
color = style.foreground(),
|
||||
)
|
||||
},
|
||||
) {
|
||||
for (category in EmojiCategoryValues) {
|
||||
if (category == EmojiCategory.RECENTLY_USED && !emojiHistoryEnabled) {
|
||||
continue
|
||||
}
|
||||
Tab(
|
||||
onClick = {
|
||||
inputFeedbackController.keyPress(TextKeyData.UNSPECIFIED)
|
||||
onCategoryChange(category)
|
||||
},
|
||||
selected = activeCategory == category,
|
||||
icon = { SnyggIcon(
|
||||
elementName = FlorisImeUi.MediaEmojiTab.elementName,
|
||||
selector = if (activeCategory == category) SnyggSelector.FOCUS else SnyggSelector.NONE,
|
||||
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||
imageVector = category.icon(),
|
||||
) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EmojiKey(
|
||||
emojiSet: EmojiSet,
|
||||
|
||||
@@ -71,7 +71,7 @@ class EmojiSuggestionProvider(private val context: Context) : SuggestionProvider
|
||||
val candidates = withContext(Dispatchers.Default) {
|
||||
emojis.parallelStream()
|
||||
.filter { emoji ->
|
||||
emoji.name.contains(query, ignoreCase = true) &&
|
||||
emoji.name.contains(query, ignoreCase = true) ||
|
||||
emoji.keywords.any { it.contains(query, ignoreCase = true) }
|
||||
}
|
||||
.limit(maxCandidateCount.toLong())
|
||||
|
||||
@@ -34,7 +34,7 @@ import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.ime.input.LocalInputFeedbackController
|
||||
import dev.patrickgold.florisboard.ime.keyboard.FlorisImeSizing
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.snygg.ui.SnyggColumn
|
||||
import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
|
||||
@@ -24,12 +24,15 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.MoreHoriz
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import dev.patrickgold.florisboard.ime.keyboard.Key
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import org.florisboard.lib.snygg.SnyggQueryAttributes
|
||||
import org.florisboard.lib.snygg.SnyggSelector
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
@@ -38,6 +41,8 @@ import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
import org.florisboard.lib.snygg.ui.SnyggRow
|
||||
import org.florisboard.lib.snygg.ui.SnyggText
|
||||
|
||||
val GlobalStateNumPopupsShowing = MutableStateFlow(0)
|
||||
|
||||
@Composable
|
||||
fun PopupBaseBox(
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -45,6 +50,13 @@ fun PopupBaseBox(
|
||||
key: Key,
|
||||
shouldIndicateExtendedPopups: Boolean,
|
||||
): Unit = with(LocalDensity.current) {
|
||||
DisposableEffect(key) {
|
||||
GlobalStateNumPopupsShowing.update { it + 1 }
|
||||
onDispose {
|
||||
GlobalStateNumPopupsShowing.update { it - 1 }
|
||||
}
|
||||
}
|
||||
|
||||
SnyggBox(
|
||||
elementName = FlorisImeUi.KeyPopupBox.elementName,
|
||||
attributes = attributes,
|
||||
|
||||
@@ -31,7 +31,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import dev.patrickgold.florisboard.ime.keyboard.KeyboardState
|
||||
import dev.patrickgold.florisboard.lib.compose.conditional
|
||||
import org.florisboard.lib.compose.conditional
|
||||
|
||||
private val SheetOutOfBoundsBgColorInactive = Color(0x00000000)
|
||||
private val SheetOutOfBoundsBgColorActive = Color(0x52000000)
|
||||
|
||||
@@ -44,11 +44,11 @@ import dev.patrickgold.florisboard.ime.nlp.ClipboardSuggestionCandidate
|
||||
import dev.patrickgold.florisboard.ime.nlp.SuggestionCandidate
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.conditional
|
||||
import dev.patrickgold.florisboard.lib.compose.florisHorizontalScroll
|
||||
import dev.patrickgold.florisboard.nlpManager
|
||||
import dev.patrickgold.florisboard.subtypeManager
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import org.florisboard.lib.compose.conditional
|
||||
import org.florisboard.lib.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.snygg.SnyggSelector
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggColumn
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
package dev.patrickgold.florisboard.ime.smartbar
|
||||
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -33,10 +35,10 @@ import androidx.compose.ui.layout.positionInParent
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import dev.patrickgold.florisboard.ime.nlp.NlpInlineAutofillSuggestion
|
||||
import dev.patrickgold.florisboard.ime.popup.GlobalStateNumPopupsShowing
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.lib.compose.florisHorizontalScroll
|
||||
import dev.patrickgold.florisboard.lib.toIntOffset
|
||||
import org.florisboard.lib.snygg.SnyggPropertySet
|
||||
import org.florisboard.lib.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.snygg.SnyggSinglePropertySet
|
||||
import org.florisboard.lib.snygg.ui.rememberSnyggThemeQuery
|
||||
|
||||
@@ -57,7 +59,8 @@ fun InlineSuggestionsUi(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
val almostEmptyRect = remember { android.graphics.Rect(0, 0, 1, 1) }
|
||||
val numPopupsShowing by GlobalStateNumPopupsShowing.collectAsState()
|
||||
val isZOrderedOnTop = numPopupsShowing == 0
|
||||
|
||||
Row(
|
||||
modifier
|
||||
@@ -78,19 +81,14 @@ fun InlineSuggestionsUi(
|
||||
modifier = Modifier.onGloballyPositioned { chipPos = it.positionInParent().toIntOffset() },
|
||||
factory = { inlineSuggestion.view },
|
||||
update = { view ->
|
||||
view.isZOrderedOnTop = isZOrderedOnTop
|
||||
view.clipBounds = android.graphics.Rect(
|
||||
(xMin - chipPos.x).coerceAtLeast(0),
|
||||
0,
|
||||
(xMax - chipPos.x).coerceAtMost(view.width),
|
||||
view.height,
|
||||
)
|
||||
// The empty rect is a workaround for a bug (I suppose) where an empty rect causes
|
||||
// no clipping, but we actually want to completely hide the view.
|
||||
// Thus we just show the topmost pixel of the view, which due to the round shape
|
||||
// of the theme should be transparent anyways.
|
||||
if (view.clipBounds.isEmpty) {
|
||||
view.clipBounds = almostEmptyRect
|
||||
}
|
||||
view.visibility = if (view.clipBounds.isEmpty) View.INVISIBLE else View.VISIBLE
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -49,7 +49,9 @@ import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.isUnspecified
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
@@ -60,13 +62,12 @@ import dev.patrickgold.florisboard.ime.smartbar.quickaction.QuickActionsRow
|
||||
import dev.patrickgold.florisboard.ime.smartbar.quickaction.ToggleOverflowPanelAction
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.horizontalTween
|
||||
import dev.patrickgold.florisboard.lib.compose.verticalTween
|
||||
import dev.patrickgold.florisboard.nlpManager
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import dev.patrickgold.jetpref.datastore.ui.vectorResource
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.compose.horizontalTween
|
||||
import org.florisboard.lib.compose.verticalTween
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggColumn
|
||||
import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
@@ -186,7 +187,7 @@ private fun SmartbarMainRow(modifier: Modifier = Modifier) {
|
||||
} else {
|
||||
Icons.AutoMirrored.Default.KeyboardArrowRight
|
||||
}
|
||||
val incognitoIcon = vectorResource(id = R.drawable.ic_incognito)
|
||||
val incognitoIcon = ImageVector.vectorResource(id = R.drawable.ic_incognito)
|
||||
val incognitoDisplayMode = prefs.keyboard.incognitoDisplayMode.observeAsState()
|
||||
val isIncognitoMode = keyboardManager.activeState.isIncognitoMode
|
||||
val icon = if (isIncognitoMode) {
|
||||
|
||||
@@ -25,9 +25,9 @@ import dev.patrickgold.florisboard.ime.keyboard.KeyData
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Serializable
|
||||
sealed class QuickAction {
|
||||
@@ -87,6 +87,7 @@ fun QuickAction.computeDisplayName(evaluator: ComputingEvaluator): String {
|
||||
KeyCode.CLIPBOARD_CUT -> R.string.quick_action__clipboard_cut
|
||||
KeyCode.CLIPBOARD_PASTE -> R.string.quick_action__clipboard_paste
|
||||
KeyCode.CLIPBOARD_SELECT_ALL -> R.string.quick_action__clipboard_select_all
|
||||
KeyCode.FORWARD_DELETE -> R.string.quick_action__forward_delete
|
||||
KeyCode.IME_UI_MODE_CLIPBOARD -> R.string.quick_action__ime_ui_mode_clipboard
|
||||
KeyCode.IME_UI_MODE_MEDIA -> R.string.quick_action__ime_ui_mode_media
|
||||
KeyCode.LANGUAGE_SWITCH -> R.string.quick_action__language_switch
|
||||
|
||||
@@ -86,6 +86,7 @@ data class QuickActionArrangement(
|
||||
QuickAction.InsertKey(TextKeyData.CLIPBOARD_PASTE),
|
||||
QuickAction.InsertKey(TextKeyData.CLIPBOARD_SELECT_ALL),
|
||||
QuickAction.InsertKey(TextKeyData.LANGUAGE_SWITCH),
|
||||
QuickAction.InsertKey(TextKeyData.FORWARD_DELETE),
|
||||
),
|
||||
hiddenActions = listOf(
|
||||
),
|
||||
|
||||
@@ -58,8 +58,8 @@ import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.toIntOffset
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggColumn
|
||||
|
||||
@@ -34,10 +34,10 @@ import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.ime.keyboard.FlorisImeSizing
|
||||
import dev.patrickgold.florisboard.ime.theme.FlorisImeUi
|
||||
import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.snygg.ui.SnyggButton
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggButton
|
||||
import org.florisboard.lib.snygg.ui.SnyggText
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -59,6 +59,7 @@ import dev.patrickgold.florisboard.FlorisImeService
|
||||
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
|
||||
import dev.patrickgold.florisboard.editorInstance
|
||||
import dev.patrickgold.florisboard.glideTypingManager
|
||||
import dev.patrickgold.florisboard.ime.editor.OperationUnit
|
||||
import dev.patrickgold.florisboard.ime.input.InputEventDispatcher
|
||||
import dev.patrickgold.florisboard.ime.keyboard.ComputingEvaluator
|
||||
import dev.patrickgold.florisboard.ime.keyboard.FlorisImeSizing
|
||||
@@ -78,7 +79,6 @@ import dev.patrickgold.florisboard.keyboardManager
|
||||
import dev.patrickgold.florisboard.lib.FlorisRect
|
||||
import dev.patrickgold.florisboard.lib.Pointer
|
||||
import dev.patrickgold.florisboard.lib.PointerMap
|
||||
import dev.patrickgold.florisboard.lib.compose.DisposableLifecycleEffect
|
||||
import dev.patrickgold.florisboard.lib.devtools.LogTopic
|
||||
import dev.patrickgold.florisboard.lib.devtools.flogDebug
|
||||
import dev.patrickgold.florisboard.lib.observeAsTransformingState
|
||||
@@ -88,6 +88,7 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.onFailure
|
||||
import kotlinx.coroutines.isActive
|
||||
import org.florisboard.lib.android.isOrientationLandscape
|
||||
import org.florisboard.lib.compose.DisposableLifecycleEffect
|
||||
import org.florisboard.lib.snygg.SnyggSelector
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
@@ -498,7 +499,7 @@ private class TextKeyboardLayoutController(
|
||||
if (pointer.hasTriggeredGestureMove && pointer.initialKey?.computedData?.code == KeyCode.DELETE) {
|
||||
val selection = editorInstance.activeContent.selection
|
||||
if (selection.isSelectionMode) {
|
||||
editorInstance.deleteBackwards()
|
||||
editorInstance.deleteBackwards(OperationUnit.CHARACTERS)
|
||||
}
|
||||
}
|
||||
onTouchCancelInternal(event, pointer)
|
||||
@@ -521,7 +522,7 @@ private class TextKeyboardLayoutController(
|
||||
prefs.gestures.deleteKeySwipeLeft.get() != SwipeAction.SELECT_WORDS_PRECISELY) {
|
||||
val selection = editorInstance.activeContent.selection
|
||||
if (selection.isSelectionMode) {
|
||||
editorInstance.deleteBackwards()
|
||||
editorInstance.deleteBackwards(OperationUnit.CHARACTERS)
|
||||
}
|
||||
}
|
||||
onTouchCancelInternal(event, pointer)
|
||||
@@ -765,10 +766,19 @@ private class TextKeyboardLayoutController(
|
||||
}
|
||||
val activeSelection = editorInstance.activeContent.selection
|
||||
if (activeSelection.isValid) {
|
||||
editorInstance.setSelection(
|
||||
(activeSelection.end + event.absUnitCountX + 1).coerceIn(0, activeSelection.end),
|
||||
activeSelection.end,
|
||||
)
|
||||
if (inputEventDispatcher.isPressed(KeyCode.SHIFT)) {
|
||||
// Forward select
|
||||
editorInstance.setSelection(
|
||||
activeSelection.start,
|
||||
(activeSelection.start - event.absUnitCountX + 1).coerceAtLeast(activeSelection.start),
|
||||
)
|
||||
} else {
|
||||
// Backward select
|
||||
editorInstance.setSelection(
|
||||
(activeSelection.end + event.absUnitCountX + 1).coerceIn(0, activeSelection.end),
|
||||
activeSelection.end,
|
||||
)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package dev.patrickgold.florisboard.lib
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.CurlyArg
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun FlorisConfirmDeleteDialog(
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2025 The FlorisBoard Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.ShapeDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
||||
//TODO: Use JetPrefDropDownMenu instead
|
||||
@Composable
|
||||
fun <T : Any> FlorisDropdownMenu(
|
||||
items: List<T>,
|
||||
expanded: Boolean,
|
||||
selectedIndex: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
isError: Boolean = false,
|
||||
labelProvider: (@Composable (T) -> String)? = null,
|
||||
onSelectItem: (Int) -> Unit = { },
|
||||
onExpandRequest: () -> Unit = { },
|
||||
onDismissRequest: () -> Unit = { },
|
||||
) {
|
||||
@Composable
|
||||
fun asString(v: T): String {
|
||||
return labelProvider?.invoke(v) ?: v.toString()
|
||||
}
|
||||
|
||||
Box(modifier = modifier.wrapContentSize(Alignment.TopStart)) {
|
||||
val indicatorRotation by animateFloatAsState(targetValue = if (expanded) 180f else 0f)
|
||||
val index = selectedIndex.coerceIn(items.indices)
|
||||
val color = if (!enabled) {
|
||||
MaterialTheme.colorScheme.outline
|
||||
} else if (isError) {
|
||||
MaterialTheme.colorScheme.error
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onBackground
|
||||
}
|
||||
OutlinedButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
border = if (isError && enabled) {
|
||||
BorderStroke(ButtonDefaults.outlinedButtonBorder.width, MaterialTheme.colorScheme.error)
|
||||
} else {
|
||||
ButtonDefaults.outlinedButtonBorder
|
||||
},
|
||||
shape = ShapeDefaults.ExtraSmall,
|
||||
enabled = enabled,
|
||||
onClick = onExpandRequest,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1.0f),
|
||||
text = asString(items[index]),
|
||||
textAlign = TextAlign.Start,
|
||||
fontWeight = FontWeight.Normal,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
color = color,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.rotate(indicatorRotation),
|
||||
imageVector = Icons.Filled.KeyboardArrowDown,
|
||||
tint = if (enabled) {
|
||||
color.copy(alpha = 0.74f) //Also test 0.60f
|
||||
} else {
|
||||
color
|
||||
},
|
||||
contentDescription = "Dropdown indicator",
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = onDismissRequest,
|
||||
) {
|
||||
for ((n, item) in items.withIndex()) {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(text = asString(item))
|
||||
},
|
||||
onClick = {
|
||||
onSelectItem(n)
|
||||
onDismissRequest()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FlorisDropdownLikeButton(
|
||||
item: String,
|
||||
modifier: Modifier = Modifier,
|
||||
isError: Boolean = false,
|
||||
onClick: () -> Unit = { },
|
||||
) {
|
||||
Box(modifier = modifier.wrapContentSize(Alignment.TopStart)) {
|
||||
val color = if (isError) {
|
||||
MaterialTheme.colorScheme.error
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onBackground
|
||||
}
|
||||
OutlinedButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
border = if (isError) {
|
||||
BorderStroke(ButtonDefaults.outlinedButtonBorder.width, MaterialTheme.colorScheme.error)
|
||||
} else {
|
||||
ButtonDefaults.outlinedButtonBorder
|
||||
},
|
||||
shape = ShapeDefaults.ExtraSmall,
|
||||
onClick = onClick,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1.0f),
|
||||
text = item,
|
||||
textAlign = TextAlign.Start,
|
||||
fontWeight = FontWeight.Normal,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
color = color,
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
||||
tint = color.copy(alpha = 0.74f), //Also test 0.60f
|
||||
contentDescription = "Dropdown indicator",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,10 @@ import dev.patrickgold.florisboard.app.LocalNavController
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceLayout
|
||||
import dev.patrickgold.jetpref.datastore.ui.PreferenceUiContent
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.compose.FlorisAppBar
|
||||
import org.florisboard.lib.compose.FlorisIconButton
|
||||
import org.florisboard.lib.compose.autoMirrorForRtl
|
||||
import org.florisboard.lib.compose.florisVerticalScroll
|
||||
|
||||
@Composable
|
||||
fun FlorisScreen(builder: @Composable FlorisScreenScope.() -> Unit) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The FlorisBoard Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
|
||||
fun Context.vectorResource(@DrawableRes id: Int): ImageVector? {
|
||||
val theme = this.theme
|
||||
return try {
|
||||
ImageVector.vectorResource(theme = theme, resId = id, res = this.resources)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -54,9 +54,11 @@ import androidx.compose.ui.text.style.TextDirection
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.patrickgold.florisboard.R
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import dev.patrickgold.florisboard.lib.util.InputMethodUtils
|
||||
import org.florisboard.lib.android.showShortToastSync
|
||||
import org.florisboard.lib.android.showShortToast
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.compose.verticalTween
|
||||
|
||||
private const val AnimationDuration = 200
|
||||
|
||||
|
||||
@@ -29,12 +29,12 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import dev.patrickgold.florisboard.BuildConfig
|
||||
import dev.patrickgold.florisboard.lib.compose.observeAsState
|
||||
import dev.patrickgold.florisboard.lib.devtools.flogDebug
|
||||
import kotlinx.coroutines.delay
|
||||
import org.florisboard.lib.android.AndroidSettings
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.android.systemServiceOrNull
|
||||
import org.florisboard.lib.compose.observeAsState
|
||||
|
||||
private const val DELIMITER = ':'
|
||||
private const val IME_SERVICE_CLASS_NAME = "dev.patrickgold.florisboard.FlorisImeService"
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
<string name="quick_action__clipboard_paste__tooltip">Поставя от междинната памет</string>
|
||||
<string name="quick_action__clipboard_select_all" maxLength="12">Избор всички</string>
|
||||
<string name="quick_action__clipboard_select_all__tooltip">Избира всичко</string>
|
||||
<string name="quick_action__forward_delete" maxLength="12">Премахване →</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard" maxLength="12">Буфер</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard__tooltip">Хронология на междинната памет</string>
|
||||
<string name="quick_action__ime_ui_mode_media" maxLength="12">Емоции</string>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<string name="quick_action__clipboard_paste__tooltip">Vykonat vložení schránky</string>
|
||||
<string name="quick_action__clipboard_select_all" maxLength="12">Vybrat vše</string>
|
||||
<string name="quick_action__clipboard_select_all__tooltip">Vykonat vybrání všeho do schránky</string>
|
||||
<string name="quick_action__forward_delete" maxLength="12">Smazat za</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard" maxLength="12">Schránka</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard__tooltip">Otevřít historii schránky</string>
|
||||
<string name="quick_action__ime_ui_mode_media" maxLength="12">Emotikony</string>
|
||||
|
||||
@@ -631,6 +631,7 @@
|
||||
<string name="clipboard__cleared_primary_clip">Clip principal borrado</string>
|
||||
<string name="clipboard__cleared_history">Historial borrado</string>
|
||||
<string name="clipboard__cleared_full_history">Historial completo borrado</string>
|
||||
<string name="clipboard__confirm_clear_history__message">¿Estás seguro de que quieres limpiar el historial del portapapeles? Esto limpiará todos los ítems excepto los fijados, sin tener en cuenta los filtros activos.</string>
|
||||
<string name="settings__clipboard__title">Portapapeles</string>
|
||||
<string name="pref__clipboard__use_internal_clipboard__label">Usar portapapeles interno</string>
|
||||
<string name="pref__clipboard__use_internal_clipboard__summary">Usar portapapeles interno en vez del portapapeles del sistema</string>
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
<string name="quick_action__clipboard_paste__tooltip">Wklej ze schowka</string>
|
||||
<string name="quick_action__clipboard_select_all" maxLength="12">Wszystko</string>
|
||||
<string name="quick_action__clipboard_select_all__tooltip">Zaznacz wszystko</string>
|
||||
<string name="quick_action__forward_delete" maxLength="12">Usuń w przód</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard" maxLength="12">Schowek</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard__tooltip">Otwórz historię schowka</string>
|
||||
<string name="quick_action__ime_ui_mode_media" maxLength="12">Emotki</string>
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
<string name="quick_action__clipboard_paste__tooltip">Panoyu yapıştır</string>
|
||||
<string name="quick_action__clipboard_select_all" maxLength="12">Tümünü seç</string>
|
||||
<string name="quick_action__clipboard_select_all__tooltip">Tümünü seç eylemini gerçekleştir</string>
|
||||
<string name="quick_action__forward_delete" maxLength="12">İletiyi sil</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard" maxLength="12">Pano</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard__tooltip">Pano geçmişini aç</string>
|
||||
<string name="quick_action__ime_ui_mode_media" maxLength="12">Emoji</string>
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<string name="quick_action__clipboard_paste__tooltip">Perform clipboard paste</string>
|
||||
<string name="quick_action__clipboard_select_all" maxLength="12">Select all</string>
|
||||
<string name="quick_action__clipboard_select_all__tooltip">Perform clipboard select all</string>
|
||||
<string name="quick_action__forward_delete" maxLength="12">Forward delete</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard" maxLength="12">Clipboard</string>
|
||||
<string name="quick_action__ime_ui_mode_clipboard__tooltip">Open clipboard history</string>
|
||||
<string name="quick_action__ime_ui_mode_media" maxLength="12">Emoji</string>
|
||||
|
||||
@@ -11,5 +11,5 @@ projectMinSdk=26
|
||||
projectTargetSdk=35
|
||||
projectCompileSdk=35
|
||||
|
||||
projectVersionCode=110
|
||||
projectVersionName=0.5.0-beta02
|
||||
projectVersionCode=112
|
||||
projectVersionName=0.5.0-beta04
|
||||
|
||||
@@ -20,7 +20,7 @@ kotlinx-serialization-json = "1.9.0"
|
||||
ksp = "2.2.0-2.0.2"
|
||||
mikepenz-aboutlibraries = "12.1.2"
|
||||
patrickgold-compose-tooltip = "0.2.0-rc02"
|
||||
patrickgold-jetpref = "0.3.0-beta01"
|
||||
patrickgold-jetpref = "0.3.0-beta02"
|
||||
|
||||
# Testing
|
||||
androidx-benchmark = "1.3.4"
|
||||
@@ -57,6 +57,7 @@ androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "
|
||||
cache4k = { module = "io.github.reactivecircus.cache4k:cache4k", version.ref = "cache4k" }
|
||||
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
|
||||
coil-gif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" }
|
||||
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
|
||||
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }
|
||||
mikepenz-aboutlibraries-core = { module = "com.mikepenz:aboutlibraries-core", version.ref = "mikepenz-aboutlibraries" }
|
||||
|
||||
89
lib/compose/build.gradle.kts
Normal file
89
lib/compose/build.gradle.kts
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2025 The FlorisBoard Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.agp.library)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.plugin.compose)
|
||||
}
|
||||
|
||||
val projectMinSdk: String by project
|
||||
val projectCompileSdk: String by project
|
||||
|
||||
android {
|
||||
namespace = "org.florisboard.lib.compose"
|
||||
compileSdk = projectCompileSdk.toInt()
|
||||
|
||||
defaultConfig {
|
||||
minSdk = projectMinSdk.toInt()
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
create("beta") {
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
freeCompilerArgs = listOf(
|
||||
"-Xconsistent-data-class-copy-visibility",
|
||||
"-Xwhen-guards",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":lib:android"))
|
||||
implementation(project(":lib:color"))
|
||||
implementation(project(":lib:kotlin"))
|
||||
|
||||
val composeBom = platform(libs.androidx.compose.bom)
|
||||
implementation(composeBom)
|
||||
// testImplementation(composeBom)
|
||||
// androidTestImplementation(composeBom)
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.compose.material3)
|
||||
implementation(libs.androidx.compose.ui)
|
||||
implementation(libs.androidx.compose.material.icons)
|
||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
implementation(libs.patrickgold.jetpref.material.ui)
|
||||
|
||||
testImplementation(libs.kotlin.test.junit5)
|
||||
}
|
||||
|
||||
0
lib/compose/consumer-rules.pro
Normal file
0
lib/compose/consumer-rules.pro
Normal file
21
lib/compose/proguard-rules.pro
vendored
Normal file
21
lib/compose/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
package org.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
package org.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
package org.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.runtime.saveable.Saver
|
||||
import androidx.compose.ui.unit.Dp
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
package org.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.animation.EnterTransition
|
||||
import androidx.compose.animation.ExitTransition
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
package org.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@@ -29,7 +29,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
@Composable
|
||||
fun FlorisAppBar(
|
||||
title: String,
|
||||
navigationIcon: FlorisScreenNavigationIcon?,
|
||||
navigationIcon: (@Composable () -> Unit)?,
|
||||
actions: @Composable RowScope.() -> Unit = { },
|
||||
scrollBehavior: TopAppBarScrollBehavior
|
||||
) {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user