Compare commits

..

7 Commits

Author SHA1 Message Date
Patrick Goldinger
ff01120925 Release v0.4.3 2024-10-21 23:20:13 +02:00
Patrick Goldinger
74b5c845aa Merge branch 'main' into release/0.4 2024-10-21 23:19:26 +02:00
Patrick Goldinger
ddc4f7f1ba Release v0.4.2 2024-10-17 19:12:13 +02:00
Patrick Goldinger
afea8c721f Merge branch 'main' into release/0.4 2024-10-17 19:10:49 +02:00
Patrick Goldinger
9cffcea246 Release v0.4.1 2024-10-10 20:53:19 +02:00
Patrick Goldinger
5acf80db0f Merge branch 'main' into release/0.4 2024-10-10 16:03:17 +02:00
Patrick Goldinger
80fb20885b Release v0.4.0 2024-09-18 18:26:47 +02:00
538 changed files with 9130 additions and 31972 deletions

View File

@@ -1,11 +0,0 @@
**/.*/
!.git/
**/build/
**/dist/
**/out/
**/target/
utils/
!utils/repr_build/scripts/
.env
gradlew.bat
local.properties

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use_flake

View File

@@ -1,4 +1,4 @@
name: 🐛 Bug Report
name: Bug Report
description: Create a report to help FlorisBoard improve
labels:
- "bug"
@@ -62,14 +62,3 @@ body:
placeholder: e.g. 10, Stock
validations:
required: true
- type: checkboxes
id: checklist
attributes:
label: "Checklist"
options:
- label: "I made sure that there are *no existing issues* - [open](https://github.com/florisboard/florisboard/issues) or [closed](https://github.com/florisboard/florisboard/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to."
required: true
- label: "I have read and understood the [contribution guidelines](https://github.com/florisboard/florisboard/blob/main/CONTRIBUTING.md)."
required: true
- label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise."
required: true

View File

@@ -1,8 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: 💬 Matrix
url: https://matrix.to/#/#florisboard:matrix.org
about: General chat about FlorisBoard and quick Q/A
- name: ❓ Questions / Feedback
url: https://github.com/florisboard/florisboard/discussions/new/choose
about: Post your questions or feedback in the discussions panel
- name: Ask a question
url: https://github.com/florisboard/florisboard/discussions/new?category=q-a
about: Ask here if you have a question about FlorisBoard or need assistance
- name: General feedback
url: https://github.com/florisboard/florisboard/discussions/new?category=feedback
about: Give general feedback about this project

View File

@@ -1,4 +1,4 @@
name: 💥 Crash report
name: Crash report
description: Create a report with a generated crash log attached to help FlorisBoard improve
labels:
- "bug"
@@ -36,14 +36,3 @@ body:
description: Paste the generated crash log below
validations:
required: true
- type: checkboxes
id: checklist
attributes:
label: "Checklist"
options:
- label: "I made sure that there are *no existing issues* - [open](https://github.com/florisboard/florisboard/issues) or [closed](https://github.com/florisboard/florisboard/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to."
required: true
- label: "I have read and understood the [contribution guidelines](https://github.com/florisboard/florisboard/blob/main/CONTRIBUTING.md)."
required: true
- label: "I have taken the time to fill in all the required details. I understand that the crash report will be dismissed otherwise."
required: true

View File

@@ -1,4 +1,4 @@
name: Feature request
name: Feature request / Suggestion
description: Suggest an idea for this project
labels:
- "proposal"
@@ -20,14 +20,3 @@ body:
description: Please explain your idea in a precise way.
validations:
required: true
- type: checkboxes
id: checklist
attributes:
label: "Checklist"
options:
- label: "I made sure that there are *no existing issues* - [open](https://github.com/florisboard/florisboard/issues) or [closed](https://github.com/florisboard/florisboard/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to."
required: true
- label: "I have read and understood the [contribution guidelines](https://github.com/florisboard/florisboard/blob/main/CONTRIBUTING.md)."
required: true
- label: "I have taken the time to fill in all the required details. I understand that the feature request will be dismissed otherwise."
required: true

View File

@@ -25,14 +25,14 @@ jobs:
with:
submodules: recursive
- uses: gradle/actions/wrapper-validation@v4
- uses: gradle/actions/wrapper-validation@v3
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- name: Set up CMake and Ninja
uses: lukka/get-cmake@v4.0.2
uses: lukka/get-cmake@latest
- name: Build with Gradle
run: ./gradlew clean assembleDebug
- uses: actions/upload-artifact@v4

1
.gitignore vendored
View File

@@ -40,7 +40,6 @@ captures/
# Intellij
*.iml
.idea/
!/.idea/copyright/
# Keystore files
*.jks

View File

@@ -1,6 +0,0 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="Copyright (C) &amp;#36;originalComment.match(&quot;Copyright \(C\) (\d+)&quot;, 1, &quot;-&quot;, &quot;&amp;#36;today.year&quot;)&amp;#36;today.year The FlorisBoard Contributors&#10;&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10;http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License." />
<option name="myName" value="copyright" />
</copyright>
</component>

View File

@@ -1,15 +0,0 @@
<component name="CopyrightManager">
<settings default="copyright">
<module2copyright>
<element module="Project Files" copyright="copyright" />
</module2copyright>
<LanguageOptions name="Shell Script">
<option name="fileTypeOverride" value="1" />
</LanguageOptions>
<LanguageOptions name="XML">
<option name="fileTypeOverride" value="1" />
<option name="prefixLines" value="false" />
</LanguageOptions>
<LanguageOptions name="__TEMPLATE__" />
</settings>
</component>

View File

@@ -4,34 +4,32 @@ Thanks for considering contributing to FlorisBoard!
There are several ways to contribute to FlorisBoard. This document provides some general guidelines for each type of contribution.
The FlorisBoard community is international, as such we require all contributions, including issues, pull requests, and participation in the Matrix chat to be in English and follow the [code of conduct](https://github.com/florisboard/florisboard/blob/main/CODE_OF_CONDUCT.md). Contributions not adhering to these requirements will be dismissed. Thanks for making the FlorisBoard community an inclusive and safe space for everyone!
## General contributions
## Non-code contributions
### Translation
### Translations
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.
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 send an email to [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.**
### Feedback
You can [give general feedback](https://github.com/florisboard/florisboard/discussions/new?category=feedback) directly here on GitHub. This is the preferred way to give feedback, as it allows not only for me to read and respond to feedback, but for everyone in this community.
### Bug reporting
Allows us to see where FlorisBoard has flaws and should be improved to maximize stability and user experience. To make this process as smooth as possible, please use the pre-made [bug report template](https://github.com/florisboard/florisboard/issues/new?template=bug_report.yml). This makes it easy for us to understand what the bug is and how to solve it.
This kind of contribution is the most important, as it tells where FlorisBoard has flaws and thus should be improved to maximize stability and user experience. To make this process as smooth as possible, please use the pre-made [issue template](.github/ISSUE_TEMPLATE/bug_report.md) for bug reporting. This makes it easy for us to understand what the bug is and how to solve it.
#### Capturing error logs
Logs are captured by FlorisBoard's crash handler, which gives you the ability to copy it to the clipboard and paste it in the crash report [issue template](https://github.com/florisboard/florisboard/issues/new?template=crash_report.yml). This is the preferred way to capture logs.
Logs are captured by FlorisBoard's crash handler, which gives you the ability to copy it to the clipboard and paste it in GitHub. This is the preferred way to capture logs.
Alternatively, you can also use ADB (Android Debug Bridge) to capture the error log. This is recommended for experienced users only.
### Feature proposals
Use the feature proposal [issue template](https://github.com/florisboard/florisboard/issues/new?template=feature_request.yml) to suggest a new idea or improvement for this project.
### Feedback
You can [give general feedback](https://github.com/florisboard/florisboard/discussions/new?category=feedback) directly here on GitHub. This is the preferred way to give feedback, as it allows not only for me to read and respond to feedback, but for everyone in this community.
Use the feature proposal issue template to suggest a new idea or improvement for this project.
## Code contributions
@@ -40,15 +38,15 @@ You are always welcome to contribute new features or work on existing issues, th
> [!NOTE]
> If you intend to implement a bigger feature please coordinate with us so we can prevent that there's a major difference in expected implementation.
If you are overwhelmed by the code don't hesitate to ask for help in the [dev chat](https://matrix.to/#/#florisboard-dev:matrix.org) or the discussions tab! Some issues are also marked as good first issue, which are easy to do tasks.
If you are overwhelmed by the code don't hesistate to ask for help in the [dev chat](https://matrix.to/#/#florisboard-dev:matrix.org) or the discussions tab! Some issues are also marked as good first issue, which are easy to do tasks.
### System requirements for development
- Desktop PC with Linux or WSL2 (Windows)
- MacOS and Windows without WSL2 probably works too however there's no official support
- At least 16GB of RAM (because of Android Studio / IntelliJ)
- At least 16GB of RAM (because of Android Studio)
- The following tools must be installed:
- Android Studio (bundles SDK and NDK) or IntelliJ with Android and Compose plugin
- Android Studio (bundles SDK and NDK)
- Java 17
- CMake 3.22+
- Clang 15+
@@ -66,7 +64,34 @@ If you want to manually build the project without Android Studio you must ensure
and Gradle should take care of every build task.
## Joining the team
If you want to join the core maintainer/moderator team on a volunteer basis and be part of this project's journey that's great to hear!
### Basic Requirements
- A passion for seeing FlorisBoard flourish
- Good English skills for team and public communication
- A GitHub account and a Matrix handle
### Why Join
You'll have the chance to work directly with me and other team members. While the general idea is for us to work on all kinds of different aspects of the project as a team, if you're particularly interested in a specific area (e.g., UI, extensions, text processing), that's totally okay too!
### Available Roles
Currently the following roles are available and need help:
Role Description | Required Dev Experience
---|---
Software Developer (Kotlin) for Core App | Java/Kotlin development experience (on Android)
Software Developer (Rust) for Native Core | Some Rust development experience
GitHub Issues/Discussions Moderator | None
Crowdin Translation Verifier | Language proficiency for the language you want to verify
Interested? Feel free to dm me ([@patrickgold](https://matrix.to/#/@patrickgold:matrix.org)) on Matrix or send an email to [florisboard@patrickgold.dev](mailto:florisboard@patrickgold.dev).
## Donating
You can also show your support by buying me a coffee, so I can stay up all night and chase away bugs or add new cool stuff :)
Alternatively you can also show your support by buying me a coffee, so I can stay up all night and chase away bugs or add new cool stuff :)
See the `Sponsors` button for available options!

View File

@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020-2025 The FlorisBoard Contributors
Copyright 2020 Patrick Goldinger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -64,7 +64,7 @@ fully respecting your privacy. Currently in early-beta state.
</tr>
</table>
Beginning with v0.7 FlorisBoard will enter the public beta on Google Play.
Beginning with v0.6.0 FlorisBoard will enter the public beta on Google Play.
## Highlighted features
- Integrated clipboard manager / history
@@ -74,7 +74,7 @@ Beginning with v0.7 FlorisBoard will enter the public beta on Google Play.
> [!IMPORTANT]
> Word suggestions/spell checking are not included in the current releases
> and are a major goal for the v0.6 milestone.
> and are a major goal for the v0.5 milestone.
Feature roadmap: See [ROADMAP.md](ROADMAP.md)
@@ -114,7 +114,7 @@ Many thanks to [Nikolay Anzarov](https://www.behance.net/nikolayanzarov) ([@Bloo
## License
```
Copyright 2020-2025 The FlorisBoard Contributors
Copyright 2020-2024 Patrick Goldinger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -129,8 +129,6 @@ See the License for the specific language governing permissions and
limitations under the License.
```
Thanks to [The FlorisBoard Contributors](https://github.com/florisboard/florisboard/graphs/contributors) for making this project possible!
<!-- BEGIN SECTION: obtainium_links -->
<!-- auto-generated link templates, do NOT edit by hand -->
<!-- see fastlane/update-readme.sh -->

View File

@@ -1,63 +1,44 @@
# Roadmap
This feature roadmap intents to provide transparency to what is planned to be added to FlorisBoard in the foreseeable future. Note that there are no ETAs for any version milestones down below, experience has shown these won't hold anyway.
This feature roadmap intents to provide transparency to what is planned to be added to FlorisBoard in the foreseeable future. Note that there are no ETAs for any version milestones down below, experience has shown these won't hold anyways.
Each major milestone has associated alpha/beta releases, so if you are interested in previewing features quicker, keep an eye out! Each major 0.x release has also patch releases after the initial major release, which will be published on both the stable and preview tracks.
## 0.5 (currently in development)
## 0.5
> [!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.
- [ ] 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)
- [ ] 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)
- Implement predictive text support / spell checking
- Consider adding proximity-based key typo detection
- Add new extension type: Language Pack
- Basically groups all locale-relevant data (predictive base model, emoji suggestion data, ...)
in a dynamically importable extension file
- New text processing logic (maybe moved back / split to 0.6)
- Add floating keyboard mode
- New keyboard layout engine + file syntax based on the upcoming Unicode Keyboard v3 standard
- Add Tablet mode / Optimizations for landscape input based on new keyboard layout engine
- Add support for any remaining new features introduced with Android 13
## 0.6
- [ ] Implement predictive text support / spell checking
- [ ] Add new extension type: Language Pack
- Basically groups all locale-relevant data (predictive base model, emoji suggestion data, ...)
in a dynamically importable extension file
## k3lp
> [!NOTE]
> The development of k3lp is not tied to a florisboard version and takes place on [codeberg.org](https://codeberg.org/k3lp/k3lp) simultaneously.
- [ ] New keyboard layout engine + file syntax based on the upcoming Unicode Keyboard v3 standard
- [ ] Add Tablet mode / Optimizations for landscape input based on new keyboard layout engine
## 0.7+
> [!NOTE]
> From 0.6 onwards we plan to have more stable 0.X releases but with at most one large feature per release, thus having a much quicker iteration of new features on the stable track, which is a benefit for everyone involved.
- [ ] Add floating keyboard mode
- [ ] New text processing logic
- [ ] Complete rework of the Emoji panel
- [ ] Emoji search
- [ ] Fully scrollable emoji list (soft category borders)
- [ ] Side scrollable emoji list (swipe for next category)
- [ ] More granular theming options
- [ ] Layout customization (e.g. placement of category buttons)
- [ ] Maybe: consider upgrading to emoji2 for better unified system-wide emoji styles
- [ ] Reimplementation of glide typing with the new layout engine and predictive text core
- [ ] Prepare FlorisBoard repository and app store presence for public beta release on Google Play (will go live with stable 0.7)
- [ ] Rework branding images and texts of FlorisBoard for the app stores
- [ ] Focus on stability and experience improvements of the app and keyboard
- [ ] Add support for new features introduced with Android 15 / 16
- Complete rework of the Emoji panel
- Emoji search
- Fully scrollable emoji list (soft category borders)
- More granular themeing options
- Layout customization (e.g. placement of category buttons)
- Maybe: consider upgrading to emoji2 for better unified system-wide emoji styles
- Reimplementation of glide typing with the new layout engine and predictive text core
- Prepare FlorisBoard repository and app store presence for public beta release on Google Play (will go live with stable 0.6)
- Rework branding images and texts of FlorisBoard for the app stores
- Focus on stability and experience improvements of the app and keyboard
- Add support for new features introduced with Android 14 / 15
- Not finalized, but planned: raise minimum required Android version from Android 7 (SDK level 24) to Android 8 (SDK level 26)
## Backlog / Planned (unassigned)
**Features that MAY be added (even in versions mentioned above) or dismissed**
- Full on-board layout editor which allows users to create their own layouts without writing a JSON file
- Theme rework part II
- Adaptive themes v2
- Voice-to-text with Mozilla's open-source voice service (or any other oss voice provider)
- Text translation
- Stickers/GIFs

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2025 The FlorisBoard Contributors
* Copyright (C) 2022 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag
import java.io.ByteArrayOutputStream
plugins {
@@ -22,39 +23,35 @@ plugins {
alias(libs.plugins.kotlin.plugin.compose)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.ksp)
alias(libs.plugins.mannodermaus.android.junit5)
alias(libs.plugins.mikepenz.aboutlibraries)
}
val projectMinSdk: String by project
val projectTargetSdk: String by project
val projectCompileSdk: String by project
val projectBuildToolsVersion: String by project
val projectNdkVersion: String by project
val projectVersionCode: String by project
val projectVersionName: String by project
val projectVersionNameSuffix = projectVersionName.substringAfter("-", "").let { suffix ->
if (suffix.isNotEmpty()) {
"-$suffix"
} else {
suffix
}
}
val projectVersionNameSuffix = projectVersionName.substringAfter("-", "")
android {
namespace = "dev.patrickgold.florisboard"
compileSdk = projectCompileSdk.toInt()
buildToolsVersion = tools.versions.buildTools.get()
ndkVersion = tools.versions.ndk.get()
buildToolsVersion = projectBuildToolsVersion
ndkVersion = projectNdkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "11"
jvmTarget = "1.8"
freeCompilerArgs = listOf(
"-opt-in=kotlin.contracts.ExperimentalContracts",
"-Xjvm-default=all-compatibility",
"-Xwhen-guards",
)
}
@@ -152,13 +149,7 @@ android {
}
aboutLibraries {
collect {
configPath = file("src/main/config")
}
}
lint {
baseline = file("lint.xml")
configPath = "app/src/main/config"
}
testOptions {
@@ -171,21 +162,21 @@ android {
}
}
composeCompiler {
// DO NOT ENABLE STRONG SKIPPING! This project currently relies on
// recomposition on parent state change to update the UI correctly.
featureFlags.add(ComposeFeatureFlag.StrongSkipping.disabled())
}
tasks.withType<Test> {
useJUnitPlatform()
}
dependencies {
val composeBom = platform(libs.androidx.compose.bom)
implementation(composeBom)
// testImplementation(composeBom)
// androidTestImplementation(composeBom)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.activity.ktx)
implementation(libs.androidx.autofill)
implementation(libs.androidx.collection.ktx)
implementation(libs.androidx.compose.material.icons)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.runtime.livedata)
implementation(libs.androidx.compose.ui)
@@ -195,6 +186,7 @@ dependencies {
implementation(libs.androidx.emoji2)
implementation(libs.androidx.emoji2.views)
implementation(libs.androidx.exifinterface)
implementation(libs.androidx.material.icons)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.profileinstaller)
ksp(libs.androidx.room.compiler)
@@ -210,12 +202,16 @@ dependencies {
implementation(libs.patrickgold.jetpref.material.ui)
implementation(project(":lib:android"))
implementation(project(":lib:color"))
implementation(project(":lib:kotlin"))
implementation(project(":lib:native"))
implementation(project(":lib:snygg"))
testImplementation(libs.kotlin.test.junit5)
testImplementation(libs.equalsverifier)
testImplementation(libs.kotest.assertions.core)
testImplementation(libs.kotest.extensions.roboelectric)
testImplementation(libs.kotest.property)
testImplementation(libs.kotest.runner.junit5)
androidTestImplementation(libs.androidx.test.ext)
androidTestImplementation(libs.androidx.test.espresso.core)
}

View File

@@ -1,3 +1,3 @@
<lint>
<issue id="ExtraTranslation" severity="warning"/>
<issue id="UsingMaterialAndMaterial3Libraries" severity="ignore" />
</lint>

View File

@@ -1,19 +1,3 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard
import androidx.test.ext.junit.runners.AndroidJUnit4

View File

@@ -1,4 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020-2022 Patrick Goldinger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
@@ -114,7 +128,6 @@
android:name="dev.patrickgold.florisboard.lib.crashutility.CrashDialogActivity"
android:icon="@mipmap/floris_app_icon"
android:label="@string/crash_dialog__title"
android:configChanges="orientation|screenSize"
android:theme="@style/CrashDialogTheme"/>
<!-- Copy to Clipboard Activity -->

View File

@@ -17,13 +17,6 @@
"direction": "rtl",
"modifier": "org.florisboard.layouts:arabic"
},
{
"id": "armenian_alt_phonetic",
"label": "Armenian Alt Phonetic",
"authors": [ "MikayelB" ],
"direction": "ltr",
"modifier": "org.florisboard.layouts:armenian"
},
{
"id": "western_armenian",
"label": "Armenian (Western)",
@@ -56,12 +49,6 @@
"authors": [ "iamrasel" ],
"direction": "ltr"
},
{
"id": "hindi_in",
"label": "हिंदी",
"authors": [ "npnpatidar" ],
"direction": "ltr"
},
{
"id": "bepo",
"label": "BÉPO",

View File

@@ -1,42 +0,0 @@
[
[
{ "$": "case_selector", "lower": { "code": 2335, "label": "ट" }, "upper": { "code": 2336, "label": "ठ" } },
{ "$": "case_selector", "lower": { "code": 2337, "label": "ड" }, "upper": { "code": 2338, "label": "ढ" } },
{ "$": "case_selector", "lower": { "code": 2375, "label": "े" }, "upper": { "code": 2376, "label": "ै" } },
{ "$": "case_selector", "lower": { "code": 2352, "label": "र" }, "upper": { "code": 2371, "label": "ृ" } },
{ "$": "case_selector", "lower": { "code": 2340, "label": "त" }, "upper": { "code": 2341, "label": "थ" } },
{ "$": "case_selector", "lower": { "code": 2351, "label": "य" }, "upper": { "code": 2399, "label": "य़" } },
{ "$": "case_selector", "lower": { "code": 2369, "label": "ु" }, "upper": { "code": 2370, "label": "ू" } },
{ "$": "case_selector", "lower": { "code": 2367, "label": "ि" }, "upper": { "code": 2368, "label": "ी" } },
{ "$": "case_selector", "lower": { "code": 2379, "label": "ो" }, "upper": { "code": 2380, "label": "ौ" } },
{ "$": "case_selector", "lower": { "code": 2346, "label": "प" }, "upper": { "code": 2398, "label": "फ़" } }
],
[
{ "$": "case_selector", "lower": { "code": 2366, "label": "ा" }, "upper": { "code": 2309, "label": "अ" } },
{ "$": "case_selector", "lower": { "code": 2360, "label": "स" }, "upper": { "code": 2358, "label": "श" } },
{ "$": "case_selector", "lower": { "code": 2342, "label": "द" }, "upper": { "code": 2343, "label": "ध" } },
{ "$": "case_selector", "lower": { "code": 2347, "label": "फ" }, "upper": { "code": 2364, "label": " ़" } },
{ "$": "case_selector", "lower": { "code": 2327, "label": "ग" }, "upper": { "code": 2328, "label": "घ" } },
{ "$": "case_selector", "lower": { "code": 2361, "label": "ह" }, "upper": { "code": 2307, "label": "" } },
{ "$": "case_selector", "lower": { "code": 2332, "label": "ज" }, "upper": { "code": 2333, "label": "झ" } },
{ "$": "case_selector", "lower": { "code": 2325, "label": "क" }, "upper": { "code": 2326, "label": "ख" } },
{ "$": "case_selector", "lower": { "code": 2354, "label": "ल" }, "upper": { "code": 2355, "label": "ळ" } }
],
[
{
"$": "case_selector",
"lower": { "$": "multi_text_key", "codePoints": [2332, 2381, 2334], "label": "ज्ञ" },
"upper": { "code": 2395, "label": "ज़" }
},
{
"$": "case_selector",
"lower": { "$": "multi_text_key", "codePoints": [2325, 2381, 2359], "label": "क्ष" },
"upper": { "code": 2359, "label": "ष" }
},
{ "$": "case_selector", "lower": { "code": 2330, "label": "च" }, "upper": { "code": 2331, "label": "छ" } },
{ "$": "case_selector", "lower": { "code": 2357, "label": "व" }, "upper": { "code": 2381, "label": "्" } },
{ "$": "case_selector", "lower": { "code": 2348, "label": "ब" }, "upper": { "code": 2349, "label": "भ" } },
{ "$": "case_selector", "lower": { "code": 2344, "label": "न" }, "upper": { "code": 2339, "label": "ण" } },
{ "$": "case_selector", "lower": { "code": 2350, "label": "म" }, "upper": { "code": 2306, "label": "ं" } }
]
]

View File

@@ -3,52 +3,46 @@
{ "code": 2535, "label": "১", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 2536, "label": "২", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 2537, "label": "৩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 2538, "label": "", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 2539, "label": "৫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 2540, "label": "৬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 2542, "label": "৮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 2543, "label": "৯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 2534, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -33,7 +33,7 @@
{ "code": 32902, "label": "肆" },
{ "code": 18825, "label": "䦉" },
{ "code": 20118, "label": "亖" },
{ "code": 65300, "label": "" }
{ "code": 65300, "label": "" }
]
} },
{ "code": 20116, "label": "五", "type": "numeric", "popup": {

View File

@@ -3,52 +3,46 @@
{ "code": 2407, "label": "१", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 2408, "label": "२", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 2409, "label": "३", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 2410, "label": "४", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 2411, "label": "५", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 2412, "label": "६", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 2414, "label": "८", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 2415, "label": "९", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 2406, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 1633, "label": "١", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 1634, "label": "٢", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 1635, "label": "٣", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 1636, "label": "٤", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 1637, "label": "٥", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 1638, "label": "٦", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 1640, "label": "٨", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 1641, "label": "٩", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 1632, "label": "٠", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 2791, "label": "૧", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 2792, "label": "૨", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 2793, "label": "૩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 2794, "label": "૪", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 2795, "label": "૫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 2796, "label": "૬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 2798, "label": "૮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 2799, "label": "૯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 2790, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 2663, "label": "", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 2664, "label": "੨", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 2665, "label": "੩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 2666, "label": "", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 2667, "label": "੫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 2668, "label": "੬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 2670, "label": "੮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 2671, "label": "੯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 2662, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 3303, "label": "೧", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 3304, "label": "೨", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 3305, "label": "೩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 3306, "label": "೪", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 3307, "label": "೫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 3308, "label": "೬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 3310, "label": "೮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 3311, "label": "೯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 3302, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 3431, "label": "൧", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 3432, "label": "൨", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 3433, "label": "൩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 3434, "label": "൪", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 3435, "label": "൫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 3436, "label": "൬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 3438, "label": "൮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 3439, "label": "൯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 3430, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 2919, "label": "୧", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 2920, "label": "", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 2921, "label": "୩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 2922, "label": "୪", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 2923, "label": "୫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 2924, "label": "୬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 2926, "label": "୮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 2927, "label": "୯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 2918, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 1777, "label": "۱", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 1778, "label": "۲", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 1779, "label": "۳", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 1780, "label": "۴", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 1781, "label": "۵", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 1782, "label": "۶", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 1784, "label": "۸", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 1785, "label": "۹", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 1776, "label": "۰", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 3047, "label": "௧", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 3048, "label": "௨", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 3049, "label": "௩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 3050, "label": "௪", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 3051, "label": "௫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 3052, "label": "௬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 3054, "label": "௮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 3055, "label": "௯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 3046, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 3175, "label": "౧", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 3176, "label": "౨", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 3177, "label": "౩", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 3178, "label": "౪", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 3179, "label": "౫", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 3180, "label": "౬", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 3182, "label": "౮", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 3183, "label": "౯", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 3174, "label": "", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -3,23 +3,20 @@
{ "code": 3665, "label": "๑", "type": "numeric", "popup": {
"main": { "code": 185, "label": "¹" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 3666, "label": "๒", "type": "numeric", "popup": {
"main": { "code": 178, "label": "²" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 8532, "label": "⅔" },
{ "code": 8534, "label": "⅖" }
]
@@ -27,59 +24,44 @@
{ "code": 3667, "label": "๓", "type": "numeric", "popup": {
"main": { "code": 179, "label": "³" },
"relevant": [
{ "code": 8540, "label": "" },
{ "code": 8323, "label": "₃"},
{ "code": 8535, "label": "" },
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "" }
{ "code": 8540, "label": "" }
]
} },
{ "code": 3668, "label": "๔", "type": "numeric", "popup": {
"main": { "code": 8308, "label": "⁴" },
"relevant": [
{ "code": 8324, "label": "₄" },
{ "code": 8536, "label": "⅘" }
]
} },
{ "code": 3669, "label": "๕", "type": "numeric", "popup": {
"main": { "code": 8309, "label": "⁵" },
"relevant": [
{ "code": 8325, "label": "₅" },
{ "code": 8538, "label": "⅚" },
{ "code": 8541, "label": "⅝" }
]
} },
{ "code": 3670, "label": "๖", "type": "numeric", "popup": {
"main": { "code": 8310, "label": "⁶" },
"relevant": [
{ "code": 8326, "label": "₆" }
]
"main": { "code": 8310, "label": "⁶" }
} },
{ "code": 3671, "label": "๗", "type": "numeric", "popup": {
"main": { "code": 8311, "label": "⁷" },
"relevant": [
{ "code": 8327, "label": "₇" },
{ "code": 8542, "label": "⅞" }
]
} },
{ "code": 3672, "label": "๘", "type": "numeric", "popup": {
"main": { "code": 8312, "label": "⁸" },
"relevant": [
{ "code": 8328, "label": "₈" }
]
"main": { "code": 8312, "label": "⁸" }
} },
{ "code": 3673, "label": "๙", "type": "numeric", "popup": {
"main": { "code": 8313, "label": "⁹" },
"relevant": [
{ "code": 8329, "label": "₉" }
]
"main": { "code": 8313, "label": "⁹" }
} },
{ "code": 3664, "label": "", "type": "numeric", "popup": {
"main": { "code": 8304, "label": "⁰" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8585, "label": "↉" },
{ "code": 8320, "label": "₀" }
{ "code": 8319, "label": "ⁿ" }
]
} }
]

View File

@@ -3,52 +3,46 @@
{ "code": 71905, "label": "𑣡", "type": "numeric", "popup": {
"main": { "code": 49, "label": "1" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 185, "label": "¹" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
} },
{ "code": 71906, "label": "𑣢", "type": "numeric", "popup": {
"main": { "code": 50, "label": "2" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 178, "label": "²" },
{ "code": 8532, "label": "⅔" },
{ "code": 178, "label": "²" },
{ "code": 8534, "label": "⅖" }
]
} },
{ "code": 71907, "label": "𑣣", "type": "numeric", "popup": {
"main": { "code": 51, "label": "3" },
"relevant": [
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "⅗" },
{ "code": 8540, "label": "" },
{ "code": 8323, "label": ""},
{ "code": 179, "label": "³" }
{ "code": 190, "label": "¾" },
{ "code": 179, "label": "³" },
{ "code": 8540, "label": "" }
]
} },
{ "code": 71908, "label": "𑣤", "type": "numeric", "popup": {
"main": { "code": 52, "label": "4" },
"relevant": [
{ "code": 8324, "label": "" },
{ "code": 8308, "label": "⁴" },
{ "code": 8536, "label": "⅘" }
{ "code": 8536, "label": "" },
{ "code": 8308, "label": "⁴" }
]
} },
{ "code": 71909, "label": "𑣥", "type": "numeric", "popup": {
"main": { "code": 53, "label": "5" },
"relevant": [
{ "code": 8538, "label": "⅚" },
{ "code": 8325, "label": "₅" },
{ "code": 8309, "label": "⁵" },
{ "code": 8541, "label": "⅝" }
]
@@ -56,7 +50,6 @@
{ "code": 71910, "label": "𑣦", "type": "numeric", "popup": {
"main": { "code": 54, "label": "6" },
"relevant": [
{ "code": 8326, "label": "₆" },
{ "code": 8310, "label": "⁶" }
]
} },
@@ -64,32 +57,27 @@
"main": { "code": 55, "label": "7" },
"relevant": [
{ "code": 8542, "label": "⅞" },
{ "code": 8327, "label": "₇" },
{ "code": 8311, "label": "⁷" }
]
} },
{ "code": 71912, "label": "𑣨", "type": "numeric", "popup": {
"main": { "code": 56, "label": "8" },
"relevant": [
{ "code": 8328, "label": "₈" },
{ "code": 8312, "label": "⁸" }
]
} },
{ "code": 71913, "label": "𑣩", "type": "numeric", "popup": {
"main": { "code": 57, "label": "9" },
"relevant": [
{ "code": 8329, "label": "₉" },
{ "code": 8313, "label": "⁹" }
]
} },
{ "code": 71904, "label": "𑣠", "type": "numeric", "popup": {
"main": { "code": 48, "label": "0" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8304, "label": "" },
{ "code": 8585, "label": "" },
{ "code": 8320, "label": "₀" }
{ "code": 8709, "label": "" },
{ "code": 8304, "label": "" }
]
} }
]

View File

@@ -10,17 +10,15 @@
"code": 49, "label": "1", "type": "numeric", "popup": {
"main": { "code": 185, "label": "¹" },
"relevant": [
{ "code": 8321, "label": "" },
{ "code": 8537, "label": "" },
{ "code": 8528, "label": "⅐" },
{ "code": 8539, "label": "⅛" },
{ "code": 8529, "label": "⅑" },
{ "code": 8530, "label": "⅒" },
{ "code": 8543, "label": "⅟" },
{ "code": 189, "label": "½" },
{ "code": 8531, "label": "⅓" },
{ "code": 188, "label": "¼" },
{ "code": 8533, "label": "⅕" },
{ "code": 8537, "label": "⅙" }
{ "code": 8533, "label": "⅕" }
]
}
}
@@ -31,7 +29,6 @@
"code": 50, "label": "2", "type": "numeric", "popup": {
"main": { "code": 178, "label": "²" },
"relevant": [
{ "code": 8322, "label": "₂"},
{ "code": 8532, "label": "⅔" },
{ "code": 8534, "label": "⅖" }
]
@@ -48,10 +45,9 @@
"code": 51, "label": "3", "type": "numeric", "popup": {
"main": { "code": 179, "label": "³" },
"relevant": [
{ "code": 8540, "label": "" },
{ "code": 8323, "label": "₃"},
{ "code": 8535, "label": "" },
{ "code": 190, "label": "¾" },
{ "code": 8535, "label": "" }
{ "code": 8540, "label": "" }
]
}
}
@@ -72,7 +68,6 @@
"code": 52, "label": "4", "type": "numeric", "popup": {
"main": { "code": 8308, "label": "⁴" },
"relevant": [
{ "code": 8324, "label": "₄" },
{ "code": 8536, "label": "⅘" }
]
}
@@ -91,7 +86,6 @@
"code": 53, "label": "5", "type": "numeric", "popup": {
"main": { "code": 8309, "label": "⁵" },
"relevant": [
{ "code": 8325, "label": "₅" },
{ "code": 8538, "label": "⅚" },
{ "code": 8541, "label": "⅝" }
]
@@ -111,10 +105,7 @@
},
"default": {
"code": 54, "label": "6", "type": "numeric", "popup": {
"main": { "code": 8310, "label": "⁶" },
"relevant": [
{ "code": 8326, "label": "₆" }
]
"main": { "code": 8310, "label": "⁶" }
}
}
},
@@ -124,7 +115,6 @@
"code": 55, "label": "7", "type": "numeric", "popup": {
"main": { "code": 8311, "label": "⁷" },
"relevant": [
{ "code": 8327, "label": "₇" },
{ "code": 8542, "label": "⅞" }
]
}
@@ -142,10 +132,7 @@
},
"default": {
"code": 56, "label": "8", "type": "numeric", "popup": {
"main": { "code": 8312, "label": "⁸" },
"relevant": [
{ "code": 8328, "label": "₈" }
]
"main": { "code": 8312, "label": "⁸" }
}
}
},
@@ -173,10 +160,7 @@
},
"default": {
"code": 57, "label": "9", "type": "numeric", "popup": {
"main": { "code": 8313, "label": "⁹" },
"relevant": [
{ "code": 8329, "label": "₉" }
]
"main": { "code": 8313, "label": "⁹" }
}
}
},
@@ -207,9 +191,7 @@
"main": { "code": 8304, "label": "⁰" },
"relevant": [
{ "code": 8709, "label": "∅" },
{ "code": 8319, "label": "ⁿ" },
{ "code": 8585, "label": "↉" },
{ "code": 8320, "label": "₀" }
{ "code": 8319, "label": "ⁿ" }
]
}
}

View File

@@ -48,7 +48,6 @@
{ "id": "fi", "authors": [ "patrickgold" ] },
{ "id": "fo", "authors": [ "BinFlush" ] },
{ "id": "fr", "authors": [ "patrickgold" ] },
{ "id": "hi-IN", "authors": [ "npnpatidar" ] },
{ "id": "hr", "authors": [ "hedidnothingwrong" ] },
{ "id": "hu", "authors": [ "zoli111, gabik65" ] },
{ "id": "hy", "authors": [ "PJTSearch" ] },
@@ -401,16 +400,6 @@
"characters": "org.florisboard.layouts:qwertz"
}
},
{
"languageTag": "hy",
"composer": "org.florisboard.composers:appender",
"currencySet": "org.florisboard.currencysets:armenian_dram",
"popupMapping": "org.florisboard.localization:hy",
"preferred": {
"characters": "org.florisboard.layouts:armenian_alt_phonetic",
"symbols": "org.florisboard.layouts:armenian"
}
},
{
"languageTag": "hy",
"composer": "org.florisboard.composers:appender",
@@ -706,16 +695,6 @@
"numericAdvanced": "org.florisboard.layouts:bengali"
}
},
{
"languageTag": "hi-IN",
"composer": "org.florisboard.composers:appender",
"currencySet": "org.florisboard.currencysets:indian_rupee",
"popupMapping": "org.florisboard.localization:hi-IN",
"preferred": {
"characters": "org.florisboard.layouts:hindi_in",
"numericRow": "org.florisboard.layouts:devanagari"
}
},
{
"languageTag": "ast",
"composer": "org.florisboard.composers:appender",

View File

@@ -72,7 +72,7 @@
"র": {
"main": { "$": "auto_text_key", "code": 2482, "label": "ল" },
"relevant": [
{ "code": -255, "label": "র্য" }
{ "code": -255, "label": "র্য" }
]
},
"ন": {

View File

@@ -1,173 +0,0 @@
{
"all": {
"क": {
"main": { "$": "auto_text_key", "code": 2392, "label": "क़" },
"relevant": [{ "$": "auto_text_key", "code": 2393, "label": "ख़" }]
},
"ग": {
"main": { "$": "auto_text_key", "code": 2394, "label": "ग़" },
"relevant": [{ "$": "auto_text_key", "code": 2427, "label": "ॻ" }]
},
"च": {
"relevant": [
{ "$": "auto_text_key", "code": 2385, "label": " ॑" },
{ "$": "auto_text_key", "code": 2386, "label": " ॒" }
]
},
"ज": {
"main": { "$": "auto_text_key", "code": 2395, "label": "ज़" },
"relevant": [
{ "$": "auto_text_key", "code": 2428, "label": "ॼ" },
{ "$": "auto_text_key", "code": 2425, "label": "ॹ" }
]
},
"ड": {
"main": { "$": "auto_text_key", "code": 2396, "label": "ड़" },
"relevant": [{ "$": "auto_text_key", "code": 2397, "label": "ढ़" }]
},
"त": {
"main": { "$": "multi_text_key", "codePoints": [2340, 2381, 2352], "label": "त्र" }
},
"द": {
"main": { "$": "auto_text_key", "code": 2396, "label": "ड़" },
"relevant": [
{ "$": "auto_text_key", "code": 2430, "label": "ॾ" },
{ "$": "auto_text_key", "code": 2397, "label": "ढ़" },
{ "$": "auto_text_key", "code": 2424, "label": "ॸ" }
]
},
"न": {
"main": { "$": "auto_text_key", "code": 2329, "label": "ङ" },
"relevant": [
{ "$": "auto_text_key", "code": 2345, "label": "ऩ" },
{ "$": "auto_text_key", "code": 2334, "label": "ञ" }
]
},
"फ": {
"main": { "$": "auto_text_key", "code": 2398, "label": "फ़" }
},
"ब": {
"relevant": [
{ "$": "auto_text_key", "code": 2431, "label": "ॿ" },
{ "$": "auto_text_key", "code": 2365, "label": "ऽ" },
{ "$": "auto_text_key", "code": 2416, "label": "॰" }
]
},
"म": {
"main": { "$": "auto_text_key", "code": 2305, "label": "ँ" },
"relevant": [{ "$": "auto_text_key", "code": 2304, "label": "ऀ" }]
},
"य": {
"main": { "$": "auto_text_key", "code": 2426, "label": "ॺ" }
},
"र": {
"main": { "$": "auto_text_key", "code": 2315, "label": "ऋ" },
"relevant": [
{ "$": "auto_text_key", "code": 2400, "label": "ॠ" },
{ "$": "auto_text_key", "code": 2372, "label": "ॄ" },
{ "$": "auto_text_key", "code": 2353, "label": "ऱ" }
]
},
"ल": {
"relevant": [
{ "$": "auto_text_key", "code": 2402, "label": "ॢ" },
{ "$": "auto_text_key", "code": 2403, "label": "ॣ" },
{ "$": "auto_text_key", "code": 2316, "label": "ऌ" },
{ "$": "auto_text_key", "code": 2401, "label": "ॡ" },
{ "$": "auto_text_key", "code": 2356, "label": "ऴ" }
]
},
"व": {
"relevant": [
{ "$": "auto_text_key", "code": 2387, "label": " ॓" },
{ "$": "auto_text_key", "code": 2388, "label": " ॔" }
]
},
"स": {
"main": { "$": "multi_text_key", "codePoints": [2358, 2381, 2352], "label": "श्र" },
"relevant": [{ "$": "auto_text_key", "code": 2359, "label": "ष" }]
},
"ा": {
"main": { "$": "auto_text_key", "code": 2310, "label": "आ" },
"relevant": [
{ "$": "auto_text_key", "code": 2373, "label": "ॅ" },
{ "$": "auto_text_key", "code": 2418, "label": "ॲ" },
{ "$": "auto_text_key", "code": 2308, "label": "ऄ" }
]
},
"ि": {
"main": { "$": "auto_text_key", "code": 2311, "label": "इ" },
"relevant": [{ "$": "auto_text_key", "code": 2312, "label": "ई" }]
},
"ु": {
"main": { "$": "auto_text_key", "code": 2313, "label": "उ" },
"relevant": [
{ "$": "auto_text_key", "code": 2422, "label": "ॶ" },
{ "$": "auto_text_key", "code": 2423, "label": "ॷ" },
{ "$": "auto_text_key", "code": 2390, "label": " ॖ" },
{ "$": "auto_text_key", "code": 2314, "label": "ऊ" },
{ "$": "auto_text_key", "code": 2391, "label": " ॗ" }
]
},
"े": {
"main": { "$": "auto_text_key", "code": 2319, "label": "ए" },
"relevant": [
{ "$": "auto_text_key", "code": 2317, "label": "ऍ" },
{ "$": "auto_text_key", "code": 2318, "label": "ऎ" },
{ "$": "auto_text_key", "code": 2374, "label": " ॆ" },
{ "$": "auto_text_key", "code": 2320, "label": "ऐ" },
{ "$": "auto_text_key", "code": 2382, "label": " ॎ" },
{ "$": "auto_text_key", "code": 2389, "label": " ॕ" }
]
},
"ो": {
"main": { "$": "auto_text_key", "code": 2323, "label": "ओ" },
"relevant": [
{ "$": "auto_text_key", "code": 2322, "label": "ऒ" },
{ "$": "auto_text_key", "code": 2378, "label": " ॊ" },
{ "$": "auto_text_key", "code": 2383, "label": " ॏ" },
{ "$": "auto_text_key", "code": 2421, "label": "ॵ" },
{ "$": "auto_text_key", "code": 2384, "label": "ॐ" },
{ "$": "auto_text_key", "code": 2377, "label": "ॉ" },
{ "$": "auto_text_key", "code": 2419, "label": "ॳ" },
{ "$": "auto_text_key", "code": 2420, "label": "ॴ" },
{ "$": "auto_text_key", "code": 2362, "label": " ऺ" },
{ "$": "auto_text_key", "code": 2363, "label": " ऻ" },
{ "$": "auto_text_key", "code": 2324, "label": "औ" },
{ "$": "auto_text_key", "code": 2321, "label": "ऑ" }
]
},
"~right": {
"main": { "code": 2404, "label": "।" },
"relevant": [
{ "code": 37, "label": "%" },
{ "code": 43, "label": "+" },
{ "code": 45, "label": "-" },
{ "code": 58, "label": ":" },
{ "code": 59, "label": ";" },
{ "code": 47, "label": "/" },
{ "$": "layout_direction_selector", "ltr": { "code": 40, "label": "(" }, "rtl": { "code": 41, "label": "(" } },
{ "$": "layout_direction_selector", "ltr": { "code": 41, "label": ")" }, "rtl": { "code": 40, "label": ")" } },
{ "code": 8205, "label": ">⁞<" },
{ "code": 8204, "label": "<⁞>" },
{ "code": 2417, "label": "ॱ" },
{ "code": 2429, "label": "" },
{ "code": 33, "label": "!" },
{ "code": 63, "label": "?" },
{ "code": 2405, "label": "॥" }
]
}
},
"uri": {
"~right": {
"main": { "code": -255, "label": ".com" },
"relevant": [
{ "code": -255, "label": ".org" },
{ "code": -255, "label": ".net" },
{ "code": -255, "label": ".in" },
{ "code": -255, "label": ".co.in" }
]
}
}
}

View File

@@ -10,9 +10,9 @@
"main": { "$": "auto_text_key" ,"code" : 237, "label": "í" }
},
"o": {
"main": { "$": "auto_text_key", "code" : 243, "label": "ó" },
"main": { "$": "auto_text_key", "code" : 246, "label": "ö" },
"relevant": [
{ "$": "auto_text_key", "code" : 246, "label": "ö" },
{ "$": "auto_text_key", "code" : 243, "label": "ó" },
{ "$": "auto_text_key", "code" : 337, "label": "ő" }
]
},
@@ -22,9 +22,9 @@
]
},
"u": {
"main": { "$": "auto_text_key", "code" : 250, "label": "ú" },
"main": { "$": "auto_text_key", "code" : 252, "label": "ü" },
"relevant": [
{ "$": "auto_text_key", "code" : 252, "label": "ü" },
{ "$": "auto_text_key", "code" : 250, "label": "ú" },
{ "$": "auto_text_key", "code" : 369, "label": "ű" }
]
},

View File

@@ -0,0 +1,65 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "gboard_day",
"label": "Gboard Day",
"authors": [ "patrickgold", "itskareem" ],
"isNightTheme": false,
"attributes": {
"window": {
"colorPrimary": "#0479ed",
"colorPrimaryDark": "#0467c9",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "true",
"semiTransparentColor": "#20000000",
"textColor": "#000000"
},
"keyboard": {
"background": "#D1D6DC"
},
"key": {
"background": "#FCFFFF",
"backgroundPressed": "#F5F5F5",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "true"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "#FFFFFF",
"foregroundPressed": "#FFFFFF"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#757575"
},
"oneHanded": {
"background": "@keyboard/background",
"foreground": "#424242"
},
"popup": {
"background": "#EEEEEE",
"backgroundActive": "#BDBDBD",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#A000FF",
"foreground": "#FFFFFF"
},
"smartbar": {
"background": "@keyboard/background",
"foreground": "@window/textColor",
"foregroundAlt": "#8A8A8A"
},
"smartbarButton": {
"background": "@key/background",
"foreground": "@key/foreground"
},
"glideTrail": {"foreground": "#200479ed"}
}
}

View File

@@ -0,0 +1,65 @@
{
"$type": "dev.patrickgold.florisboard.ime.theme.Theme",
"name": "gboard_night",
"label": "Gboard Night",
"authors": [ "Netscaping" ],
"isNightTheme": true,
"attributes": {
"window": {
"colorPrimary": "#5e97f6",
"colorPrimaryDark": "#4285f4",
"colorAccent": "#FF9800",
"navigationBarColor": "@keyboard/background",
"navigationBarLight": "false",
"semiTransparentColor": "#20FFFFFF",
"textColor": "#FFFFFF"
},
"keyboard": {
"background": "#292e33"
},
"key": {
"background": "#484c4f",
"backgroundPressed": "#5e5e60",
"foreground": "@window/textColor",
"foregroundPressed": "@window/textColor",
"showBorder": "true"
},
"key:enter": {
"background": "@window/colorPrimary",
"backgroundPressed": "@window/colorPrimaryDark",
"foreground": "#FFFFFF",
"foregroundPressed": "#FFFFFF"
},
"key:shift:capslock": {
"foreground": "@window/colorAccent",
"foregroundPressed": "@window/colorAccent"
},
"media": {
"foreground": "@window/textColor",
"foregroundAlt": "#BDBDBD"
},
"oneHanded": {
"background": "#373c41",
"foreground": "#9b9da0"
},
"popup": {
"background": "#373c41",
"backgroundActive": "#5a5e60",
"foreground": "@window/textColor"
},
"privateMode": {
"background": "#A000FF",
"foreground": "#FFFFFF"
},
"smartbar": {
"background": "transparent",
"foreground": "#d4d5d6",
"foregroundAlt": "#73FFFFFF"
},
"smartbarButton": {
"background": "#FFFFFF",
"foreground": "#686868"
},
"glideTrail": {"foreground": "#205e97f6"}
}
}

View File

@@ -2,10 +2,10 @@
"$": "ime.extension.theme",
"meta": {
"id": "org.florisboard.themes",
"version": "0.2.0",
"version": "0.1.0",
"title": "FlorisBoard default themes",
"description": "Default themes (both day and night) for the keyboard UI",
"maintainers": [ "patrickgold <patrick@patrickgold.dev>", "lm41 <lm41@lm41.xyz>" ],
"maintainers": [ "patrickgold <patrick@patrickgold.dev>" ],
"license": "apache-2.0"
},
"themes": [
@@ -13,37 +13,49 @@
"id": "floris_day",
"label": "Floris Day",
"authors": [ "patrickgold" ],
"isNight": false
"isNight": false,
"isBorderless": false,
"isMaterialYouAware": false
},
{
"id": "floris_day_borderless",
"label": "Floris Day (Borderless)",
"authors": [ "patrickgold" ],
"isNight": false
"isNight": false,
"isBorderless": true,
"isMaterialYouAware": false
},
{
"id": "floris_night",
"label": "Floris Night",
"authors": [ "patrickgold" ],
"isNight": true
"isNight": true,
"isBorderless": false,
"isMaterialYouAware": false
},
{
"id": "floris_night_borderless",
"label": "Floris Night (Borderless)",
"authors": [ "patrickgold" ],
"isNight": true
"isNight": true,
"isBorderless": true,
"isMaterialYouAware": false
},
{
"id": "floris_pure_night",
"label": "Floris Pure Night",
"authors": [ "serebit" ],
"isNight": true
"isNight": true,
"isBorderless": false,
"isMaterialYouAware": false
},
{
"id": "floris_pure_night_borderless",
"label": "Floris Pure Night (Borderless)",
"authors": [ "serebit" ],
"isNight": true
"isNight": true,
"isBorderless": true,
"isMaterialYouAware": false
}
]
}

View File

@@ -1,40 +1,23 @@
{
"$schema": "https://schemas.florisboard.org/snygg/v2/stylesheet",
"@defines": {
"--primary": "#4caf50",
"--primary-variant": "#388e3c",
"--secondary": "#ff9800",
"--secondary-variant": "#e65100",
"--background": "#e0e0e0",
"--background-variant": "#d0d0d0",
"--surface": "#ffffff",
"--surface-variant": "#f5f5f5",
"--popup-surface": "#eeeeee",
"--focused-popup-surface": "#bdbdbd",
"--drag-marker": "rgb(255,0,0)",
"--spacer-color": "rgba(0 ,0, 0, 0.25)",
"--one-hand-background": "#e8f5e9",
"--one-hand-foreground": "#424242",
"--incognito-icon-color": "#00000011",
"--on-primary": "#f0f0f0",
"--on-background": "#121212",
"--on-background-disabled": "rgb(175,175,175)",
"--on-surface": "#000000",
"--on-surface-variant": "#5f5f5f",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"--shape-chip": "rounded-corner(50%, 50%, 50%, 50%)"
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"window": {
"background": "var(--background)",
"foreground": "var(--on-background)"
"keyboard": {
"background": "var(--background)"
},
"key": {
@@ -42,322 +25,170 @@
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp",
"text-max-lines": "1"
"shadow-elevation": "2dp"
},
"key:pressed": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)"
},
"key[code=10]": {
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)"
},
"key[code=10]:pressed": {
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code=32]": {
"key[code={c:shift}][shiftstate={sh:caps_lock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"text-overflow": "ellipsis"
},
"key[code=-201,-202,-203]": {
"font-size": "18sp"
},
"key[code=-204,-205]": {
"font-size": "12sp"
},
"key[code=-205]": {
"text-max-lines": "2"
},
"key[code=-11][shiftstate=`caps_lock`]": {
"foreground": "var(--secondary)"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-family": "monospace",
"font-size": "12sp",
"padding": "0dp 1dp 1dp 0dp",
"text-max-lines": "1"
"font-size": "12sp"
},
"key-popup-box": {
"background": "var(--popup-surface)",
"key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"key-popup-extended-indicator": {
"font-size": "16sp"
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar": {
"font-size": "18sp"
},
"smartbar-shared-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "6dp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-extended-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"margin": "6dp",
"shape": "circle()"
},
"smartbar-action-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-key:disabled": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-overflow": {
"margin": "4dp"
},
"smartbar-actions-overflow-customize-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"font-size": "14sp",
"margin": "0dp 8dp 0dp 0dp",
"shape": "rounded-corner(24dp, 24dp, 24dp, 24dp)"
"background": "transparent",
"foreground": "#12121248"
},
"smartbar-action-tile": {
"background": "var(--background-variant)",
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "4dp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-tile:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-tile:disabled": {
"foreground": "var(--on-background-disabled)"
"background": "transparent",
"foreground": "#12121248"
},
"smartbar-action-tile-icon": {
"font-size": "24sp",
"margin": "0dp 0dp 0dp 8dp"
"smartbar-actions-overflow-customize-button": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-actions-editor": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"smartbar-actions-editor-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "16sp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-header-button": {
"margin": "4dp",
"shape": "circle()"
"font-size": "16sp"
},
"smartbar-actions-editor-subheader": {
"foreground": "var(--secondary)",
"font-size": "16sp",
"font-weight": "bold",
"padding": "12dp 16dp 12dp 8dp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"smartbar-actions-editor-tile-grid": {
"margin": "4dp 0dp"
},
"smartbar-actions-editor-tile": {
"margin": "4dp",
"padding": "8dp",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-tile[code=-999]": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-editor-tile[code=-991]": {
"foreground": "var(--drag-marker)"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rectangle()",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-candidate-word-secondary-text": {
"font-size": "8sp",
"margin": "0dp 2dp 0dp 0dp"
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-candidate-clip-icon": {
"margin": "0dp 0dp 4dp 0dp"
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--spacer-color)"
"foreground": "var(--surface)"
},
"clipboard-header": {
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"clipboard-header-button": {
"margin": "4dp",
"shape": "circle()"
},
"clipboard-header-button:disabled": {
"foreground": "var(--on-background-disabled)"
},
"clipboard-header-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"clipboard-subheader": {
"font-size": "14sp",
"margin": "6dp 10dp 6dp 6dp"
},
"clipboard-content": {
"padding": "10dp 0dp"
},
"clipboard-filter-row": {
"background": "var(--background-variant)",
"foreground": "var(--on-background)",
"padding": "0dp 0dp 4dp 0dp",
"shape": "var(--shape-variant)"
},
"clipboard-filter-chip": {
"background": "var(--surface)",
"background": "transparent",
"foreground": "var(--on-surface)",
"margin": "4dp 4dp 0dp 4dp",
"padding": "8dp 4dp",
"shape": "var(--shape-chip)"
},
"clipboard-filter-chip[state=`active`]": {
"background": "var(--primary)",
"foreground": "var(--on-primary)"
},
"clipboard-filter-chip-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-grid": {
"shape": "var(--shape-variant)"
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp",
"text-max-lines": "10",
"text-overflow": "ellipsis"
},
"clipboard-item[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-description": {
"font-size": "12sp",
"font-style": "italic"
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface)",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-timestamp": {
"font-size": "11sp",
"padding": "16dp 8dp"
},
"clipboard-item-actions": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-action": {
"font-size": "16sp",
"padding": "12dp"
},
"clipboard-item-action-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-clear-all-dialog": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)",
"shadow-elevation": "1dp"
},
"clipboard-clear-all-dialog-message": {
"padding": "16dp"
},
"clipboard-clear-all-dialog-buttons": {
"padding": "4dp"
},
"clipboard-clear-all-dialog-button": {
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)"
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"clipboard-history-disabled-title": {
"font-weight": "bold"
"emoji-tab": {
"foreground": "var(--on-background)"
},
"clipboard-history-disabled-message": {
"padding": "0dp 4dp 0dp 8dp"
},
"clipboard-history-disabled-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"shape": "rounded-corner(24dp,24dp,24dp,24dp)"
},
"clipboard-history-locked-title": {
"font-weight": "bold",
"text-align": "center"
},
"clipboard-history-locked-message": {
"padding": "0dp 4dp 0dp 0dp",
"text-align": "center"
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
@@ -382,82 +213,15 @@
},
"incognito-mode-indicator": {
"foreground": "var(--incognito-icon-color)"
},
"inline-autofill-chip": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-subheader": {
"font-weight": "bold",
"margin": "4dp"
},
"media-emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"media-emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-key-popup-box": {
"background": "var(--popup-surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"media-emoji-key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"media-emoji-tab": {
"foreground": "var(--on-background)"
},
"media-emoji-tab:focus": {
"foreground": "var(--primary)"
},
"media-bottom-row-button": {
"padding": "16dp 0dp",
"shape": "var(--shape)"
},
"media-emoji-key-popup-extended-indicator": {
"foreground": "inherit"
"foreground": "#00000011"
},
"one-handed-panel": {
"background": "var(--one-hand-background)",
"foreground": "var(--one-hand-foreground)"
"background": "#e8f5e9",
"foreground": "#424242"
},
"subtype-panel": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"subtype-panel-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "18sp",
"padding": "12dp",
"text-align": "center",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"subtype-panel-list-item": {
"font-size": "16sp",
"padding": "16dp"
},
"subtype-panel-list-item-icon-leading": {
"font-size": "24sp",
"padding": "0dp 0dp 16dp 0dp"
},
"subtype-panel-list-item-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -1,124 +1,83 @@
{
"$schema": "https://schemas.florisboard.org/snygg/v2/stylesheet",
"@defines": {
"--primary": "#4caf50",
"--primary-variant": "#388e3c",
"--secondary": "#ff9800",
"--secondary-variant": "#e65100",
"--background": "#e0e0e0",
"--background-variant": "#d0d0d0",
"--surface": "#f0f0f0",
"--surface-variant": "#ffffff",
"--popup-surface": "#eeeeee",
"--focused-popup-surface": "#bdbdbd",
"--drag-marker": "rgb(255,0,0)",
"--spacer-color": "rgba(0 ,0, 0, 0.25)",
"--one-hand-background": "#e8f5e9",
"--one-hand-foreground": "#424242",
"--incognito-icon-color": "#00000011",
"--on-primary": "#f0f0f0",
"--on-background": "#121212",
"--on-background-disabled": "#12121248",
"--on-surface": "#000000",
"--on-surface-variant": "#5f5f5f",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"--shape-chip": "rounded-corner(50%, 50%, 50%, 50%)"
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"window": {
"background": "var(--background)",
"foreground": "var(--on-background)"
"keyboard": {
"background": "var(--background)"
},
"key": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"text-max-lines": "1"
"shape": "var(--shape)"
},
"key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"key[code=10]": {
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)",
"margin": "0dp 6dp"
"foreground": "var(--on-surface)"
},
"key[code=10]:pressed": {
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code=32]": {
"key[code={c:shift}][shiftstate={sh:caps_lock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"margin": "0dp 6dp",
"text-overflow": "ellipsis"
},
"key[code=-201,-202,-203]": {
"font-size": "18sp"
},
"key[code=-204,-205]": {
"font-size": "12sp"
},
"key[code=-205]": {
"text-max-lines": "2"
},
"key[code=-11][shiftstate=`caps_lock`]": {
"foreground": "var(--secondary)"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"font-family": "monospace",
"padding": "0dp 1dp 1dp 0dp",
"text-max-lines": "1"
"font-size": "12sp"
},
"key-popup-box": {
"background": "var(--popup-surface)",
"key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape)"
},
"key-popup-extended-indicator": {
"font-size": "16sp"
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar": {
"font-size": "18sp"
},
"smartbar-shared-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "6dp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-extended-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"margin": "6dp",
"shape": "circle()"
},
"smartbar-action-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-key:pressed": {
@@ -126,244 +85,109 @@
"foreground": "var(--on-surface)"
},
"smartbar-action-key:disabled": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-overflow": {
"margin": "4dp"
},
"smartbar-actions-overflow-customize-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"font-size": "14sp",
"margin": "0dp 8dp 0dp 0dp",
"shape": "rounded-corner(24dp, 24dp, 24dp, 24dp)"
"background": "transparent",
"foreground": "#12121248"
},
"smartbar-action-tile": {
"background": "var(--background-variant)",
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "4dp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-tile:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-tile:disabled": {
"foreground": "var(--on-background-disabled)"
"background": "transparent",
"foreground": "#12121248"
},
"smartbar-action-tile-icon": {
"font-size": "24sp",
"margin": "0dp 0dp 0dp 8dp"
"smartbar-actions-overflow-customize-button": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-actions-editor": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"smartbar-actions-editor-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "16sp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-header-button": {
"margin": "4dp",
"shape": "circle()"
"font-size": "16sp"
},
"smartbar-actions-editor-subheader": {
"foreground": "var(--on-background)",
"font-size": "16sp",
"font-weight": "bold",
"padding": "12dp 16dp 12dp 8dp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"font-size": "16sp"
},
"smartbar-actions-editor-tile-grid": {
"margin": "4dp 0dp"
},
"smartbar-actions-editor-tile": {
"margin": "4dp",
"padding": "8dp",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-tile[code=-999]": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-editor-tile[code=-991]": {
"foreground": "var(--drag-marker)"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rectangle()",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-word-secondary-text": {
"font-size": "8sp",
"margin": "0dp 2dp 0dp 0dp"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip-icon": {
"margin": "0dp 0dp 4dp 0dp"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"clipboard-header-button": {
"margin": "4dp",
"shape": "circle()"
},
"clipboard-header-button:disabled": {
"foreground": "var(--on-background-disabled)"
},
"clipboard-header-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"clipboard-subheader": {
"font-size": "14sp",
"margin": "6dp 10dp 6dp 6dp"
},
"clipboard-content": {
"padding": "10dp 0dp"
},
"clipboard-filter-row": {
"background": "var(--background-variant)",
"foreground": "var(--on-background)",
"padding": "0dp 0dp 4dp 0dp",
"shape": "var(--shape-variant)"
},
"clipboard-filter-chip": {
"background": "var(--surface)",
"background": "transparent",
"foreground": "var(--on-surface)",
"margin": "4dp 4dp 0dp 4dp",
"padding": "8dp 4dp",
"shape": "var(--shape-chip)"
},
"clipboard-filter-chip[state=`active`]": {
"background": "var(--primary)",
"foreground": "var(--on-primary)"
},
"clipboard-filter-chip-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-grid": {
"shape": "var(--shape-variant)"
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp",
"text-max-lines": "10",
"text-overflow": "ellipsis"
},
"clipboard-item[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-description": {
"font-size": "12sp",
"font-style": "italic"
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface)",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-timestamp": {
"font-size": "11sp",
"padding": "16dp 8dp"
},
"clipboard-item-actions": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-action": {
"font-size": "16sp",
"padding": "12dp"
},
"clipboard-item-action-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-clear-all-dialog": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)",
"shadow-elevation": "1dp"
},
"clipboard-clear-all-dialog-message": {
"padding": "16dp"
},
"clipboard-clear-all-dialog-buttons": {
"padding": "4dp"
},
"clipboard-clear-all-dialog-button": {
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#eeeeee",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)"
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"clipboard-history-disabled-title": {
"font-weight": "bold"
"emoji-tab": {
"foreground": "var(--on-background)"
},
"clipboard-history-disabled-message": {
"padding": "0dp 4dp 0dp 8dp"
},
"clipboard-history-disabled-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"shape": "rounded-corner(24dp,24dp,24dp,24dp)"
},
"clipboard-history-locked-title": {
"font-weight": "bold",
"text-align": "center"
},
"clipboard-history-locked-message": {
"padding": "0dp 4dp 0dp 0dp",
"text-align": "center"
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
@@ -388,82 +212,15 @@
},
"incognito-mode-indicator": {
"foreground": "var(--incognito-icon-color)"
},
"inline-autofill-chip": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-subheader": {
"font-weight": "bold",
"margin": "4dp"
},
"media-emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"media-emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-key-popup-box": {
"background": "var(--popup-surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"media-emoji-key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"media-emoji-tab": {
"foreground": "var(--on-background)"
},
"media-emoji-tab:focus": {
"foreground": "var(--primary)"
},
"media-bottom-row-button": {
"padding": "16dp 0dp",
"shape": "var(--shape)"
},
"media-emoji-key-popup-extended-indicator": {
"foreground": "inherit"
"foreground": "#00000011"
},
"one-handed-panel": {
"background": "var(--one-hand-background)",
"foreground": "var(--one-hand-foreground)"
"background": "#e8f5e9",
"foreground": "#424242"
},
"subtype-panel": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"subtype-panel-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "18sp",
"padding": "12dp",
"text-align": "center",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"subtype-panel-list-item": {
"font-size": "16sp",
"padding": "16dp"
},
"subtype-panel-list-item-icon-leading": {
"font-size": "24sp",
"padding": "0dp 0dp 16dp 0dp"
},
"subtype-panel-list-item-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -1,35 +1,23 @@
{
"$schema": "https://schemas.florisboard.org/snygg/v2/stylesheet",
"@defines": {
"--primary": "#4caf50",
"--primary-variant": "#388e3c",
"--secondary": "#f57c00",
"--secondary-variant": "#e65100",
"--background": "#212121",
"--background-variant": "#313131",
"--surface": "#424242",
"--surface-variant": "#616161",
"--popup-surface": "#757575",
"--focused-popup-surface": "#bdbdbd",
"--drag-marker": "rgb(255,0,0)",
"--spacer-color": "rgba(255, 255, 255, 0.25)",
"--one-hand-background": "#1b5e20",
"--one-hand-foreground": "#eeeeee",
"--incognito-icon-color": "#ffffff11",
"--on-primary": "#f0f0f0",
"--on-background": "#dcdcdc",
"--on-background-disabled": "#dcdcdc48",
"--on-surface": "#ffffff",
"--on-surface-variant": "#a0a0a0",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"--shape-chip": "rounded-corner(50%, 50%, 50%, 50%)"
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"window": {
"background": "var(--background)",
"foreground": "var(--on-background)"
"keyboard": {
"background": "var(--background)"
},
"key": {
@@ -37,322 +25,170 @@
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp",
"text-max-lines": "1"
"shadow-elevation": "2dp"
},
"key:pressed": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)"
},
"key[code=10]": {
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)"
},
"key[code=10]:pressed": {
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code=32]": {
"key[code={c:shift}][shiftstate={sh:caps_lock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"text-overflow": "ellipsis"
},
"key[code=-201,-202,-203]": {
"font-size": "18sp"
},
"key[code=-204,-205]": {
"font-size": "12sp"
},
"key[code=-205]": {
"text-max-lines": "2"
},
"key[code=-11][shiftstate=`caps_lock`]": {
"foreground": "var(--secondary)"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-family": "monospace",
"font-size": "12sp",
"padding": "0dp 1dp 1dp 0dp",
"text-max-lines": "1"
"font-size": "12sp"
},
"key-popup-box": {
"background": "var(--popup-surface)",
"key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"key-popup-extended-indicator": {
"font-size": "16sp"
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar": {
"font-size": "18sp"
},
"smartbar-shared-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "6dp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-extended-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"margin": "6dp",
"shape": "circle()"
},
"smartbar-action-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-key:disabled": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-overflow": {
"margin": "4dp"
},
"smartbar-actions-overflow-customize-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"font-size": "14sp",
"margin": "0dp 8dp 0dp 0dp",
"shape": "rounded-corner(24dp, 24dp, 24dp, 24dp)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile": {
"background": "var(--background-variant)",
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "4dp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-tile:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-tile:disabled": {
"foreground": "var(--on-background-disabled)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile-icon": {
"font-size": "24sp",
"margin": "0dp 0dp 0dp 8dp"
"smartbar-actions-overflow-customize-button": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-actions-editor": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"smartbar-actions-editor-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "16sp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-header-button": {
"margin": "4dp",
"shape": "circle()"
"font-size": "16sp"
},
"smartbar-actions-editor-subheader": {
"foreground": "var(--secondary)",
"font-size": "16sp",
"font-weight": "bold",
"padding": "12dp 16dp 12dp 8dp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"smartbar-actions-editor-tile-grid": {
"margin": "4dp 0dp"
},
"smartbar-actions-editor-tile": {
"margin": "4dp",
"padding": "8dp",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-tile[code=-999]": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-editor-tile[code=-991]": {
"foreground": "var(--drag-marker)"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rectangle()",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-candidate-word-secondary-text": {
"font-size": "8sp",
"margin": "0dp 2dp 0dp 0dp"
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-candidate-clip-icon": {
"margin": "0dp 0dp 4dp 0dp"
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--spacer-color)"
"foreground": "var(--surface)"
},
"clipboard-header": {
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"clipboard-header-button": {
"margin": "4dp",
"shape": "circle()"
},
"clipboard-header-button:disabled": {
"foreground": "var(--on-background-disabled)"
},
"clipboard-header-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"clipboard-subheader": {
"font-size": "14sp",
"margin": "6dp 10dp 6dp 6dp"
},
"clipboard-content": {
"padding": "10dp 0dp"
},
"clipboard-filter-row": {
"background": "var(--background-variant)",
"foreground": "var(--on-background)",
"padding": "0dp 0dp 4dp 0dp",
"shape": "var(--shape-variant)"
},
"clipboard-filter-chip": {
"background": "var(--surface)",
"background": "transparent",
"foreground": "var(--on-surface)",
"margin": "4dp 4dp 0dp 4dp",
"padding": "8dp 4dp",
"shape": "var(--shape-chip)"
},
"clipboard-filter-chip[state=`active`]": {
"background": "var(--primary)",
"foreground": "var(--on-primary)"
},
"clipboard-filter-chip-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-grid": {
"shape": "var(--shape-variant)"
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp",
"text-max-lines": "10",
"text-overflow": "ellipsis"
},
"clipboard-item[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-description": {
"font-size": "12sp",
"font-style": "italic"
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface)",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-timestamp": {
"font-size": "11sp",
"padding": "16dp 8dp"
},
"clipboard-item-actions": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-action": {
"font-size": "16sp",
"padding": "12dp"
},
"clipboard-item-action-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-clear-all-dialog": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)",
"shadow-elevation": "1dp"
},
"clipboard-clear-all-dialog-message": {
"padding": "16dp"
},
"clipboard-clear-all-dialog-buttons": {
"padding": "4dp"
},
"clipboard-clear-all-dialog-button": {
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)"
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"clipboard-history-disabled-title": {
"font-weight": "bold"
"emoji-tab": {
"foreground": "var(--on-background)"
},
"clipboard-history-disabled-message": {
"padding": "0dp 4dp 0dp 8dp"
},
"clipboard-history-disabled-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"shape": "rounded-corner(24dp,24dp,24dp,24dp)"
},
"clipboard-history-locked-title": {
"font-weight": "bold",
"text-align": "center"
},
"clipboard-history-locked-message": {
"padding": "0dp 4dp 0dp 0dp",
"text-align": "center"
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
@@ -377,81 +213,15 @@
},
"incognito-mode-indicator": {
"foreground": "var(--incognito-icon-color)"
},
"inline-autofill-chip": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-subheader": {
"font-weight": "bold",
"margin": "4dp"
},
"media-emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"media-emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-key-popup-box": {
"background": "var(--popup-surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"media-emoji-key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"media-emoji-tab": {
"foreground": "var(--on-background)"
},
"media-emoji-tab:focus": {
"foreground": "var(--primary)"
},
"media-bottom-row-button": {
"padding": "16dp 0dp",
"shape": "var(--shape)"
},
"media-emoji-key-popup-extended-indicator": {
"foreground": "inherit"
"foreground": "#ffffff11"
},
"one-handed-panel": {
"background": "var(--one-hand-background)",
"foreground": "var(--one-hand-foreground)"
"background": "#1b5e20",
"foreground": "#eeeeee"
},
"subtype-panel": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"subtype-panel-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "18sp",
"padding": "12dp",
"text-align": "center",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"subtype-panel-list-item": {
"font-size": "16sp",
"padding": "16dp"
},
"subtype-panel-list-item-icon-leading": {
"font-size": "24sp",
"padding": "0dp 0dp 16dp 0dp"
},
"subtype-panel-list-item-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -1,119 +1,83 @@
{
"$schema": "https://schemas.florisboard.org/snygg/v2/stylesheet",
"@defines": {
"--primary": "#4caf50",
"--primary-variant": "#388e3c",
"--secondary": "#f57c00",
"--secondary-variant": "#e65100",
"--background": "#212121",
"--background-variant": "#313131",
"--surface": "#424242",
"--surface-variant": "#616161",
"--popup-surface": "#757575",
"--focused-popup-surface": "#bdbdbd",
"--drag-marker": "rgb(255,0,0)",
"--spacer-color": "rgba(255, 255, 255, 0.25)",
"--one-hand-background": "#1b5e20",
"--one-hand-foreground": "#eeeeee",
"--incognito-icon-color": "#ffffff11",
"--on-primary": "#f0f0f0",
"--on-background": "#dcdcdc",
"--on-background-disabled": "#dcdcdc48",
"--on-surface": "#ffffff",
"--on-surface-variant": "#a0a0a0",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"--shape-chip": "rounded-corner(50%, 50%, 50%, 50%)"
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"window": {
"background": "var(--background)",
"foreground": "var(--on-background)"
"keyboard": {
"background": "var(--background)"
},
"key": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"text-max-lines": "1"
"shape": "var(--shape)"
},
"key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"key[code=10]": {
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)",
"margin": "0dp 6dp"
"foreground": "var(--on-surface)"
},
"key[code=10]:pressed": {
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code=32]": {
"key[code={c:shift}][shiftstate={sh:caps_lock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"margin": "0dp 6dp",
"text-overflow": "ellipsis"
},
"key[code=-201,-202,-203]": {
"font-size": "18sp"
},
"key[code=-204,-205]": {
"font-size": "12sp"
},
"key[code=-205]": {
"text-max-lines": "2"
},
"key[code=-11][shiftstate=`caps_lock`]": {
"foreground": "var(--secondary)"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"font-family": "monospace",
"padding": "0dp 1dp 1dp 0dp",
"text-max-lines": "1"
"font-size": "12sp"
},
"key-popup-box": {
"background": "var(--popup-surface)",
"key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape)"
},
"key-popup-extended-indicator": {
"font-size": "16sp"
"key-popup:focus": {
"background": "#bdbdbd",
"foreground": "var(--on-surface)"
},
"smartbar": {
"font-size": "18sp"
},
"smartbar-shared-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "6dp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-extended-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"margin": "6dp",
"shape": "circle()"
},
"smartbar-action-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-key:pressed": {
@@ -121,244 +85,109 @@
"foreground": "var(--on-surface)"
},
"smartbar-action-key:disabled": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-overflow": {
"margin": "4dp"
},
"smartbar-actions-overflow-customize-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"font-size": "14sp",
"margin": "0dp 8dp 0dp 0dp",
"shape": "rounded-corner(24dp, 24dp, 24dp, 24dp)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile": {
"background": "var(--background-variant)",
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "4dp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-tile:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-tile:disabled": {
"foreground": "var(--on-background-disabled)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile-icon": {
"font-size": "24sp",
"margin": "0dp 0dp 0dp 8dp"
"smartbar-actions-overflow-customize-button": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-actions-editor": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"smartbar-actions-editor-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "16sp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-header-button": {
"margin": "4dp",
"shape": "circle()"
"font-size": "16sp"
},
"smartbar-actions-editor-subheader": {
"foreground": "var(--on-background)",
"font-size": "16sp",
"font-weight": "bold",
"padding": "12dp 16dp 12dp 8dp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"font-size": "16sp"
},
"smartbar-actions-editor-tile-grid": {
"margin": "4dp 0dp"
},
"smartbar-actions-editor-tile": {
"margin": "4dp",
"padding": "8dp",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-tile[code=-999]": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-editor-tile[code=-991]": {
"foreground": "var(--drag-marker)"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rectangle()",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-word-secondary-text": {
"font-size": "8sp",
"margin": "0dp 2dp 0dp 0dp"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip-icon": {
"margin": "0dp 0dp 4dp 0dp"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"clipboard-header-button": {
"margin": "4dp",
"shape": "circle()"
},
"clipboard-header-button:disabled": {
"foreground": "var(--on-background-disabled)"
},
"clipboard-header-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"clipboard-subheader": {
"font-size": "14sp",
"margin": "6dp 10dp 6dp 6dp"
},
"clipboard-content": {
"padding": "10dp 0dp"
},
"clipboard-filter-row": {
"background": "var(--background-variant)",
"foreground": "var(--on-background)",
"padding": "0dp 0dp 4dp 0dp",
"shape": "var(--shape-variant)"
},
"clipboard-filter-chip": {
"background": "var(--surface)",
"background": "transparent",
"foreground": "var(--on-surface)",
"margin": "4dp 4dp 0dp 4dp",
"padding": "8dp 4dp",
"shape": "var(--shape-chip)"
},
"clipboard-filter-chip[state=`active`]": {
"background": "var(--primary)",
"foreground": "var(--on-primary)"
},
"clipboard-filter-chip-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-grid": {
"shape": "var(--shape-variant)"
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp",
"text-max-lines": "10",
"text-overflow": "ellipsis"
},
"clipboard-item[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-description": {
"font-size": "12sp",
"font-style": "italic"
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface)",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-timestamp": {
"font-size": "11sp",
"padding": "16dp 8dp"
},
"clipboard-item-actions": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-action": {
"font-size": "16sp",
"padding": "12dp"
},
"clipboard-item-action-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-clear-all-dialog": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)",
"shadow-elevation": "1dp"
},
"clipboard-clear-all-dialog-message": {
"padding": "16dp"
},
"clipboard-clear-all-dialog-buttons": {
"padding": "4dp"
},
"clipboard-clear-all-dialog-button": {
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)"
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"clipboard-history-disabled-title": {
"font-weight": "bold"
"emoji-tab": {
"foreground": "var(--on-background)"
},
"clipboard-history-disabled-message": {
"padding": "0dp 4dp 0dp 8dp"
},
"clipboard-history-disabled-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"shape": "rounded-corner(24dp,24dp,24dp,24dp)"
},
"clipboard-history-locked-title": {
"font-weight": "bold",
"text-align": "center"
},
"clipboard-history-locked-message": {
"padding": "0dp 4dp 0dp 0dp",
"text-align": "center"
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
@@ -383,81 +212,15 @@
},
"incognito-mode-indicator": {
"foreground": "var(--incognito-icon-color)"
},
"inline-autofill-chip": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-subheader": {
"font-weight": "bold",
"margin": "4dp"
},
"media-emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"media-emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-key-popup-box": {
"background": "var(--popup-surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"media-emoji-key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"media-emoji-tab": {
"foreground": "var(--on-background)"
},
"media-emoji-tab:focus": {
"foreground": "var(--primary)"
},
"media-bottom-row-button": {
"padding": "16dp 0dp",
"shape": "var(--shape)"
},
"media-emoji-key-popup-extended-indicator": {
"foreground": "inherit"
"foreground": "#ffffff11"
},
"one-handed-panel": {
"background": "var(--one-hand-background)",
"foreground": "var(--one-hand-foreground)"
"background": "#1b5e20",
"foreground": "#eeeeee"
},
"subtype-panel": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"subtype-panel-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "18sp",
"padding": "12dp",
"text-align": "center",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"subtype-panel-list-item": {
"font-size": "16sp",
"padding": "16dp"
},
"subtype-panel-list-item-icon-leading": {
"font-size": "24sp",
"padding": "0dp 0dp 16dp 0dp"
},
"subtype-panel-list-item-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -1,35 +1,23 @@
{
"$schema": "https://schemas.florisboard.org/snygg/v2/stylesheet",
"@defines": {
"--primary": "#388e3c",
"--primary-variant": "#306d32",
"--secondary": "#ff9800",
"--secondary-variant": "#804c00",
"--background": "#000000",
"--background-variant": "#111111",
"--surface": "#212121",
"--surface-variant": "#3d3d3d",
"--popup-surface": "#424242",
"--focused-popup-surface": "#707070",
"--drag-marker": "rgb(255,0,0)",
"--spacer-color": "rgba(255, 255, 255, 0.25)",
"--one-hand-background": "#1b5e20",
"--one-hand-foreground": "#eeeeee",
"--incognito-icon-color": "#ffffff11",
"--on-primary": "#f0f0f0",
"--on-background-disabled": "#dcdcdc48",
"--on-background": "#eeeeee",
"--on-surface": "#eeeeee",
"--on-surface-variant": "#ffffff73",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"--shape-chip": "rounded-corner(50%, 50%, 50%, 50%)"
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"window": {
"background": "var(--background)",
"foreground": "var(--on-background)"
"keyboard": {
"background": "var(--background)"
},
"key": {
@@ -37,81 +25,60 @@
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp",
"text-max-lines": "1"
"shadow-elevation": "2dp"
},
"key:pressed": {
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)"
},
"key[code=10]": {
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)"
},
"key[code=10]:pressed": {
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code=32]": {
"key[code={c:shift}][shiftstate={sh:caps_lock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"text-overflow": "ellipsis"
},
"key[code=-201,-202,-203]": {
"font-size": "18sp"
},
"key[code=-204,-205]": {
"font-size": "12sp"
},
"key[code=-205]": {
"text-max-lines": "2"
},
"key[code=-11][shiftstate=`caps_lock`]": {
"foreground": "var(--secondary)"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-family": "monospace",
"font-size": "12sp",
"padding": "0dp 1dp 1dp 0dp",
"text-max-lines": "1"
"font-size": "12sp"
},
"key-popup-box": {
"background": "var(--popup-surface)",
"key-popup": {
"background": "#424242",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"key-popup-extended-indicator": {
"font-size": "16sp"
"key-popup:focus": {
"background": "#707070",
"foreground": "var(--on-surface)"
},
"smartbar": {
"font-size": "18sp"
},
"smartbar-shared-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "6dp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-extended-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"margin": "6dp",
"shape": "circle()"
},
"smartbar-action-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-key:pressed": {
@@ -119,244 +86,109 @@
"foreground": "var(--on-surface)"
},
"smartbar-action-key:disabled": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-overflow": {
"margin": "4dp"
},
"smartbar-actions-overflow-customize-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"font-size": "14sp",
"margin": "0dp 8dp 0dp 0dp",
"shape": "rounded-corner(24dp, 24dp, 24dp, 24dp)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile": {
"background": "var(--background-variant)",
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "4dp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-tile:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-tile:disabled": {
"foreground": "var(--on-background-disabled)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile-icon": {
"font-size": "24sp",
"margin": "0dp 0dp 0dp 8dp"
"smartbar-actions-overflow-customize-button": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-actions-editor": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"smartbar-actions-editor-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "16sp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-header-button": {
"margin": "4dp",
"shape": "circle()"
"font-size": "16sp"
},
"smartbar-actions-editor-subheader": {
"foreground": "var(--secondary)",
"font-size": "16sp",
"font-weight": "bold",
"padding": "12dp 16dp 12dp 8dp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"smartbar-actions-editor-tile-grid": {
"margin": "4dp 0dp"
},
"smartbar-actions-editor-tile": {
"margin": "4dp",
"padding": "8dp",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-tile[code=-999]": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-editor-tile[code=-991]": {
"foreground": "var(--drag-marker)"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rectangle()",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-candidate-word-secondary-text": {
"font-size": "8sp",
"margin": "0dp 2dp 0dp 0dp"
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-candidate-clip-icon": {
"margin": "0dp 0dp 4dp 0dp"
"foreground": "var(--on-background)"
},
"smartbar-candidate-spacer": {
"foreground": "var(--spacer-color)"
"foreground": "var(--surface)"
},
"clipboard-header": {
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"clipboard-header-button": {
"margin": "4dp",
"shape": "circle()"
},
"clipboard-header-button:disabled": {
"foreground": "var(--on-background-disabled)"
},
"clipboard-header-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"clipboard-subheader": {
"font-size": "14sp",
"margin": "6dp 10dp 6dp 6dp"
},
"clipboard-content": {
"padding": "10dp 0dp"
},
"clipboard-filter-row": {
"background": "var(--background-variant)",
"foreground": "var(--on-background)",
"padding": "0dp 0dp 4dp 0dp",
"shape": "var(--shape-variant)"
},
"clipboard-filter-chip": {
"background": "var(--surface)",
"background": "transparent",
"foreground": "var(--on-surface)",
"margin": "4dp 4dp 0dp 4dp",
"padding": "8dp 4dp",
"shape": "var(--shape-chip)"
},
"clipboard-filter-chip[state=`active`]": {
"background": "var(--primary)",
"foreground": "var(--on-primary)"
},
"clipboard-filter-chip-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-grid": {
"shape": "var(--shape-variant)"
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp",
"text-max-lines": "10",
"text-overflow": "ellipsis"
},
"clipboard-item[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-description": {
"font-size": "12sp",
"font-style": "italic"
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface)",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-timestamp": {
"font-size": "11sp",
"padding": "16dp 8dp"
},
"clipboard-item-actions": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-action": {
"font-size": "16sp",
"padding": "12dp"
},
"clipboard-item-action-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-clear-all-dialog": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)",
"shadow-elevation": "1dp"
},
"clipboard-clear-all-dialog-message": {
"padding": "16dp"
},
"clipboard-clear-all-dialog-buttons": {
"padding": "4dp"
},
"clipboard-clear-all-dialog-button": {
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)"
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"clipboard-history-disabled-title": {
"font-weight": "bold"
"emoji-tab": {
"foreground": "var(--on-background)"
},
"clipboard-history-disabled-message": {
"padding": "0dp 4dp 0dp 8dp"
},
"clipboard-history-disabled-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"shape": "rounded-corner(24dp,24dp,24dp,24dp)"
},
"clipboard-history-locked-title": {
"font-weight": "bold",
"text-align": "center"
},
"clipboard-history-locked-message": {
"padding": "0dp 4dp 0dp 0dp",
"text-align": "center"
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
@@ -367,95 +199,29 @@
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary)",
"border-width": "2dp"
"border-color": "var(--secondary-variant)",
"border-width": "1dp"
},
"extracted-landscape-input-action": {
"background": "var(--primary)",
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary)"
"foreground": "var(--primary-variant)"
},
"incognito-mode-indicator": {
"foreground": "var(--incognito-icon-color)"
},
"inline-autofill-chip": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-subheader": {
"font-weight": "bold",
"margin": "4dp"
},
"media-emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"media-emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-key-popup-box": {
"background": "var(--popup-surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"media-emoji-key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"media-emoji-tab": {
"foreground": "var(--on-background)"
},
"media-emoji-tab:focus": {
"foreground": "var(--primary)"
},
"media-bottom-row-button": {
"padding": "16dp 0dp",
"shape": "var(--shape)"
},
"media-emoji-key-popup-extended-indicator": {
"foreground": "inherit"
"foreground": "#ffffff11"
},
"one-handed-panel": {
"background": "var(--one-hand-background)",
"foreground": "var(--one-hand-foreground)"
"background": "#000000",
"foreground": "#eeeeee"
},
"subtype-panel": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"subtype-panel-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "18sp",
"padding": "12dp",
"text-align": "center",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"subtype-panel-list-item": {
"font-size": "16sp",
"padding": "16dp"
},
"subtype-panel-list-item-icon-leading": {
"font-size": "24sp",
"padding": "0dp 0dp 16dp 0dp"
},
"subtype-panel-list-item-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -1,119 +1,83 @@
{
"$schema": "https://schemas.florisboard.org/snygg/v2/stylesheet",
"@defines": {
"--primary": "#388e3c",
"--primary-variant": "#306d32",
"--secondary": "#ff9800",
"--secondary-variant": "#804c00",
"--background": "#000000",
"--background-variant": "#111111",
"--surface": "#212121",
"--surface-variant": "#3d3d3d",
"--popup-surface": "#424242",
"--focused-popup-surface": "#707070",
"--drag-marker": "rgb(255,0,0)",
"--spacer-color": "rgba(255, 255, 255, 0.25)",
"--one-hand-background": "#1b5e20",
"--one-hand-foreground": "#eeeeee",
"--incognito-icon-color": "#ffffff11",
"--on-primary": "#f0f0f0",
"--on-background-disabled": "#dcdcdc48",
"--on-background": "#eeeeee",
"--on-surface": "#eeeeee",
"--on-surface-variant": "#ffffff73",
"--shape": "rounded-corner(8dp, 8dp, 8dp, 8dp)",
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"--shape-chip": "rounded-corner(50%, 50%, 50%, 50%)"
"--shape-variant": "rounded-corner(12dp, 12dp, 12dp, 12dp)"
},
"window": {
"background": "var(--background)",
"foreground": "var(--on-background)"
"keyboard": {
"background": "var(--background)"
},
"key": {
"background": "transparent",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"text-max-lines": "1"
"shape": "var(--shape)"
},
"key:pressed": {
"background": "var(--surface)",
"background": "#6161617f",
"foreground": "var(--on-surface)"
},
"key[code=10]": {
"key[code={c:enter}]": {
"background": "var(--primary)",
"foreground": "var(--on-surface)",
"margin": "0dp 6dp"
"foreground": "var(--on-surface)"
},
"key[code=10]:pressed": {
"key[code={c:enter}]:pressed": {
"background": "var(--primary-variant)",
"foreground": "var(--on-surface)"
},
"key[code=32]": {
"background": "var(--surface)",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"margin": "0dp 6dp",
"text-overflow": "ellipsis"
},
"key[code=-201,-202,-203]": {
"font-size": "18sp"
},
"key[code=-204,-205]": {
"font-size": "12sp"
},
"key[code=-205]": {
"text-max-lines": "2"
},
"key[code=-11][shiftstate=`caps_lock`]": {
"key[code={c:shift}][shiftstate={sh:caps_lock}]": {
"foreground": "var(--secondary)"
},
"key[code={c:space}]": {
"background": "#61616146",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp"
},
"key-hint": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"font-size": "12sp",
"font-family": "monospace",
"padding": "0dp 1dp 1dp 0dp",
"text-max-lines": "1"
"font-size": "12sp"
},
"key-popup-box": {
"background": "var(--popup-surface)",
"key-popup": {
"background": "#363636",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape)"
},
"key-popup-extended-indicator": {
"font-size": "16sp"
"key-popup:focus": {
"background": "#5F5F5F",
"foreground": "var(--on-surface)"
},
"smartbar": {
"font-size": "18sp"
},
"smartbar-shared-actions-toggle": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "6dp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-extended-actions-toggle": {
"background": "transparent",
"foreground": "var(--on-surface-variant)",
"margin": "6dp",
"shape": "circle()"
},
"smartbar-action-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-key:pressed": {
@@ -121,244 +85,109 @@
"foreground": "var(--on-surface)"
},
"smartbar-action-key:disabled": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-overflow": {
"margin": "4dp"
},
"smartbar-actions-overflow-customize-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"font-size": "14sp",
"margin": "0dp 8dp 0dp 0dp",
"shape": "rounded-corner(24dp, 24dp, 24dp, 24dp)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile": {
"background": "var(--background-variant)",
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "4dp",
"shape": "rounded-corner(20%, 20%, 20%, 20%)",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
"font-size": "18sp",
"shape": "var(--shape)"
},
"smartbar-action-tile:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"smartbar-action-tile:disabled": {
"foreground": "var(--on-background-disabled)"
"background": "transparent",
"foreground": "#dcdcdc48"
},
"smartbar-action-tile-icon": {
"font-size": "24sp",
"margin": "0dp 0dp 0dp 8dp"
"smartbar-actions-overflow-customize-button": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"shape": "circle()",
"shadow-elevation": "2dp"
},
"smartbar-actions-editor": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"smartbar-actions-editor-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "16sp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-header-button": {
"margin": "4dp",
"shape": "circle()"
"font-size": "16sp"
},
"smartbar-actions-editor-subheader": {
"foreground": "var(--on-background)",
"font-size": "16sp",
"font-weight": "bold",
"padding": "12dp 16dp 12dp 8dp",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"font-size": "16sp"
},
"smartbar-actions-editor-tile-grid": {
"margin": "4dp 0dp"
},
"smartbar-actions-editor-tile": {
"margin": "4dp",
"padding": "8dp",
"text-align": "center",
"text-max-lines": "2",
"text-overflow": "ellipsis"
},
"smartbar-actions-editor-tile[code=-999]": {
"foreground": "var(--on-background-disabled)"
},
"smartbar-actions-editor-tile[code=-991]": {
"foreground": "var(--drag-marker)"
},
"smartbar-candidate-word": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rectangle()",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rectangle()"
},
"smartbar-candidate-word:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-word-secondary-text": {
"font-size": "8sp",
"margin": "0dp 2dp 0dp 0dp"
},
"smartbar-candidate-clip": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "14sp",
"margin": "4dp",
"padding": "8dp 0dp",
"shape": "rounded-corner(8%, 8%, 8%, 8%)",
"text-max-lines": "1",
"text-overflow": "ellipsis"
"shape": "rounded-corner(8%, 8%, 8%, 8%)"
},
"smartbar-candidate-clip:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-background)"
},
"smartbar-candidate-clip-icon": {
"margin": "0dp 0dp 4dp 0dp"
},
"smartbar-candidate-spacer": {
"foreground": "var(--surface)"
},
"clipboard-header": {
"foreground": "var(--on-background)",
"font-size": "16sp"
},
"clipboard-header-button": {
"margin": "4dp",
"shape": "circle()"
},
"clipboard-header-button:disabled": {
"foreground": "var(--on-background-disabled)"
},
"clipboard-header-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"clipboard-subheader": {
"font-size": "14sp",
"margin": "6dp 10dp 6dp 6dp"
},
"clipboard-content": {
"padding": "10dp 0dp"
},
"clipboard-filter-row": {
"background": "var(--background-variant)",
"foreground": "var(--on-background)",
"padding": "0dp 0dp 4dp 0dp",
"shape": "var(--shape-variant)"
},
"clipboard-filter-chip": {
"background": "var(--surface)",
"background": "transparent",
"foreground": "var(--on-surface)",
"margin": "4dp 4dp 0dp 4dp",
"padding": "8dp 4dp",
"shape": "var(--shape-chip)"
},
"clipboard-filter-chip[state=`active`]": {
"background": "var(--primary)",
"foreground": "var(--on-primary)"
},
"clipboard-filter-chip-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-grid": {
"shape": "var(--shape-variant)"
"font-size": "16sp"
},
"clipboard-item": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp",
"text-max-lines": "10",
"text-overflow": "ellipsis"
},
"clipboard-item[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-description": {
"font-size": "12sp",
"font-style": "italic"
"shadow-elevation": "2dp"
},
"clipboard-item-popup": {
"background": "var(--surface)",
"background": "var(--surface-variant)",
"foreground": "var(--on-surface)",
"font-size": "14sp",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-popup[type=`text`]": {
"padding": "12dp 8dp"
},
"clipboard-item-timestamp": {
"font-size": "11sp",
"padding": "16dp 8dp"
},
"clipboard-item-actions": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"margin": "4dp",
"shape": "var(--shape-variant)",
"shadow-elevation": "2dp"
},
"clipboard-item-action": {
"font-size": "16sp",
"padding": "12dp"
},
"clipboard-item-action-text": {
"margin": "4dp 0dp 0dp 0dp"
},
"clipboard-clear-all-dialog": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)",
"shadow-elevation": "1dp"
},
"clipboard-clear-all-dialog-message": {
"padding": "16dp"
},
"clipboard-clear-all-dialog-buttons": {
"padding": "4dp"
},
"clipboard-clear-all-dialog-button": {
"emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"emoji-key-popup": {
"background": "#757575",
"foreground": "var(--on-surface)",
"shape": "var(--shape-variant)"
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"clipboard-history-disabled-title": {
"font-weight": "bold"
"emoji-tab": {
"foreground": "var(--on-background)"
},
"clipboard-history-disabled-message": {
"padding": "0dp 4dp 0dp 8dp"
},
"clipboard-history-disabled-button": {
"background": "var(--primary)",
"foreground": "var(--on-primary)",
"shape": "rounded-corner(24dp,24dp,24dp,24dp)"
},
"clipboard-history-locked-title": {
"font-weight": "bold",
"text-align": "center"
},
"clipboard-history-locked-message": {
"padding": "0dp 4dp 0dp 0dp",
"text-align": "center"
"emoji-tab:focus": {
"foreground": "var(--primary)"
},
"extracted-landscape-input-layout": {
@@ -369,95 +198,29 @@
"foreground": "var(--on-background)",
"font-size": "16sp",
"shape": "rounded-corner(12dp, 12dp, 12dp, 12dp)",
"border-color": "var(--secondary)",
"border-width": "2dp"
"border-color": "var(--secondary-variant)",
"border-width": "1dp"
},
"extracted-landscape-input-action": {
"background": "var(--primary)",
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"shape": "rounded-corner(4dp, 4dp, 4dp, 4dp)"
},
"glide-trail": {
"foreground": "var(--primary)"
"foreground": "var(--primary-variant)"
},
"incognito-mode-indicator": {
"foreground": "var(--incognito-icon-color)"
},
"inline-autofill-chip": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-subheader": {
"font-weight": "bold",
"margin": "4dp"
},
"media-emoji-key": {
"background": "transparent",
"foreground": "var(--on-background)",
"font-size": "22sp",
"shape": "var(--shape)"
},
"media-emoji-key:pressed": {
"background": "var(--surface)",
"foreground": "var(--on-surface)"
},
"media-emoji-key-popup-box": {
"background": "var(--popup-surface)",
"foreground": "var(--on-surface)",
"font-size": "22sp",
"shape": "var(--shape)",
"shadow-elevation": "2dp"
},
"media-emoji-key-popup-element:focus": {
"background": "var(--focused-popup-surface)",
"shape": "var(--shape)"
},
"media-emoji-tab": {
"foreground": "var(--on-background)"
},
"media-emoji-tab:focus": {
"foreground": "var(--primary)"
},
"media-bottom-row-button": {
"padding": "16dp 0dp",
"shape": "var(--shape)"
},
"media-emoji-key-popup-extended-indicator": {
"foreground": "inherit"
"foreground": "#ffffff11"
},
"one-handed-panel": {
"background": "var(--one-hand-background)",
"foreground": "var(--one-hand-foreground)"
"background": "#000000",
"foreground": "#eeeeee"
},
"subtype-panel": {
"background": "var(--background)",
"foreground": "var(--on-background)",
"shape": "rounded-corner(24dp, 24dp, 0dp, 0dp)"
},
"subtype-panel-header": {
"background": "var(--surface)",
"foreground": "var(--on-surface)",
"font-size": "18sp",
"padding": "12dp",
"text-align": "center",
"text-max-lines": "1",
"text-overflow": "ellipsis"
},
"subtype-panel-list-item": {
"font-size": "16sp",
"padding": "16dp"
},
"subtype-panel-list-item-icon-leading": {
"font-size": "24sp",
"padding": "0dp 0dp 16dp 0dp"
},
"subtype-panel-list-item-text": {
"text-max-lines": "1",
"text-overflow": "ellipsis"
"system-nav-bar": {
"background": "var(--background)"
}
}

View File

@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020-2025 The FlorisBoard Contributors
Copyright 2020 Patrick Goldinger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@ import dev.patrickgold.florisboard.ime.keyboard.KeyboardManager
import dev.patrickgold.florisboard.ime.media.emoji.FlorisEmojiCompat
import dev.patrickgold.florisboard.ime.nlp.NlpManager
import dev.patrickgold.florisboard.ime.text.gestures.GlideTypingManager
import dev.patrickgold.florisboard.ime.theme.FlorisImeTheme
import dev.patrickgold.florisboard.ime.theme.ThemeManager
import dev.patrickgold.florisboard.lib.cache.CacheManager
import dev.patrickgold.florisboard.lib.crashutility.CrashUtility
@@ -60,6 +61,7 @@ class FlorisApplication : Application() {
System.loadLibrary("fl_native")
} catch (_: Exception) {
}
FlorisImeTheme.init()
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package dev.patrickgold.florisboard
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.inputmethodservice.ExtractEditText
import android.os.Build
@@ -47,11 +46,11 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material3.ButtonDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -79,8 +78,6 @@ import dev.patrickgold.florisboard.app.devtools.DevtoolsOverlay
import dev.patrickgold.florisboard.app.florisPreferenceModel
import dev.patrickgold.florisboard.ime.ImeUiMode
import dev.patrickgold.florisboard.ime.clipboard.ClipboardInputLayout
import dev.patrickgold.florisboard.ime.core.SelectSubtypePanel
import dev.patrickgold.florisboard.ime.core.isSubtypeSelectionShowing
import dev.patrickgold.florisboard.ime.editor.EditorRange
import dev.patrickgold.florisboard.ime.editor.FlorisEditorInfo
import dev.patrickgold.florisboard.ime.input.InputFeedbackController
@@ -101,7 +98,7 @@ import dev.patrickgold.florisboard.ime.smartbar.quickaction.QuickActionsEditorPa
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.FlorisButton
import dev.patrickgold.florisboard.lib.compose.ProvideLocalizedResources
import dev.patrickgold.florisboard.lib.compose.SystemUiIme
import dev.patrickgold.florisboard.lib.devtools.LogTopic
@@ -109,11 +106,17 @@ import dev.patrickgold.florisboard.lib.devtools.flogError
import dev.patrickgold.florisboard.lib.devtools.flogInfo
import dev.patrickgold.florisboard.lib.devtools.flogWarning
import dev.patrickgold.florisboard.lib.observeAsTransformingState
import org.florisboard.lib.snygg.ui.SnyggSurface
import org.florisboard.lib.snygg.ui.shape
import org.florisboard.lib.snygg.ui.snyggBackground
import org.florisboard.lib.snygg.ui.snyggBorder
import org.florisboard.lib.snygg.ui.snyggShadow
import org.florisboard.lib.snygg.ui.solidColor
import org.florisboard.lib.snygg.ui.spSize
import dev.patrickgold.florisboard.lib.util.ViewUtils
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 org.florisboard.lib.android.AndroidInternalR
import org.florisboard.lib.android.AndroidVersion
import org.florisboard.lib.android.isOrientationLandscape
@@ -121,11 +124,7 @@ import org.florisboard.lib.android.isOrientationPortrait
import org.florisboard.lib.android.showShortToast
import org.florisboard.lib.android.systemServiceOrNull
import org.florisboard.lib.kotlin.collectLatestIn
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.SnyggText
import org.florisboard.lib.snygg.ui.rememberSnyggThemeQuery
import java.lang.ref.WeakReference
/**
* Global weak reference for the [FlorisImeService] class. This is needed as certain actions (request hide, switch to
@@ -232,10 +231,10 @@ class FlorisImeService : LifecycleInputMethodService() {
val imm = ims.systemServiceOrNull(InputMethodManager::class) ?: return false
val list: List<InputMethodInfo> = imm.enabledInputMethodList
for (el in list) {
for (i in 0 until el.subtypeCount) {
for (i in 0 until el.subtypeCount){
if (el.getSubtypeAt(i).mode != "voice") continue
if (AndroidVersion.ATLEAST_API28_P) {
ims.switchInputMethod(el.id, el.getSubtypeAt(i))
ims.switchInputMethod(el.id)
return true
} else {
ims.window.window?.let { window ->
@@ -267,8 +266,6 @@ class FlorisImeService : LifecycleInputMethodService() {
private var isExtractUiShown by mutableStateOf(false)
private var resourcesContext by mutableStateOf(this as Context)
private val wallpaperChangeReceiver = WallpaperChangeReceiver()
init {
setTheme(R.style.FlorisImeTheme)
}
@@ -279,23 +276,9 @@ class FlorisImeService : LifecycleInputMethodService() {
WindowCompat.setDecorFitsSystemWindows(window.window!!, false)
subtypeManager.activeSubtypeFlow.collectLatestIn(lifecycleScope) { subtype ->
val config = Configuration(resources.configuration)
if (prefs.localization.displayKeyboardLabelsInSubtypeLanguage.get()) {
config.setLocale(subtype.primaryLocale.base)
}
config.setLocale(subtype.primaryLocale.base)
resourcesContext = createConfigurationContext(config)
}
prefs.localization.displayKeyboardLabelsInSubtypeLanguage.observeForever { shouldSync ->
val config = Configuration(resources.configuration)
if (shouldSync) {
config.setLocale(subtypeManager.activeSubtype.primaryLocale.base)
}
resourcesContext = createConfigurationContext(config)
}
prefs.physicalKeyboard.showOnScreenKeyboard.observeForever {
updateInputViewShown()
}
@Suppress("DEPRECATION") // We do not retrieve the wallpaper but only listen to changes
registerReceiver(wallpaperChangeReceiver, IntentFilter(Intent.ACTION_WALLPAPER_CHANGED))
}
override fun onCreateInputView(): View {
@@ -334,7 +317,6 @@ class FlorisImeService : LifecycleInputMethodService() {
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(wallpaperChangeReceiver)
FlorisImeServiceReference = WeakReference(null)
inputWindowView = null
}
@@ -359,13 +341,6 @@ class FlorisImeService : LifecycleInputMethodService() {
}
}
override fun onEvaluateInputViewShown(): Boolean {
val config = resources.configuration
return super.onEvaluateInputViewShown()
|| config.keyboard == Configuration.KEYBOARD_NOKEYS
|| prefs.physicalKeyboard.showOnScreenKeyboard.get()
}
override fun onUpdateSelection(
oldSelStart: Int,
oldSelEnd: Int,
@@ -472,10 +447,6 @@ class FlorisImeService : LifecycleInputMethodService() {
flogInfo(LogTopic.IMS_EVENTS) { "Creating inline suggestions request" }
val stylesBundle = themeManager.createInlineSuggestionUiStyleBundle(this)
if (stylesBundle == null) {
flogWarning(LogTopic.IMS_EVENTS) { "Failed to retrieve inline suggestions style bundle" }
return null
}
val spec = InlinePresentationSpec.Builder(
InlineSuggestionUiSmallestSize,
InlineSuggestionUiBiggestSize,
@@ -523,9 +494,7 @@ class FlorisImeService : LifecycleInputMethodService() {
outInsets.visibleTopInsets = visibleTopY
outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_REGION
val left = 0
val top = if (keyboardManager.activeState.isBottomSheetShowing() || keyboardManager.activeState.isSubtypeSelectionShowing()) {
0
} else {
val top = if (keyboardManager.activeState.isBottomSheetShowing()) { 0 } else {
visibleTopY - if (needAdditionalOverlay) FlorisImeSizing.Static.smartbarHeightPx else 0
}
val right = inputViewSize.width
@@ -538,8 +507,7 @@ class FlorisImeService : LifecycleInputMethodService() {
*/
private fun updateSoftInputWindowLayoutParameters() {
val w = window?.window ?: return
// TODO: Verify that this doesn't give us a padding problem
WindowCompat.setDecorFitsSystemWindows(w, false)
WindowCompat.setDecorFitsSystemWindows(w, true)
ViewUtils.updateLayoutHeightOf(w, WindowManager.LayoutParams.MATCH_PARENT)
val layoutHeight = if (isFullscreenUiMode) {
WindowManager.LayoutParams.WRAP_CONTENT
@@ -576,18 +544,19 @@ class FlorisImeService : LifecycleInputMethodService() {
ProvideKeyboardRowBaseHeight {
CompositionLocalProvider(LocalInputFeedbackController provides inputFeedbackController) {
FlorisImeTheme {
// Do not apply system bar padding here yet, we want to draw it ourselves
Column(modifier = Modifier.fillMaxWidth()) {
if (!(isFullscreenUiMode && isExtractUiShown)) {
DevtoolsOverlay(
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
)
) {
DevtoolsUi()
}
}
ImeUi()
SystemUiIme()
}
SystemUiIme()
}
}
}
@@ -598,27 +567,25 @@ class FlorisImeService : LifecycleInputMethodService() {
@Composable
private fun ImeUi() {
val state by keyboardManager.activeState.collectAsState()
val attributes = mapOf(
FlorisImeUi.Attr.Mode to state.keyboardMode.toString(),
FlorisImeUi.Attr.ShiftState to state.inputShiftState.toString(),
val keyboardStyle = FlorisImeTheme.style.get(
element = FlorisImeUi.Keyboard,
mode = state.inputShiftState.value,
)
val layoutDirection = LocalLayoutDirection.current
LaunchedEffect(layoutDirection) {
keyboardManager.activeState.layoutDirection = layoutDirection
SideEffect {
if (keyboardManager.activeState.layoutDirection != layoutDirection) {
keyboardManager.activeState.layoutDirection = layoutDirection
}
}
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
SnyggBox(
elementName = FlorisImeUi.Window.elementName,
attributes = attributes,
SnyggSurface(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.onGloballyPositioned { coords -> inputViewSize = coords.size },
clickAndSemanticsModifier = Modifier
.onGloballyPositioned { coords -> inputViewSize = coords.size }
// Do not remove below line or touch input may get stuck
.pointerInteropFilter { false },
supportsBackgroundImage = true,
allowClip = false,
style = keyboardStyle,
) {
val configuration = LocalConfiguration.current
val bottomOffset by if (configuration.isOrientationPortrait()) {
@@ -630,18 +597,17 @@ class FlorisImeService : LifecycleInputMethodService() {
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
// Apply system bars padding here (we already drew our keyboard background)
.safeDrawingPadding()
// FIXME: removing this fixes the Smartbar sizing but breaks one-handed-mode
//.height(IntrinsicSize.Min)
.padding(bottom = bottomOffset),
) {
val oneHandedMode by prefs.keyboard.oneHandedMode.observeAsState()
val oneHandedModeEnabled by prefs.keyboard.oneHandedModeEnabled.observeAsState()
val oneHandedModeScaleFactor by prefs.keyboard.oneHandedModeScaleFactor.observeAsState()
val keyboardWeight = when {
!oneHandedModeEnabled || configuration.isOrientationLandscape() -> 1f
oneHandedMode == OneHandedMode.OFF || configuration.isOrientationLandscape() -> 1f
else -> oneHandedModeScaleFactor / 100f
}
if (oneHandedModeEnabled && oneHandedMode == OneHandedMode.END && configuration.isOrientationPortrait()) {
if (oneHandedMode == OneHandedMode.END && configuration.isOrientationPortrait()) {
OneHandedPanel(
panelSide = OneHandedMode.START,
weight = 1f - keyboardWeight,
@@ -660,7 +626,7 @@ class FlorisImeService : LifecycleInputMethodService() {
}
}
}
if (oneHandedModeEnabled && oneHandedMode == OneHandedMode.START && configuration.isOrientationPortrait()) {
if (oneHandedMode == OneHandedMode.START && configuration.isOrientationPortrait()) {
OneHandedPanel(
panelSide = OneHandedMode.END,
weight = 1f - keyboardWeight,
@@ -671,6 +637,14 @@ class FlorisImeService : LifecycleInputMethodService() {
}
}
@Composable
private fun DevtoolsUi() {
val devtoolsEnabled by prefs.devtools.enabled.observeAsState()
if (devtoolsEnabled) {
DevtoolsOverlay(modifier = Modifier.fillMaxSize())
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean =
if (keyboardManager.onHardwareKeyDown(keyCode, event)) true
else super.onKeyDown(keyCode, event)
@@ -712,22 +686,12 @@ class FlorisImeService : LifecycleInputMethodService() {
ProvideLocalizedResources(resourcesContext, forceLayoutDirection = LayoutDirection.Ltr) {
FlorisImeTheme {
BottomSheetHostUi(
isShowing = state.isBottomSheetShowing() || state.isSubtypeSelectionShowing(),
isShowing = state.isBottomSheetShowing(),
onHide = {
if (state.isBottomSheetShowing()) {
keyboardManager.activeState.isActionsEditorVisible = false
}
if (state.isSubtypeSelectionShowing()) {
keyboardManager.activeState.isSubtypeSelectionVisible = false
}
keyboardManager.activeState.isActionsEditorVisible = false
},
) {
if (state.isBottomSheetShowing()) {
QuickActionsEditorPanel()
}
if (state.isSubtypeSelectionShowing()) {
SelectSubtypePanel()
}
QuickActionsEditorPanel()
}
}
}
@@ -761,39 +725,44 @@ class FlorisImeService : LifecycleInputMethodService() {
@Composable
fun Content() {
val context = LocalContext.current
ProvideLocalizedResources(resourcesContext, forceLayoutDirection = LayoutDirection.Ltr) {
FlorisImeTheme {
val layoutStyle = FlorisImeTheme.style.get(FlorisImeUi.ExtractedLandscapeInputLayout)
val fieldStyle = FlorisImeTheme.style.get(FlorisImeUi.ExtractedLandscapeInputField)
val actionStyle = FlorisImeTheme.style.get(FlorisImeUi.ExtractedLandscapeInputAction)
val activeEditorInfo by editorInstance.activeInfoFlow.collectAsState()
SnyggBox(FlorisImeUi.ExtractedLandscapeInputLayout.elementName) {
SnyggRow(
Box(
modifier = Modifier
.snyggBackground(context, layoutStyle, FlorisImeTheme.fallbackSurfaceColor()),
) {
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
) {
SnyggBox(
elementName = FlorisImeUi.ExtractedLandscapeInputLayout.elementName,
val fieldColor = fieldStyle.foreground.solidColor(context, FlorisImeTheme.fallbackContentColor())
AndroidView(
modifier = Modifier
.padding(8.dp)
.fillMaxHeight()
.weight(1f),
) {
val fieldStyle = rememberSnyggThemeQuery(FlorisImeUi.ExtractedLandscapeInputField.elementName)
val foreground = fieldStyle.foreground()
AndroidView(
factory = { extractEditText },
update = { view ->
view.background = null
view.backgroundTintList = null
view.foregroundTintList = null
view.setTextColor(foreground.toArgb())
view.setHintTextColor(foreground.copy(foreground.alpha * 0.6f).toArgb())
view.setTextSize(
TypedValue.COMPLEX_UNIT_SP,
fieldStyle.fontSize(default = 16.sp).value,
)
},
)
}
SnyggButton(
FlorisImeUi.ExtractedLandscapeInputAction.elementName,
.weight(1f)
.snyggShadow(fieldStyle)
.snyggBorder(context, fieldStyle)
.snyggBackground(context, fieldStyle),
factory = { extractEditText },
update = { view ->
view.background = null
view.backgroundTintList = null
view.foregroundTintList = null
view.setTextColor(fieldColor.toArgb())
view.setHintTextColor(fieldColor.copy(fieldColor.alpha * 0.6f).toArgb())
view.setTextSize(
TypedValue.COMPLEX_UNIT_SP,
fieldStyle.fontSize.spSize(default = 16.sp).value,
)
},
)
FlorisButton(
onClick = {
if (activeEditorInfo.extractedActionId != 0) {
currentInputConnection?.performEditorAction(activeEditorInfo.extractedActionId)
@@ -802,13 +771,15 @@ class FlorisImeService : LifecycleInputMethodService() {
}
},
modifier = Modifier.padding(horizontal = 8.dp),
) {
SnyggText(
text = activeEditorInfo.extractedActionLabel
?: getTextForImeAction(activeEditorInfo.imeOptions.action.toInt())
?: "ACTION",
)
}
text = activeEditorInfo.extractedActionLabel
?: getTextForImeAction(activeEditorInfo.imeOptions.action.toInt())
?: "ACTION",
shape = actionStyle.shape.shape(),
colors = ButtonDefaults.buttonColors(
containerColor = actionStyle.background.solidColor(context, FlorisImeTheme.fallbackContentColor()),
contentColor = actionStyle.foreground.solidColor(context, FlorisImeTheme.fallbackSurfaceColor()),
),
)
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021-2024 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,12 +18,10 @@ package dev.patrickgold.florisboard.app
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.DisplayColorsAs
import dev.patrickgold.florisboard.app.settings.theme.DisplayKbdAfterDialogs
import dev.patrickgold.florisboard.app.settings.theme.SnyggLevel
import dev.patrickgold.florisboard.app.setup.NotificationPermissionState
import dev.patrickgold.florisboard.ime.clipboard.CLIPBOARD_HISTORY_NUM_GRID_COLUMNS_AUTO
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
import dev.patrickgold.florisboard.ime.core.Subtype
import dev.patrickgold.florisboard.ime.input.CapitalizationBehavior
@@ -42,36 +40,58 @@ import dev.patrickgold.florisboard.ime.smartbar.CandidatesDisplayMode
import dev.patrickgold.florisboard.ime.smartbar.ExtendedActionsPlacement
import dev.patrickgold.florisboard.ime.smartbar.IncognitoDisplayMode
import dev.patrickgold.florisboard.ime.smartbar.SmartbarLayout
import dev.patrickgold.florisboard.ime.smartbar.quickaction.QuickAction
import dev.patrickgold.florisboard.ime.smartbar.quickaction.QuickActionArrangement
import dev.patrickgold.florisboard.ime.smartbar.quickaction.QuickActionJsonConfig
import dev.patrickgold.florisboard.ime.text.gestures.SwipeAction
import dev.patrickgold.florisboard.ime.text.key.KeyCode
import dev.patrickgold.florisboard.ime.text.key.KeyHintConfiguration
import dev.patrickgold.florisboard.ime.text.key.KeyHintMode
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 org.florisboard.lib.android.isOrientationPortrait
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
import dev.patrickgold.florisboard.lib.observeAsTransformingState
import org.florisboard.lib.snygg.SnyggLevel
import dev.patrickgold.florisboard.lib.util.VersionName
import dev.patrickgold.jetpref.datastore.JetPref
import dev.patrickgold.jetpref.datastore.model.LocalTime
import dev.patrickgold.jetpref.datastore.model.PreferenceData
import dev.patrickgold.jetpref.datastore.model.PreferenceMigrationEntry
import dev.patrickgold.jetpref.datastore.model.PreferenceModel
import dev.patrickgold.jetpref.datastore.model.PreferenceType
import dev.patrickgold.jetpref.datastore.model.observeAsState
import dev.patrickgold.jetpref.material.ui.ColorRepresentation
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.florisboard.lib.android.AndroidVersion
import org.florisboard.lib.android.isOrientationPortrait
import org.florisboard.lib.color.DEFAULT_GREEN
fun florisPreferenceModel() = JetPref.getOrCreatePreferenceModel(AppPrefs::class, ::AppPrefs)
class AppPrefs : PreferenceModel("florisboard-app-prefs") {
val advanced = Advanced()
inner class Advanced {
val settingsTheme = enum(
key = "advanced__settings_theme",
default = AppTheme.AUTO,
)
val useMaterialYou = boolean(
key = "advanced__use_material_you",
default = true,
)
val settingsLanguage = string(
key = "advanced__settings_language",
default = "auto",
)
val showAppIcon = boolean(
key = "advanced__show_app_icon",
default = true,
)
val incognitoMode = enum(
key = "advanced__incognito_mode",
default = IncognitoMode.DYNAMIC_ON_OFF,
)
// Internal pref
val forceIncognitoModeFromDynamic = boolean(
key = "advanced__force_incognito_mode_from_dynamic",
default = false,
)
}
val clipboard = Clipboard()
inner class Clipboard {
val useInternalClipboard = boolean(
@@ -90,23 +110,6 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
key = "clipboard__history_enabled",
default = false,
)
val numHistoryGridColumnsPortrait = int(
key = "clipboard__num_history_grid_columns_portrait",
default = CLIPBOARD_HISTORY_NUM_GRID_COLUMNS_AUTO,
)
val numHistoryGridColumnsLandscape = int(
key = "clipboard__num_history_grid_columns_landscape",
default = CLIPBOARD_HISTORY_NUM_GRID_COLUMNS_AUTO,
)
@Composable
fun numHistoryGridColumns(): PreferenceData<Int> {
val configuration = LocalConfiguration.current
return if (configuration.isOrientationPortrait()) {
numHistoryGridColumnsPortrait
} else {
numHistoryGridColumnsLandscape
}
}
val cleanUpOld = boolean(
key = "clipboard__clean_up_old",
default = false,
@@ -115,14 +118,6 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
key = "clipboard__clean_up_after",
default = 20,
)
val autoCleanSensitive = boolean(
key = "clipboard__auto_clean_sensitive",
default = false,
)
val autoCleanSensitiveAfter = int(
key = "clipboard__auto_clean_sensitive_after",
default = 20,
)
val limitHistorySize = boolean(
key = "clipboard__limit_history_size",
default = true,
@@ -135,14 +130,6 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
key = "clipboard__clear_primary_clip_deletes_last_item",
default = true,
)
val suggestionEnabled = boolean(
key = "clipboard__suggestion_enabled",
default = true,
)
val suggestionTimeout = int(
key = "clipboard__suggestion_timeout",
default = 60,
)
}
val correction = Correction()
@@ -171,6 +158,10 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
key = "devtools__enabled",
default = false,
)
val showHeapMemoryStats = boolean(
key = "devtools__show_heap_memory_stats",
default = false,
)
val showPrimaryClip = boolean(
key = "devtools__show_primary_clip",
default = false,
@@ -503,11 +494,7 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
)
val oneHandedMode = enum(
key = "keyboard__one_handed_mode",
default = OneHandedMode.END,
)
val oneHandedModeEnabled = boolean(
key = "keyboard__one_handed_mode_enabled",
default = false,
default = OneHandedMode.OFF,
)
val oneHandedModeScaleFactor = int(
key = "keyboard__one_handed_mode_scale_factor",
@@ -579,14 +566,14 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
@Composable
fun fontSizeMultiplier(): Float {
val configuration = LocalConfiguration.current
val oneHandedModeEnabled by oneHandedModeEnabled.observeAsState()
val oneHandedMode by oneHandedMode.observeAsState()
val oneHandedModeFactor by oneHandedModeScaleFactor.observeAsTransformingState { it / 100.0f }
val fontSizeMultiplierBase by if (configuration.isOrientationPortrait()) {
fontSizeMultiplierPortrait
} else {
fontSizeMultiplierLandscape
}.observeAsTransformingState { it / 100.0f }
val fontSizeMultiplier = fontSizeMultiplierBase * if (oneHandedModeEnabled && configuration.isOrientationPortrait()) {
val fontSizeMultiplier = fontSizeMultiplierBase * if (oneHandedMode != OneHandedMode.OFF && configuration.isOrientationPortrait()) {
oneHandedModeFactor
} else {
1.0f
@@ -601,10 +588,6 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
key = "localization__display_language_names_in",
default = DisplayLanguageNamesIn.SYSTEM_LOCALE,
)
val displayKeyboardLabelsInSubtypeLanguage = boolean(
key = "localization__display_keyboard_labels_in_subtype_language",
default = false,
)
val activeSubtypeId = long(
key = "localization__active_subtype_id",
default = Subtype.DEFAULT.id,
@@ -615,38 +598,6 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
)
}
val other = Other()
inner class Other {
val settingsTheme = enum(
key = "other__settings_theme",
default = AppTheme.AUTO,
)
val accentColor = custom(
key = "other__accent_color",
default = when (AndroidVersion.ATLEAST_API31_S) {
true -> Color.Unspecified
false -> DEFAULT_GREEN
},
serializer = ColorPreferenceSerializer,
)
val settingsLanguage = string(
key = "other__settings_language",
default = "auto",
)
val showAppIcon = boolean(
key = "other__show_app_icon",
default = true,
)
}
val physicalKeyboard = PhysicalKeyboard()
inner class PhysicalKeyboard {
val showOnScreenKeyboard = boolean(
key = "physical_keyboard__show_on_screen_keyboard",
default = false,
)
}
val smartbar = Smartbar()
inner class Smartbar {
val enabled = boolean(
@@ -723,14 +674,13 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
key = "suggestion__block_possibly_offensive",
default = true,
)
val incognitoMode = enum(
key = "suggestion__incognito_mode",
default = IncognitoMode.DYNAMIC_ON_OFF,
val clipboardContentEnabled = boolean(
key = "suggestion__clipboard_content_enabled",
default = true,
)
// Internal pref
val forceIncognitoModeFromDynamic = boolean(
key = "suggestion__force_incognito_mode_from_dynamic",
default = false,
val clipboardContentTimeout = int(
key = "suggestion__clipboard_content_timeout",
default = 60,
)
}
@@ -750,25 +700,17 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
default = extCoreTheme("floris_night"),
serializer = ExtensionComponentName.Serializer,
)
val accentColor = custom(
key = "theme__accent_color",
default = when (AndroidVersion.ATLEAST_API31_S) {
true -> Color.Unspecified
false -> DEFAULT_GREEN
},
serializer = ColorPreferenceSerializer,
)
val sunriseTime = time(
key = "theme__sunrise_time",
default = LocalTime(6, 0),
)
val sunsetTime = time(
key = "theme__sunset_time",
default = LocalTime(18, 0),
)
val editorColorRepresentation = enum(
key = "theme__editor_color_representation",
default = ColorRepresentation.HEX,
//val sunriseTime = localTime(
// key = "theme__sunrise_time",
// default = LocalTime.of(6, 0),
//)
//val sunsetTime = localTime(
// key = "theme__sunset_time",
// default = LocalTime.of(18, 0),
//)
val editorDisplayColorsAs = enum(
key = "theme__editor_display_colors_as",
default = DisplayColorsAs.HEX8,
)
val editorDisplayKbdAfterDialogs = enum(
key = "theme__editor_display_kbd_after_dialogs",
@@ -782,6 +724,34 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
override fun migrate(entry: PreferenceMigrationEntry): PreferenceMigrationEntry {
return when (entry.key) {
// Migrate enums from their lowercase to uppercase representation
// Keep migration rule until: 0.5 dev cycle
"advanced__settings_theme", "gestures__swipe_up", "gestures__swipe_down", "gestures__swipe_left",
"gestures__swipe_right", "gestures__space_bar_swipe_up", "gestures__space_bar_swipe_left",
"gestures__space_bar_swipe_right", "gestures__space_bar_long_press", "gestures__delete_key_swipe_left",
"gestures__delete_key_long_press", "keyboard__hinted_number_row_mode", "keyboard__hinted_symbols_mode",
"keyboard__utility_key_action", "keyboard__one_handed_mode", "keyboard__landscape_input_ui_mode",
"localization__display_language_names_in", "smartbar__primary_actions_row_type",
"smartbar__secondary_actions_placement", "smartbar__secondary_actions_row_type", "spelling__language_mode",
"suggestion__display_mode", "theme__mode", "theme__editor_display_colors_as",
"theme__editor_display_kbd_after_dialogs", "theme__editor_level",
-> {
entry.transform(rawValue = entry.rawValue.uppercase())
}
// Migrate old private mode force flag as this is a sensitive preference
// Keep migration rule until: 0.5 dev cycle
"advanced__force_private_mode" -> {
if (entry.rawValue.toBoolean()) {
entry.transform(
type = PreferenceType.string(),
key = "advanced__incognito_mode",
rawValue = IncognitoMode.FORCE_ON.toString(),
)
} else {
entry.reset()
}
}
// Migrate media prefs to emoji prefs
// Keep migration rule until: 0.6 dev cycle
@@ -796,81 +766,18 @@ class AppPrefs : PreferenceModel("florisboard-app-prefs") {
"media__emoji_recently_used_max_size" -> {
entry.transform(key = "emoji__history_recent_max_size")
}
// Migrate advanced prefs to other prefs
// Keep migration rules until: 0.7 dev cycle
"advanced__settings_theme" -> {
entry.transform(key = "other__settings_theme")
}
"advanced__accent_color" -> {
entry.transform(key = "other__accent_color")
}
"advanced__settings_language" -> {
entry.transform(key = "other__settings_language")
}
"advanced__show_app_icon" -> {
entry.transform(key = "other__show_app_icon")
}
"advanced__incognito_mode" -> {
entry.transform(key = "suggestion__incognito_mode")
}
"advanced__force_incognito_mode_from_dynamic" -> {
entry.transform(key = "suggestion__force_incognito_mode_from_dynamic")
}
// Migrate clipboard suggestion prefs to clipboard
// Keep migration rules until: 0.7 dev cycle
"suggestion__clipboard_content_enabled" -> {
entry.transform(key = "clipboard__suggestion_enabled")
}
"suggestion__clipboard_content_timeout" -> {
entry.transform(key = "clipboard__suggestion_timeout")
}
//Migrate one hand mode prefs keep until: 0.7 dev cycle
"keyboard__one_handed_mode" -> {
if (entry.rawValue == "OFF") {
entry.reset()
} else {
entry.keepAsIs()
}
}
"smartbar__action_arrangement" -> {
fun migrateAction(action: QuickAction): QuickAction {
return if (action is QuickAction.InsertKey && action.data.code == KeyCode.COMPACT_LAYOUT_TO_RIGHT) {
action.copy(TextKeyData.TOGGLE_COMPACT_LAYOUT)
} else {
action
}
}
val arrangement = QuickActionJsonConfig.decodeFromString<QuickActionArrangement>(entry.rawValue)
var newArrangement = arrangement.copy(
stickyAction = arrangement.stickyAction?.let{ migrateAction(it) },
dynamicActions = arrangement.dynamicActions.map { migrateAction(it) },
hiddenActions = arrangement.hiddenActions.map { migrateAction(it) },
)
if (QuickAction.InsertKey(TextKeyData.LANGUAGE_SWITCH) !in newArrangement) {
newArrangement = newArrangement.copy(
dynamicActions = newArrangement.dynamicActions.plus(QuickAction.InsertKey(TextKeyData.LANGUAGE_SWITCH))
)
}
val json = QuickActionJsonConfig.encodeToString(newArrangement.distinct())
entry.transform(rawValue = json)
}
// Migrate theme editor fine-tuning
// Keep migration rule until: 0.6 dev cycle
"theme__editor_display_colors_as" -> {
val colorRepresentation = when (entry.rawValue) {
"RGBA" -> ColorRepresentation.RGB
else -> ColorRepresentation.HEX
}
"media__emoji_preferred_skin_tone" -> {
entry.transform(
key = "theme__editor_color_representation",
rawValue = colorRepresentation.name,
key = "emoji__preferred_skin_tone",
rawValue = entry.rawValue.uppercase(), // keep until: 0.5 dev cycle
)
}
"media__emoji_preferred_hair_style" -> {
entry.transform(
key = "emoji__preferred_hair_style",
rawValue = entry.rawValue.uppercase(), // keep until: 0.5 dev cycle
)
}
// Default: keep entry
else -> entry.keepAsIs()

View File

@@ -1,32 +1,14 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app
import androidx.compose.runtime.Composable
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.settings.theme.DisplayColorsAs
import dev.patrickgold.florisboard.app.settings.theme.DisplayKbdAfterDialogs
import dev.patrickgold.florisboard.app.settings.theme.SnyggLevel
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
import dev.patrickgold.florisboard.ime.input.CapitalizationBehavior
import dev.patrickgold.florisboard.ime.input.HapticVibrationMode
import dev.patrickgold.florisboard.ime.input.InputFeedbackActivationMode
import dev.patrickgold.florisboard.ime.input.InputShiftState
import dev.patrickgold.florisboard.ime.keyboard.IncognitoMode
import dev.patrickgold.florisboard.ime.keyboard.KeyboardMode
import dev.patrickgold.florisboard.ime.keyboard.SpaceBarMode
import dev.patrickgold.florisboard.ime.landscapeinput.LandscapeInputUiMode
import dev.patrickgold.florisboard.ime.media.emoji.EmojiHistory
@@ -43,9 +25,9 @@ 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 org.florisboard.lib.snygg.SnyggLevel
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.kotlin.curlyFormat
import kotlin.reflect.KClass
@@ -60,19 +42,19 @@ private val ENUM_DISPLAY_ENTRIES = mapOf<Pair<KClass<*>, String>, @Composable ()
)
entry(
key = AppTheme.AUTO_AMOLED,
label = stringRes(R.string.pref__other__settings_theme__auto_amoled),
label = stringRes(R.string.pref__advanced__settings_theme__auto_amoled),
)
entry(
key = AppTheme.LIGHT,
label = stringRes(R.string.pref__other__settings_theme__light),
label = stringRes(R.string.pref__advanced__settings_theme__light),
)
entry(
key = AppTheme.DARK,
label = stringRes(R.string.pref__other__settings_theme__dark),
label = stringRes(R.string.pref__advanced__settings_theme__dark),
)
entry(
key = AppTheme.AMOLED_DARK,
label = stringRes(R.string.pref__other__settings_theme__amoled_dark),
label = stringRes(R.string.pref__advanced__settings_theme__amoled_dark),
)
}
},
@@ -104,24 +86,18 @@ private val ENUM_DISPLAY_ENTRIES = mapOf<Pair<KClass<*>, String>, @Composable ()
)
}
},
ColorRepresentation::class to DEFAULT to {
DisplayColorsAs::class to DEFAULT to {
listPrefEntries {
entry(
key = ColorRepresentation.HEX,
label = stringRes(R.string.enum__color_representation__hex),
key = DisplayColorsAs.HEX8,
label = stringRes(R.string.enum__display_colors_as__hex8),
description = stringRes(R.string.general__example_given).curlyFormat("example" to "#4caf50ff"),
showDescriptionOnlyIfSelected = true,
)
entry(
key = ColorRepresentation.RGB,
label = stringRes(R.string.enum__color_representation__rgb),
description = stringRes(R.string.general__example_given).curlyFormat("example" to "rgba(76, 175, 80, 1.0)"),
showDescriptionOnlyIfSelected = true,
)
entry(
key = ColorRepresentation.HSV,
label = stringRes(R.string.enum__color_representation__hsv),
description = stringRes(R.string.general__example_given).curlyFormat("example" to "hsva(122, 56, 68, 1.0)"),
key = DisplayColorsAs.RGBA,
label = stringRes(R.string.enum__display_colors_as__rgba),
description = stringRes(R.string.general__example_given).curlyFormat("example" to "rgba(76,175,80,1.0)"),
showDescriptionOnlyIfSelected = true,
)
}
@@ -366,58 +342,6 @@ private val ENUM_DISPLAY_ENTRIES = mapOf<Pair<KClass<*>, String>, @Composable ()
)
}
},
InputShiftState::class to DEFAULT to {
listPrefEntries {
entry(
key = InputShiftState.UNSHIFTED,
label = stringRes(R.string.enum__input_shift_state__unshifted),
)
entry(
key = InputShiftState.SHIFTED_MANUAL,
label = stringRes(R.string.enum__input_shift_state__shifted_manual),
)
entry(
key = InputShiftState.SHIFTED_AUTOMATIC,
label = stringRes(R.string.enum__input_shift_state__shifted_automatic),
)
entry(
key = InputShiftState.CAPS_LOCK,
label = stringRes(R.string.enum__input_shift_state__caps_lock),
)
}
},
KeyboardMode::class to DEFAULT to {
listPrefEntries {
entry(
key = KeyboardMode.CHARACTERS,
label = stringRes(R.string.enum__keyboard_mode__characters),
)
entry(
key = KeyboardMode.SYMBOLS,
label = stringRes(R.string.enum__keyboard_mode__symbols),
)
entry(
key = KeyboardMode.SYMBOLS2,
label = stringRes(R.string.enum__keyboard_mode__symbols2),
)
entry(
key = KeyboardMode.NUMERIC,
label = stringRes(R.string.enum__keyboard_mode__numeric),
)
entry(
key = KeyboardMode.NUMERIC_ADVANCED,
label = stringRes(R.string.enum__keyboard_mode__numeric_advanced),
)
entry(
key = KeyboardMode.PHONE,
label = stringRes(R.string.enum__keyboard_mode__phone),
)
entry(
key = KeyboardMode.PHONE2,
label = stringRes(R.string.enum__keyboard_mode__phone2),
)
}
},
LandscapeInputUiMode::class to DEFAULT to {
listPrefEntries {
entry(
@@ -436,6 +360,10 @@ private val ENUM_DISPLAY_ENTRIES = mapOf<Pair<KClass<*>, String>, @Composable ()
},
OneHandedMode::class to DEFAULT to {
listPrefEntries {
entry(
key = OneHandedMode.OFF,
label = stringRes(R.string.enum__one_handed_mode__off),
)
entry(
key = OneHandedMode.START,
label = stringRes(R.string.enum__one_handed_mode__start),
@@ -598,10 +526,6 @@ private val ENUM_DISPLAY_ENTRIES = mapOf<Pair<KClass<*>, String>, @Composable ()
key = SwipeAction.SHOW_INPUT_METHOD_PICKER,
label = stringRes(R.string.enum__swipe_action__show_input_method_picker),
)
entry(
key = SwipeAction.SHOW_SUBTYPE_PICKER,
label = "Show subtype picker"
)
entry(
key = SwipeAction.SWITCH_TO_PREV_SUBTYPE,
label = stringRes(R.string.enum__swipe_action__switch_to_prev_subtype),

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,17 +88,17 @@ class FlorisAppActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
prefs.other.settingsTheme.observe(this) {
prefs.advanced.settingsTheme.observe(this) {
appTheme = it
}
prefs.other.settingsLanguage.observe(this) {
prefs.advanced.settingsLanguage.observe(this) {
val config = Configuration(resources.configuration)
val locale = if (it == "auto") FlorisLocale.default() else FlorisLocale.fromTag(it)
config.setLocale(locale.base)
resourcesContext = createConfigurationContext(config)
}
if (AndroidVersion.ATMOST_API28_P) {
prefs.other.showAppIcon.observe(this) {
prefs.advanced.showAppIcon.observe(this) {
showAppIcon = it
}
}
@@ -117,7 +117,8 @@ class FlorisAppActivity : ComponentActivity() {
AppVersionUtils.updateVersionOnInstallAndLastUse(this, prefs)
setContent {
ProvideLocalizedResources(resourcesContext) {
FlorisAppTheme(theme = appTheme) {
val useMaterialYou by prefs.advanced.useMaterialYou.observeAsState()
FlorisAppTheme(theme = appTheme, isMaterialYouAware = useMaterialYou) {
Surface(color = MaterialTheme.colorScheme.background) {
AppContent()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,9 +47,8 @@ import dev.patrickgold.florisboard.app.settings.HomeScreen
import dev.patrickgold.florisboard.app.settings.about.AboutScreen
import dev.patrickgold.florisboard.app.settings.about.ProjectLicenseScreen
import dev.patrickgold.florisboard.app.settings.about.ThirdPartyLicensesScreen
import dev.patrickgold.florisboard.app.settings.advanced.AdvancedScreen
import dev.patrickgold.florisboard.app.settings.advanced.BackupScreen
import dev.patrickgold.florisboard.app.settings.advanced.OtherScreen
import dev.patrickgold.florisboard.app.settings.advanced.PhysicalKeyboardScreen
import dev.patrickgold.florisboard.app.settings.advanced.RestoreScreen
import dev.patrickgold.florisboard.app.settings.clipboard.ClipboardScreen
import dev.patrickgold.florisboard.app.settings.dictionary.DictionaryScreen
@@ -111,10 +110,9 @@ object Routes {
const val Media = "settings/media"
const val Other = "settings/other"
const val PhysicalKeyboard = "settings/other/physical-keyboard"
const val Backup = "settings/other/backup"
const val Restore = "settings/other/restore"
const val Advanced = "settings/advanced"
const val Backup = "settings/advanced/backup"
const val Restore = "settings/advanced/restore"
const val About = "settings/about"
const val ProjectLicense = "settings/about/project-license"
@@ -241,8 +239,7 @@ object Routes {
composableWithDeepLink(Settings.Media) { MediaScreen() }
composableWithDeepLink(Settings.Other) { OtherScreen() }
composableWithDeepLink(Settings.PhysicalKeyboard) { PhysicalKeyboardScreen() }
composableWithDeepLink(Settings.Advanced) { AdvancedScreen() }
composableWithDeepLink(Settings.Backup) { BackupScreen() }
composableWithDeepLink(Settings.Restore) { RestoreScreen() }

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,22 +17,19 @@
package dev.patrickgold.florisboard.app.apptheme
import android.app.Activity
import android.content.Context
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.ColorScheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import dev.patrickgold.florisboard.app.AppTheme
import dev.patrickgold.florisboard.app.florisPreferenceModel
import dev.patrickgold.jetpref.datastore.model.observeAsState
import org.florisboard.lib.android.AndroidVersion
import org.florisboard.lib.color.ColorMappings
/*private val AmoledDarkColorPalette = darkColorScheme(
primary = Green500,
@@ -73,66 +70,170 @@ private val LightColorPalette = lightColorScheme(
*/
)*/
private val lightScheme = lightColorScheme(
primary = primaryLight,
onPrimary = onPrimaryLight,
primaryContainer = primaryContainerLight,
onPrimaryContainer = onPrimaryContainerLight,
secondary = secondaryLight,
onSecondary = onSecondaryLight,
secondaryContainer = secondaryContainerLight,
onSecondaryContainer = onSecondaryContainerLight,
tertiary = tertiaryLight,
onTertiary = onTertiaryLight,
tertiaryContainer = tertiaryContainerLight,
onTertiaryContainer = onTertiaryContainerLight,
error = errorLight,
onError = onErrorLight,
errorContainer = errorContainerLight,
onErrorContainer = onErrorContainerLight,
background = backgroundLight,
onBackground = onBackgroundLight,
surface = surfaceLight,
onSurface = onSurfaceLight,
surfaceVariant = surfaceVariantLight,
onSurfaceVariant = onSurfaceVariantLight,
outline = outlineLight,
outlineVariant = outlineVariantLight,
scrim = scrimLight,
inverseSurface = inverseSurfaceLight,
inverseOnSurface = inverseOnSurfaceLight,
inversePrimary = inversePrimaryLight,
surfaceDim = surfaceDimLight,
surfaceBright = surfaceBrightLight,
surfaceContainerLowest = surfaceContainerLowestLight,
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
)
@Composable
fun getColorScheme(
context: Context,
theme: AppTheme,
): ColorScheme {
val prefs by florisPreferenceModel()
val accentColor by prefs.other.accentColor.observeAsState()
val isDark = isSystemInDarkTheme()
private val darkScheme = darkColorScheme(
primary = primaryDark,
onPrimary = onPrimaryDark,
primaryContainer = primaryContainerDark,
onPrimaryContainer = onPrimaryContainerDark,
secondary = secondaryDark,
onSecondary = onSecondaryDark,
secondaryContainer = secondaryContainerDark,
onSecondaryContainer = onSecondaryContainerDark,
tertiary = tertiaryDark,
onTertiary = onTertiaryDark,
tertiaryContainer = tertiaryContainerDark,
onTertiaryContainer = onTertiaryContainerDark,
error = errorDark,
onError = onErrorDark,
errorContainer = errorContainerDark,
onErrorContainer = onErrorContainerDark,
background = backgroundDark,
onBackground = onBackgroundDark,
surface = surfaceDark,
onSurface = onSurfaceDark,
surfaceVariant = surfaceVariantDark,
onSurfaceVariant = onSurfaceVariantDark,
outline = outlineDark,
outlineVariant = outlineVariantDark,
scrim = scrimDark,
inverseSurface = inverseSurfaceDark,
inverseOnSurface = inverseOnSurfaceDark,
inversePrimary = inversePrimaryDark,
surfaceDim = surfaceDimDark,
surfaceBright = surfaceBrightDark,
surfaceContainerLowest = surfaceContainerLowestDark,
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
)
return when (theme) {
AppTheme.AUTO -> {
if (isDark) {
ColorMappings.dynamicDarkColorScheme(context, accentColor)
} else {
ColorMappings.dynamicLightColorScheme(context, accentColor)
}
}
AppTheme.DARK -> {
ColorMappings.dynamicDarkColorScheme(context, accentColor)
}
AppTheme.LIGHT -> {
ColorMappings.dynamicLightColorScheme(context, accentColor)
}
AppTheme.AMOLED_DARK -> {
ColorMappings.dynamicDarkColorScheme(context, accentColor).amoled()
}
AppTheme.AUTO_AMOLED -> {
if (isDark) {
ColorMappings.dynamicDarkColorScheme(context, accentColor).amoled()
} else {
ColorMappings.dynamicLightColorScheme(context, accentColor)
}
}
}
}
fun ColorScheme.amoled(): ColorScheme {
return this.copy(background = Color.Black, surface = Color.Black)
}
private val amoledScheme = darkScheme.copy(
background = amoledDark,
surface = amoledDark
)
@Composable
fun FlorisAppTheme(
theme: AppTheme,
content: @Composable () -> Unit,
isMaterialYouAware: Boolean,
content: @Composable () -> Unit
) {
val colors = getColorScheme(
context = LocalContext.current,
theme = theme,
)
val colors = if (AndroidVersion.ATLEAST_API31_S) {
when (theme) {
AppTheme.AUTO -> when {
isMaterialYouAware -> when {
isSystemInDarkTheme() -> dynamicDarkColorScheme(LocalContext.current)
else -> dynamicLightColorScheme(LocalContext.current)
}
else -> {
when {
isSystemInDarkTheme() -> darkScheme
else -> lightScheme
}
}
}
AppTheme.AUTO_AMOLED -> when {
isMaterialYouAware -> when {
isSystemInDarkTheme() -> dynamicDarkColorScheme(LocalContext.current).copy(
background = amoledDark,
surface = amoledDark,
)
else -> dynamicLightColorScheme(LocalContext.current)
}
else -> {
when {
isSystemInDarkTheme() -> amoledScheme
else -> lightScheme
}
}
}
AppTheme.LIGHT -> when {
isMaterialYouAware -> dynamicLightColorScheme(LocalContext.current)
else -> lightScheme
}
AppTheme.DARK -> when {
isMaterialYouAware -> dynamicDarkColorScheme(LocalContext.current)
else -> darkScheme
}
AppTheme.AMOLED_DARK -> when {
isMaterialYouAware -> dynamicDarkColorScheme(LocalContext.current).copy(
background = amoledDark,
surface = amoledDark,
)
else -> amoledScheme
}
}
} else {
when (theme) {
AppTheme.AUTO -> when {
isSystemInDarkTheme() -> darkScheme
else -> lightScheme
}
AppTheme.AUTO_AMOLED -> when {
isSystemInDarkTheme() -> darkScheme
else -> lightScheme
}
AppTheme.LIGHT -> lightScheme
AppTheme.DARK -> darkScheme
AppTheme.AMOLED_DARK -> amoledScheme
}
}
val darkTheme =
theme == AppTheme.DARK
|| theme == AppTheme.AMOLED_DARK
|| (theme == AppTheme.AUTO && isSystemInDarkTheme())
|| (theme == AppTheme.AUTO_AMOLED && isSystemInDarkTheme())
|| theme == AppTheme.AMOLED_DARK
|| (theme == AppTheme.AUTO && isSystemInDarkTheme())
|| (theme == AppTheme.AUTO_AMOLED && isSystemInDarkTheme())
val view = LocalView.current
if (!view.isInEditMode) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -43,18 +42,12 @@ import androidx.compose.ui.unit.sp
import dev.patrickgold.florisboard.app.florisPreferenceModel
import dev.patrickgold.florisboard.clipboardManager
import dev.patrickgold.florisboard.editorInstance
import dev.patrickgold.florisboard.ime.keyboard.CachedLayout
import dev.patrickgold.florisboard.ime.keyboard.DebugLayoutComputationResult
import dev.patrickgold.florisboard.ime.nlp.NlpInlineAutofill
import dev.patrickgold.florisboard.ime.theme.ThemeManager
import dev.patrickgold.florisboard.keyboardManager
import dev.patrickgold.florisboard.lib.FlorisLocale
import dev.patrickgold.florisboard.lib.observeAsNonNullState
import dev.patrickgold.florisboard.nlpManager
import dev.patrickgold.florisboard.themeManager
import dev.patrickgold.jetpref.datastore.model.observeAsState
import org.florisboard.lib.android.AndroidVersion
import org.florisboard.lib.snygg.SnyggMissingSchemaException
import java.text.SimpleDateFormat
import java.util.*
@@ -63,44 +56,30 @@ private val DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH-mm-ss", FlorisLocale.
@Composable
fun DevtoolsOverlay(modifier: Modifier = Modifier) {
val context = LocalContext.current
val prefs by florisPreferenceModel()
val keyboardManager by context.keyboardManager()
val themeManager by context.themeManager()
val devtoolsEnabled by prefs.devtools.enabled.observeAsState()
val showPrimaryClip by prefs.devtools.showPrimaryClip.observeAsState()
val showInputStateOverlay by prefs.devtools.showInputStateOverlay.observeAsState()
val showSpellingOverlay by prefs.devtools.showSpellingOverlay.observeAsState()
val showInlineAutofillOverlay by prefs.devtools.showInlineAutofillOverlay.observeAsState()
val debugLayoutResult by keyboardManager.layoutManager.debugLayoutComputationResultFlow.collectAsState()
val themeInfo by themeManager.activeThemeInfo.observeAsState()
CompositionLocalProvider(
LocalContentColor provides Color.White,
LocalLayoutDirection provides LayoutDirection.Ltr,
) {
Column(modifier = modifier) {
if (devtoolsEnabled && showPrimaryClip) {
if (showPrimaryClip) {
DevtoolsClipboardOverlay()
}
if (devtoolsEnabled && showInputStateOverlay) {
if (showInputStateOverlay) {
DevtoolsInputStateOverlay()
}
if (debugLayoutResult?.allLayoutsSuccess() == false) {
DevtoolsLastLayoutComputationOverlay(debugLayoutResult)
}
if (devtoolsEnabled && showSpellingOverlay) {
if (showSpellingOverlay) {
DevtoolsSpellingOverlay()
}
if (devtoolsEnabled && showInlineAutofillOverlay && AndroidVersion.ATLEAST_API30_R) {
if (showInlineAutofillOverlay && AndroidVersion.ATLEAST_API30_R) {
DevtoolsInlineAutofillOverlay()
}
val loadFailure = themeInfo?.loadFailure
if (loadFailure != null) {
DevtoolsStylesheetFailedToLoadOverlay(loadFailure)
}
}
}
}
@@ -146,34 +125,6 @@ private fun DevtoolsInputStateOverlay() {
}
}
@Composable
private fun DevtoolsLastLayoutComputationOverlay(debugLayoutResult: DebugLayoutComputationResult?) {
@Composable
fun PrintResult(result: Result<CachedLayout?>) {
if (result.isSuccess) {
DevtoolsText(text = "loaded: ${result.getOrNull()?.name}")
} else {
DevtoolsText(text = "error: ${result.exceptionOrNull()}")
}
}
DevtoolsOverlayBox(title = "Last layout computation") {
if (debugLayoutResult == null) {
DevtoolsText(text = "No layout computation result available.")
return@DevtoolsOverlayBox
}
DevtoolsSubGroup(title = "main") {
PrintResult(debugLayoutResult!!.main)
}
DevtoolsSubGroup(title = "mod") {
PrintResult(debugLayoutResult!!.mod)
}
DevtoolsSubGroup(title = "ext") {
PrintResult(debugLayoutResult!!.ext)
}
}
}
@Composable
private fun DevtoolsSpellingOverlay() {
val context = LocalContext.current
@@ -235,39 +186,6 @@ private fun DevtoolsInlineAutofillOverlay() {
}
}
@Composable
private fun DevtoolsStylesheetFailedToLoadOverlay(loadFailure: ThemeManager.LoadFailure) {
DevtoolsOverlayBox(title = "Failed to load stylesheet, fell back to base style") {
DevtoolsSubGroup(title = "Extension") {
DevtoolsText(text = "id: ${loadFailure.extension.id}")
DevtoolsText(text = "title: ${loadFailure.extension.title}")
DevtoolsText(text = "version: ${loadFailure.extension.version}")
}
DevtoolsSubGroup(title = "Component") {
DevtoolsText(text = "id: ${loadFailure.component.id}")
DevtoolsText(text = "label: ${loadFailure.component.label}")
DevtoolsText(text = "path: ${loadFailure.component.stylesheetPath()}")
}
val cause = loadFailure.cause
DevtoolsSubGroup(title = "Cause") {
DevtoolsText(text = "${cause.message}")
}
if (cause is SnyggMissingSchemaException) {
DevtoolsSubGroup(title = "Explanation") {
DevtoolsText(
text = """
It appears youre trying to load a theme designed for FlorisBoard v0.4 (Snygg v1), which isnt compatible with the latest release using Snygg v2.
If you are the theme author, please update your theme to support Snygg v2.
If youre a user, please update your theme via the Addons Store. If an updated version isnt available yet, please select one of the built-in themes during this transition period.
""".trimIndent()
)
}
}
}
}
@Composable
private fun DevtoolsOverlayBox(
title: String,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,8 +27,6 @@ import dev.patrickgold.florisboard.app.Routes
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
@@ -63,6 +61,12 @@ fun DevtoolsScreen() = FlorisScreen {
)
PreferenceGroup(title = stringRes(R.string.devtools__title)) {
SwitchPreference(
prefs.devtools.showHeapMemoryStats,
title = stringRes(R.string.devtools__show_heap_memory_stats__label),
summary = stringRes(R.string.devtools__show_heap_memory_stats__summary),
enabledIf = { prefs.devtools.enabled isEqualTo true },
)
SwitchPreference(
prefs.devtools.showPrimaryClip,
title = stringRes(R.string.devtools__show_primary_clip__label),
@@ -106,15 +110,6 @@ fun DevtoolsScreen() = FlorisScreen {
onClick = { setShowDialog(true) },
enabledIf = { prefs.devtools.enabled isEqualTo true },
)
Preference(
title = stringRes(R.string.devtools__reset_quick_actions_to_default__label),
summary = stringRes(R.string.devtools__reset_quick_actions_to_default__summary),
onClick = {
prefs.smartbar.actionArrangement.set(QuickActionArrangement.Default)
context.showLongToast(R.string.devtools__reset_quick_actions_to_default__toast_success)
},
enabledIf = { prefs.devtools.enabled isEqualTo true },
)
Preference(
title = stringRes(R.string.devtools__reset_flag__label, "flag_name" to "isImeSetUp"),
summary = stringRes(R.string.devtools__reset_flag_is_ime_set_up__summary),
@@ -133,13 +128,6 @@ fun DevtoolsScreen() = FlorisScreen {
onClick = { navController.navigate(Routes.Devtools.ExportDebugLog) },
enabledIf = { prefs.devtools.enabled isEqualTo true },
)
SwitchPreference(
prefs.glide.enabled,
title = "prefs.glide.enabled (debug)",
summaryOn = "This impacts your performance and may trigger the all keys invisible bug!",
summaryOff = "Recommended to keep this off!",
enabledIf = { prefs.devtools.enabled isEqualTo true },
)
}
PreferenceGroup(title = stringRes(R.string.devtools__group_android__title)) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2025 The FlorisBoard Contributors
* Copyright (C) 2022 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,19 +1,3 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.ext
import androidx.compose.foundation.layout.Row
@@ -21,7 +5,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Input
import androidx.compose.material.icons.filled.Shop
import androidx.compose.material.icons.outlined.FileDownload
import androidx.compose.material3.MaterialTheme
@@ -30,8 +13,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import dev.patrickgold.florisboard.BuildConfig
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes
@@ -44,41 +25,6 @@ import dev.patrickgold.florisboard.lib.ext.generateUpdateUrl
import dev.patrickgold.florisboard.lib.util.launchUrl
import org.florisboard.lib.kotlin.curlyFormat
@Composable
fun ImportExtensionBox(navController: NavController) {
val context = LocalContext.current
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
) {
Text(
modifier = Modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 4.dp),
text = stringRes(id = R.string.ext__home__info),
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
FlorisTextButton(
onClick = {
context.launchUrl("https://${BuildConfig.FLADDONS_STORE_URL}/")
},
icon = Icons.Default.Shop,
text = stringRes(id = R.string.ext__home__visit_store),
)
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Import(ExtensionImportScreenType.EXT_ANY, null))
},
icon = Icons.AutoMirrored.Filled.Input,
text = stringRes(R.string.action__import),
)
}
}
}
@Composable
fun UpdateBox(extensionIndex: List<Extension>) {
val context = LocalContext.current

View File

@@ -1,19 +1,3 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.ext
import androidx.compose.runtime.Composable

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2025 The FlorisBoard Contributors
* Copyright (C) 2022 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,11 +81,14 @@ fun ExtensionComponentView(
when (component) {
is ThemeExtensionComponent -> {
val text = remember(
component.authors, component.isNightTheme, component.stylesheetPath(),
component.authors, component.isNightTheme, component.isBorderless,
component.isMaterialYouAware, component.stylesheetPath(),
) {
buildString {
appendLine("authors = ${component.authors}")
appendLine("isNightTheme = ${component.isNightTheme}")
appendLine("isBorderless = ${component.isBorderless}")
appendLine("isMaterialYouAware = ${component.isMaterialYouAware}")
append("stylesheetPath = ${component.stylesheetPath()}")
}
}

View File

@@ -1,290 +0,0 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.ext
import android.provider.OpenableColumns
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Photo
import androidx.compose.material.icons.filled.TextFields
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
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.text.font.FontWeight
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
import java.io.File
import java.util.*
import org.florisboard.lib.android.query
import org.florisboard.lib.android.readToFile
import org.florisboard.lib.android.showLongToast
import org.florisboard.lib.android.showShortToast
import org.florisboard.lib.kotlin.io.parentDir
import org.florisboard.lib.kotlin.io.subDir
import org.florisboard.lib.kotlin.io.subFile
import org.florisboard.lib.kotlin.mimeTypeFilterOf
const val FONTS = "fonts"
const val IMAGES = "images"
val MIME_TYPES = mapOf(
FONTS to mimeTypeFilterOf(
// Source: https://www.alienfactory.co.uk/articles/mime-types-for-web-fonts-in-bedsheet#mimeTypes
"font/*",
"application/font-*",
"application/x-font-*",
"application/vnd.ms-fontobject",
),
IMAGES to mimeTypeFilterOf(
"image/*",
),
)
@Composable
fun ExtensionEditFilesScreen(workspace: CacheManager.ExtEditorWorkspace<*>) = FlorisScreen {
title = stringRes(R.string.ext__editor__files__title)
fun handleBackPress() {
workspace.currentAction = null
}
navigationIcon {
FlorisIconButton(
onClick = { handleBackPress() },
icon = Icons.Default.Close,
)
}
content {
val context = LocalContext.current
var version by rememberSaveable { mutableIntStateOf(0) }
val fontFiles = remember(version) {
workspace.extDir.subDir(FONTS).listFiles { it.isFile }.orEmpty().asList()
}
val imageFiles = remember(version) {
workspace.extDir.subDir(IMAGES).listFiles { it.isFile }.orEmpty().asList()
}
var currentImportDest by remember { mutableStateOf<String?>(null) }
var currentImportResult by remember { mutableStateOf<Result<Pair<File, String>>?>(null) }
val importLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetContent(),
onResult = { uri ->
currentImportResult = runCatching {
checkNotNull(uri) { "" }
val tempFile = context.cacheDir.subFile("temp_${UUID.randomUUID()}")
context.contentResolver.readToFile(uri, tempFile)
val mimeType = context.contentResolver.getType(uri)
val filter = MIME_TYPES[currentImportDest!!]!!
check(filter.matches(mimeType)) {
"Given file mime type was '$mimeType', expected one of ${filter.types}"
}
val fileName = context.contentResolver.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME)).use { cursor ->
if (cursor == null || !cursor.moveToFirst()) return@use null
val name = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.getString(name)
}
tempFile to fileName.orEmpty()
}
},
)
LaunchedEffect(currentImportResult) {
val message = currentImportResult?.exceptionOrNull()?.message
if (!message.isNullOrBlank()) {
context.showLongToast(message)
}
}
BackHandler {
handleBackPress()
}
@Composable
fun FileList(title: String, icon: ImageVector, files: List<File>, onAdd: () -> Unit) {
var dialogFile by remember { mutableStateOf<File?>(null) }
ListItem(
headlineContent = {
Text(
text = title,
color = MaterialTheme.colorScheme.secondary,
fontWeight = FontWeight.Bold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
leadingContent = {
Spacer(modifier = Modifier.width(24.dp))
},
trailingContent = {
IconButton(
onClick = onAdd,
) {
Icon(Icons.Default.Add, null)
}
},
)
for (file in files) {
Preference(
onClick = {
dialogFile = file
},
icon = icon,
title = file.name,
)
}
dialogFile?.let { file ->
var fileNameInput by rememberSaveable { mutableStateOf(file.name) }
JetPrefAlertDialog(
title = stringRes(R.string.general__properties),
confirmLabel = stringRes(R.string.action__apply),
dismissLabel = stringRes(R.string.action__cancel),
neutralLabel = stringRes(R.string.action__delete),
allowOutsideDismissal = true,
onNeutral = {
if (file.delete()) {
context.showShortToast("Successfully deleted")
} else {
context.showShortToast("Failed to delete")
}
dialogFile = null
version++
},
onConfirm = {
val newFile = file.parentFile!!.subFile(fileNameInput).canonicalFile
if (newFile.parentFile != file.canonicalFile.parentFile) {
context.showLongToast("Invalid file name!")
return@JetPrefAlertDialog
}
if (newFile.exists()) {
context.showShortToast("Filename already exists.")
return@JetPrefAlertDialog
}
val success = file.renameTo(newFile)
if (success) {
context.showShortToast("Successfully renamed")
} else {
context.showShortToast("Failed to rename the file.")
}
dialogFile = null
version++
},
onDismiss = {
dialogFile = null
},
) {
JetPrefTextField(
labelText = stringRes(R.string.general__file_name),
value = fileNameInput,
onValueChange = { fileNameInput = it },
singleLine = true,
)
}
}
}
FileList(
title = stringRes(R.string.ext__editor__files__type_fonts),
icon = Icons.Default.TextFields,
files = fontFiles,
) {
currentImportDest = FONTS
importLauncher.launch("*/*")
}
FileList(
title = stringRes(R.string.ext__editor__files__type_images),
icon = Icons.Default.Photo,
files = imageFiles,
) {
currentImportDest = IMAGES
importLauncher.launch("*/*")
}
val dest = currentImportDest
val result = currentImportResult?.getOrNull()
if (dest != null && result != null) {
var fileNameInput by rememberSaveable { mutableStateOf(result.second) }
JetPrefAlertDialog(
title = stringRes(R.string.action__import_file),
confirmLabel = stringRes(R.string.action__add),
onConfirm = {
val fileName = fileNameInput.trim()
val dir = workspace.extDir.subDir(dest)
dir.mkdirs()
val file = dir.subFile(fileName)
if (file.parentDir != workspace.extDir.subDir(dest)) {
context.showShortToast("Invalid file name")
} else if (file.exists()) {
context.showShortToast("File already exists")
} else {
val tempFile = result.first
if (!tempFile.renameTo(file)) {
context.showShortToast("Failed to rename file")
tempFile.delete()
}
currentImportDest = null
currentImportResult = null
version++
}
},
dismissLabel = stringRes(R.string.action__cancel),
onDismiss = {
val tempFile = result.first
tempFile.delete()
currentImportDest = null
currentImportResult = null
},
) {
JetPrefTextField(
value = fileNameInput,
onValueChange = { fileNameInput = it },
singleLine = true,
)
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import androidx.compose.material.icons.automirrored.outlined.LibraryBooks
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Code
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -48,7 +49,6 @@ import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.settings.advanced.RadioListItem
import dev.patrickgold.florisboard.app.settings.theme.DialogProperty
import dev.patrickgold.florisboard.app.settings.theme.PrettyPrintConfig
import dev.patrickgold.florisboard.app.settings.theme.ThemeEditorScreen
import dev.patrickgold.florisboard.cacheManager
import dev.patrickgold.florisboard.extensionManager
@@ -64,9 +64,9 @@ 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.FlorisOutlinedTextField
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
@@ -83,17 +83,15 @@ import dev.patrickgold.florisboard.lib.ext.validate
import dev.patrickgold.florisboard.lib.io.FlorisRef
import dev.patrickgold.florisboard.lib.io.ZipUtils
import dev.patrickgold.florisboard.lib.rememberValidationResult
import org.florisboard.lib.snygg.SnyggStylesheetJsonConfig
import dev.patrickgold.florisboard.themeManager
import dev.patrickgold.jetpref.datastore.ui.Preference
import dev.patrickgold.jetpref.datastore.ui.vectorResource
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
import dev.patrickgold.jetpref.material.ui.JetPrefTextField
import java.util.*
import org.florisboard.lib.android.showLongToast
import org.florisboard.lib.kotlin.io.deleteContentsRecursively
import org.florisboard.lib.kotlin.io.subDir
import org.florisboard.lib.kotlin.io.subFile
import org.florisboard.lib.kotlin.io.writeJson
import java.util.UUID
import kotlin.reflect.KClass
private val TextFieldVerticalPadding = 8.dp
@@ -199,7 +197,7 @@ private fun ExtensionEditScreenSheetSwitcher(
ManageDependenciesScreen(workspace)
}
is EditorAction.ManageFiles -> {
ExtensionEditFilesScreen(workspace)
ManageFilesScreen(workspace)
}
is EditorAction.CreateComponent<*> -> {
CreateComponentScreen(workspace, action.type)
@@ -263,33 +261,17 @@ private fun EditScreen(
return
}
val manifest = extEditor.build()
workspace.saverDir.deleteContentsRecursively()
val manifestFile = workspace.saverDir.subFile(ExtensionDefaults.MANIFEST_FILE_NAME)
manifestFile.writeJson(manifest, ExtensionJsonConfig)
when (extEditor) {
is ThemeExtensionEditor -> {
// TODO: this is hacky
val fonts = workspace.extDir.subDir("fonts")
if (fonts.exists()) {
fonts.copyRecursively(workspace.saverDir.subDir("fonts"), overwrite = true)
}
val images = workspace.extDir.subDir("images")
if (images.exists()) {
images.copyRecursively(workspace.saverDir.subDir("images"), overwrite = true)
}
for (theme in extEditor.themes) {
val stylesheetFile = workspace.saverDir.subFile(theme.stylesheetPath())
stylesheetFile.parentFile?.mkdirs()
val stylesheetEditor = theme.stylesheetEditor
if (stylesheetEditor != null) {
runCatching {
val stylesheet = stylesheetEditor.build().toJson(PrettyPrintConfig).getOrThrow()
stylesheetFile.writeText(stylesheet)
}.onFailure {
// TODO: better error handling
context.showLongToast(it.message.toString())
return
}
val stylesheet = stylesheetEditor.build()
stylesheetFile.writeJson(stylesheet, SnyggStylesheetJsonConfig)
} else {
val unmodifiedStylesheetFile = workspace.extDir.subFile(theme.stylesheetPath())
if (unmodifiedStylesheetFile.exists()) {
@@ -600,6 +582,35 @@ private fun ManageDependenciesScreen(workspace: CacheManager.ExtEditorWorkspace<
}
}
@Composable
private fun ManageFilesScreen(workspace: CacheManager.ExtEditorWorkspace<*>) = FlorisScreen {
title = stringRes(R.string.ext__editor__files__title)
fun handleBackPress() {
workspace.currentAction = null
}
navigationIcon {
FlorisIconButton(
onClick = { handleBackPress() },
icon = Icons.Default.Close,
)
}
content {
BackHandler {
handleBackPress()
}
FlorisInfoCard(
modifier = Modifier.padding(all = 8.dp),
text = """
Managing archive files is currently not supported.
""".trimIndent().replace('\n', ' '),
)
}
}
private enum class CreateFrom {
EMPTY,
EXISTING;
@@ -692,14 +703,15 @@ private fun <T : ExtensionComponent> CreateComponentScreen(
val component = editor.themes.find { it.id == componentName.componentId } ?: return
val componentEditor = component.let { c ->
ThemeExtensionComponentEditor(
componentId, c.label, c.authors, c.isNightTheme, stylesheetPath = "",
componentId, c.label, c.authors, c.isNightTheme, c.isBorderless,
c.isMaterialYouAware, stylesheetPath = "",
).also { it.stylesheetEditor = c.stylesheetEditor }
}
if (componentEditor.stylesheetEditor != null) {
val stylesheet = componentEditor.stylesheetEditor!!.build()
val stylesheetFile = workspace.extDir.subFile(componentEditor.stylesheetPath())
stylesheetFile.parentFile?.mkdirs()
val stylesheet = componentEditor.stylesheetEditor!!.build().toJson(PrettyPrintConfig).getOrThrow()
stylesheetFile.writeText(stylesheet)
stylesheetFile.writeJson(stylesheet, SnyggStylesheetJsonConfig)
componentEditor.stylesheetEditor = null
} else {
val srcStylesheetFile = workspace.extDir.subFile(component.stylesheetPath())
@@ -801,37 +813,36 @@ private fun <T : ExtensionComponent> CreateComponentScreen(
modifier = Modifier.padding(horizontal = 16.dp),
text = stringRes(R.string.ext__meta__id),
) {
JetPrefTextField(
modifier = Modifier.fillMaxWidth(),
FlorisOutlinedTextField(
value = newId,
onValueChange = { newId = it },
singleLine = true,
showValidationError = showValidationErrors,
validationResult = newIdValidation,
)
Validation(showValidationErrors, newIdValidation)
}
DialogProperty(
modifier = Modifier.padding(horizontal = 16.dp),
text = stringRes(R.string.ext__meta__label),
) {
JetPrefTextField(
modifier = Modifier.fillMaxWidth(),
FlorisOutlinedTextField(
value = newLabel,
onValueChange = { newLabel = it },
singleLine = true,
showValidationError = showValidationErrors,
validationResult = newLabelValidation,
)
Validation(showValidationErrors, newLabelValidation)
}
DialogProperty(
modifier = Modifier.padding(horizontal = 16.dp),
text = stringRes(R.string.ext__meta__authors),
) {
JetPrefTextField(
modifier = Modifier.fillMaxWidth(),
FlorisOutlinedTextField(
value = newAuthors,
onValueChange = { newAuthors = it },
showValidationError = showValidationErrors,
validationResult = newAuthorsValidation,
)
Validation(showValidationErrors, newAuthorsValidation)
}
}
}
@@ -849,6 +860,7 @@ private fun EditorSheetTextField(
showValidationError: Boolean = false,
validationResult: ValidationResult? = null,
) {
val borderColor = MaterialTheme.colorScheme.outline
Column(modifier = Modifier.padding(vertical = TextFieldVerticalPadding)) {
Row(
modifier = Modifier
@@ -868,13 +880,18 @@ private fun EditorSheetTextField(
)
}
}
JetPrefTextField(
FlorisOutlinedTextField(
modifier = modifier.fillMaxWidth(),
enabled = enabled,
value = value,
onValueChange = onValueChange,
singleLine = singleLine,
showValidationError = showValidationError,
validationResult = validationResult,
colors = OutlinedTextFieldDefaults.colors(
unfocusedBorderColor = borderColor,
disabledBorderColor = borderColor,
)
)
Validation(showValidationError, validationResult)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,33 +1,32 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.ext
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Input
import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Language
import androidx.compose.material.icons.filled.Palette
import androidx.compose.material.icons.filled.Shop
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import dev.patrickgold.florisboard.BuildConfig
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.extensionManager
import dev.patrickgold.florisboard.lib.compose.FlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
import dev.patrickgold.florisboard.lib.compose.FlorisTextButton
import dev.patrickgold.florisboard.lib.compose.defaultFlorisOutlinedBox
import dev.patrickgold.florisboard.lib.compose.stringRes
import dev.patrickgold.florisboard.lib.util.launchUrl
import dev.patrickgold.jetpref.datastore.ui.Preference
@Composable
@@ -41,7 +40,36 @@ fun ExtensionHomeScreen() = FlorisScreen {
val extensionIndex = extensionManager.combinedExtensionList()
content {
ImportExtensionBox(navController)
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
) {
Text(
modifier = Modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 4.dp),
text = stringRes(id = R.string.ext__home__info),
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
FlorisTextButton(
onClick = {
context.launchUrl("https://${BuildConfig.FLADDONS_STORE_URL}/")
},
icon = Icons.Default.Shop,
text = stringRes(id = R.string.ext__home__visit_store),
)
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Import(ExtensionImportScreenType.EXT_ANY, null))
},
icon = Icons.AutoMirrored.Filled.Input,
text = stringRes(R.string.action__import),
)
}
}
UpdateBox(extensionIndex = extensionIndex)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024-2025 The FlorisBoard Contributors
* Copyright (C) 2024 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,15 +17,10 @@
package dev.patrickgold.florisboard.app.ext
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Edit
@@ -38,13 +33,8 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import dev.patrickgold.florisboard.R
@@ -56,7 +46,6 @@ 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
@@ -91,69 +80,49 @@ enum class ExtensionListScreenType(
fun ExtensionListScreen(type: ExtensionListScreenType, showUpdate: Boolean) = FlorisScreen {
title = stringRes(type.titleResId)
previewFieldVisible = false
scrollable = false
val context = LocalContext.current
val navController = LocalNavController.current
val extensionManager by context.extensionManager()
val extensionIndex by type.getExtensionIndex(extensionManager).observeAsNonNullState()
var fabHeight by remember {
mutableStateOf(0)
}
val fabHeightDp = with(LocalDensity.current) { fabHeight.toDp()+16.dp }
val listState = rememberLazyListState()
content {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.florisScrollbar(state = listState, isVertical = true),
state = listState,
contentPadding = PaddingValues(bottom = fabHeightDp),
) {
if (showUpdate) {
item {
ImportExtensionBox(navController)
}
item {
UpdateBox(extensionIndex = extensionIndex)
}
}
items(extensionIndex) { ext ->
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
title = ext.meta.title,
subtitle = ext.meta.id,
if (showUpdate) {
UpdateBox(extensionIndex = extensionIndex)
}
for (ext in extensionIndex) {
FlorisOutlinedBox(
modifier = Modifier.defaultFlorisOutlinedBox(),
title = ext.meta.title,
subtitle = ext.meta.id,
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
text = ext.meta.description ?: "",
style = MaterialTheme.typography.bodySmall,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
text = ext.meta.description ?: "",
style = MaterialTheme.typography.bodySmall,
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.View(ext.meta.id))
},
icon = Icons.Outlined.Info,
text = stringRes(id = R.string.ext__list__view_details),//stringRes(R.string.action__add),
colors = ButtonDefaults.textButtonColors(),
)
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Edit(ext.meta.id))
},
icon = Icons.Default.Edit,
text = stringRes(R.string.action__edit),
enabled = extensionManager.canDelete(ext),
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 6.dp),
) {
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.View(ext.meta.id))
},
icon = Icons.Outlined.Info,
text = stringRes(id = R.string.ext__list__view_details),//stringRes(R.string.action__add),
colors = ButtonDefaults.textButtonColors(),
)
Spacer(modifier = Modifier.weight(1f))
FlorisTextButton(
onClick = {
navController.navigate(Routes.Ext.Edit(ext.meta.id))
},
icon = Icons.Default.Edit,
text = stringRes(R.string.action__edit),
enabled = extensionManager.canDelete(ext),
)
}
}
}
}
@@ -173,9 +142,6 @@ fun ExtensionListScreen(type: ExtensionListScreenType, showUpdate: Boolean) = Fl
text = stringRes(id = R.string.ext__editor__title_create_any),
)
},
modifier = Modifier.onGloballyPositioned {
fabHeight = it.size.height
},
shape = FloatingActionButtonDefaults.extendedFabShape,
onClick = { type.launchExtensionCreate.invoke(navController) },
)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -152,8 +152,8 @@ fun HomeScreen() = FlorisScreen {
)
Preference(
icon = Icons.Outlined.Build,
title = stringRes(R.string.settings__other__title),
onClick = { navController.navigate(Routes.Settings.Other) },
title = stringRes(R.string.settings__advanced__title),
onClick = { navController.navigate(Routes.Settings.Advanced) },
)
Preference(
icon = Icons.Outlined.Info,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,9 +21,8 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults
import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
import com.mikepenz.aboutlibraries.ui.compose.m3.libraryColors
import com.mikepenz.aboutlibraries.ui.compose.m3.LibraryDefaults
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
import dev.patrickgold.florisboard.lib.compose.florisScrollbar

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,72 +19,58 @@ package dev.patrickgold.florisboard.app.settings.advanced
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Adb
import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.filled.FormatColorFill
import androidx.compose.material.icons.filled.FormatPaint
import androidx.compose.material.icons.filled.Language
import androidx.compose.material.icons.filled.Palette
import androidx.compose.material.icons.filled.Preview
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.platform.LocalContext
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.AppTheme
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
import dev.patrickgold.florisboard.ime.keyboard.IncognitoMode
import dev.patrickgold.florisboard.lib.FlorisLocale
import org.florisboard.lib.android.AndroidVersion
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
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.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
@Composable
fun OtherScreen() = FlorisScreen {
title = stringRes(R.string.settings__other__title)
fun AdvancedScreen() = FlorisScreen {
title = stringRes(R.string.settings__advanced__title)
previewFieldVisible = false
val navController = LocalNavController.current
val context = LocalContext.current
content {
ListPreference(
prefs.other.settingsTheme,
prefs.advanced.settingsTheme,
icon = Icons.Default.Palette,
title = stringRes(R.string.pref__other__settings_theme__label),
title = stringRes(R.string.pref__advanced__settings_theme__label),
entries = enumDisplayEntriesOf(AppTheme::class),
)
ColorPickerPreference(
pref = prefs.other.accentColor,
title = stringRes(R.string.pref__other__settings_accent_color__label),
defaultValueLabel = stringRes(R.string.action__default),
icon = Icons.Default.FormatColorFill,
defaultColors = ColorMappings.colors,
showAlphaSlider = false,
enableAdvancedLayout = false,
colorOverride = {
if (it.isMaterialYou(context)) {
Color.Unspecified
} else {
it
}
}
SwitchPreference(
pref = prefs.advanced.useMaterialYou,
icon = Icons.Default.FormatPaint,
title = stringRes(R.string.pref__advanced__settings_material_you__label),
visibleIf = {
AndroidVersion.ATLEAST_API31_S
},
)
ListPreference(
prefs.other.settingsLanguage,
prefs.advanced.settingsLanguage,
icon = Icons.Default.Language,
title = stringRes(R.string.pref__other__settings_language__label),
title = stringRes(R.string.pref__advanced__settings_language__label),
entries = listPrefEntries {
listOf(
"auto",
@@ -146,19 +132,20 @@ fun OtherScreen() = FlorisScreen {
}
)
SwitchPreference(
prefs.other.showAppIcon,
prefs.advanced.showAppIcon,
icon = Icons.Default.Preview,
title = stringRes(R.string.pref__other__show_app_icon__label),
title = stringRes(R.string.pref__advanced__show_app_icon__label),
summary = when {
AndroidVersion.ATLEAST_API29_Q -> stringRes(R.string.pref__other__show_app_icon__summary_atleast_q)
AndroidVersion.ATLEAST_API29_Q -> stringRes(R.string.pref__advanced__show_app_icon__summary_atleast_q)
else -> null
},
enabledIf = { AndroidVersion.ATMOST_API28_P },
)
Preference(
icon = vectorResource(R.drawable.ic_keyboard_keys),
title = stringRes(R.string.physical_keyboard__title),
onClick = { navController.navigate(Routes.Settings.PhysicalKeyboard) },
ListPreference(
prefs.advanced.incognitoMode,
icon = vectorResource(id = R.drawable.ic_incognito),
title = stringRes(R.string.pref__advanced__incognito_mode__label),
entries = enumDisplayEntriesOf(IncognitoMode::class),
)
Preference(
icon = Icons.Default.Adb,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.settings.advanced
import android.content.Intent
import android.content.res.Configuration
import android.provider.Settings
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
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
@Composable
fun PhysicalKeyboardScreen() = FlorisScreen {
title = stringRes(R.string.physical_keyboard__title)
val context = LocalContext.current
val physicalKeyboardAttached by remember {
mutableStateOf(context.resources.configuration.keyboard != Configuration.KEYBOARD_NOKEYS)
}
val activityForResult = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { }
content {
if (physicalKeyboardAttached) {
Preference(
title = stringRes(R.string.physical_keyboard__system_settings__title),
summary = stringRes(R.string.physical_keyboard__system_settings__summary),
onClick = {
activityForResult.launch(Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS))
}
)
} else {
Preference(
title = stringRes(R.string.physical_keyboard__system_settings__title),
summary = stringRes(R.string.physical_keyboard__system_settings__summary_not_attached),
)
}
SwitchPreference(
pref = prefs.physicalKeyboard.showOnScreenKeyboard,
title = stringRes(R.string.physical_keyboard__show_on_screen_keyboard__title),
summary = stringRes(R.string.physical_keyboard__show_on_screen_keyboard__summary),
)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package dev.patrickgold.florisboard.app.settings.clipboard
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
@@ -26,7 +25,6 @@ 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
@OptIn(ExperimentalJetPrefDatastoreUi::class)
@Composable
@@ -53,47 +51,12 @@ fun ClipboardScreen() = FlorisScreen {
enabledIf = { prefs.clipboard.useInternalClipboard isEqualTo true },
)
PreferenceGroup(title = stringRes(R.string.pref__clipboard__group_clipboard_suggestion__label)) {
SwitchPreference(
prefs.clipboard.suggestionEnabled,
title = stringRes(R.string.pref__clipboard__suggestion_enabled__label),
summary = stringRes(R.string.pref__clipboard__suggestion_enabled__summary),
)
DialogSliderPreference(
prefs.clipboard.suggestionTimeout,
title = stringRes(R.string.pref__clipboard__suggestion_timeout__label),
valueLabel = { stringRes(R.string.pref__clipboard__suggestion_timeout__summary, "v" to it) },
min = 30,
max = 300,
stepIncrement = 5,
enabledIf = { prefs.clipboard.suggestionEnabled isEqualTo true },
)
}
PreferenceGroup(title = stringRes(R.string.pref__clipboard__group_clipboard_history__label)) {
SwitchPreference(
prefs.clipboard.historyEnabled,
title = stringRes(R.string.pref__clipboard__enable_clipboard_history__label),
summary = stringRes(R.string.pref__clipboard__enable_clipboard_history__summary),
)
DialogSliderPreference(
primaryPref = prefs.clipboard.numHistoryGridColumnsPortrait,
secondaryPref = prefs.clipboard.numHistoryGridColumnsLandscape,
title = stringRes(R.string.pref__clipboard__num_history_grid_columns__label),
primaryLabel = stringRes(R.string.screen_orientation__portrait),
secondaryLabel = stringRes(R.string.screen_orientation__landscape),
valueLabel = { numGridColumns ->
if (numGridColumns == CLIPBOARD_HISTORY_NUM_GRID_COLUMNS_AUTO) {
stringRes(R.string.general__auto)
} else {
numGridColumns.toString()
}
},
min = 0,
max = 10,
stepIncrement = 1,
enabledIf = { prefs.clipboard.historyEnabled isEqualTo true },
)
SwitchPreference(
prefs.clipboard.cleanUpOld,
title = stringRes(R.string.pref__clipboard__clean_up_old__label),
@@ -108,22 +71,6 @@ fun ClipboardScreen() = FlorisScreen {
stepIncrement = 5,
enabledIf = { prefs.clipboard.historyEnabled isEqualTo true && prefs.clipboard.cleanUpOld isEqualTo true },
)
SwitchPreference(
prefs.clipboard.autoCleanSensitive,
title = stringRes(R.string.pref__clipboard__auto_clean_sensitive__label),
enabledIf = { prefs.clipboard.historyEnabled isEqualTo true },
visibleIf = { AndroidVersion.ATLEAST_API33_T },
)
DialogSliderPreference(
prefs.clipboard.autoCleanSensitiveAfter,
title = stringRes(R.string.pref__clipboard__auto_clean_sensitive_after__label),
valueLabel = { pluralsRes(R.plurals.unit__seconds__written, it, "v" to it) },
min = 0,
max = 300,
stepIncrement = 10,
enabledIf = { prefs.clipboard.historyEnabled isEqualTo true && prefs.clipboard.autoCleanSensitive isEqualTo true },
visibleIf = { AndroidVersion.ATLEAST_API33_T },
)
SwitchPreference(
prefs.clipboard.limitHistorySize,
title = stringRes(R.string.pref__clipboard__limit_history_size__label),

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,15 +56,14 @@ 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.FlorisOutlinedTextField
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
import dev.patrickgold.jetpref.material.ui.JetPrefListItem
import dev.patrickgold.jetpref.material.ui.JetPrefTextField
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.florisboard.lib.android.showLongToast
@@ -367,35 +366,39 @@ fun UserDictionaryScreen(type: UserDictionaryType) = FlorisScreen {
) {
Column {
DialogProperty(text = stringRes(R.string.settings__udm__dialog__word_label)) {
JetPrefTextField(
FlorisOutlinedTextField(
value = word,
onValueChange = { word = it },
showValidationError = showValidationErrors,
validationResult = wordValidation,
)
Validation(showValidationErrors, wordValidation)
}
DialogProperty(text = stringRes(
R.string.settings__udm__dialog__freq_label,
"f_min" to FREQUENCY_MIN, "f_max" to FREQUENCY_MAX,
)) {
JetPrefTextField(
FlorisOutlinedTextField(
value = freq,
onValueChange = { freq = it },
showValidationError = showValidationErrors,
validationResult = freqValidation,
)
Validation(showValidationErrors, freqValidation)
}
DialogProperty(text = stringRes(R.string.settings__udm__dialog__shortcut_label)) {
JetPrefTextField(
FlorisOutlinedTextField(
value = shortcut,
onValueChange = { shortcut = it },
showValidationError = showValidationErrors,
validationResult = shortcutValidation,
)
Validation(showValidationErrors, shortcutValidation)
}
DialogProperty(text = stringRes(R.string.settings__udm__dialog__locale_label)) {
JetPrefTextField(
FlorisOutlinedTextField(
value = locale,
onValueChange = { locale = it },
showValidationError = showValidationErrors,
validationResult = localeValidation,
)
Validation(showValidationErrors, localeValidation)
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
import dev.patrickgold.florisboard.ime.input.HapticVibrationMode
import dev.patrickgold.florisboard.ime.input.InputFeedbackActivationMode
import dev.patrickgold.florisboard.ime.input.HapticVibrationMode
import org.florisboard.lib.android.AndroidVersion
import org.florisboard.lib.android.systemVibratorOrNull
import org.florisboard.lib.android.vibrate
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
import dev.patrickgold.florisboard.lib.compose.stringRes
import dev.patrickgold.jetpref.datastore.ui.DialogSliderPreference
@@ -29,8 +32,6 @@ import dev.patrickgold.jetpref.datastore.ui.ExperimentalJetPrefDatastoreUi
import dev.patrickgold.jetpref.datastore.ui.ListPreference
import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup
import dev.patrickgold.jetpref.datastore.ui.SwitchPreference
import org.florisboard.lib.android.systemVibratorOrNull
import org.florisboard.lib.android.vibrate
@OptIn(ExperimentalJetPrefDatastoreUi::class)
@Composable
@@ -137,6 +138,8 @@ fun InputFeedbackScreen() = FlorisScreen {
summary = { strength ->
if (vibrator == null || !vibrator.hasVibrator()) {
stringRes(R.string.pref__input_feedback__haptic_vibration_strength__summary_no_vibrator)
} else if (AndroidVersion.ATMOST_API25_N_MR1) {
stringRes(R.string.pref__input_feedback__haptic_vibration_strength__summary_unsupported_android_version)
} else if (!vibrator.hasAmplitudeControl()) {
stringRes(R.string.pref__input_feedback__haptic_vibration_strength__summary_no_amplitude_ctrl)
} else {
@@ -154,7 +157,7 @@ fun InputFeedbackScreen() = FlorisScreen {
prefs.inputFeedback.hapticEnabled isEqualTo true &&
prefs.inputFeedback.hapticVibrationMode isEqualTo HapticVibrationMode.USE_VIBRATOR_DIRECTLY &&
vibrator != null && vibrator.hasVibrator() &&
vibrator.hasAmplitudeControl()
AndroidVersion.ATLEAST_API26_O && vibrator.hasAmplitudeControl()
},
)
SwitchPreference(

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,10 +107,8 @@ fun KeyboardScreen() = FlorisScreen {
PreferenceGroup(title = stringRes(R.string.pref__keyboard__group_layout__label)) {
ListPreference(
prefs.keyboard.oneHandedMode,
prefs.keyboard.oneHandedModeEnabled,
title = stringRes(R.string.pref__keyboard__one_handed_mode__label),
entries = enumDisplayEntriesOf(OneHandedMode::class),
summarySwitchDisabled = stringRes(R.string.state__disabled),
)
DialogSliderPreference(
prefs.keyboard.oneHandedModeScaleFactor,
@@ -119,7 +117,7 @@ fun KeyboardScreen() = FlorisScreen {
min = 70,
max = 90,
stepIncrement = 1,
enabledIf = { prefs.keyboard.oneHandedModeEnabled.isTrue() },
enabledIf = { prefs.keyboard.oneHandedMode isNotEqualTo OneHandedMode.OFF },
)
ListPreference(
prefs.keyboard.landscapeInputUiMode,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,7 +53,6 @@ import dev.patrickgold.jetpref.datastore.model.observeAsState
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.material.ui.JetPrefAlertDialog
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@@ -104,10 +103,6 @@ fun LocalizationScreen() = FlorisScreen {
title = stringRes(R.string.settings__localization__display_language_names_in__label),
entries = enumDisplayEntriesOf(DisplayLanguageNamesIn::class),
)
SwitchPreference(
prefs.localization.displayKeyboardLabelsInSubtypeLanguage,
title = stringRes(R.string.settings__localization__display_keyboard_labels_in_subtype_language),
)
Preference(
title = stringRes(R.string.settings__localization__language_pack_title),
summary = stringRes(R.string.settings__localization__language_pack_summary),

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,17 +25,12 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -78,7 +73,6 @@ 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
@@ -184,7 +178,7 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
})
val selectValue = stringRes(R.string.settings__localization__subtype_select_placeholder)
val selectListValues = remember(selectValue) { listOf(selectValue) }
val selectListValues = remember (selectValue) { listOf(selectValue) }
val prefs by florisPreferenceModel()
val navController = LocalNavController.current
@@ -235,7 +229,7 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
@Composable
fun SubtypePropertyDropdown(
title: String,
layoutType: LayoutType,
layoutType: LayoutType
) {
SubtypeProperty(title) {
SubtypeLayoutDropdown(
@@ -333,7 +327,6 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
DisplayLanguageNamesIn.NATIVE_LOCALE -> suggestedPreset.locale.displayName(suggestedPreset.locale)
},
secondaryText = suggestedPreset.preferred.characters.componentId,
colors = ListItemDefaults.colors(containerColor = CardDefaults.cardColors().containerColor),
)
}
} else {
@@ -488,30 +481,20 @@ fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
showSubtypePresetsDialog = false
},
) {
Column {
HorizontalDivider()
val lazyListState = rememberLazyListState()
LazyColumn(
modifier = Modifier
.florisScrollbar(lazyListState, isVertical = true).weight(1f),
state = lazyListState,
) {
items(subtypePresets) { subtypePreset ->
JetPrefListItem(
modifier = Modifier.clickable {
subtypeEditor.applySubtype(subtypePreset.toSubtype())
showSubtypePresetsDialog = false
},
text = when (displayLanguageNamesIn) {
DisplayLanguageNamesIn.SYSTEM_LOCALE -> subtypePreset.locale.displayName()
DisplayLanguageNamesIn.NATIVE_LOCALE -> subtypePreset.locale.displayName(subtypePreset.locale)
},
secondaryText = subtypePreset.preferred.characters.componentId,
colors = ListItemDefaults.colors(containerColor = AlertDialogDefaults.containerColor),
)
}
LazyColumn {
items(subtypePresets) { subtypePreset ->
JetPrefListItem(
modifier = Modifier.clickable {
subtypeEditor.applySubtype(subtypePreset.toSubtype())
showSubtypePresetsDialog = false
},
text = when (displayLanguageNamesIn) {
DisplayLanguageNamesIn.SYSTEM_LOCALE -> subtypePreset.locale.displayName()
DisplayLanguageNamesIn.NATIVE_LOCALE -> subtypePreset.locale.displayName(subtypePreset.locale)
},
secondaryText = subtypePreset.preferred.characters.componentId,
)
}
HorizontalDivider()
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024-2025 The FlorisBoard Contributors
* Copyright (C) 2024 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,18 +19,10 @@ package dev.patrickgold.florisboard.app.settings.media
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.EmojiSymbols
import androidx.compose.material.icons.outlined.Schedule
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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 dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.enumDisplayEntriesOf
import dev.patrickgold.florisboard.app.florisPreferenceModel
import dev.patrickgold.florisboard.ime.media.emoji.EmojiHistory
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
@@ -39,11 +31,8 @@ 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 dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
import kotlinx.coroutines.launch
@OptIn(ExperimentalJetPrefDatastoreUi::class)
@Composable
@@ -52,11 +41,6 @@ fun MediaScreen() = FlorisScreen {
previewFieldVisible = true
iconSpaceReserved = true
val prefs by florisPreferenceModel()
var shouldDelete by remember { mutableStateOf<ShouldDelete?>(null) }
val scope = rememberCoroutineScope()
content {
ListPreference(
prefs.emoji.preferredSkinTone,
@@ -101,21 +85,6 @@ fun MediaScreen() = FlorisScreen {
stepIncrement = 1,
enabledIf = { prefs.emoji.historyEnabled.isTrue() },
)
Preference(
title = stringRes(R.string.prefs__media__emoji_history_pinned_reset),
onClick = {
shouldDelete = ShouldDelete(true)
},
enabledIf = { prefs.emoji.historyEnabled.isTrue() },
)
Preference(
title = stringRes(R.string.prefs__media__emoji_history_reset),
onClick = {
shouldDelete = ShouldDelete(false)
},
enabledIf = { prefs.emoji.historyEnabled.isTrue() },
)
}
PreferenceGroup(title = stringRes(R.string.prefs__media__emoji_suggestion__title)) {
@@ -169,49 +138,4 @@ fun MediaScreen() = FlorisScreen {
)
}
}
DeleteEmojiHistoryConfirmDialog(
shouldDelete = shouldDelete,
onDismiss = {
shouldDelete = null
},
onConfirm = {
shouldDelete?.let {
scope.launch {
if (it.pinned) {
EmojiHistoryHelper.deletePinned(prefs = prefs)
} else {
EmojiHistoryHelper.deleteHistory(prefs = prefs)
}
}
shouldDelete = null
}
},
)
}
@Composable
fun DeleteEmojiHistoryConfirmDialog(
shouldDelete: ShouldDelete?,
onDismiss: () -> Unit,
onConfirm: () -> Unit,
) {
shouldDelete?.let {
JetPrefAlertDialog(
title = stringRes(R.string.action__reset_confirm_title),
confirmLabel = stringRes(R.string.action__yes),
dismissLabel = stringRes(R.string.action__no),
onDismiss = onDismiss,
onConfirm = onConfirm,
) {
if (it.pinned) {
Text(stringRes(R.string.action__reset_confirm_message, "name" to "pinned emojis"))
} else {
Text(stringRes(R.string.action__reset_confirm_message, "name" to "emoji history"))
}
}
}
}
data class ShouldDelete(val pinned: Boolean)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2025 The FlorisBoard Contributors
* Copyright (C) 2021 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2025 The FlorisBoard Contributors
* Copyright (C) 2022 Patrick Goldinger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,16 +14,12 @@
* limitations under the License.
*/
package org.florisboard.lib.kotlin
package dev.patrickgold.florisboard.app.settings.theme
import kotlin.reflect.KClass
fun KClass<*>.simpleNameOrEnclosing(): String? {
return if (this.simpleName == "Companion") {
// Companion object => get the enclosing class
this.java.enclosingClass.simpleName
} else {
// Normal object => directly get class
this.simpleName
}
/**
* DisplayColorsAs indicates how color strings should be visually presented to the user.
*/
enum class DisplayColorsAs {
HEX8,
RGBA;
}

Some files were not shown because too many files have changed in this diff Show More