Compare commits
1 Commits
release/0.
...
test/inlin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11a41f30e4 |
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -44,8 +44,7 @@ body:
|
||||
label: Install Source
|
||||
options:
|
||||
- Google PlayStore
|
||||
- F-Droid (F-Droid Main)
|
||||
- F-Droid (IzzyOnDroid)
|
||||
- F-Droid
|
||||
- GitHub
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -10,7 +10,7 @@ The FlorisBoard community is international, as such we require all contributions
|
||||
|
||||
### Translations
|
||||
|
||||
To make FlorisBoard accessible in as many languages as possible, the platform [Crowdin](https://crowdin.florisboard.org) is used to crowdsource and manage translations. The list of languages in Crowdin covers a good range of languages, but feel free to email [florisboard@patrickgold.dev](mailto:florisboard@patrickgold.dev) to request a new language.
|
||||
To make FlorisBoard accessible in as many languages as possible, the platform [Crowdin](https://crowdin.florisboard.patrickgold.dev) is used to crowdsource and manage translations. The list of languages in Crowdin covers a good range of languages, but feel free to email [florisboard@patrickgold.dev](mailto:florisboard@patrickgold.dev) to request a new language.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This is the only source of translations - **PRs that add/update translations are not accepted.**
|
||||
|
||||
31
README.md
31
README.md
@@ -1,11 +1,11 @@
|
||||
<img align="left" width="80" height="80"
|
||||
src=".github/repo_icon.png" alt="App icon">
|
||||
|
||||
# FlorisBoard [](https://crowdin.florisboard.org) [](https://matrix.to/#/#florisboard:matrix.org) [](CODE_OF_CONDUCT.md) [](https://github.com/florisboard/florisboard/actions/workflows/android.yml)
|
||||
# FlorisBoard [](https://crowdin.florisboard.patrickgold.dev) [](https://matrix.to/#/#florisboard:matrix.org) [](CODE_OF_CONDUCT.md) [](https://github.com/florisboard/florisboard/actions/workflows/android.yml)
|
||||
|
||||
**FlorisBoard** is a free and open-source keyboard for Android 8.0+
|
||||
**FlorisBoard** is a free and open-source keyboard for Android 7.0+
|
||||
devices. It aims at being modern, user-friendly and customizable while
|
||||
fully respecting your privacy. Currently in beta state.
|
||||
fully respecting your privacy. Currently in early-beta state.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@@ -26,13 +26,10 @@ fully respecting your privacy. Currently in beta state.
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<p>
|
||||
<a href="https://apt.izzysoft.de/fdroid/index/apk/dev.patrickgold.florisboard"><img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png" height="64" alt="IzzySoft repo badge"></a>
|
||||
<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><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-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))
|
||||
**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))
|
||||
|
||||
</p>
|
||||
<p>
|
||||
@@ -50,7 +47,7 @@ fully respecting your privacy. Currently in 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-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))
|
||||
**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))
|
||||
|
||||
</p>
|
||||
<p>
|
||||
@@ -99,22 +96,6 @@ 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)
|
||||
|
||||
@@ -9,11 +9,13 @@ Each major milestone has associated alpha/beta releases, so if you are intereste
|
||||
> [!NOTE]
|
||||
> The milestone 0.5 was split, thus the word suggestions now come with version 0.6. The old version 0.6 has been moved down and is now 0.7. The time it takes to implement word suggestions will not change, but we can now release the new theme editor earlier, which would otherwise lie dormant.
|
||||
|
||||
- [x] Theme rework part II / Snygg v2
|
||||
- [ ] Theme rework part II / Snygg v2
|
||||
- [x] See https://github.com/florisboard/florisboard/pull/2855
|
||||
- [x] Spaces in URI bug (See https://github.com/florisboard/florisboard/issues/2898)
|
||||
- [ ] Rework cache manager (See https://github.com/florisboard/florisboard/issues/2870)
|
||||
- [x] Re-add time based theme switching (See https://github.com/florisboard/florisboard/pull/2977)
|
||||
- [x] Add support for any remaining new features introduced with Android 13 / 14
|
||||
- [ ] Add support for any remaining new features introduced with Android 13 / 14
|
||||
- [ ] Proper physical keyboard support (See https://github.com/florisboard/florisboard/issues/2815)
|
||||
- [x] Raise minimum required Android version from Android 7 (SDK level 24) to Android 8 (SDK level 26)
|
||||
|
||||
## 0.6
|
||||
@@ -22,8 +24,6 @@ Each major milestone has associated alpha/beta releases, so if you are intereste
|
||||
- [ ] Add new extension type: Language Pack
|
||||
- Basically groups all locale-relevant data (predictive base model, emoji suggestion data, ...)
|
||||
in a dynamically importable extension file
|
||||
- [ ] Proper physical keyboard support (See https://github.com/florisboard/florisboard/issues/1972)
|
||||
- [ ] Rework cache manager (See https://github.com/florisboard/florisboard/issues/2870)
|
||||
|
||||
## k3lp
|
||||
|
||||
@@ -62,6 +62,7 @@ Each major milestone has associated alpha/beta releases, so if you are intereste
|
||||
- Text translation
|
||||
- Stickers/GIFs
|
||||
- Kaomoji panel implementation
|
||||
- FlorisBoard landing web page for presentation
|
||||
- Implementing additional layouts
|
||||
- Support for Tasker/Automate/MacroDroid plugins
|
||||
- Support for WearOS/Smartwatches
|
||||
|
||||
@@ -200,7 +200,6 @@ 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)
|
||||
@@ -213,7 +212,6 @@ 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"))
|
||||
|
||||
@@ -157,13 +157,6 @@
|
||||
"direction": "ltr",
|
||||
"modifier": "org.florisboard.layouts:dvorak"
|
||||
},
|
||||
{
|
||||
"id": "dvorak_se",
|
||||
"label": "Dvorak (SE)",
|
||||
"authors": [ "iceaway" ],
|
||||
"direction": "ltr",
|
||||
"modifier": "org.florisboard.layouts:dvorak_se"
|
||||
},
|
||||
{
|
||||
"id": "esperanto",
|
||||
"label": "Esperanto",
|
||||
@@ -517,12 +510,6 @@
|
||||
"authors": [ "msrd0" ],
|
||||
"direction": "ltr"
|
||||
},
|
||||
{
|
||||
"id": "dvorak_se",
|
||||
"label": "Dvorak (SE)",
|
||||
"authors": [ "iceaway" ],
|
||||
"direction": "ltr"
|
||||
},
|
||||
{
|
||||
"id": "hebrew",
|
||||
"label": "עברית",
|
||||
@@ -621,12 +608,6 @@
|
||||
"authors": [ "waelwindows" ],
|
||||
"direction": "ltr"
|
||||
},
|
||||
{
|
||||
"id": "czech",
|
||||
"label": "Czech",
|
||||
"authors": [ "bmondream" ],
|
||||
"direction": "ltr"
|
||||
},
|
||||
{
|
||||
"id": "devanagari",
|
||||
"label": "Devanagari",
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
[
|
||||
[
|
||||
{ "$": "auto_text_key", "code": 229, "label": "å" },
|
||||
{ "$": "auto_text_key", "code": 228, "label": "ä" },
|
||||
{ "$": "auto_text_key", "code": 246, "label": "ö" },
|
||||
{ "$": "auto_text_key", "code": 112, "label": "p" },
|
||||
{ "$": "auto_text_key", "code": 121, "label": "y" },
|
||||
{ "$": "auto_text_key", "code": 102, "label": "f" },
|
||||
{ "$": "auto_text_key", "code": 103, "label": "g" },
|
||||
{ "$": "auto_text_key", "code": 99, "label": "c" },
|
||||
{ "$": "auto_text_key", "code": 114, "label": "r" },
|
||||
{ "$": "auto_text_key", "code": 108, "label": "l" }
|
||||
],
|
||||
[
|
||||
{ "$": "auto_text_key", "code": 97, "label": "a" },
|
||||
{ "$": "auto_text_key", "code": 111, "label": "o" },
|
||||
{ "$": "auto_text_key", "code": 101, "label": "e" },
|
||||
{ "$": "auto_text_key", "code": 117, "label": "u" },
|
||||
{ "$": "auto_text_key", "code": 105, "label": "i" },
|
||||
{ "$": "auto_text_key", "code": 100, "label": "d" },
|
||||
{ "$": "auto_text_key", "code": 104, "label": "h" },
|
||||
{ "$": "auto_text_key", "code": 116, "label": "t" },
|
||||
{ "$": "auto_text_key", "code": 110, "label": "n" },
|
||||
{ "$": "auto_text_key", "code": 115, "label": "s" }
|
||||
],
|
||||
[
|
||||
{ "$": "auto_text_key", "code": 113, "label": "q" },
|
||||
{ "$": "auto_text_key", "code": 106, "label": "j" },
|
||||
{ "$": "auto_text_key", "code": 107, "label": "k" },
|
||||
{ "$": "auto_text_key", "code": 120, "label": "x" },
|
||||
{ "$": "auto_text_key", "code": 98, "label": "b" },
|
||||
{ "$": "auto_text_key", "code": 109, "label": "m" },
|
||||
{ "$": "auto_text_key", "code": 119, "label": "w" },
|
||||
{ "$": "auto_text_key", "code": 118, "label": "v" },
|
||||
{ "$": "auto_text_key", "code": 122, "label": "z" }
|
||||
]
|
||||
]
|
||||
@@ -1,16 +0,0 @@
|
||||
[
|
||||
[
|
||||
{ "code": -11, "label": "shift", "type": "modifier" },
|
||||
{ "code": 0, "type": "placeholder" },
|
||||
{ "code": -7, "label": "delete", "type": "enter_editing" }
|
||||
],
|
||||
[
|
||||
{ "code": -202, "label": "view_symbols", "type": "system_gui" },
|
||||
{ "$": "auto_text_key", "code": 44, "label": "," },
|
||||
{ "code": -227, "label": "language_switch", "type": "system_gui" },
|
||||
{ "code": -212, "label": "ime_ui_mode_media", "type": "system_gui" },
|
||||
{ "code": 32, "label": "space" },
|
||||
{ "$": "auto_text_key", "code": 46, "label": "." },
|
||||
{ "code": 10, "label": "enter", "groupId": 3, "type": "enter_editing" }
|
||||
]
|
||||
]
|
||||
@@ -1,119 +0,0 @@
|
||||
[
|
||||
[
|
||||
{ "$": "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" }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -23,17 +23,13 @@
|
||||
{ "code": 45, "label": "-", "popup": {
|
||||
"main": { "code": 95, "label": "_" },
|
||||
"relevant": [
|
||||
{ "code": 8315, "label": "⁻" },
|
||||
{ "code": 8212, "label": "—" },
|
||||
{ "code": 8211, "label": "–" },
|
||||
{ "code": 183, "label": "·" }
|
||||
]
|
||||
} },
|
||||
{ "code": 43, "label": "+", "popup": {
|
||||
"main": { "code": 177, "label": "±" },
|
||||
"relevant": [
|
||||
{ "code": 8314, "label": "⁺" }
|
||||
]
|
||||
"main": { "code": 177, "label": "±" }
|
||||
} },
|
||||
{ "$": "layout_direction_selector",
|
||||
"ltr": { "code": 40, "label": "(", "popup": {
|
||||
|
||||
@@ -70,9 +70,8 @@
|
||||
]
|
||||
},
|
||||
"~right": {
|
||||
"main": { "code": 1567, "label": "؟" },
|
||||
"main": { "code": 1611, "label": "ً" },
|
||||
"relevant": [
|
||||
{ "code": 1611, "label": "ً" },
|
||||
{ "code": 1622, "label": "ٖ" },
|
||||
{ "code": 1648, "label": "ٰ" },
|
||||
{ "code": 1619, "label": "ٓ" },
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
]
|
||||
},
|
||||
"h": {
|
||||
"main": { "$": "auto_text_key", "code": 7717, "label": "ḥ" }
|
||||
"relevant": [
|
||||
{ "$": "auto_text_key", "code": 7717, "label": "ḥ" }
|
||||
]
|
||||
},
|
||||
"i": {
|
||||
"main": { "$": "auto_text_key", "code": 237, "label": "í" },
|
||||
@@ -47,11 +49,13 @@
|
||||
]
|
||||
},
|
||||
"l": {
|
||||
"main": { "$": "auto_text_key", "code": 7735, "label": "ḷ" }
|
||||
"relevant": [
|
||||
{ "$": "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": "ń" }
|
||||
]
|
||||
},
|
||||
@@ -69,7 +73,9 @@
|
||||
]
|
||||
},
|
||||
"r": {
|
||||
"main": { "$": "auto_text_key", "code": 691, "label": "ʳ" }
|
||||
"relevant": [
|
||||
{ "$": "auto_text_key", "code": 691, "label": "ʳ" }
|
||||
]
|
||||
},
|
||||
"s": {
|
||||
"relevant": [
|
||||
@@ -106,4 +112,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ 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
|
||||
@@ -113,19 +114,17 @@ import dev.patrickgold.florisboard.lib.util.debugSummarize
|
||||
import dev.patrickgold.florisboard.lib.util.launchActivity
|
||||
import dev.patrickgold.jetpref.datastore.model.observeAsState
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlinx.coroutines.flow.update
|
||||
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
|
||||
|
||||
@@ -334,11 +333,6 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
return defaultExtractView
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
themeManager.configurationChangeCounter.update { it + 1 }
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
unregisterReceiver(wallpaperChangeReceiver)
|
||||
@@ -578,10 +572,7 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
|
||||
@Composable
|
||||
private fun ImeUiWrapper() {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
) {
|
||||
ProvideLocalizedResources(resourcesContext) {
|
||||
ProvideKeyboardRowBaseHeight {
|
||||
CompositionLocalProvider(LocalInputFeedbackController provides inputFeedbackController) {
|
||||
FlorisImeTheme {
|
||||
@@ -626,19 +617,9 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
clickAndSemanticsModifier = Modifier
|
||||
// Do not remove below line or touch input may get stuck
|
||||
.pointerInteropFilter { false },
|
||||
supportsBackgroundImage = !AndroidVersion.ATLEAST_API30_R,
|
||||
supportsBackgroundImage = true,
|
||||
allowClip = false,
|
||||
) {
|
||||
// The SurfaceView is used to render the background image under inline-autofill chips. These are only
|
||||
// available on Android >=11, and SurfaceView causes trouble on Android 8/9, thus we render the image
|
||||
// in the SurfaceView for Android >=11, and in the Compose View Tree for Android <=10.
|
||||
if (AndroidVersion.ATLEAST_API30_R) {
|
||||
SnyggSurfaceView(
|
||||
elementName = FlorisImeUi.Window.elementName,
|
||||
attributes = attributes,
|
||||
modifier = Modifier.matchParentSize(),
|
||||
)
|
||||
}
|
||||
val configuration = LocalConfiguration.current
|
||||
val bottomOffset by if (configuration.isOrientationPortrait()) {
|
||||
prefs.keyboard.bottomOffsetPortrait
|
||||
@@ -690,13 +671,10 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
return keyboardManager.onHardwareKeyDown(keyCode, event) || super.onKeyDown(keyCode, event)
|
||||
}
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean =
|
||||
if (keyboardManager.onHardwareKeyDown(keyCode, event)) true
|
||||
else 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 {
|
||||
@@ -731,11 +709,7 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
val keyboardManager by context.keyboardManager()
|
||||
val state by keyboardManager.activeState.collectAsState()
|
||||
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
forceLayoutDirection = LayoutDirection.Ltr,
|
||||
) {
|
||||
ProvideLocalizedResources(resourcesContext, forceLayoutDirection = LayoutDirection.Ltr) {
|
||||
FlorisImeTheme {
|
||||
BottomSheetHostUi(
|
||||
isShowing = state.isBottomSheetShowing() || state.isSubtypeSelectionShowing(),
|
||||
@@ -787,11 +761,7 @@ class FlorisImeService : LifecycleInputMethodService() {
|
||||
|
||||
@Composable
|
||||
fun Content() {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
forceLayoutDirection = LayoutDirection.Ltr,
|
||||
) {
|
||||
ProvideLocalizedResources(resourcesContext, forceLayoutDirection = LayoutDirection.Ltr) {
|
||||
FlorisImeTheme {
|
||||
val activeEditorInfo by editorInstance.activeInfoFlow.collectAsState()
|
||||
SnyggBox(FlorisImeUi.ExtractedLandscapeInputLayout.elementName) {
|
||||
|
||||
@@ -20,7 +20,6 @@ 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
|
||||
@@ -54,6 +53,7 @@ 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,11 +860,6 @@ 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,10 +121,7 @@ class FlorisAppActivity : ComponentActivity() {
|
||||
}
|
||||
AppVersionUtils.updateVersionOnInstallAndLastUse(this, prefs)
|
||||
setContent {
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext,
|
||||
appName = R.string.app_name,
|
||||
) {
|
||||
ProvideLocalizedResources(resourcesContext) {
|
||||
FlorisAppTheme(theme = appTheme) {
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
AppContent()
|
||||
@@ -197,7 +194,7 @@ class FlorisAppActivity : ComponentActivity() {
|
||||
Routes.AppNavHost(
|
||||
modifier = Modifier.weight(1.0f),
|
||||
navController = navController,
|
||||
startDestination = if (isImeSetUp) Routes.Settings.Home::class else Routes.Setup.Screen::class,
|
||||
startDestination = if (isImeSetUp) Routes.Settings.Home else Routes.Setup.Screen,
|
||||
)
|
||||
PreviewKeyboardField(previewFieldController)
|
||||
}
|
||||
|
||||
@@ -17,17 +17,12 @@
|
||||
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
|
||||
@@ -35,7 +30,6 @@ 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
|
||||
@@ -76,185 +70,113 @@ 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 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,
|
||||
)
|
||||
}
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
|
||||
@Suppress("FunctionName", "ConstPropertyName")
|
||||
object Routes {
|
||||
object Setup {
|
||||
@Serializable
|
||||
object Screen
|
||||
const val Screen = "setup"
|
||||
}
|
||||
|
||||
object Settings {
|
||||
@Serializable
|
||||
@Deeplink("settings/home")
|
||||
object Home
|
||||
const val Home = "settings"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/localization")
|
||||
object Localization
|
||||
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/select-locale")
|
||||
object SelectLocale
|
||||
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/language-pack-manage")
|
||||
data class LanguagePackManager(val action: LanguagePackManagerScreenAction)
|
||||
const val Keyboard = "settings/keyboard"
|
||||
const val InputFeedback = "settings/keyboard/input-feedback"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/localization/subtype/add")
|
||||
object SubtypeAdd
|
||||
const val Smartbar = "settings/smartbar"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/localization/subtype/edit")
|
||||
data class SubtypeEdit(val id: Long)
|
||||
const val Typing = "settings/typing"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/theme")
|
||||
object Theme
|
||||
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/manage")
|
||||
data class ThemeManager(val action: ThemeManagerScreenAction)
|
||||
const val Gestures = "settings/gestures"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/keyboard")
|
||||
object Keyboard
|
||||
const val Clipboard = "settings/clipboard"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/keyboard/input-feedback")
|
||||
object InputFeedback
|
||||
const val Media = "settings/media"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("settings/smartbar")
|
||||
object Smartbar
|
||||
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/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
|
||||
const val About = "settings/about"
|
||||
const val ProjectLicense = "settings/about/project-license"
|
||||
const val ThirdPartyLicenses = "settings/about/third-party-licenses"
|
||||
}
|
||||
|
||||
object Devtools {
|
||||
@Serializable
|
||||
@Deeplink("devtools")
|
||||
object Home
|
||||
const val Home = "devtools"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("devtools/android/locales")
|
||||
object AndroidLocales
|
||||
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/settings")
|
||||
data class AndroidSettings(val name: String)
|
||||
|
||||
@Serializable
|
||||
@Deeplink("export-debug-log")
|
||||
object ExportDebugLog
|
||||
const val ExportDebugLog = "export-debug-log"
|
||||
}
|
||||
|
||||
object Ext {
|
||||
@Serializable
|
||||
@Deeplink("ext")
|
||||
object Home
|
||||
const val Home = "ext"
|
||||
|
||||
@Serializable
|
||||
@Deeplink("ext/list")
|
||||
data class List(val type: ExtensionListScreenType, val showUpdate: Boolean? = null)
|
||||
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/edit")
|
||||
data class Edit(val id: String, @SerialName("create") val serialType: String? = 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/export")
|
||||
data class Export(val id: String)
|
||||
const val Export = "ext/export/{id}"
|
||||
fun Export(id: String) = Export.curlyFormat("id" to id)
|
||||
|
||||
@Serializable
|
||||
@Deeplink("ext/import")
|
||||
data class Import(val type: ExtensionImportScreenType, val uuid: String? = null)
|
||||
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/view")
|
||||
data class View(val id: String)
|
||||
const val View = "ext/view/{id}"
|
||||
fun View(id: String) = View.curlyFormat("id" to id)
|
||||
|
||||
@Serializable
|
||||
@Deeplink("ext/check-updates")
|
||||
object CheckUpdates
|
||||
const val CheckUpdates = "ext/check-updates"
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppNavHost(
|
||||
modifier: Modifier,
|
||||
navController: NavHostController,
|
||||
startDestination: KClass<*>,
|
||||
startDestination: String,
|
||||
) {
|
||||
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,
|
||||
@@ -265,103 +187,109 @@ object Routes {
|
||||
exitTransition = {
|
||||
slideOut { IntOffset(-it.width, 0) } + fadeOut()
|
||||
},
|
||||
popEnterTransition = { EnterTransition.None },
|
||||
popExitTransition = {
|
||||
scaleOut(
|
||||
targetScale = 0.85F,
|
||||
transformOrigin = TransformOrigin(pivotFractionX = 0.8f, pivotFractionY = 0.5f)
|
||||
) + fadeOut(spring(stiffness = Spring.StiffnessMedium))
|
||||
popEnterTransition = {
|
||||
slideIn { IntOffset(-it.width, 0) } + fadeIn()
|
||||
},
|
||||
popExitTransition = {
|
||||
slideOut { IntOffset(it.width, 0) } + fadeOut()
|
||||
}
|
||||
) {
|
||||
composable<Setup.Screen> { SetupScreen() }
|
||||
composable(Setup.Screen) { SetupScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Home::class) { HomeScreen() }
|
||||
composableWithDeepLink(Settings.Home) { HomeScreen() }
|
||||
|
||||
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.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.SubtypeAdd::class) { SubtypeEditorScreen(null) }
|
||||
composableWithDeepLink(Settings.SubtypeEdit::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Settings.SubtypeEdit>()
|
||||
SubtypeEditorScreen(payload.id)
|
||||
composableWithDeepLink(Settings.SubtypeAdd) { SubtypeEditorScreen(null) }
|
||||
composableWithDeepLink(Settings.SubtypeEdit) { navBackStack ->
|
||||
val id = navBackStack.arguments?.getString("id")?.toLongOrNull()
|
||||
SubtypeEditorScreen(id)
|
||||
}
|
||||
|
||||
composableWithDeepLink(Settings.Theme::class) { ThemeScreen() }
|
||||
composableWithDeepLink(Settings.ThemeManager::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Settings.ThemeManager>()
|
||||
ThemeManagerScreen(payload.action)
|
||||
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.Keyboard::class) { KeyboardScreen() }
|
||||
composableWithDeepLink(Settings.InputFeedback::class) { InputFeedbackScreen() }
|
||||
composableWithDeepLink(Settings.Keyboard) { KeyboardScreen() }
|
||||
composableWithDeepLink(Settings.InputFeedback) { InputFeedbackScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Smartbar::class) { SmartbarScreen() }
|
||||
composableWithDeepLink(Settings.Smartbar) { SmartbarScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Typing::class) { TypingScreen() }
|
||||
composableWithDeepLink(Settings.Typing) { TypingScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Dictionary::class) { DictionaryScreen() }
|
||||
composableWithDeepLink(Settings.UserDictionary::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Settings.UserDictionary>()
|
||||
UserDictionaryScreen(payload.type)
|
||||
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.Gestures::class) { GesturesScreen() }
|
||||
composableWithDeepLink(Settings.Gestures) { GesturesScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Clipboard::class) { ClipboardScreen() }
|
||||
composableWithDeepLink(Settings.Clipboard) { ClipboardScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Media::class) { MediaScreen() }
|
||||
composableWithDeepLink(Settings.Media) { MediaScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.Other::class) { OtherScreen() }
|
||||
composableWithDeepLink(Settings.PhysicalKeyboard::class) { PhysicalKeyboardScreen() }
|
||||
composableWithDeepLink(Settings.Backup::class) { BackupScreen() }
|
||||
composableWithDeepLink(Settings.Restore::class) { RestoreScreen() }
|
||||
composableWithDeepLink(Settings.Other) { OtherScreen() }
|
||||
composableWithDeepLink(Settings.PhysicalKeyboard) { PhysicalKeyboardScreen() }
|
||||
composableWithDeepLink(Settings.Backup) { BackupScreen() }
|
||||
composableWithDeepLink(Settings.Restore) { RestoreScreen() }
|
||||
|
||||
composableWithDeepLink(Settings.About::class) { AboutScreen() }
|
||||
composableWithDeepLink(Settings.ProjectLicense::class) { ProjectLicenseScreen() }
|
||||
composableWithDeepLink(Settings.ThirdPartyLicenses::class) { ThirdPartyLicensesScreen() }
|
||||
composableWithDeepLink(Settings.About) { AboutScreen() }
|
||||
composableWithDeepLink(Settings.ProjectLicense) { ProjectLicenseScreen() }
|
||||
composableWithDeepLink(Settings.ThirdPartyLicenses) { ThirdPartyLicensesScreen() }
|
||||
|
||||
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.Home) { DevtoolsScreen() }
|
||||
composableWithDeepLink(Devtools.AndroidLocales) { AndroidLocalesScreen() }
|
||||
composableWithDeepLink(Devtools.AndroidSettings) { navBackStack ->
|
||||
val name = navBackStack.arguments?.getString("name")
|
||||
AndroidSettingsScreen(name)
|
||||
}
|
||||
composableWithDeepLink(Devtools.ExportDebugLog::class) { ExportDebugLogScreen() }
|
||||
composableWithDeepLink(Devtools.ExportDebugLog) { ExportDebugLogScreen() }
|
||||
|
||||
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.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.Edit::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.Edit>()
|
||||
val extensionId = payload.id
|
||||
val serialType = payload.serialType
|
||||
composableWithDeepLink(Ext.Edit) { navBackStack ->
|
||||
val extensionId = navBackStack.arguments?.getString("id")
|
||||
val serialType = navBackStack.arguments?.getString("serial_type")
|
||||
ExtensionEditScreen(
|
||||
id = extensionId,
|
||||
id = extensionId.toString(),
|
||||
createSerialType = serialType.takeIf { !it.isNullOrBlank() },
|
||||
)
|
||||
}
|
||||
composableWithDeepLink(Ext.Export::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.Export>()
|
||||
val extensionId = payload.id
|
||||
ExtensionExportScreen(id = extensionId)
|
||||
composableWithDeepLink(Ext.Export) { navBackStack ->
|
||||
val extensionId = navBackStack.arguments?.getString("id")
|
||||
ExtensionExportScreen(id = extensionId.toString())
|
||||
}
|
||||
composableWithDeepLink(Ext.Import::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.Import>()
|
||||
val uuid = payload.uuid
|
||||
ExtensionImportScreen(payload.type, uuid)
|
||||
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.View::class) { navBackStack ->
|
||||
val payload = navBackStack.toRoute<Ext.View>()
|
||||
val extensionId = payload.id
|
||||
ExtensionViewScreen(id = extensionId)
|
||||
composableWithDeepLink(Ext.View) { navBackStack ->
|
||||
val extensionId = navBackStack.arguments?.getString("id")
|
||||
ExtensionViewScreen(id = extensionId.toString())
|
||||
}
|
||||
composableWithDeepLink(Ext.CheckUpdates::class) {
|
||||
composableWithDeepLink(Ext.CheckUpdates) {
|
||||
CheckUpdatesScreen()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,12 @@ 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,7 +40,6 @@ 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
|
||||
@@ -53,10 +52,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 java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import org.florisboard.lib.android.AndroidVersion
|
||||
import org.florisboard.lib.snygg.SnyggMissingSchemaException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
private val CardBackground = Color.Black.copy(0.6f)
|
||||
private val DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", FlorisLocale.default().base)
|
||||
@@ -65,7 +64,6 @@ 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()
|
||||
|
||||
@@ -74,7 +72,6 @@ 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()
|
||||
@@ -100,7 +97,7 @@ fun DevtoolsOverlay(modifier: Modifier = Modifier) {
|
||||
DevtoolsInlineAutofillOverlay()
|
||||
}
|
||||
val loadFailure = themeInfo.loadFailure
|
||||
if (loadFailure != null && prefsLoaded) {
|
||||
if (loadFailure != null) {
|
||||
DevtoolsStylesheetFailedToLoadOverlay(loadFailure)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,17 +29,18 @@ 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 org.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.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,7 +48,9 @@ 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
|
||||
@@ -60,8 +62,6 @@ 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,9 +42,7 @@ 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
|
||||
@@ -62,9 +60,15 @@ 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
|
||||
@@ -81,15 +85,11 @@ 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.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.showLongToast
|
||||
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 = ImageVector.vectorResource(R.drawable.ic_file_blank),
|
||||
icon = vectorResource(R.drawable.ic_file_blank),
|
||||
title = stringRes(R.string.ext__editor__files__title),
|
||||
)
|
||||
}
|
||||
@@ -628,7 +628,7 @@ private fun <T : ExtensionComponent> CreateComponentScreen(
|
||||
for (theme in editor.themes) {
|
||||
put(ExtensionComponentName(extId, theme.id), theme)
|
||||
}
|
||||
for ((componentName, theme) in themeManager.indexedThemeConfigs.value.first) {
|
||||
for ((componentName, theme) in themeManager.indexedThemeConfigs.value ?: emptyMap()) {
|
||||
if (componentName.extensionId != extId) {
|
||||
put(componentName, theme)
|
||||
}
|
||||
@@ -710,7 +710,7 @@ private fun <T : ExtensionComponent> CreateComponentScreen(
|
||||
}
|
||||
editor.themes.add(componentEditor)
|
||||
} else {
|
||||
val component = themeManager.indexedThemeConfigs.value.first.get(componentName) ?: return
|
||||
val component = themeManager.indexedThemeConfigs.value?.get(componentName) ?: return
|
||||
val componentEditor = (component as? ThemeExtensionComponentImpl)?.edit() ?: return
|
||||
componentEditor.id = componentId
|
||||
componentEditor.stylesheetPath = ""
|
||||
|
||||
@@ -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,16 +50,17 @@ 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 org.florisboard.lib.compose.FlorisChip
|
||||
import dev.patrickgold.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 org.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
internal fun ExtensionNotFoundScreen(id: String) = FlorisScreen {
|
||||
|
||||
@@ -51,17 +51,18 @@ 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.compose.FlorisScreen
|
||||
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
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisCanvasIcon
|
||||
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.Preference
|
||||
|
||||
@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 org.florisboard.lib.compose.florisScrollbar
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.compose.florisScrollbar
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
|
||||
@Composable
|
||||
fun ThirdPartyLicensesScreen() = FlorisScreen {
|
||||
|
||||
@@ -50,7 +50,12 @@ 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
|
||||
@@ -64,11 +69,6 @@ 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,9 +27,7 @@ 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
|
||||
@@ -38,6 +36,7 @@ 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
|
||||
@@ -46,9 +45,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
|
||||
@@ -157,7 +156,7 @@ fun OtherScreen() = FlorisScreen {
|
||||
enabledIf = { AndroidVersion.ATMOST_API28_P },
|
||||
)
|
||||
Preference(
|
||||
icon = ImageVector.vectorResource(R.drawable.ic_keyboard_keys),
|
||||
icon = 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
|
||||
@@ -148,13 +148,11 @@ fun RestoreScreen() = FlorisScreen {
|
||||
val workspace = restoreWorkspace!!
|
||||
val shouldReset = importStrategy == ImportStrategy.Erase
|
||||
if (restoreFilesSelector.jetprefDatastore) {
|
||||
val file = workspace.outputDir
|
||||
val fileBasedStorage = workspace.outputDir
|
||||
.subDir(AndroidAppDataStorage.JETPREF_DIR_NAME)
|
||||
.subFile("${FlorisPreferenceModel.NAME}.${AndroidAppDataStorage.JETPREF_FILE_EXT}")
|
||||
if (file.exists()) {
|
||||
val fileBasedStorage = FileBasedStorage(file.path)
|
||||
FlorisPreferenceStore.import(importStrategy, fileBasedStorage).getOrThrow()
|
||||
}
|
||||
.let { FileBasedStorage(it.path) }
|
||||
FlorisPreferenceStore.import(importStrategy, fileBasedStorage).getOrThrow()
|
||||
}
|
||||
val workspaceFilesDir = workspace.outputDir.subDir("files")
|
||||
if (restoreFilesSelector.imeKeyboard) {
|
||||
|
||||
@@ -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,8 +55,11 @@ 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
|
||||
@@ -67,9 +70,6 @@ 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,13 +23,14 @@ 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 org.florisboard.lib.compose.FlorisInfoCard
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
|
||||
|
||||
@OptIn(ExperimentalJetPrefDatastoreUi::class)
|
||||
@Composable
|
||||
|
||||
@@ -23,6 +23,7 @@ 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
|
||||
@@ -30,7 +31,6 @@ 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,6 +45,8 @@ 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
|
||||
@@ -53,9 +55,8 @@ 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,7 +37,6 @@ 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
|
||||
@@ -75,20 +74,18 @@ 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()
|
||||
@@ -368,7 +365,6 @@ 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)) {
|
||||
@@ -378,15 +374,16 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val popupMappingLabels = remember(popupMappings) {
|
||||
selectListValues + popupMappings.values.map { it.label }
|
||||
}
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val selectedIndex = popupMappingIds.indexOf(popupMapping).coerceAtLeast(0)
|
||||
JetPrefDropdown(
|
||||
options = popupMappingLabels,
|
||||
FlorisDropdownMenu(
|
||||
items = popupMappingLabels,
|
||||
expanded = expanded,
|
||||
selectedOptionIndex = selectedIndex,
|
||||
selectedIndex = selectedIndex,
|
||||
isError = showSelectAsError && selectedIndex == 0,
|
||||
onSelectOption = { popupMapping = popupMappingIds[it] },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
onSelectItem = { popupMapping = popupMappingIds[it] },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
)
|
||||
}
|
||||
SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_characters_layout), LayoutType.CHARACTERS)
|
||||
@@ -407,18 +404,19 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val nlpProviderMappingLabels = remember(nlpProviderMappings) {
|
||||
selectListValues + nlpProviderMappings.values.map { it }
|
||||
}
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val selectedIndex = nlpProviderMappingIds.indexOf(nlpProviders.suggestion).coerceAtLeast(0)
|
||||
JetPrefDropdown(
|
||||
options = nlpProviderMappingLabels,
|
||||
FlorisDropdownMenu(
|
||||
items = nlpProviderMappingLabels,
|
||||
expanded = expanded,
|
||||
selectedOptionIndex = selectedIndex,
|
||||
selectedIndex = selectedIndex,
|
||||
isError = showSelectAsError && selectedIndex == 0,
|
||||
onSelectOption = { nlpProviders = SubtypeNlpProviderMap(
|
||||
onSelectItem = { nlpProviders = SubtypeNlpProviderMap(
|
||||
suggestion = nlpProviderMappingIds[it],
|
||||
spelling = nlpProviderMappingIds[it]
|
||||
) },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -434,14 +432,15 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val composerNames = remember(composers) {
|
||||
selectListValues + composers.values.map { it.label }
|
||||
}
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
JetPrefDropdown(
|
||||
options = composerNames,
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
FlorisDropdownMenu(
|
||||
items = composerNames,
|
||||
expanded = expanded,
|
||||
selectedOptionIndex = composerIds.indexOf(composer).coerceAtLeast(0),
|
||||
selectedIndex = composerIds.indexOf(composer).coerceAtLeast(0),
|
||||
isError = showSelectAsError && composer == SelectComponentName,
|
||||
onSelectOption = { composer = composerIds[it] },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
onSelectItem = { composer = composerIds[it] },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
)
|
||||
}
|
||||
SubtypeProperty(stringRes(R.string.settings__localization__subtype_currency_set)) {
|
||||
@@ -451,14 +450,15 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
|
||||
val currencySetNames = remember(currencySets) {
|
||||
selectListValues + currencySets.values.map { it.label }
|
||||
}
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
JetPrefDropdown(
|
||||
options = currencySetNames,
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
FlorisDropdownMenu(
|
||||
items = currencySetNames,
|
||||
expanded = expanded,
|
||||
selectedOptionIndex = currencySetIds.indexOf(currencySet).coerceAtLeast(0),
|
||||
selectedIndex = currencySetIds.indexOf(currencySet).coerceAtLeast(0),
|
||||
isError = showSelectAsError && currencySet == SelectComponentName,
|
||||
onSelectOption = { currencySet = currencySetIds[it] },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
onSelectItem = { currencySet = currencySetIds[it] },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -556,15 +556,16 @@ 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] }
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
val selectedIndex = layoutIds.indexOf(layoutId).coerceAtLeast(0)
|
||||
JetPrefDropdown(
|
||||
options = layoutLabels,
|
||||
FlorisDropdownMenu(
|
||||
items = layoutLabels,
|
||||
expanded = expanded,
|
||||
selectedOptionIndex = selectedIndex,
|
||||
selectedIndex = selectedIndex,
|
||||
isError = showSelectAsError && selectedIndex == 0,
|
||||
onSelectOption = { onLayoutMapChanged(layoutMap.copy(layoutType = layoutType, componentName = layoutIds[it])!!) },
|
||||
appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
|
||||
onSelectItem = { onLayoutMapChanged(layoutMap.copy(layoutType, layoutIds[it])!!) },
|
||||
onExpandRequest = { expanded = true },
|
||||
onDismissRequest = { expanded = false },
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ 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
|
||||
@@ -42,8 +44,6 @@ 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 {
|
||||
|
||||
@@ -77,7 +77,13 @@ 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
|
||||
@@ -88,14 +94,7 @@ 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
|
||||
@@ -132,6 +131,7 @@ 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,7 +85,11 @@ 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
|
||||
@@ -94,10 +98,6 @@ 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,10 +80,16 @@ 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
|
||||
@@ -94,13 +100,7 @@ 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,6 +37,7 @@ 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
|
||||
@@ -46,7 +47,6 @@ 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 {
|
||||
@@ -60,7 +60,7 @@ fun ThemeScreen() = FlorisScreen {
|
||||
@Composable
|
||||
fun ThemeManager.getThemeLabel(id: ExtensionComponentName): String {
|
||||
val configs by indexedThemeConfigs.collectAsState()
|
||||
configs.first[id]?.let { return it.label }
|
||||
configs[id]?.let { return it.label }
|
||||
return id.toString()
|
||||
}
|
||||
|
||||
|
||||
@@ -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,8 +30,6 @@ 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
|
||||
@@ -39,17 +37,19 @@ 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 = ImageVector.vectorResource(id = R.drawable.ic_incognito),
|
||||
icon = vectorResource(id = R.drawable.ic_incognito),
|
||||
title = stringRes(R.string.pref__suggestion__incognito_mode__label),
|
||||
entries = enumDisplayEntriesOf(IncognitoMode::class),
|
||||
)
|
||||
|
||||
@@ -46,8 +46,13 @@ 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
|
||||
@@ -57,11 +62,6 @@ 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,23 +102,23 @@ 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
|
||||
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,6 +128,7 @@ 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
|
||||
@@ -147,12 +148,12 @@ fun ClipboardInputLayout(
|
||||
|
||||
val deviceLocked = androidKeyguardManager.let { it.isDeviceLocked || it.isKeyguardLocked }
|
||||
val historyEnabled by prefs.clipboard.historyEnabled.observeAsState()
|
||||
val unfilteredHistory by clipboardManager.history.observeAsNonNullState()
|
||||
|
||||
var isFilterRowShown by remember { mutableStateOf(false) }
|
||||
val activeFilterTypes = remember { mutableStateSetOf<ItemType>() }
|
||||
|
||||
val unfilteredHistory by clipboardManager.history.observeAsNonNullState()
|
||||
val filteredHistory = remember(unfilteredHistory, activeFilterTypes.toSet()) {
|
||||
val history = remember(unfilteredHistory, activeFilterTypes.toSet()) {
|
||||
if (activeFilterTypes.isEmpty()) {
|
||||
unfilteredHistory
|
||||
} else {
|
||||
@@ -163,7 +164,7 @@ fun ClipboardInputLayout(
|
||||
}
|
||||
|
||||
val gridState = rememberLazyStaggeredGridState()
|
||||
var popupItem by remember(filteredHistory) { mutableStateOf<ClipboardItem?>(null) }
|
||||
var popupItem by remember(history) { mutableStateOf<ClipboardItem?>(null) }
|
||||
var showClearAllHistory by remember { mutableStateOf(false) }
|
||||
|
||||
fun isPopupSurfaceActive() = popupItem != null || showClearAllHistory
|
||||
@@ -222,7 +223,7 @@ fun ClipboardInputLayout(
|
||||
elementName = FlorisImeUi.ClipboardHeaderButton.elementName,
|
||||
onClick = { showClearAllHistory = true },
|
||||
modifier = sizeModifier.autoMirrorForRtl(),
|
||||
enabled = !deviceLocked && historyEnabled && filteredHistory.all.isNotEmpty() && !isPopupSurfaceActive(),
|
||||
enabled = !deviceLocked && historyEnabled && unfilteredHistory.all.isNotEmpty() && !isPopupSurfaceActive(),
|
||||
) {
|
||||
SnyggIcon(
|
||||
imageVector = Icons.Default.DeleteSweep,
|
||||
@@ -467,17 +468,17 @@ fun ClipboardInputLayout(
|
||||
columns = staggeredGridCells,
|
||||
) {
|
||||
clipboardItems(
|
||||
items = filteredHistory.pinned,
|
||||
items = history.pinned,
|
||||
key = "pinned-header",
|
||||
title = R.string.clipboard__group_pinned,
|
||||
)
|
||||
clipboardItems(
|
||||
items = filteredHistory.recent,
|
||||
items = history.recent,
|
||||
key = "recent-header",
|
||||
title = R.string.clipboard__group_recent,
|
||||
)
|
||||
clipboardItems(
|
||||
items = filteredHistory.other,
|
||||
items = history.other,
|
||||
key = "other-header",
|
||||
title = R.string.clipboard__group_other,
|
||||
)
|
||||
@@ -566,13 +567,7 @@ fun ClipboardInputLayout(
|
||||
) {
|
||||
SnyggText(
|
||||
elementName = FlorisImeUi.ClipboardClearAllDialogMessage.elementName,
|
||||
text = stringRes(
|
||||
if (isFilterRowShown) {
|
||||
R.string.clipboard__confirm_clear_filtered_history__message
|
||||
} else {
|
||||
R.string.clipboard__confirm_clear_unfiltered_history__message
|
||||
}
|
||||
),
|
||||
text = stringRes(R.string.clipboard__confirm_clear_history__message),
|
||||
)
|
||||
SnyggRow(FlorisImeUi.ClipboardClearAllDialogButtons.elementName) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
@@ -591,9 +586,10 @@ fun ClipboardInputLayout(
|
||||
elementName = FlorisImeUi.ClipboardClearAllDialogButton.elementName,
|
||||
attributes = mapOf("action" to "yes"),
|
||||
onClick = {
|
||||
clipboardManager.clearExactHistory(filteredHistory.unpinned)
|
||||
clipboardManager.clearHistory()
|
||||
context.showShortToastSync(R.string.clipboard__cleared_history)
|
||||
showClearAllHistory = false
|
||||
isFilterRowShown = false
|
||||
},
|
||||
) {
|
||||
SnyggText(
|
||||
@@ -674,7 +670,7 @@ fun ClipboardInputLayout(
|
||||
HistoryLockedView()
|
||||
} else {
|
||||
if (historyEnabled) {
|
||||
if (filteredHistory.all.isNotEmpty() || !activeFilterTypes.isEmpty()) {
|
||||
if (history.all.isNotEmpty() || !activeFilterTypes.isEmpty()) {
|
||||
HistoryMainView()
|
||||
} else {
|
||||
HistoryEmptyView()
|
||||
|
||||
@@ -286,15 +286,6 @@ class ClipboardManager(
|
||||
}
|
||||
}
|
||||
|
||||
fun clearExactHistory(items: List<ClipboardItem>) {
|
||||
ioScope.launch {
|
||||
for (item in items) {
|
||||
item.close(appContext)
|
||||
}
|
||||
clipHistoryDao?.delete(items)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all unpinned items from the clipboard history
|
||||
*/
|
||||
@@ -400,8 +391,7 @@ class ClipboardManager(
|
||||
private val now = System.currentTimeMillis()
|
||||
|
||||
val pinned = all.filter { it.isPinned }
|
||||
val unpinned = all.filter { !it.isPinned }
|
||||
val recent = unpinned.filter { (now - it.creationTimestampMs) < RECENT_TIMESPAN_MS }
|
||||
val other = unpinned.filter { (now - it.creationTimestampMs) >= RECENT_TIMESPAN_MS }
|
||||
val recent = all.filter { !it.isPinned && (now - it.creationTimestampMs < RECENT_TIMESPAN_MS) }
|
||||
val other = all.filter { !it.isPinned && (now - it.creationTimestampMs >= RECENT_TIMESPAN_MS) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,11 +136,7 @@ class FlorisCopyToClipboardActivity : ComponentActivity() {
|
||||
@Composable
|
||||
private fun Content() {
|
||||
val prefs by FlorisPreferenceStore
|
||||
ProvideLocalizedResources(
|
||||
resourcesContext = this,
|
||||
appName = R.string.app_name,
|
||||
forceLayoutDirection = LayoutDirection.Ltr,
|
||||
) {
|
||||
ProvideLocalizedResources(this, 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,16 +40,6 @@ 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 {
|
||||
@@ -438,69 +428,41 @@ abstract class AbstractEditorInstance(context: Context) {
|
||||
return true
|
||||
}
|
||||
|
||||
protected suspend fun deleteAroundCursor(unit: OperationUnit, scope: OperationScope, n: Int = 0): Boolean {
|
||||
protected fun deleteBeforeCursor(type: TextType, n: Int): 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 scopeText = when (scope) {
|
||||
OperationScope.BEFORE_CURSOR -> content.textBeforeSelection
|
||||
OperationScope.AFTER_CURSOR -> content.textAfterSelection
|
||||
}
|
||||
return (if (activeInfo.isRawInputEditor || scopeText.isEmpty()) {
|
||||
val oldTextBeforeSelection = content.textBeforeSelection
|
||||
return (if (activeInfo.isRawInputEditor || oldTextBeforeSelection.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/forward delete.
|
||||
val keyEventCode = when (scope) {
|
||||
OperationScope.BEFORE_CURSOR -> KeyEvent.KEYCODE_DEL
|
||||
OperationScope.AFTER_CURSOR -> KeyEvent.KEYCODE_FORWARD_DEL
|
||||
// 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)
|
||||
}
|
||||
val metaState = when (unit) {
|
||||
OperationUnit.CHARACTERS -> meta()
|
||||
OperationUnit.WORDS -> meta(ctrl = true)
|
||||
}
|
||||
sendDownUpKeyEvent(keyEventCode, metaState, count = n)
|
||||
} else {
|
||||
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()
|
||||
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 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()
|
||||
}
|
||||
@@ -661,6 +623,11 @@ abstract class AbstractEditorInstance(context: Context) {
|
||||
return true
|
||||
}
|
||||
|
||||
protected enum class TextType {
|
||||
CHARACTERS,
|
||||
WORDS;
|
||||
}
|
||||
|
||||
private class ExpectedContentQueue {
|
||||
private val list = guardedByLock { mutableListOf<EditorContent>() }
|
||||
|
||||
|
||||
@@ -91,9 +91,6 @@ data class EditorContent(
|
||||
val currentWordText: String
|
||||
get() = if (localCurrentWord.isValid) text.safeSubstring(localCurrentWord.start, localCurrentWord.end) else ""
|
||||
|
||||
val safeEditorBounds: EditorRange
|
||||
get() = if (offset >= 0) EditorRange(0, offset + text.length) else EditorRange(0, 0)
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Default editor content which indicates an unspecified content. This is used for raw editors or if there is
|
||||
|
||||
@@ -42,6 +42,7 @@ 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) {
|
||||
@@ -335,75 +336,49 @@ class EditorInstance(context: Context) : AbstractEditorInstance(context) {
|
||||
*
|
||||
* @return True on success, false if an error occurred or the input connection is invalid.
|
||||
*/
|
||||
fun deleteBackwards(unit: OperationUnit): Boolean {
|
||||
fun deleteBackwards(): Boolean {
|
||||
val content = activeContent
|
||||
if (unit == OperationUnit.CHARACTERS) {
|
||||
if (phantomSpace.isActive && content.currentWord.isValid && prefs.glide.immediateBackspaceDeletesWord.get()) {
|
||||
return deleteBackwards(OperationUnit.WORDS)
|
||||
}
|
||||
if (phantomSpace.isActive && content.currentWord.isValid && prefs.glide.immediateBackspaceDeletesWord.get()) {
|
||||
return deleteWordBackwards()
|
||||
}
|
||||
autoSpace.setInactive()
|
||||
phantomSpace.setInactive()
|
||||
return if (content.selection.isSelectionMode) {
|
||||
commitText("")
|
||||
} else runBlocking {
|
||||
deleteAroundCursor(unit, OperationScope.BEFORE_CURSOR, n = 1)
|
||||
} else {
|
||||
deleteBeforeCursor(TextType.CHARACTERS, 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 character from
|
||||
* characters inside this selection will be removed, else only the left-most word from
|
||||
* the cursor's position.
|
||||
*
|
||||
* @return True on success, false if an error occurred or the input connection is invalid.
|
||||
*/
|
||||
fun deleteForwards(unit: OperationUnit): Boolean {
|
||||
val content = activeContent
|
||||
fun deleteWordBackwards(): Boolean {
|
||||
autoSpace.setInactive()
|
||||
phantomSpace.setInactive()
|
||||
return if (content.selection.isSelectionMode) {
|
||||
return if (activeContent.selection.isSelectionMode) {
|
||||
commitText("")
|
||||
} else runBlocking {
|
||||
deleteAroundCursor(unit, OperationScope.AFTER_CURSOR, n = 1)
|
||||
} else {
|
||||
deleteBeforeCursor(TextType.WORDS, 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun setSelectionSurrounding(n: Int, unit: OperationUnit, scope: OperationScope): Boolean {
|
||||
fun selectionSetNWordsLeft(n: Int): Boolean {
|
||||
autoSpace.setInactive()
|
||||
phantomSpace.setInactive()
|
||||
val content = activeContent
|
||||
val selection = content.selection
|
||||
val safeEditorBounds = content.safeEditorBounds
|
||||
if (selection.isNotValid) return false
|
||||
when (scope) {
|
||||
OperationScope.BEFORE_CURSOR -> {
|
||||
if (n <= 0) {
|
||||
return setSelection(selection.end, selection.end)
|
||||
}
|
||||
val textToAnalyze = content.text.substring(0, content.localSelection.end)
|
||||
val length = runBlocking {
|
||||
when (unit) {
|
||||
OperationUnit.CHARACTERS -> breakIterators.measureLastUChars(textToAnalyze, n)
|
||||
OperationUnit.WORDS -> breakIterators.measureLastUWords(textToAnalyze, n)
|
||||
}
|
||||
}
|
||||
return setSelection((selection.end - length).coerceAtLeast(safeEditorBounds.start), selection.end)
|
||||
}
|
||||
OperationScope.AFTER_CURSOR -> {
|
||||
if (n <= 0) {
|
||||
return setSelection(selection.start, selection.start)
|
||||
}
|
||||
val textToAnalyze = content.text.substring(content.localSelection.start)
|
||||
val length = runBlocking {
|
||||
when (unit) {
|
||||
OperationUnit.CHARACTERS -> breakIterators.measureUChars(textToAnalyze, n)
|
||||
OperationUnit.WORDS -> breakIterators.measureUWords(textToAnalyze, n)
|
||||
}
|
||||
}
|
||||
return setSelection(selection.start, (selection.start + length).coerceAtMost(safeEditorBounds.end))
|
||||
}
|
||||
if (n <= 0) {
|
||||
return setSelection(selection.end, selection.end)
|
||||
}
|
||||
val textToAnalyze = content.text.substring(0, content.localSelection.end)
|
||||
val length = runBlocking { breakIterators.measureLastUWords(textToAnalyze, n) }
|
||||
return setSelection((selection.end - length).coerceAtLeast(0), selection.end)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,7 +396,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(OperationUnit.CHARACTERS)
|
||||
return deleteBackwards()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,10 +19,8 @@ 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
|
||||
@@ -57,8 +55,7 @@ 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.florisboard.lib.compose.vectorResource
|
||||
import org.florisboard.lib.compose.icons.ForwardDelete
|
||||
import dev.patrickgold.jetpref.datastore.ui.vectorResource
|
||||
|
||||
interface ComputingEvaluator {
|
||||
val version: Int
|
||||
@@ -237,9 +234,6 @@ fun ComputingEvaluator.computeImageVector(data: KeyData): ImageVector? {
|
||||
}
|
||||
}
|
||||
}
|
||||
KeyCode.FORWARD_DELETE -> {
|
||||
Icons.AutoMirrored.Default.ForwardDelete
|
||||
}
|
||||
KeyCode.IME_UI_MODE_MEDIA -> {
|
||||
Icons.Default.SentimentSatisfiedAlt
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ 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
|
||||
@@ -76,6 +75,7 @@ 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,30 +417,27 @@ class KeyboardManager(context: Context) : InputKeyEventReceiver {
|
||||
/**
|
||||
* Handles a [KeyCode.DELETE] event.
|
||||
*/
|
||||
private fun handleBackwardDelete(unit: OperationUnit) {
|
||||
if (inputEventDispatcher.isPressed(KeyCode.SHIFT)) {
|
||||
return handleForwardDelete(unit)
|
||||
}
|
||||
private fun handleDelete() {
|
||||
activeState.batchEdit {
|
||||
it.isManualSelectionMode = false
|
||||
it.isManualSelectionModeStart = false
|
||||
it.isManualSelectionModeEnd = false
|
||||
}
|
||||
revertPreviouslyAcceptedCandidate()
|
||||
editorInstance.deleteBackwards(unit)
|
||||
editorInstance.deleteBackwards()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a [KeyCode.FORWARD_DELETE] event.
|
||||
* Handles a [KeyCode.DELETE_WORD] event.
|
||||
*/
|
||||
private fun handleForwardDelete(unit: OperationUnit) {
|
||||
private fun handleDeleteWord() {
|
||||
activeState.batchEdit {
|
||||
it.isManualSelectionMode = false
|
||||
it.isManualSelectionModeStart = false
|
||||
it.isManualSelectionModeEnd = false
|
||||
}
|
||||
revertPreviouslyAcceptedCandidate()
|
||||
editorInstance.deleteForwards(unit)
|
||||
editorInstance.deleteWordBackwards()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,7 +566,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(OperationUnit.CHARACTERS)
|
||||
editorInstance.deleteBackwards()
|
||||
editorInstance.commitText(". ")
|
||||
return
|
||||
}
|
||||
@@ -732,11 +729,9 @@ class KeyboardManager(context: Context) : InputKeyEventReceiver {
|
||||
prefs.keyboard.oneHandedMode.set(OneHandedMode.END)
|
||||
toggleOneHandedMode()
|
||||
}
|
||||
KeyCode.DELETE -> handleBackwardDelete(OperationUnit.CHARACTERS)
|
||||
KeyCode.DELETE_WORD -> handleBackwardDelete(OperationUnit.WORDS)
|
||||
KeyCode.DELETE -> handleDelete()
|
||||
KeyCode.DELETE_WORD -> handleDeleteWord()
|
||||
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()
|
||||
@@ -871,20 +866,6 @@ 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,8 +38,6 @@ 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
|
||||
@@ -54,7 +52,6 @@ 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
|
||||
@@ -63,7 +60,6 @@ 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
|
||||
@@ -91,14 +87,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
|
||||
@@ -173,6 +169,7 @@ fun EmojiPaletteView(
|
||||
}
|
||||
}
|
||||
var recentlyUsedVersion by remember { mutableIntStateOf(0) }
|
||||
val lazyListState = rememberLazyGridState()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
@Composable
|
||||
@@ -207,111 +204,22 @@ fun EmojiPaletteView(
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
Column(modifier = modifier) {
|
||||
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()
|
||||
|
||||
// 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) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
) {
|
||||
val emojiMapping = if (activeCategory == 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) {
|
||||
@@ -326,68 +234,63 @@ fun EmojiPaletteView(
|
||||
EmojiMappingForView(
|
||||
pinned = emptyList(),
|
||||
recent = emptyList(),
|
||||
simple = emojiMappings[category]!!,
|
||||
simple = emojiMappings[activeCategory]!!,
|
||||
)
|
||||
}
|
||||
|
||||
val isEmojiHistoryEmpty = emojiMapping.pinned.isEmpty() && emojiMapping.recent.isEmpty()
|
||||
when (category) {
|
||||
EmojiCategory.RECENTLY_USED if deviceLocked -> {
|
||||
Column(
|
||||
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(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(all = 8.dp),
|
||||
.florisScrollbar(lazyListState),
|
||||
columns = GridCells.Adaptive(minSize = EmojiBaseWidth),
|
||||
state = lazyListState,
|
||||
) {
|
||||
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)
|
||||
}
|
||||
if (emojiMapping.pinned.isNotEmpty()) {
|
||||
header("header_pinned") {
|
||||
GridHeader(text = stringRes(R.string.emoji__history__pinned))
|
||||
}
|
||||
if (emojiMapping.recent.isNotEmpty()) {
|
||||
header("header_recent") {
|
||||
GridHeader(text = stringRes(R.string.emoji__history__recent))
|
||||
}
|
||||
items(emojiMapping.recent) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet, isRecent = true)
|
||||
}
|
||||
items(emojiMapping.pinned) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet, isPinned = true)
|
||||
}
|
||||
if (emojiMapping.simple.isNotEmpty()) {
|
||||
items(emojiMapping.simple) { emojiSet ->
|
||||
EmojiKeyWrapper(emojiSet)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,6 +300,59 @@ 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,
|
||||
|
||||
@@ -70,17 +70,12 @@ class EmojiSuggestionProvider(private val context: Context) : SuggestionProvider
|
||||
val emojis = cachedEmojiMappings.get(subtype.primaryLocale)?.get(preferredSkinTone) ?: emptyList()
|
||||
val candidates = withContext(Dispatchers.Default) {
|
||||
emojis.parallelStream()
|
||||
.map { emoji ->
|
||||
val nameWeight = emoji.name.containsWeighted(query, ignoreCase = true)
|
||||
val keywordWeight = emoji.keywords
|
||||
.any { it.contains(query, ignoreCase = true) }
|
||||
.let { if (it) 1.0 else 0.0 }
|
||||
emoji to (nameWeight * 0.7 + keywordWeight * 0.3)
|
||||
.filter { emoji ->
|
||||
emoji.name.contains(query, ignoreCase = true) &&
|
||||
emoji.keywords.any { it.contains(query, ignoreCase = true) }
|
||||
}
|
||||
.sorted { (_, a), (_, b) -> b.compareTo(a) }
|
||||
.limit(maxCandidateCount.toLong())
|
||||
.filter { (_, a) -> a > 0 }
|
||||
.map { (emoji, _) ->
|
||||
.map { emoji ->
|
||||
EmojiSuggestionCandidate(
|
||||
emoji = emoji,
|
||||
showName = showName,
|
||||
@@ -133,11 +128,3 @@ class EmojiSuggestionProvider(private val context: Context) : SuggestionProvider
|
||||
return emojiPartialName
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.containsWeighted(other: String, ignoreCase: Boolean = false): Double = let { str ->
|
||||
if (str.contains(other, ignoreCase = ignoreCase)) {
|
||||
other.length.toDouble() / str.length.toDouble()
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 org.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.snygg.ui.SnyggColumn
|
||||
import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
|
||||
@@ -24,15 +24,13 @@ 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 androidx.compose.ui.zIndex
|
||||
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
|
||||
@@ -41,8 +39,6 @@ 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,
|
||||
@@ -50,13 +46,6 @@ 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,
|
||||
@@ -70,7 +59,7 @@ fun PopupBaseBox(
|
||||
.align(Alignment.TopCenter),
|
||||
) {
|
||||
SnyggText(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
modifier = Modifier.align(Alignment.Center).zIndex(100f),
|
||||
text = label,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.zIndex
|
||||
import dev.patrickgold.florisboard.ime.keyboard.ComputingEvaluator
|
||||
import dev.patrickgold.florisboard.ime.keyboard.DefaultComputingEvaluator
|
||||
import dev.patrickgold.florisboard.ime.keyboard.Key
|
||||
@@ -38,6 +39,7 @@ import dev.patrickgold.florisboard.ime.keyboard.KeyData
|
||||
import dev.patrickgold.florisboard.ime.keyboard.computeImageVector
|
||||
import dev.patrickgold.florisboard.ime.keyboard.computeLabel
|
||||
import dev.patrickgold.florisboard.ime.media.emoji.EmojiSet
|
||||
import dev.patrickgold.florisboard.ime.smartbar.Temp
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyHintConfiguration
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKey
|
||||
@@ -452,11 +454,12 @@ class PopupUiController(
|
||||
FlorisImeUi.Attr.Mode to evaluator.keyboard.mode.toString(),
|
||||
FlorisImeUi.Attr.ShiftState to evaluator.state.inputShiftState.toString(),
|
||||
)
|
||||
Temp = !(baseRenderInfo != null || extRenderInfo != null)
|
||||
baseRenderInfo?.let { renderInfo ->
|
||||
PopupBaseBox(
|
||||
modifier = Modifier
|
||||
.requiredSize(renderInfo.bounds.size.toDpSize())
|
||||
.absoluteOffset { renderInfo.bounds.topLeft.toIntOffset() },
|
||||
.absoluteOffset { renderInfo.bounds.topLeft.toIntOffset() }.zIndex(100f),
|
||||
attributes = attributes,
|
||||
key = renderInfo.key,
|
||||
shouldIndicateExtendedPopups = renderInfo.shouldIndicateExtendedPopups && extRenderInfo == null,
|
||||
|
||||
@@ -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 org.florisboard.lib.compose.conditional
|
||||
import dev.patrickgold.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
|
||||
|
||||
@@ -16,15 +16,16 @@
|
||||
|
||||
package dev.patrickgold.florisboard.ime.smartbar
|
||||
|
||||
import android.graphics.PixelFormat
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.SurfaceView
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.background
|
||||
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
|
||||
@@ -34,16 +35,18 @@ import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.positionInParent
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.view.forEach
|
||||
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.compose.florisHorizontalScroll
|
||||
import org.florisboard.lib.snygg.SnyggSinglePropertySet
|
||||
import org.florisboard.lib.snygg.ui.rememberSnyggThemeQuery
|
||||
|
||||
var CachedInlineSuggestionsChipStyleSet: SnyggSinglePropertySet? = null
|
||||
|
||||
var Temp: Boolean = false
|
||||
|
||||
@Composable
|
||||
fun InlineSuggestionsStyleCache() {
|
||||
val chipStyleSet = rememberSnyggThemeQuery(FlorisImeUi.InlineAutofillChip.elementName)
|
||||
@@ -59,8 +62,9 @@ fun InlineSuggestionsUi(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
val numPopupsShowing by GlobalStateNumPopupsShowing.collectAsState()
|
||||
val isZOrderedOnTop = numPopupsShowing == 0
|
||||
val almostEmptyRect = remember { android.graphics.Rect(0, 0, 1, 1) }
|
||||
|
||||
val backgroundColor = rememberSnyggThemeQuery(FlorisImeUi.SmartbarCandidatesRow.elementName).background()
|
||||
|
||||
Row(
|
||||
modifier
|
||||
@@ -68,7 +72,8 @@ fun InlineSuggestionsUi(
|
||||
.florisHorizontalScroll(
|
||||
state = scrollState,
|
||||
scrollbarHeight = CandidatesRowScrollbarHeight,
|
||||
),
|
||||
)
|
||||
.background(backgroundColor),
|
||||
) {
|
||||
val xMin = scrollState.value
|
||||
val xMax = scrollState.value + scrollState.viewportSize
|
||||
@@ -76,19 +81,34 @@ fun InlineSuggestionsUi(
|
||||
if (inlineSuggestion.view == null) {
|
||||
continue
|
||||
}
|
||||
//inlineSuggestion.view.background = ColorDrawable(backgroundColor.toArgb())
|
||||
inlineSuggestion.view.forEach {
|
||||
with (it as SurfaceView) {
|
||||
//this.setBackgroundColor(backgroundColor.toArgb())
|
||||
setZOrderOnTop(false)
|
||||
holder.setFormat(PixelFormat.OPAQUE)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
var chipPos by remember { mutableStateOf(IntOffset.Zero) }
|
||||
AndroidView(
|
||||
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,
|
||||
)
|
||||
view.visibility = if (view.clipBounds.isEmpty) View.INVISIBLE else View.VISIBLE
|
||||
// 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
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -49,9 +49,7 @@ 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
|
||||
@@ -62,12 +60,13 @@ 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
|
||||
@@ -143,6 +142,7 @@ private fun SmartbarMainRow(modifier: Modifier = Modifier) {
|
||||
val prefs by FlorisPreferenceStore
|
||||
val context = LocalContext.current
|
||||
val keyboardManager by context.keyboardManager()
|
||||
val activeEvaluator by keyboardManager.activeEvaluator.collectAsState()
|
||||
val nlpManager by context.nlpManager()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
@@ -187,7 +187,7 @@ private fun SmartbarMainRow(modifier: Modifier = Modifier) {
|
||||
} else {
|
||||
Icons.AutoMirrored.Default.KeyboardArrowRight
|
||||
}
|
||||
val incognitoIcon = ImageVector.vectorResource(id = R.drawable.ic_incognito)
|
||||
val incognitoIcon = 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,7 +87,6 @@ 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,7 +86,6 @@ 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(
|
||||
),
|
||||
|
||||
@@ -39,6 +39,7 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -57,9 +58,9 @@ 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.runBlocking
|
||||
import kotlinx.coroutines.launch
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggColumn
|
||||
import org.florisboard.lib.snygg.ui.SnyggIcon
|
||||
@@ -75,6 +76,7 @@ private val DragMarkerAction = QuickAction.InsertKey(TextKeyData(code = KeyCode.
|
||||
fun QuickActionsEditorPanel() {
|
||||
val prefs by FlorisPreferenceStore
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val keyboardManager by context.keyboardManager()
|
||||
|
||||
// We get the current arrangement once and do not observe on purpose
|
||||
@@ -234,7 +236,7 @@ fun QuickActionsEditorPanel() {
|
||||
dynamicActions.filter { it != NoopAction && it != DragMarkerAction },
|
||||
hiddenActions.filter { it != NoopAction && it != DragMarkerAction },
|
||||
)
|
||||
runBlocking {
|
||||
scope.launch {
|
||||
prefs.smartbar.actionArrangement.set(newActionArrangement)
|
||||
}
|
||||
if (keyboardManager.activeState.isActionsEditorVisible) {
|
||||
|
||||
@@ -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.jetpref.datastore.model.observeAsState
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.snygg.ui.SnyggBox
|
||||
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.snygg.ui.SnyggBox
|
||||
import org.florisboard.lib.snygg.ui.SnyggText
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -59,8 +59,6 @@ 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.OperationScope
|
||||
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
|
||||
@@ -80,6 +78,7 @@ 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
|
||||
@@ -89,7 +88,6 @@ 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
|
||||
@@ -500,7 +498,7 @@ private class TextKeyboardLayoutController(
|
||||
if (pointer.hasTriggeredGestureMove && pointer.initialKey?.computedData?.code == KeyCode.DELETE) {
|
||||
val selection = editorInstance.activeContent.selection
|
||||
if (selection.isSelectionMode) {
|
||||
editorInstance.deleteBackwards(OperationUnit.CHARACTERS)
|
||||
editorInstance.deleteBackwards()
|
||||
}
|
||||
}
|
||||
onTouchCancelInternal(event, pointer)
|
||||
@@ -523,7 +521,7 @@ private class TextKeyboardLayoutController(
|
||||
prefs.gestures.deleteKeySwipeLeft.get() != SwipeAction.SELECT_WORDS_PRECISELY) {
|
||||
val selection = editorInstance.activeContent.selection
|
||||
if (selection.isSelectionMode) {
|
||||
editorInstance.deleteBackwards(OperationUnit.CHARACTERS)
|
||||
editorInstance.deleteBackwards()
|
||||
}
|
||||
}
|
||||
onTouchCancelInternal(event, pointer)
|
||||
@@ -767,21 +765,10 @@ private class TextKeyboardLayoutController(
|
||||
}
|
||||
val activeSelection = editorInstance.activeContent.selection
|
||||
if (activeSelection.isValid) {
|
||||
if (!inputEventDispatcher.isPressed(KeyCode.SHIFT)) {
|
||||
// Backward select
|
||||
editorInstance.setSelectionSurrounding(
|
||||
n = -event.absUnitCountX - 1,
|
||||
unit = OperationUnit.CHARACTERS,
|
||||
scope = OperationScope.BEFORE_CURSOR,
|
||||
)
|
||||
} else {
|
||||
// Forward select
|
||||
editorInstance.setSelectionSurrounding(
|
||||
n = -event.absUnitCountX - 1,
|
||||
unit = OperationUnit.CHARACTERS,
|
||||
scope = OperationScope.AFTER_CURSOR,
|
||||
)
|
||||
}
|
||||
editorInstance.setSelection(
|
||||
(activeSelection.end + event.absUnitCountX + 1).coerceIn(0, activeSelection.end),
|
||||
activeSelection.end,
|
||||
)
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -790,22 +777,8 @@ private class TextKeyboardLayoutController(
|
||||
inputFeedbackController?.gestureMovingSwipe(TextKeyData.DELETE)
|
||||
}
|
||||
val activeSelection = editorInstance.activeContent.selection
|
||||
if (activeSelection.isValid) {
|
||||
if (!inputEventDispatcher.isPressed(KeyCode.SHIFT)) {
|
||||
// Backward select
|
||||
editorInstance.setSelectionSurrounding(
|
||||
n = -event.absUnitCountX / 2 - 1,
|
||||
unit = OperationUnit.WORDS,
|
||||
scope = OperationScope.BEFORE_CURSOR,
|
||||
)
|
||||
} else {
|
||||
// Forward select
|
||||
editorInstance.setSelectionSurrounding(
|
||||
n = -event.absUnitCountX / 2 - 1,
|
||||
unit = OperationUnit.WORDS,
|
||||
scope = OperationScope.AFTER_CURSOR,
|
||||
)
|
||||
}
|
||||
if (activeSelection.isValid && event.absUnitCountX <= 0) {
|
||||
editorInstance.selectionSetNWordsLeft(abs(event.absUnitCountX / 2) - 1)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ import dev.patrickgold.florisboard.lib.ext.ExtensionMeta
|
||||
import dev.patrickgold.florisboard.lib.io.ZipUtils
|
||||
import dev.patrickgold.florisboard.lib.util.TimeUtils.javaLocalTime
|
||||
import dev.patrickgold.florisboard.lib.util.ViewUtils
|
||||
import java.time.LocalTime
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@@ -67,7 +65,8 @@ import org.florisboard.lib.kotlin.io.subDir
|
||||
import org.florisboard.lib.kotlin.io.subFile
|
||||
import org.florisboard.lib.snygg.SnyggStylesheet
|
||||
import org.florisboard.lib.snygg.value.SnyggStaticColorValue
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.time.LocalTime
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Core class which manages the keyboard theme. Note, that this does not affect the UI theme of the
|
||||
@@ -80,13 +79,11 @@ class ThemeManager(context: Context) {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
|
||||
private val _indexedThemeConfigs = MutableStateFlow(mapOf<ExtensionComponentName, ThemeExtensionComponent>() to 0)
|
||||
private val _indexedThemeConfigs = MutableStateFlow(mapOf<ExtensionComponentName, ThemeExtensionComponent>())
|
||||
val indexedThemeConfigs get() = _indexedThemeConfigs.asStateFlow()
|
||||
private val indexedThemeConfigVersion = AtomicInteger(0)
|
||||
|
||||
val previewThemeId = MutableStateFlow<ExtensionComponentName?>(null)
|
||||
val previewThemeInfo = MutableStateFlow<ThemeInfo?>(null)
|
||||
val configurationChangeCounter = MutableStateFlow(0)
|
||||
val wallpaperChangedCounter = MutableStateFlow(0)
|
||||
|
||||
private val cachedThemeInfos = mutableListOf<ThemeInfo>()
|
||||
private val activeThemeGuard = Mutex(locked = false)
|
||||
@@ -95,14 +92,13 @@ class ThemeManager(context: Context) {
|
||||
|
||||
init {
|
||||
extensionManager.themes.observeForever { themeExtensions ->
|
||||
val version = indexedThemeConfigVersion.incrementAndGet()
|
||||
_indexedThemeConfigs.value = buildMap {
|
||||
for (themeExtension in themeExtensions) {
|
||||
for (themeComponent in themeExtension.themes) {
|
||||
put(ExtensionComponentName(themeExtension.meta.id, themeComponent.id), themeComponent)
|
||||
}
|
||||
}
|
||||
} to version
|
||||
}
|
||||
}
|
||||
indexedThemeConfigs.collectIn(scope) {
|
||||
updateActiveTheme { cachedThemeInfos.clear() }
|
||||
@@ -113,7 +109,7 @@ class ThemeManager(context: Context) {
|
||||
prefs.theme.nightThemeId.asFlow(),
|
||||
previewThemeId,
|
||||
previewThemeInfo,
|
||||
configurationChangeCounter,
|
||||
wallpaperChangedCounter,
|
||||
) {}.collectIn(scope) {
|
||||
updateActiveTheme()
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class WallpaperChangeReceiver : BroadcastReceiver() {
|
||||
if (intent.action == Intent.ACTION_WALLPAPER_CHANGED) {
|
||||
flogDebug { "Wallpaper changed" }
|
||||
val themeManager by context.themeManager()
|
||||
themeManager.configurationChangeCounter.update { it + 1 }
|
||||
themeManager.wallpaperChangedCounter.update { it + 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package dev.patrickgold.florisboard.lib
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import org.florisboard.lib.compose.stringRes
|
||||
import dev.patrickgold.florisboard.lib.compose.stringRes
|
||||
import org.florisboard.lib.kotlin.CurlyArg
|
||||
import org.florisboard.lib.kotlin.curlyFormat
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.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.app.settings.theme
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import dev.patrickgold.jetpref.datastore.model.PreferenceSerializer
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.runtime.saveable.Saver
|
||||
import androidx.compose.ui.unit.Dp
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.animation.EnterTransition
|
||||
import androidx.compose.animation.ExitTransition
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.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: (@Composable () -> Unit)?,
|
||||
navigationIcon: FlorisScreenNavigationIcon?,
|
||||
actions: @Composable RowScope.() -> Unit = { },
|
||||
scrollBehavior: TopAppBarScrollBehavior
|
||||
) {
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -14,8 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.DrawableRes
|
||||
@@ -25,7 +26,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.createBitmap
|
||||
|
||||
@Composable
|
||||
fun FlorisCanvasIcon(
|
||||
@@ -52,9 +52,9 @@ fun FlorisCanvasIcon(
|
||||
modifier: Modifier = Modifier,
|
||||
contentDescription: String? = null,
|
||||
) {
|
||||
val bitmap = createBitmap(
|
||||
width = drawable.intrinsicWidth,
|
||||
height = drawable.intrinsicHeight,
|
||||
val bitmap = Bitmap.createBitmap(
|
||||
drawable.intrinsicWidth, drawable.intrinsicHeight,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
val canvas = Canvas(bitmap)
|
||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.florisboard.lib.compose
|
||||
package dev.patrickgold.florisboard.lib.compose
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
@@ -35,6 +35,7 @@ import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.outlined.Warning
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user