Compare commits
30 Commits
v0.3.13-be
...
v0.3.13-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37bb4cea43 | ||
|
|
79d608feea | ||
|
|
54573de3e3 | ||
|
|
2fba2d3b4a | ||
|
|
fd0cbbdcb1 | ||
|
|
b6e3deedf4 | ||
|
|
4c74bf1b4a | ||
|
|
2a4e3c8c58 | ||
|
|
e34e5b4260 | ||
|
|
ae2df7dfe4 | ||
|
|
1b3d0a5cf2 | ||
|
|
4c94329071 | ||
|
|
6ffcf2f865 | ||
|
|
e2c9a66880 | ||
|
|
e9bc25ebc7 | ||
|
|
6379e63669 | ||
|
|
70a0763e7f | ||
|
|
863080e6ce | ||
|
|
3ef454b8bd | ||
|
|
2bbdfc71d0 | ||
|
|
d1c783dde1 | ||
|
|
644da67601 | ||
|
|
b8d99efd29 | ||
|
|
4067d92a44 | ||
|
|
13a17f3a6b | ||
|
|
57c679e500 | ||
|
|
f70f45dab6 | ||
|
|
8d8f723d66 | ||
|
|
7c3c6a7ad7 | ||
|
|
d7a1c9377a |
@@ -45,7 +45,11 @@ _A. IzzySoft's repo for F-Droid_:
|
||||
|
||||
[<img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png" height="64" alt="IzzySoft repo badge">](https://apt.izzysoft.de/fdroid/index/apk/dev.patrickgold.florisboard.beta)
|
||||
|
||||
_B. Use the APK provided in the release section of this repo_
|
||||
_B. Google Play_:
|
||||
|
||||
Follow the same steps as for the stable track, the app can then be accessed [here](https://play.google.com/store/apps/details?id=dev.patrickgold.florisboard.beta).
|
||||
|
||||
_C. Use the APK provided in the release section of this repo_
|
||||
|
||||
### Giving feedback
|
||||
If you want to give feedback to FlorisBoard, there are several ways to
|
||||
|
||||
@@ -24,7 +24,7 @@ android {
|
||||
applicationId = "dev.patrickgold.florisboard"
|
||||
minSdkVersion(23)
|
||||
targetSdkVersion(30)
|
||||
versionCode(46)
|
||||
versionCode(47)
|
||||
versionName("0.3.13")
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
@@ -73,7 +73,7 @@ android {
|
||||
create("beta") // Needed because by default the "beta" BuildType does not exist
|
||||
named("beta").configure {
|
||||
applicationIdSuffix = ".beta"
|
||||
versionNameSuffix = "-beta03"
|
||||
versionNameSuffix = "-beta04"
|
||||
proguardFiles.add(getDefaultProguardFile("proguard-android-optimize.txt"))
|
||||
|
||||
resValue("mipmap", "floris_app_icon", "@mipmap/ic_app_icon_beta")
|
||||
|
||||
@@ -4,28 +4,22 @@
|
||||
"authors": [ "GoRaN" ],
|
||||
"mapping": {
|
||||
"all": {
|
||||
|
||||
"ﻪ": {
|
||||
"relevant": [
|
||||
{ "code": 1577, "label": "ة" },
|
||||
{ "code": 1729, "label": "ـہ" }
|
||||
]
|
||||
},
|
||||
"ر": {
|
||||
"relevant": [
|
||||
{ "code": 1685, "label": "ڕ" },
|
||||
{ "code": 1682, "label": "ڒ" }
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
"ی": {
|
||||
"relevant": [
|
||||
{ "code": 1746, "label": "ے" },
|
||||
{ "code": 1610, "label": "ي" },
|
||||
{ "code": 1744, "label": "ې" },
|
||||
{ "code": 1741, "label": "ۍ" },
|
||||
{ "code": 1742, "label": "ێ" },
|
||||
{ "code": 1744, "label": "ې" },
|
||||
{ "code": 1610, "label": "ي" },
|
||||
{ "code": 1597, "label": "ؽ" }
|
||||
]
|
||||
},
|
||||
@@ -34,10 +28,15 @@
|
||||
"ﺋ": {
|
||||
"relevant": [
|
||||
{ "code": 65163, "label": "ﺋ" },
|
||||
{ "code": 1569, "label": "ء" },
|
||||
{ "code": 65139, "label": "ﹳ" }
|
||||
]
|
||||
},
|
||||
"ح": {
|
||||
"relevant": [
|
||||
{ "code": 65010, "label": "ﷲ" },
|
||||
{ "code": 65019, "label": "ﷻ" }
|
||||
]
|
||||
},
|
||||
|
||||
"ع": {
|
||||
"relevant": [
|
||||
@@ -56,12 +55,9 @@
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
|
||||
"ف": {
|
||||
"relevant": [
|
||||
{ "code": 1701, "label": "ڥ" },
|
||||
{ "code": 1700, "label": "ڤ" },
|
||||
{ "code": 1698, "label": "ڢ" },
|
||||
{ "code": 1697, "label": "ڡ" }
|
||||
]
|
||||
@@ -70,7 +66,6 @@
|
||||
"د": {
|
||||
"relevant": [
|
||||
{ "code": 1676, "label": "ڌ" },
|
||||
{ "code": 1584, "label": "ذ" },
|
||||
{ "code": 64390, "label": "ﮆ" },
|
||||
{ "code": 1774, "label": "ۮ" }
|
||||
]
|
||||
@@ -93,9 +88,7 @@
|
||||
},
|
||||
"ب": {
|
||||
"relevant": [
|
||||
{ "code": 65010, "label": "ﷲ" },
|
||||
{ "code": 65021, "label": "﷽" },
|
||||
{ "code": 65019, "label": "ﷻ" }
|
||||
{ "code": 65021, "label": "﷽" }
|
||||
]
|
||||
},
|
||||
"م": {
|
||||
@@ -108,7 +101,6 @@
|
||||
"relevant": [
|
||||
{ "code": 1718, "label": "ڶ" },
|
||||
{ "code": 1719, "label": "ڷ" },
|
||||
{ "code": 1717, "label": "ڵ" },
|
||||
{ "code": 1720, "label": "ڸ" }
|
||||
]
|
||||
},
|
||||
|
||||
77
app/src/main/assets/ime/text/characters/halmak.json
Normal file
77
app/src/main/assets/ime/text/characters/halmak.json
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"type": "characters",
|
||||
"name": "halmak",
|
||||
"label": "Halmak",
|
||||
"authors": [ "dessalines" ],
|
||||
"direction": "ltr",
|
||||
"arrangement": [
|
||||
[
|
||||
{ "$": "auto_text_key", "code": 119, "label": "w" },
|
||||
{ "$": "auto_text_key", "code": 108, "label": "l" },
|
||||
{ "$": "auto_text_key", "code": 114, "label": "r" },
|
||||
{ "$": "auto_text_key", "code": 98, "label": "b" },
|
||||
{ "$": "auto_text_key", "code": 122, "label": "z" },
|
||||
{ "$": "case_selector",
|
||||
"lower": { "code": 59, "label": ";", "popup": {
|
||||
"relevant": [
|
||||
{ "code": 58, "label": ":" }
|
||||
]
|
||||
} },
|
||||
"upper": { "code": 58, "label": ":", "popup": {
|
||||
"relevant": [
|
||||
{ "code": 59, "label": ";" }
|
||||
]
|
||||
} }
|
||||
},
|
||||
{ "$": "auto_text_key", "code": 113, "label": "q" },
|
||||
{ "$": "auto_text_key", "code": 117, "label": "u" },
|
||||
{ "$": "auto_text_key", "code": 100, "label": "d" },
|
||||
{ "$": "auto_text_key", "code": 106, "label": "j" }
|
||||
],
|
||||
[
|
||||
{ "$": "auto_text_key", "code": 115, "label": "s" },
|
||||
{ "$": "auto_text_key", "code": 104, "label": "h" },
|
||||
{ "$": "auto_text_key", "code": 110, "label": "n" },
|
||||
{ "$": "auto_text_key", "code": 116, "label": "t" },
|
||||
{ "$": "case_selector",
|
||||
"lower": { "code": 44, "label": ",", "popup": {
|
||||
"relevant": [
|
||||
{ "code": 40, "label": "(" }
|
||||
]
|
||||
} },
|
||||
"upper": { "code": 40, "label": "(", "popup": {
|
||||
"relevant": [
|
||||
{ "code": 44, "label": "," }
|
||||
]
|
||||
} }
|
||||
},
|
||||
{ "$": "case_selector",
|
||||
"lower": { "code": 46, "label": ".", "popup": {
|
||||
"relevant": [
|
||||
{ "code": 41, "label": ")" }
|
||||
]
|
||||
} },
|
||||
"upper": { "code": 41, "label": ")", "popup": {
|
||||
"relevant": [
|
||||
{ "code": 46, "label": "." }
|
||||
]
|
||||
} }
|
||||
},
|
||||
{ "$": "auto_text_key", "code": 97, "label": "a" },
|
||||
{ "$": "auto_text_key", "code": 101, "label": "e" },
|
||||
{ "$": "auto_text_key", "code": 111, "label": "o" },
|
||||
{ "$": "auto_text_key", "code": 105, "label": "i" }
|
||||
],
|
||||
[
|
||||
{ "$": "auto_text_key", "code": 102, "label": "f" },
|
||||
{ "$": "auto_text_key", "code": 109, "label": "m" },
|
||||
{ "$": "auto_text_key", "code": 118, "label": "v" },
|
||||
{ "$": "auto_text_key", "code": 99, "label": "c" },
|
||||
{ "$": "auto_text_key", "code": 103, "label": "g" },
|
||||
{ "$": "auto_text_key", "code": 112, "label": "p" },
|
||||
{ "$": "auto_text_key", "code": 120, "label": "x" },
|
||||
{ "$": "auto_text_key", "code": 107, "label": "k" },
|
||||
{ "$": "auto_text_key", "code": 121, "label": "y" }
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "characters",
|
||||
"name": "kurdish",
|
||||
"label": "کوردی",
|
||||
"label": "کوردی (قوەرتی نوێ)",
|
||||
"authors": [ "GoRaN" ],
|
||||
"direction": "rtl",
|
||||
"modifier": "kurdish",
|
||||
@@ -13,34 +13,46 @@
|
||||
{ "code": 1608, "label": "و", "popup": {
|
||||
"main": { "code": -255, "label": "وو" }
|
||||
} },
|
||||
{ "code": 1749, "label": "ﻪ" },
|
||||
{ "code": 1585, "label": "ر" },
|
||||
|
||||
{ "code": 1749, "label": "ﻪ", "popup": {
|
||||
"main": { "code": 1577, "label": "ة" }
|
||||
} },
|
||||
{ "code": 1585, "label": "ر", "popup": {
|
||||
"main": { "code": 1685, "label": "ڕ" }
|
||||
} },
|
||||
{ "code": 1578, "label": "ت", "popup": {
|
||||
"main": { "code": 1591, "label": "ط" }
|
||||
} },
|
||||
{ "code": 1740, "label": "ی" },
|
||||
|
||||
{ "code": 1574, "label": "ﺋ"},
|
||||
|
||||
{ "code": 1740, "label": "ی", "popup": {
|
||||
"main": { "code": 1742, "label": "ێ" }
|
||||
} },
|
||||
{ "code": 1574, "label": "ﺋ", "popup": {
|
||||
"main": { "code": 1569, "label": "ء" }
|
||||
} },
|
||||
{ "code": 1593, "label": "ع", "popup": {
|
||||
"main": { "code": 1594, "label": "غ" }
|
||||
} },
|
||||
{ "code": 1734, "label": "ۆ" },
|
||||
|
||||
{ "code": 1662, "label": "پ", "popup": {
|
||||
"main": { "code": 1579, "label": "ث" }
|
||||
} }
|
||||
],
|
||||
[
|
||||
{ "code": 1575, "label": "ا" },
|
||||
{"code": 1575, "label": "ا"},
|
||||
{ "code": 1587, "label": "س" },
|
||||
{ "code": 1588, "label": "ش" },
|
||||
{ "code": 1583, "label": "د" },
|
||||
{ "code": 1601, "label": "ف" },
|
||||
{ "code": 1583, "label": "د", "popup": {
|
||||
"main": {"code": 1584, "label": "ذ" }
|
||||
} },
|
||||
{ "code": 1601, "label": "ف" , "popup": {
|
||||
"main": {"code": 1700, "label": "ڤ" }
|
||||
} },
|
||||
{ "code": 1607, "label": "ھ" },
|
||||
{ "code": 1688, "label": "ژ" },
|
||||
{ "code": 1604, "label": "ل" },
|
||||
{ "code": 1688, "label": "ژ", "popup": {
|
||||
"main": { "code": 1600, "label": "▬" }
|
||||
} },
|
||||
{ "code": 1604, "label": "ل", "popup": {
|
||||
"main": { "code": 1717, "label": "ڵ" }
|
||||
} },
|
||||
{ "code": 1705, "label": "ک" },
|
||||
{ "code": 1711, "label": "گ" }
|
||||
],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "characters",
|
||||
"name": "kurdish_standard",
|
||||
"label": "کوردی - ستاندارد",
|
||||
"label": "کوردی (قڤفغ)",
|
||||
"authors": [ "GoRaN" ],
|
||||
"direction": "rtl",
|
||||
"modifier": "kurdish",
|
||||
@@ -10,16 +10,14 @@
|
||||
{ "code": 1602, "label": "ق", "popup": {
|
||||
"main": { "code": 1647, "label": "ٯ" }
|
||||
} },
|
||||
{ "code": 1700, "label": "ڤ", "popup": {
|
||||
"main": { "code": 1701, "label": "ڥ" }
|
||||
} },
|
||||
{ "code": 1601, "label": "ف", "popup": {
|
||||
"main": { "code": 1698, "label": "ڢ" }
|
||||
} },
|
||||
{ "code": 1700, "label": "ڤ" },
|
||||
{ "code": 1601, "label": "ف" },
|
||||
{ "code": 1594, "label": "غ" },
|
||||
{ "code": 1593, "label": "ع"},
|
||||
{ "code": 1607, "label": "ھ" },
|
||||
{ "code": 1749, "label": "ﻪ" },
|
||||
{ "code": 1749, "label": "ﻪ", "popup": {
|
||||
"main": { "code": 1577, "label": "ة" }
|
||||
} },
|
||||
|
||||
{ "code": 1578, "label": "ت", "popup": {
|
||||
"main": { "code": 1591, "label": "ط" }
|
||||
@@ -46,7 +44,9 @@
|
||||
} },
|
||||
{ "code": 1585, "label": "ر" },
|
||||
{ "code": 1685, "label": "ڕ" },
|
||||
{ "code": 1583, "label": "د" },
|
||||
{ "code": 1583, "label": "د", "popup": {
|
||||
"main": {"code": 1584, "label": "ذ" }
|
||||
} },
|
||||
{ "code": -255, "label": "وو" },
|
||||
{ "code": 1608, "label": "و" },
|
||||
{ "code": 1734, "label": "ۆ" },
|
||||
@@ -55,8 +55,10 @@
|
||||
|
||||
],
|
||||
[
|
||||
{ "code": 1600, "label": "kashida", "variation": "normal" },
|
||||
{ "code": 1574, "label": "ﺋ"},
|
||||
|
||||
{ "code": 1574, "label": "ﺋ", "popup": {
|
||||
"main": { "code": 1569, "label": "ء" }
|
||||
} },
|
||||
|
||||
{ "code": 1662, "label": "پ", "popup": {
|
||||
"main": { "code": 1579, "label": "ث" }
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
"direction": "rtl",
|
||||
"arrangement": [
|
||||
[
|
||||
{ "code": 1600, "label": "kashida", "popup":
|
||||
{ "main": { "code": 8204, "label": "half_space" }
|
||||
} },
|
||||
{ "code": 0, "type": "placeholder" },
|
||||
{ "code": -5, "label": "delete", "type": "enter_editing" }
|
||||
],
|
||||
[
|
||||
{ "code": -202, "label": "view_symbols", "type": "system_gui" },
|
||||
{ "$": "variation_selector",
|
||||
"default": { "code": 1567, "label": "؟", "groupId": 1 },
|
||||
"password": { "code": 1548, "label": "،", "groupId": 1 },
|
||||
"default": { "code": 1548, "label": "،", "groupId": 1 },
|
||||
"password": { "code": 35, "label": "#", "groupId": 1 },
|
||||
"email": { "code": 64, "label": "@", "groupId": 1 },
|
||||
"uri": { "code": 47, "label": "/", "groupId": 1 }
|
||||
},
|
||||
|
||||
@@ -25,12 +25,10 @@ import dev.patrickgold.florisboard.ime.core.SubtypeManager
|
||||
import dev.patrickgold.florisboard.ime.dictionary.DictionaryManager
|
||||
import dev.patrickgold.florisboard.ime.extension.AssetManager
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.MainScope
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("unused")
|
||||
class FlorisApplication : Application(), CoroutineScope by MainScope() {
|
||||
class FlorisApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (BuildConfig.DEBUG) {
|
||||
|
||||
@@ -64,7 +64,7 @@ class ClipboardHistoryView : LinearLayout, FlorisBoard.EventListener,
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
val height = florisboard?.inputView?.desiredMediaKeyboardViewHeight ?: 0.0f
|
||||
val height = florisboard?.uiBinding?.inputView?.desiredMediaKeyboardViewHeight ?: 0.0f
|
||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height.roundToInt(), MeasureSpec.EXACTLY))
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,14 @@ package dev.patrickgold.florisboard.ime.clip
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||
import dev.patrickgold.florisboard.BuildConfig
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.databinding.FlorisboardBinding
|
||||
import dev.patrickgold.florisboard.ime.clip.provider.ClipboardItem
|
||||
import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
import dev.patrickgold.florisboard.ime.core.InputKeyEvent
|
||||
import dev.patrickgold.florisboard.ime.core.InputView
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.BasicTextKeyData
|
||||
import kotlinx.coroutines.*
|
||||
@@ -43,27 +42,23 @@ class ClipboardInputManager private constructor() : CoroutineScope by MainScope(
|
||||
florisboard.addEventListener(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new input view has been registered. Used to initialize all media-relevant
|
||||
* views and layouts.
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onRegisterInputView(inputView: InputView) {
|
||||
inputView.findViewById<ImageButton>(R.id.back_to_keyboard_button)
|
||||
override fun onInitializeInputUi(uiBinding: FlorisboardBinding) {
|
||||
uiBinding.clipboard.backToKeyboardButton
|
||||
.setOnTouchListener { view, event -> onButtonPressEvent(view, event) }
|
||||
uiBinding.clipboard.clearClipboardHistory
|
||||
.setOnTouchListener { view, event -> onButtonPressEvent(view, event) }
|
||||
|
||||
inputView.findViewById<ImageButton>(R.id.clear_clipboard_history)
|
||||
.setOnTouchListener { view, event -> onButtonPressEvent(view, event) }
|
||||
recyclerView = uiBinding.clipboard.clipboardHistoryItems.also {
|
||||
if (BuildConfig.DEBUG && adapter == null) {
|
||||
error("initClipboard() not called")
|
||||
}
|
||||
|
||||
recyclerView = inputView.findViewById(R.id.clipboard_history_items)
|
||||
|
||||
if (BuildConfig.DEBUG && adapter == null) {
|
||||
error("initClipboard() not called")
|
||||
it.adapter = adapter
|
||||
val manager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
|
||||
it.layoutManager = manager
|
||||
}
|
||||
|
||||
recyclerView!!.adapter = adapter
|
||||
val manager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
|
||||
recyclerView!!.layoutManager = manager
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +73,7 @@ class ClipboardInputManager private constructor() : CoroutineScope by MainScope(
|
||||
* Returns a reference to the [ClipboardHistoryView]
|
||||
*/
|
||||
fun getClipboardHistoryView(): ClipboardHistoryView {
|
||||
return FlorisBoard.getInstance().inputView?.mainViewFlipper?.getChildAt(2) as ClipboardHistoryView
|
||||
return florisboard.uiBinding?.mainViewFlipper?.getChildAt(2) as ClipboardHistoryView
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,21 +108,44 @@ class FlorisClipboardManager private constructor() : ClipboardManager.OnPrimaryC
|
||||
val clipboardPrefs = prefs.clipboard
|
||||
|
||||
if (clipboardPrefs.enableHistory) {
|
||||
if (clipboardPrefs.limitHistorySize) {
|
||||
var numRemoved = 0
|
||||
while (history.size >= clipboardPrefs.maxHistorySize) {
|
||||
numRemoved += 1
|
||||
history.removeLast().data.close()
|
||||
}
|
||||
ClipboardInputManager.getInstance().notifyItemRangeRemoved(history.size, numRemoved)
|
||||
}
|
||||
val clipboardInputManager = ClipboardInputManager.getInstance()
|
||||
|
||||
val timed = TimedClipData(newData, System.currentTimeMillis())
|
||||
history.addFirst(timed)
|
||||
ClipboardInputManager.getInstance().notifyItemInserted(pins.size)
|
||||
val historyElement = history.firstOrNull { it.data.type == ItemType.TEXT && it.data.text == newData.text }
|
||||
if (historyElement != null) {
|
||||
moveToTheBeginning(historyElement, newData, clipboardInputManager)
|
||||
} else {
|
||||
if (clipboardPrefs.limitHistorySize) {
|
||||
var numRemoved = 0
|
||||
while (history.size >= clipboardPrefs.maxHistorySize) {
|
||||
numRemoved += 1
|
||||
history.removeLast().data.close()
|
||||
}
|
||||
clipboardInputManager.notifyItemRangeRemoved(history.size, numRemoved)
|
||||
}
|
||||
|
||||
createAndAddNewTimedClipData(newData)
|
||||
clipboardInputManager.notifyItemInserted(pins.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a ClipboardItem to the beginning of the history by removing the old one and creating a new one
|
||||
*/
|
||||
private fun moveToTheBeginning(
|
||||
historyElement: TimedClipData,
|
||||
newData: ClipboardItem,
|
||||
clipboardInputManager: ClipboardInputManager
|
||||
) {
|
||||
val elementsPosition = history.indexOf(historyElement)
|
||||
history.remove(historyElement)
|
||||
|
||||
createAndAddNewTimedClipData(newData)
|
||||
|
||||
clipboardInputManager.notifyItemMoved(elementsPosition, 0)
|
||||
clipboardInputManager.notifyItemChanged(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used so that [onPrimaryClipChanged] knows whether it was called by [changeCurrent] (and hence shouldn't update
|
||||
* history)
|
||||
@@ -341,8 +364,7 @@ class FlorisClipboardManager private constructor() : ClipboardManager.OnPrimaryC
|
||||
ClipboardInputManager.getInstance().notifyItemRangeRemoved(history.size, numRemoved)
|
||||
}
|
||||
|
||||
val timed = TimedClipData(item, System.currentTimeMillis())
|
||||
history.addFirst(timed)
|
||||
createAndAddNewTimedClipData(item)
|
||||
|
||||
clipInputManager.notifyItemMoved(adapterPos, pins.size)
|
||||
clipInputManager.notifyItemChanged(pins.size)
|
||||
@@ -352,6 +374,14 @@ class FlorisClipboardManager private constructor() : ClipboardManager.OnPrimaryC
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TimedClipData and adds it to the history
|
||||
*/
|
||||
private fun createAndAddNewTimedClipData(newData: ClipboardItem) {
|
||||
val timed = TimedClipData(newData, System.currentTimeMillis())
|
||||
history.addFirst(timed)
|
||||
}
|
||||
|
||||
fun removeClip(pos: Int) {
|
||||
when {
|
||||
pos < pins.size -> {
|
||||
|
||||
@@ -62,16 +62,6 @@ class EditorInstance private constructor(
|
||||
}
|
||||
val inputConnection: InputConnection?
|
||||
get() = ims?.currentInputConnection
|
||||
var isComposingEnabled: Boolean = false
|
||||
set(v) {
|
||||
field = v
|
||||
cachedInput.reevaluate()
|
||||
if (v && !activeState.isRawInputEditor) {
|
||||
markComposingRegion(cachedInput.currentWord)
|
||||
} else {
|
||||
markComposingRegion(null)
|
||||
}
|
||||
}
|
||||
var shouldReevaluateComposingSuggestions: Boolean = false
|
||||
var selection: Selection = Selection(this)
|
||||
private set
|
||||
@@ -137,7 +127,7 @@ class EditorInstance private constructor(
|
||||
}
|
||||
if (selection.isCursorMode) {
|
||||
cachedInput.update()
|
||||
if (isComposingEnabled) {
|
||||
if (activeState.isComposingEnabled) {
|
||||
if (candidatesStart >= 0 && candidatesEnd >= 0) {
|
||||
shouldReevaluateComposingSuggestions = true
|
||||
}
|
||||
@@ -154,6 +144,15 @@ class EditorInstance private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun composingEnabledChanged() {
|
||||
cachedInput.reevaluate()
|
||||
if (activeState.isComposingEnabled && activeState.isRichInputEditor) {
|
||||
markComposingRegion(cachedInput.currentWord)
|
||||
} else {
|
||||
markComposingRegion(null)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the given [text] in the current composing region. Does nothing if the current
|
||||
* composing region is of zero length or null.
|
||||
@@ -212,7 +211,7 @@ class EditorInstance private constructor(
|
||||
*/
|
||||
fun commitText(text: String): Boolean {
|
||||
val ic = inputConnection ?: return false
|
||||
return if (activeState.isRawInputEditor || selection.isSelectionMode || !isComposingEnabled) {
|
||||
return if (activeState.isRawInputEditor || selection.isSelectionMode || !activeState.isComposingEnabled) {
|
||||
doCommitText(text).first
|
||||
} else {
|
||||
ic.beginBatchEdit()
|
||||
|
||||
@@ -68,13 +68,13 @@ import dev.patrickgold.florisboard.ime.text.composing.Composer
|
||||
import dev.patrickgold.florisboard.ime.text.gestures.SwipeAction
|
||||
import dev.patrickgold.florisboard.ime.text.key.CurrencySet
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import dev.patrickgold.florisboard.ime.theme.Theme
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeManager
|
||||
import dev.patrickgold.florisboard.setup.SetupActivity
|
||||
import dev.patrickgold.florisboard.util.AppVersionUtils
|
||||
import dev.patrickgold.florisboard.common.ViewUtils
|
||||
import dev.patrickgold.florisboard.databinding.FlorisboardBinding
|
||||
import dev.patrickgold.florisboard.ime.keyboard.KeyboardState
|
||||
import dev.patrickgold.florisboard.ime.keyboard.updateKeyboardState
|
||||
import dev.patrickgold.florisboard.util.debugSummarize
|
||||
@@ -128,10 +128,9 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
private val prefs: Preferences get() = Preferences.default()
|
||||
val activeState: KeyboardState = KeyboardState.new()
|
||||
|
||||
private var extractEditLayout: WeakReference<ViewGroup?> = WeakReference(null)
|
||||
var inputView: InputView? = null
|
||||
var uiBinding: FlorisboardBinding? = null
|
||||
private set
|
||||
private var inputWindowView: InputWindowView? = null
|
||||
private var extractEditLayout: WeakReference<ViewGroup?> = WeakReference(null)
|
||||
var popupLayerView: PopupLayerView? = null
|
||||
private set
|
||||
private var eventListeners: CopyOnWriteArrayList<EventListener> = CopyOnWriteArrayList()
|
||||
@@ -160,7 +159,6 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
lateinit var activeSubtype: Subtype
|
||||
private var currentThemeIsNight: Boolean = false
|
||||
private var currentThemeResId: Int = 0
|
||||
private var isNumberRowVisible: Boolean = false
|
||||
private var isWindowShown: Boolean = false
|
||||
|
||||
private var responseState = ResponseState.RESET
|
||||
@@ -235,7 +233,6 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
|
||||
currentThemeIsNight = themeManager.activeTheme.isNightTheme
|
||||
currentThemeResId = getDayNightBaseThemeId(currentThemeIsNight)
|
||||
isNumberRowVisible = prefs.keyboard.numberRow
|
||||
setTheme(currentThemeResId)
|
||||
themeManager.registerOnThemeUpdatedListener(this)
|
||||
|
||||
@@ -267,13 +264,28 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
updateThemeContext(currentThemeResId)
|
||||
|
||||
popupLayerView = PopupLayerView(themeContext)
|
||||
window?.window?.findViewById<View>(android.R.id.content)?.let { content ->
|
||||
if (content is ViewGroup) {
|
||||
content.addView(popupLayerView)
|
||||
}
|
||||
}
|
||||
|
||||
inputWindowView = LayoutInflater.from(themeContext).inflate(R.layout.florisboard, null) as? InputWindowView
|
||||
inputWindowView?.isHapticFeedbackEnabled = true
|
||||
uiBinding = FlorisboardBinding.inflate(LayoutInflater.from(themeContext))
|
||||
|
||||
eventListeners.toList().forEach { it?.onCreateInputView() }
|
||||
eventListeners.toList().forEach { it?.onInitializeInputUi(uiBinding!!) }
|
||||
|
||||
return inputWindowView
|
||||
return uiBinding!!.inputWindowView
|
||||
}
|
||||
|
||||
fun initWindow() {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
|
||||
updateSoftInputWindowLayoutParameters()
|
||||
updateOneHandedPanelVisibility()
|
||||
|
||||
themeManager.requestThemeUpdate(this)
|
||||
|
||||
dispatchCurrentStateToInputUi()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,8 +331,7 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
imeManager = null
|
||||
vibrator = null
|
||||
popupLayerView = null
|
||||
inputView = null
|
||||
inputWindowView = null
|
||||
uiBinding = null
|
||||
florisboardInstance = null
|
||||
|
||||
eventListeners.toList().forEach { it?.onDestroy() }
|
||||
@@ -355,24 +366,6 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
}
|
||||
}
|
||||
|
||||
fun registerInputView(inputView: InputView) {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
|
||||
window?.window?.findViewById<View>(android.R.id.content)?.let { content ->
|
||||
if (content is ViewGroup) {
|
||||
popupLayerView?.let { content.addView(it) }
|
||||
}
|
||||
}
|
||||
this.inputView = inputView
|
||||
updateSoftInputWindowLayoutParameters()
|
||||
updateOneHandedPanelVisibility()
|
||||
themeManager.notifyCallbackReceivers()
|
||||
setActiveInput(R.id.text_input)
|
||||
dispatchCurrentStateToInputUi()
|
||||
|
||||
eventListeners.toList().forEach { it?.onRegisterInputView(inputView) }
|
||||
}
|
||||
|
||||
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
|
||||
@@ -390,8 +383,10 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
flogInfo(LogTopic.IMS_EVENTS) { info?.debugSummarize() ?: "" }
|
||||
|
||||
super.onStartInputView(info, restarting)
|
||||
prefs.sync()
|
||||
if (info != null) {
|
||||
activeState.update(info)
|
||||
activeState.isSelectionMode = (info.initialSelEnd - info.initialSelStart) != 0
|
||||
}
|
||||
activeEditorInstance = EditorInstance.from(info, this, activeState)
|
||||
themeManager.updateRemoteColorValues(activeEditorInstance.packageName)
|
||||
@@ -433,12 +428,12 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
val stylesBundle = themeManager.createInlineSuggestionUiStyleBundle(themeContext)
|
||||
InlinePresentationSpec.Builder(
|
||||
Size(
|
||||
inputView?.desiredInlineSuggestionsMinWidth ?: 0,
|
||||
inputView?.desiredInlineSuggestionsMinHeight ?: 0
|
||||
uiBinding?.inputView?.desiredInlineSuggestionsMinWidth ?: 0,
|
||||
uiBinding?.inputView?.desiredInlineSuggestionsMinHeight ?: 0
|
||||
),
|
||||
Size(
|
||||
inputView?.desiredInlineSuggestionsMaxWidth ?: 0,
|
||||
inputView?.desiredInlineSuggestionsMaxHeight ?: 0
|
||||
uiBinding?.inputView?.desiredInlineSuggestionsMaxWidth ?: 0,
|
||||
uiBinding?.inputView?.desiredInlineSuggestionsMaxHeight ?: 0
|
||||
)
|
||||
).let { spec ->
|
||||
spec.setStyle(stylesBundle)
|
||||
@@ -490,7 +485,7 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
}
|
||||
|
||||
fun dispatchCurrentStateToInputUi() {
|
||||
inputView?.updateKeyboardState(activeState)
|
||||
uiBinding?.inputView?.updateKeyboardState(activeState)
|
||||
}
|
||||
|
||||
override fun onWindowShown() {
|
||||
@@ -504,23 +499,23 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
isWindowShown = true
|
||||
|
||||
prefs.sync()
|
||||
val newIsNumberRowVisible = prefs.keyboard.numberRow
|
||||
if (isNumberRowVisible != newIsNumberRowVisible) {
|
||||
textInputManager.keyboards.clear(KeyboardMode.CHARACTERS)
|
||||
isNumberRowVisible = newIsNumberRowVisible
|
||||
val newActiveSubtype = subtypeManager.getActiveSubtype() ?: Subtype.DEFAULT
|
||||
if (newActiveSubtype != activeSubtype) {
|
||||
activeSubtype = newActiveSubtype
|
||||
onSubtypeChanged(activeSubtype, true)
|
||||
} else {
|
||||
onSubtypeChanged(activeSubtype, false)
|
||||
}
|
||||
themeManager.update()
|
||||
activeSubtype = subtypeManager.getActiveSubtype() ?: Subtype.DEFAULT
|
||||
onSubtypeChanged(activeSubtype)
|
||||
setActiveInput(R.id.text_input)
|
||||
updateOneHandedPanelVisibility()
|
||||
themeManager.update()
|
||||
|
||||
if (prefs.devtools.enabled && prefs.devtools.showHeapMemoryStats) {
|
||||
devtoolsOverlaySyncJob?.cancel()
|
||||
devtoolsOverlaySyncJob = uiScope.launch(Dispatchers.Default) {
|
||||
while (true) {
|
||||
if (!isActive) break
|
||||
withContext(Dispatchers.Main) { inputView?.invalidate() }
|
||||
withContext(Dispatchers.Main) { uiBinding?.inputView?.invalidate() }
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
@@ -612,7 +607,6 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
candidatesStart, candidatesEnd
|
||||
)
|
||||
eventListeners.toList().forEach { it?.onUpdateSelection() }
|
||||
dispatchCurrentStateToInputUi()
|
||||
} else {
|
||||
flogInfo(LogTopic.IMS_EVENTS) { "onUpdateSelection($oldSelStart, $oldSelEnd, $newSelStart, $newSelEnd, $candidatesStart, $candidatesEnd): caught due to internal batch level of $internalBatchNestingLevel!" }
|
||||
if (internalSelectionCache.selectionCatchCount++ == 0) {
|
||||
@@ -624,6 +618,7 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
internalSelectionCache.candidatesStart = candidatesStart
|
||||
internalSelectionCache.candidatesEnd = candidatesEnd
|
||||
}
|
||||
dispatchCurrentStateToInputUi()
|
||||
}
|
||||
|
||||
override fun onThemeUpdated(theme: Theme) {
|
||||
@@ -664,8 +659,8 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
w.decorView.systemUiVisibility = flags
|
||||
|
||||
// Update InputView theme
|
||||
inputView?.setBackgroundColor(theme.getAttr(Theme.Attr.KEYBOARD_BACKGROUND).toSolidColor().color)
|
||||
inputView?.invalidate()
|
||||
uiBinding?.inputView?.setBackgroundColor(theme.getAttr(Theme.Attr.KEYBOARD_BACKGROUND).toSolidColor().color)
|
||||
uiBinding?.inputView?.invalidate()
|
||||
|
||||
// Update ExtractTextView theme and attributes
|
||||
extractEditLayout.get()?.let { eel ->
|
||||
@@ -699,8 +694,8 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
|
||||
override fun onComputeInsets(outInsets: Insets?) {
|
||||
super.onComputeInsets(outInsets)
|
||||
val inputView = this.inputView ?: return
|
||||
val inputWindowView = this.inputWindowView ?: return
|
||||
val inputView = uiBinding?.inputView ?: return
|
||||
val inputWindowView = uiBinding?.inputWindowView ?: return
|
||||
// TODO: Check also if the keyboard is currently suppressed by a hardware keyboard
|
||||
|
||||
if (!isInputViewShown) {
|
||||
@@ -724,7 +719,7 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
private fun updateSoftInputWindowLayoutParameters() {
|
||||
val w = window?.window ?: return
|
||||
ViewUtils.updateLayoutHeightOf(w, WindowManager.LayoutParams.MATCH_PARENT)
|
||||
val inputWindowView = this.inputWindowView
|
||||
val inputWindowView = uiBinding?.inputWindowView
|
||||
if (inputWindowView != null) {
|
||||
val layoutHeight = if (isFullscreenMode) {
|
||||
WindowManager.LayoutParams.WRAP_CONTENT
|
||||
@@ -752,9 +747,9 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
|
||||
val hapticsPerformed = if (vibrationDuration < 0 && vibrationStrength < 0) {
|
||||
if (isMovingGestureEffect && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
inputWindowView?.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE)
|
||||
uiBinding?.inputWindowView?.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE)
|
||||
} else {
|
||||
inputWindowView?.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
||||
uiBinding?.inputWindowView?.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
||||
}
|
||||
} else {
|
||||
false
|
||||
@@ -884,35 +879,35 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
fun switchToPrevSubtype() {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
activeSubtype = subtypeManager.switchToPrevSubtype() ?: Subtype.DEFAULT
|
||||
onSubtypeChanged(activeSubtype)
|
||||
onSubtypeChanged(activeSubtype, true)
|
||||
}
|
||||
|
||||
fun switchToNextSubtype() {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
activeSubtype = subtypeManager.switchToNextSubtype() ?: Subtype.DEFAULT
|
||||
onSubtypeChanged(activeSubtype)
|
||||
onSubtypeChanged(activeSubtype, true)
|
||||
}
|
||||
|
||||
private fun onSubtypeChanged(newSubtype: Subtype) {
|
||||
private fun onSubtypeChanged(newSubtype: Subtype, doRefreshLayouts: Boolean) {
|
||||
flogInfo(LogTopic.SUBTYPE_MANAGER) { "New subtype: $newSubtype" }
|
||||
textInputManager.onSubtypeChanged(newSubtype)
|
||||
mediaInputManager.onSubtypeChanged(newSubtype)
|
||||
clipInputManager.onSubtypeChanged(newSubtype)
|
||||
textInputManager.onSubtypeChanged(newSubtype, doRefreshLayouts)
|
||||
mediaInputManager.onSubtypeChanged(newSubtype, doRefreshLayouts)
|
||||
clipInputManager.onSubtypeChanged(newSubtype, doRefreshLayouts)
|
||||
}
|
||||
|
||||
fun setActiveInput(type: Int, forceSwitchToCharacters: Boolean = false) {
|
||||
when (type) {
|
||||
R.id.text_input -> {
|
||||
inputView?.mainViewFlipper?.displayedChild = 0
|
||||
uiBinding?.mainViewFlipper?.displayedChild = 0
|
||||
if (forceSwitchToCharacters) {
|
||||
textInputManager.inputEventDispatcher.send(InputKeyEvent.downUp(TextKeyData.VIEW_CHARACTERS))
|
||||
}
|
||||
}
|
||||
R.id.media_input -> {
|
||||
inputView?.mainViewFlipper?.displayedChild = 1
|
||||
uiBinding?.mainViewFlipper?.displayedChild = 1
|
||||
}
|
||||
R.id.clip_input -> {
|
||||
inputView?.mainViewFlipper?.displayedChild = 2
|
||||
uiBinding?.mainViewFlipper?.displayedChild = 2
|
||||
}
|
||||
}
|
||||
textInputManager.isGlidePostEffect = false
|
||||
@@ -928,27 +923,27 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
|
||||
fun updateOneHandedPanelVisibility() {
|
||||
if (resources.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) {
|
||||
inputView?.oneHandedCtrlPanelStart?.visibility = View.GONE
|
||||
inputView?.oneHandedCtrlPanelEnd?.visibility = View.GONE
|
||||
uiBinding?.oneHandedCtrlPanelStart?.visibility = View.GONE
|
||||
uiBinding?.oneHandedCtrlPanelEnd?.visibility = View.GONE
|
||||
} else {
|
||||
when (prefs.keyboard.oneHandedMode) {
|
||||
OneHandedMode.OFF -> {
|
||||
inputView?.oneHandedCtrlPanelStart?.visibility = View.GONE
|
||||
inputView?.oneHandedCtrlPanelEnd?.visibility = View.GONE
|
||||
uiBinding?.oneHandedCtrlPanelStart?.visibility = View.GONE
|
||||
uiBinding?.oneHandedCtrlPanelEnd?.visibility = View.GONE
|
||||
}
|
||||
OneHandedMode.START -> {
|
||||
inputView?.oneHandedCtrlPanelStart?.visibility = View.GONE
|
||||
inputView?.oneHandedCtrlPanelEnd?.visibility = View.VISIBLE
|
||||
uiBinding?.oneHandedCtrlPanelStart?.visibility = View.GONE
|
||||
uiBinding?.oneHandedCtrlPanelEnd?.visibility = View.VISIBLE
|
||||
}
|
||||
OneHandedMode.END -> {
|
||||
inputView?.oneHandedCtrlPanelStart?.visibility = View.VISIBLE
|
||||
inputView?.oneHandedCtrlPanelEnd?.visibility = View.GONE
|
||||
uiBinding?.oneHandedCtrlPanelStart?.visibility = View.VISIBLE
|
||||
uiBinding?.oneHandedCtrlPanelEnd?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
// Delay execution so this function can return, then refresh the whole layout
|
||||
uiScope.launch {
|
||||
refreshLayoutOf(inputView)
|
||||
refreshLayoutOf(uiBinding?.inputView)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,8 +976,7 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
|
||||
interface EventListener {
|
||||
fun onCreate() {}
|
||||
fun onCreateInputView() {}
|
||||
fun onRegisterInputView(inputView: InputView) {}
|
||||
fun onInitializeInputUi(uiBinding: FlorisboardBinding) {}
|
||||
fun onDestroy() {}
|
||||
|
||||
fun onStartInputView(instance: EditorInstance, restarting: Boolean) {}
|
||||
@@ -995,7 +989,7 @@ open class FlorisBoard : InputMethodService(), LifecycleOwner, FlorisClipboardMa
|
||||
|
||||
fun onApplyThemeAttributes() {}
|
||||
fun onPrimaryClipChanged() {}
|
||||
fun onSubtypeChanged(newSubtype: Subtype) {}
|
||||
fun onSubtypeChanged(newSubtype: Subtype, doRefreshLayouts: Boolean) {}
|
||||
}
|
||||
|
||||
private enum class ResponseState {
|
||||
|
||||
@@ -57,7 +57,7 @@ class InputEventDispatcher private constructor(
|
||||
/**
|
||||
* The default input event channel capacity to be used in [new].
|
||||
*/
|
||||
private const val DEFAULT_CHANNEL_CAPACITY: Int = 32
|
||||
private const val DEFAULT_CHANNEL_CAPACITY: Int = 64
|
||||
|
||||
/**
|
||||
* Creates a new [InputEventDispatcher] instance from given arguments and returns it.
|
||||
|
||||
@@ -26,19 +26,16 @@ import android.os.Build
|
||||
import android.text.TextPaint
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ViewFlipper
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.onehanded.OneHandedMode
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyVariation
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
|
||||
import dev.patrickgold.florisboard.common.ViewUtils
|
||||
import timber.log.Timber
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Root view of the keyboard. Notifies [FlorisBoard] when it has been attached to a window.
|
||||
* Root view of the keyboard.
|
||||
*/
|
||||
class InputView : LinearLayout {
|
||||
private val florisboard get() = FlorisBoard.getInstance()
|
||||
@@ -66,13 +63,6 @@ class InputView : LinearLayout {
|
||||
var desiredInlineSuggestionsMaxHeight: Int = 0
|
||||
private set
|
||||
|
||||
var mainViewFlipper: ViewFlipper? = null
|
||||
private set
|
||||
var oneHandedCtrlPanelStart: ViewGroup? = null
|
||||
private set
|
||||
var oneHandedCtrlPanelEnd: ViewGroup? = null
|
||||
private set
|
||||
|
||||
private val overlayTextPaint: TextPaint = TextPaint().apply {
|
||||
color = Color.GREEN
|
||||
textAlign = Paint.Align.RIGHT
|
||||
@@ -88,18 +78,6 @@ class InputView : LinearLayout {
|
||||
defStyleAttr
|
||||
)
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
Timber.i("onAttachedToWindow()")
|
||||
|
||||
super.onAttachedToWindow()
|
||||
|
||||
mainViewFlipper = findViewById(R.id.main_view_flipper)
|
||||
oneHandedCtrlPanelStart = findViewById(R.id.one_handed_ctrl_panel_start)
|
||||
oneHandedCtrlPanelEnd = findViewById(R.id.one_handed_ctrl_panel_end)
|
||||
|
||||
florisboard.registerInputView(this)
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
heightFactor = when (resources.configuration.orientation) {
|
||||
Configuration.ORIENTATION_LANDSCAPE -> 1.0f
|
||||
|
||||
@@ -21,10 +21,17 @@ import android.util.AttributeSet
|
||||
import android.widget.FrameLayout
|
||||
|
||||
/**
|
||||
* Root view of the keyboard.
|
||||
* Root window view of the keyboard.
|
||||
*/
|
||||
class InputWindowView : FrameLayout {
|
||||
private val florisboard get() = FlorisBoard.getInstanceOrNull()
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
florisboard?.initWindow()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
|
||||
* | | 1 | | Is private mode
|
||||
* | 1 | | | Is Smartbar quick actions visible
|
||||
* | 1 | | | Is Smartbar showing inline suggestions
|
||||
* | 1 | | | Is composing enabled
|
||||
*
|
||||
* <Byte 7> | <Byte 6> | <Byte 5> | <Byte 4> | Description
|
||||
* ---------|----------|----------|----------|---------------------------------
|
||||
@@ -77,10 +78,10 @@ import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
|
||||
*/
|
||||
class KeyboardState private constructor(var value: ULong, var maskOfInterest: ULong) {
|
||||
companion object {
|
||||
const val M_KEY_VARIATION: ULong = 0x0Fu
|
||||
const val O_KEY_VARIATION: Int = 0
|
||||
const val M_KEYBOARD_MODE: ULong = 0x0Fu
|
||||
const val O_KEYBOARD_MODE: Int = 4
|
||||
const val O_KEYBOARD_MODE: Int = 0
|
||||
const val M_KEY_VARIATION: ULong = 0x0Fu
|
||||
const val O_KEY_VARIATION: Int = 4
|
||||
|
||||
const val F_CAPS: ULong = 0x00000100u
|
||||
const val F_CAPS_LOCK: ULong = 0x00000200u
|
||||
@@ -88,6 +89,7 @@ class KeyboardState private constructor(var value: ULong, var maskOfInterest: UL
|
||||
const val F_IS_PRIVATE_MODE: ULong = 0x00008000u
|
||||
const val F_IS_QUICK_ACTIONS_VISIBLE: ULong = 0x00010000u
|
||||
const val F_IS_SHOWING_INLINE_SUGGESTIONS: ULong = 0x00020000u
|
||||
const val F_IS_COMPOSING_ENABLED: ULong = 0x00040000u
|
||||
|
||||
const val STATE_ALL_ZERO: ULong = 0uL
|
||||
|
||||
@@ -152,11 +154,12 @@ class KeyboardState private constructor(var value: ULong, var maskOfInterest: UL
|
||||
value = (value and (m shl o).inv()) or ((v.toULong() and m) shl o)
|
||||
}
|
||||
|
||||
override operator fun equals(other: Any?): Boolean {
|
||||
if (other is KeyboardState) {
|
||||
return (other.value and maskOfInterest) == (value and maskOfInterest)
|
||||
}
|
||||
return false
|
||||
fun isEqualTo(other: KeyboardState): Boolean {
|
||||
return (other.value and maskOfInterest) == (value and maskOfInterest)
|
||||
}
|
||||
|
||||
fun isDifferentTo(other: KeyboardState): Boolean {
|
||||
return !isEqualTo(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
@@ -165,13 +168,27 @@ class KeyboardState private constructor(var value: ULong, var maskOfInterest: UL
|
||||
return result
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as KeyboardState
|
||||
|
||||
if (value != other.value) return false
|
||||
if (maskOfInterest != other.maskOfInterest) return false
|
||||
if (imeOptions != other.imeOptions) return false
|
||||
if (inputAttributes != other.inputAttributes) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
var keyVariation: KeyVariation
|
||||
get() = KeyVariation.fromInt(getRegion(M_KEY_VARIATION, O_KEY_VARIATION))
|
||||
set(v) { setRegion(M_KEY_VARIATION, O_KEY_VARIATION, v.toInt()) }
|
||||
|
||||
var keyboardMode: KeyboardMode
|
||||
get() = KeyboardMode.fromInt(getRegion(M_KEYBOARD_MODE, O_KEYBOARD_MODE))
|
||||
set(v) { setRegion(M_KEY_VARIATION, O_KEY_VARIATION, v.toInt()) }
|
||||
set(v) { setRegion(M_KEYBOARD_MODE, O_KEYBOARD_MODE, v.toInt()) }
|
||||
|
||||
var caps: Boolean
|
||||
get() = getFlag(F_CAPS)
|
||||
@@ -207,6 +224,10 @@ class KeyboardState private constructor(var value: ULong, var maskOfInterest: UL
|
||||
get() = getFlag(F_IS_SHOWING_INLINE_SUGGESTIONS)
|
||||
set(v) { setFlag(F_IS_SHOWING_INLINE_SUGGESTIONS, v) }
|
||||
|
||||
var isComposingEnabled: Boolean
|
||||
get() = getFlag(F_IS_COMPOSING_ENABLED)
|
||||
set(v) { setFlag(F_IS_COMPOSING_ENABLED, v) }
|
||||
|
||||
interface OnUpdateStateListener {
|
||||
/**
|
||||
* Adds the ability for Views to intercept a update keyboard state dispatch.
|
||||
|
||||
@@ -20,7 +20,7 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
import dev.patrickgold.florisboard.ime.core.Preferences
|
||||
import dev.patrickgold.florisboard.ime.theme.ThemeManager
|
||||
@@ -29,7 +29,7 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.sendBlocking
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
abstract class KeyboardView : View, KeyboardState.OnUpdateStateListener, ThemeManager.OnThemeUpdatedListener {
|
||||
abstract class KeyboardView : ViewGroup, KeyboardState.OnUpdateStateListener, ThemeManager.OnThemeUpdatedListener {
|
||||
protected val florisboard get() = FlorisBoard.getInstanceOrNull()
|
||||
protected val prefs get() = Preferences.default()
|
||||
protected val themeManager get() = ThemeManager.defaultOrNull()
|
||||
@@ -37,7 +37,7 @@ abstract class KeyboardView : View, KeyboardState.OnUpdateStateListener, ThemeMa
|
||||
var isMeasured: Boolean = false
|
||||
private set
|
||||
protected var isTouchable: Boolean = true
|
||||
protected val touchEventChannel: Channel<MotionEvent> = Channel(16)
|
||||
protected val touchEventChannel: Channel<MotionEvent> = Channel(64)
|
||||
protected val mainScope: CoroutineScope = CoroutineScope(Dispatchers.Main.immediate + SupervisorJob())
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
@@ -64,6 +64,10 @@ abstract class KeyboardView : View, KeyboardState.OnUpdateStateListener, ThemeMa
|
||||
themeManager?.unregisterOnThemeUpdatedListener(this)
|
||||
}
|
||||
|
||||
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
||||
event ?: return false
|
||||
|
||||
@@ -22,17 +22,18 @@ import android.view.View
|
||||
import android.widget.*
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.databinding.FlorisboardBinding
|
||||
import dev.patrickgold.florisboard.debug.LogTopic
|
||||
import dev.patrickgold.florisboard.debug.flogInfo
|
||||
import dev.patrickgold.florisboard.ime.core.EditorInstance
|
||||
import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
import dev.patrickgold.florisboard.ime.core.InputKeyEvent
|
||||
import dev.patrickgold.florisboard.ime.core.InputView
|
||||
import dev.patrickgold.florisboard.ime.media.emoji.EmojiKeyData
|
||||
import dev.patrickgold.florisboard.ime.media.emoji.EmojiKeyboardView
|
||||
import dev.patrickgold.florisboard.ime.media.emoticon.EmoticonKeyData
|
||||
import dev.patrickgold.florisboard.ime.media.emoticon.EmoticonKeyboardView
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.TextKeyData
|
||||
import kotlinx.coroutines.*
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -57,8 +58,6 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
private var tabLayout: TabLayout? = null
|
||||
private val tabViews = EnumMap<Tab, LinearLayout>(Tab::class.java)
|
||||
|
||||
private var mediaViewGroup: LinearLayout? = null
|
||||
|
||||
companion object {
|
||||
private var instance: MediaInputManager? = null
|
||||
|
||||
@@ -75,27 +74,20 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
florisboard.addEventListener(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new input view has been registered. Used to initialize all media-relevant
|
||||
* views and layouts.
|
||||
* TODO: evaluate if the view initializing process can be optimized.
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onRegisterInputView(inputView: InputView) {
|
||||
Timber.i("onRegisterInputView(inputView)")
|
||||
override fun onInitializeInputUi(uiBinding: FlorisboardBinding) {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
|
||||
launch(Dispatchers.Default) {
|
||||
mediaViewGroup = inputView.findViewById(R.id.media_input)
|
||||
mediaViewFlipper = inputView.findViewById(R.id.media_input_view_flipper)
|
||||
mediaViewFlipper = uiBinding.media.mediaInputViewFlipper
|
||||
|
||||
// Init bottom buttons
|
||||
inputView.findViewById<Button>(R.id.media_input_switch_to_text_input_button)
|
||||
.setOnTouchListener { view, event -> onBottomButtonEvent(view, event) }
|
||||
inputView.findViewById<ImageButton>(R.id.media_input_backspace_button)
|
||||
.setOnTouchListener { view, event -> onBottomButtonEvent(view, event) }
|
||||
// Init bottom buttons
|
||||
uiBinding.media.mediaInputSwitchToTextInputButton
|
||||
.setOnTouchListener { view, event -> onBottomButtonEvent(view, event) }
|
||||
uiBinding.media.mediaInputBackspaceButton
|
||||
.setOnTouchListener { view, event -> onBottomButtonEvent(view, event) }
|
||||
|
||||
tabLayout = inputView.findViewById(R.id.media_input_tabs)
|
||||
tabLayout?.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
tabLayout = uiBinding.media.mediaInputTabs.also {
|
||||
it.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
when (tab.position) {
|
||||
0 -> setActiveTab(Tab.EMOJI)
|
||||
@@ -107,15 +99,15 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
override fun onTabUnselected(tab: TabLayout.Tab) {}
|
||||
override fun onTabReselected(tab: TabLayout.Tab) {}
|
||||
})
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
for (tab in Tab.values()) {
|
||||
val tabView = createTabViewFor(tab)
|
||||
tabViews[tab] = tabView
|
||||
mediaViewFlipper?.addView(tabView)
|
||||
}
|
||||
tabLayout?.selectTab(tabLayout?.getTabAt(0))
|
||||
launch(Dispatchers.Main) {
|
||||
for (tab in Tab.values()) {
|
||||
val tabView = createTabViewFor(tab)
|
||||
tabViews[tab] = tabView
|
||||
mediaViewFlipper?.addView(tabView)
|
||||
}
|
||||
tabLayout?.selectTab(tabLayout?.getTabAt(0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +115,7 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
* Clean-up of resources and stopping all coroutines.
|
||||
*/
|
||||
override fun onDestroy() {
|
||||
Timber.i("onDestroy()")
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
|
||||
cancel()
|
||||
instance = null
|
||||
|
||||
@@ -72,7 +72,7 @@ class MediaInputView : LinearLayout, FlorisBoard.EventListener,
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
val height = florisboard?.inputView?.desiredMediaKeyboardViewHeight ?: 0.0f
|
||||
val height = florisboard?.uiBinding?.inputView?.desiredMediaKeyboardViewHeight ?: 0.0f
|
||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height.roundToInt(), MeasureSpec.EXACTLY))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ class PopupLayerView : FrameLayout {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
setWillNotDraw(true)
|
||||
}
|
||||
|
||||
var clipboardPopupManager: ClipboardPopupManager? = null
|
||||
|
||||
@@ -146,8 +146,22 @@ class PopupManager<V : View>(
|
||||
}
|
||||
|
||||
fun isSuitableForPopups(key: Key): Boolean {
|
||||
return isSuitableForBasicPopup(key) || isSuitableForExtendedPopup(key)
|
||||
}
|
||||
|
||||
private fun isSuitableForBasicPopup(key: Key): Boolean {
|
||||
return if (key is TextKey) {
|
||||
key.computedData.code > KeyCode.SPACE && key.computedData.code != KeyCode.MULTIPLE_CODE_POINTS
|
||||
val c = key.computedData.code
|
||||
c > KeyCode.SPACE && c != KeyCode.MULTIPLE_CODE_POINTS
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSuitableForExtendedPopup(key: Key): Boolean {
|
||||
return if (key is TextKey) {
|
||||
val c = key.computedData.code
|
||||
c > KeyCode.SPACE && c != KeyCode.MULTIPLE_CODE_POINTS || exceptionsForKeyCodes.contains(c)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@@ -194,7 +208,7 @@ class PopupManager<V : View>(
|
||||
* @param keyHintConfiguration The key hint configuration to use.
|
||||
*/
|
||||
fun show(key: Key, keyHintConfiguration: KeyHintConfiguration) {
|
||||
if (!isSuitableForPopups(key)) return
|
||||
if (!isSuitableForBasicPopup(key)) return
|
||||
|
||||
calc(key)
|
||||
|
||||
@@ -242,10 +256,7 @@ class PopupManager<V : View>(
|
||||
* @param keyHintConfiguration The key hint configuration to use.
|
||||
*/
|
||||
fun extend(key: Key, keyHintConfiguration: KeyHintConfiguration) {
|
||||
if (key is TextKey && !isSuitableForPopups(key)
|
||||
&& !exceptionsForKeyCodes.contains(key.computedData.code)) {
|
||||
return
|
||||
}
|
||||
if (!isSuitableForExtendedPopup(key)) return
|
||||
|
||||
if (!isShowingPopup) {
|
||||
calc(key)
|
||||
@@ -424,7 +435,7 @@ class PopupManager<V : View>(
|
||||
return false
|
||||
}
|
||||
|
||||
popupViewExt.properties.activeElementIndex = when {
|
||||
val newActiveElementIndex = when {
|
||||
anchorLeft -> when {
|
||||
// check if out of boundary on x-axis
|
||||
x < keyPopupDiffX - (anchorOffset + 1) * keyPopupWidth ||
|
||||
@@ -469,7 +480,10 @@ class PopupManager<V : View>(
|
||||
}
|
||||
else -> -1
|
||||
}
|
||||
popupViewExt.invalidate()
|
||||
if (newActiveElementIndex != popupViewExt.properties.activeElementIndex) {
|
||||
popupViewExt.properties.activeElementIndex = newActiveElementIndex
|
||||
popupViewExt.invalidate()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
package dev.patrickgold.florisboard.ime.text
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.view.KeyEvent
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.core.text.isDigitsOnly
|
||||
import dev.patrickgold.florisboard.BuildConfig
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.databinding.FlorisboardBinding
|
||||
import dev.patrickgold.florisboard.debug.*
|
||||
import dev.patrickgold.florisboard.ime.clip.provider.ClipboardItem
|
||||
import dev.patrickgold.florisboard.ime.core.*
|
||||
@@ -43,7 +41,6 @@ import dev.patrickgold.florisboard.ime.text.layout.LayoutManager
|
||||
import dev.patrickgold.florisboard.ime.text.smartbar.SmartbarView
|
||||
import kotlinx.coroutines.*
|
||||
import org.json.JSONArray
|
||||
import kotlin.math.roundToLong
|
||||
|
||||
/**
|
||||
* TextInputManager is responsible for managing everything which is related to text input. All of
|
||||
@@ -72,7 +69,6 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
private var textInputKeyboardView: TextKeyboardView? = null
|
||||
lateinit var textKeyboardIconSet: TextKeyboardIconSet
|
||||
private set
|
||||
private var textViewGroup: LinearLayout? = null
|
||||
private val dictionaryManager: DictionaryManager get() = DictionaryManager.default()
|
||||
val inputEventDispatcher: InputEventDispatcher = InputEventDispatcher.new(
|
||||
repeatableKeyCodes = intArrayOf(
|
||||
@@ -89,6 +85,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
|
||||
val activeState: KeyboardState get() = florisboard.activeState
|
||||
private var newCapsState: Boolean = false
|
||||
private var isNumberRowVisible: Boolean = false
|
||||
|
||||
// Composing text related properties
|
||||
var isManualSelectionMode: Boolean = false
|
||||
@@ -213,6 +210,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
layoutManager = LayoutManager()
|
||||
textKeyboardIconSet = TextKeyboardIconSet.new(florisboard)
|
||||
inputEventDispatcher.keyEventReceiver = this
|
||||
isNumberRowVisible = prefs.keyboard.numberRow
|
||||
var subtypes = florisboard.subtypeManager.subtypes
|
||||
if (subtypes.isEmpty()) {
|
||||
subtypes = listOf(Subtype.DEFAULT)
|
||||
@@ -224,64 +222,21 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateInputView() {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the newly registered input view.
|
||||
*/
|
||||
override fun onRegisterInputView(inputView: InputView) {
|
||||
override fun onInitializeInputUi(uiBinding: FlorisboardBinding) {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
|
||||
textViewGroup = inputView.findViewById(R.id.text_input)
|
||||
textInputKeyboardView = inputView.findViewById(R.id.text_input_keyboard_view)
|
||||
textInputKeyboardView?.setIconSet(textKeyboardIconSet)
|
||||
textInputKeyboardView?.setComputingEvaluator(evaluator)
|
||||
textInputKeyboardView?.sync()
|
||||
|
||||
launch(Dispatchers.Main) {
|
||||
val animator1 = textViewGroup?.let {
|
||||
ObjectAnimator.ofFloat(it, "alpha", 0.9f, 1.0f).apply {
|
||||
duration = 125
|
||||
repeatCount = 0
|
||||
start()
|
||||
}
|
||||
}
|
||||
val animator2 = textViewGroup?.let {
|
||||
ObjectAnimator.ofFloat(it, "alpha", 1.0f, 0.4f).apply {
|
||||
startDelay = 125
|
||||
duration = 500
|
||||
repeatCount = ValueAnimator.INFINITE
|
||||
repeatMode = ValueAnimator.REVERSE
|
||||
start()
|
||||
}
|
||||
}
|
||||
setActiveKeyboardMode(getActiveKeyboardMode())
|
||||
animator1?.cancel()
|
||||
animator2?.cancel()
|
||||
val animator3 = textViewGroup?.let {
|
||||
ObjectAnimator.ofFloat(it, "alpha", it.alpha, 1.0f).apply {
|
||||
duration = (((1.0f - it.alpha) / 0.6f) * 125f).roundToLong()
|
||||
repeatCount = 0
|
||||
start()
|
||||
}
|
||||
}
|
||||
delay(animator3?.duration ?: 1)
|
||||
animator3?.end()
|
||||
textInputKeyboardView = uiBinding.text.mainKeyboardView.also {
|
||||
it.setIconSet(textKeyboardIconSet)
|
||||
it.setComputingEvaluator(evaluator)
|
||||
it.sync()
|
||||
}
|
||||
}
|
||||
|
||||
fun registerSmartbarView(view: SmartbarView) {
|
||||
smartbarView = view
|
||||
smartbarView?.setEventListener(this)
|
||||
smartbarView?.sync()
|
||||
}
|
||||
|
||||
fun unregisterSmartbarView(view: SmartbarView) {
|
||||
if (smartbarView == view) {
|
||||
smartbarView = null
|
||||
smartbarView = uiBinding.text.smartbar.root.also {
|
||||
it.setEventListener(this)
|
||||
it.sync()
|
||||
}
|
||||
|
||||
setActiveKeyboardMode(getActiveKeyboardMode(), updateState = false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,18 +245,25 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
override fun onDestroy() {
|
||||
flogInfo(LogTopic.IMS_EVENTS)
|
||||
|
||||
smartbarView?.setEventListener(null)
|
||||
smartbarView = null
|
||||
|
||||
textInputKeyboardView?.setComputingEvaluator(null)
|
||||
textInputKeyboardView = null
|
||||
keyboards.clear()
|
||||
|
||||
inputEventDispatcher.keyEventReceiver = null
|
||||
inputEventDispatcher.close()
|
||||
|
||||
dictionaryManager.unloadUserDictionariesIfNecessary()
|
||||
|
||||
cancel()
|
||||
layoutManager.onDestroy()
|
||||
instance = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the [KeyboardState.keyboardMode], [KeyboardState.keyVariation] and [EditorInstance.isComposingEnabled]
|
||||
* Evaluates the [KeyboardState.keyboardMode], [KeyboardState.keyVariation] and [KeyboardState.isComposingEnabled]
|
||||
* property values when starting to interact with a input editor. Also resets the composing
|
||||
* texts and sets the initial caps mode accordingly.
|
||||
*/
|
||||
@@ -340,25 +302,29 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
KeyboardMode.CHARACTERS
|
||||
}
|
||||
}
|
||||
instance.apply {
|
||||
isComposingEnabled = when (keyboardMode) {
|
||||
KeyboardMode.NUMERIC,
|
||||
KeyboardMode.PHONE,
|
||||
KeyboardMode.PHONE2 -> false
|
||||
else -> activeState.keyVariation != KeyVariation.PASSWORD &&
|
||||
prefs.suggestion.enabled// &&
|
||||
//!instance.inputAttributes.flagTextAutoComplete &&
|
||||
//!instance.inputAttributes.flagTextNoSuggestions
|
||||
}
|
||||
activeState.isPrivateMode = prefs.advanced.forcePrivateMode ||
|
||||
activeState.imeOptions.flagNoPersonalizedLearning
|
||||
activeState.isComposingEnabled = when (keyboardMode) {
|
||||
KeyboardMode.NUMERIC,
|
||||
KeyboardMode.PHONE,
|
||||
KeyboardMode.PHONE2 -> false
|
||||
else -> activeState.keyVariation != KeyVariation.PASSWORD &&
|
||||
prefs.suggestion.enabled// &&
|
||||
//!instance.inputAttributes.flagTextAutoComplete &&
|
||||
//!instance.inputAttributes.flagTextNoSuggestions
|
||||
}
|
||||
val newIsNumberRowVisible = prefs.keyboard.numberRow
|
||||
if (isNumberRowVisible != newIsNumberRowVisible) {
|
||||
keyboards.clear(KeyboardMode.CHARACTERS)
|
||||
isNumberRowVisible = newIsNumberRowVisible
|
||||
}
|
||||
setActiveKeyboardMode(keyboardMode, updateState = false)
|
||||
instance.composingEnabledChanged()
|
||||
activeState.isPrivateMode = prefs.advanced.forcePrivateMode ||
|
||||
activeState.imeOptions.flagNoPersonalizedLearning
|
||||
if (!prefs.correction.rememberCapsLockState) {
|
||||
activeState.capsLock = false
|
||||
}
|
||||
isGlidePostEffect = false
|
||||
updateCapsState()
|
||||
setActiveKeyboardMode(keyboardMode, updateState = false)
|
||||
smartbarView?.setCandidateSuggestionWords(System.nanoTime(), null)
|
||||
}
|
||||
|
||||
@@ -382,7 +348,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
/**
|
||||
* Sets the active keyboard mode and updates the [KeyboardState.isQuickActionsVisible] state.
|
||||
*/
|
||||
private fun setActiveKeyboardMode(mode: KeyboardMode, updateState: Boolean = true) = launch {
|
||||
private fun setActiveKeyboardMode(mode: KeyboardMode, updateState: Boolean = true) {
|
||||
activeState.keyboardMode = mode
|
||||
isManualSelectionMode = false
|
||||
isManualSelectionModeStart = false
|
||||
@@ -406,15 +372,17 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSubtypeChanged(newSubtype: Subtype) {
|
||||
override fun onSubtypeChanged(newSubtype: Subtype, doRefreshLayouts: Boolean) {
|
||||
launch {
|
||||
if (activeEditorInstance.isComposingEnabled) {
|
||||
if (activeState.isComposingEnabled) {
|
||||
dictionaryManager.prepareDictionaries(newSubtype)
|
||||
}
|
||||
if (prefs.glide.enabled) {
|
||||
GlideTypingManager.getInstance().setWordData(newSubtype)
|
||||
}
|
||||
setActiveKeyboard(getActiveKeyboardMode(), newSubtype)
|
||||
if (doRefreshLayouts) {
|
||||
setActiveKeyboard(getActiveKeyboardMode(), newSubtype)
|
||||
}
|
||||
}
|
||||
isGlidePostEffect = false
|
||||
}
|
||||
@@ -428,7 +396,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(), In
|
||||
updateCapsState()
|
||||
}
|
||||
flogInfo(LogTopic.IMS_EVENTS) { "current word: ${activeEditorInstance.cachedInput.currentWord.text}" }
|
||||
if (activeEditorInstance.isComposingEnabled && !inputEventDispatcher.isPressed(KeyCode.DELETE) && !isGlidePostEffect) {
|
||||
if (activeState.isComposingEnabled && !inputEventDispatcher.isPressed(KeyCode.DELETE) && !isGlidePostEffect) {
|
||||
if (activeEditorInstance.shouldReevaluateComposingSuggestions) {
|
||||
activeEditorInstance.shouldReevaluateComposingSuggestions = false
|
||||
launch(Dispatchers.Default) {
|
||||
|
||||
@@ -98,11 +98,11 @@ class EditingKeyboardView : ConstraintLayout, FlorisBoard.EventListener,
|
||||
}
|
||||
MeasureSpec.AT_MOST -> {
|
||||
// Can't be bigger than...
|
||||
(florisboard?.inputView?.desiredTextKeyboardViewHeight ?: 0.0f).coerceAtMost(heightSize)
|
||||
(florisboard?.uiBinding?.inputView?.desiredTextKeyboardViewHeight ?: 0.0f).coerceAtMost(heightSize)
|
||||
}
|
||||
else -> {
|
||||
// Be whatever you want
|
||||
florisboard?.inputView?.desiredTextKeyboardViewHeight ?: 0.0f
|
||||
florisboard?.uiBinding?.inputView?.desiredTextKeyboardViewHeight ?: 0.0f
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.ime.text.keyboard
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.PaintDrawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import dev.patrickgold.florisboard.common.ViewUtils
|
||||
|
||||
class TextKeyView : View {
|
||||
private val parentKeyboardView get() = parent as? TextKeyboardView
|
||||
|
||||
var key: TextKey? = null
|
||||
|
||||
val bgDrawable = PaintDrawable().also {
|
||||
it.setCornerRadius(ViewUtils.dp2px(6.0f))
|
||||
}
|
||||
val labelPaint: Paint = Paint().also {
|
||||
it.isAntiAlias = true
|
||||
it.isFakeBoldText = false
|
||||
it.textAlign = Paint.Align.CENTER
|
||||
it.typeface = Typeface.DEFAULT
|
||||
}
|
||||
val hintedLabelPaint: Paint = Paint().also {
|
||||
it.isAntiAlias = true
|
||||
it.isFakeBoldText = false
|
||||
it.textAlign = Paint.Align.CENTER
|
||||
it.typeface = Typeface.MONOSPACE
|
||||
}
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
background = bgDrawable
|
||||
setWillNotDraw(false)
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onHoverEvent(event: MotionEvent?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
return // This view does not measure itself
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas?) {
|
||||
super.onDraw(canvas)
|
||||
val key = key ?: return
|
||||
canvas ?: return
|
||||
canvas.save()
|
||||
canvas.translate(-x, -y)
|
||||
parentKeyboardView?.onDrawComputedKey(canvas, key, this)
|
||||
canvas.restore()
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,9 @@ class TextKeyboard(
|
||||
val rowCount: Int
|
||||
get() = arrangement.size
|
||||
|
||||
val keyCount: Int
|
||||
get() = arrangement.sumOf { it.size }
|
||||
|
||||
companion object {
|
||||
fun layoutDrawableBounds(key: TextKey, factor: Double) {
|
||||
layoutForegroundBounds(key, key.visibleDrawableBounds, 0.21 * (1.0 / factor), isLabel = false)
|
||||
|
||||
@@ -55,9 +55,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
private var computedKeyboard: TextKeyboard? = null
|
||||
private var iconSet: TextKeyboardIconSet? = null
|
||||
|
||||
// IS ONLY USED IF KEYBOARD IS IN PREVIEW MODE
|
||||
private var cachedTheme: Theme? = null
|
||||
|
||||
private var cachedState: KeyboardState = KeyboardState.new(maskOfInterest = KeyboardState.INTEREST_TEXT)
|
||||
|
||||
private var externalComputingEvaluator: TextComputingEvaluator? = null
|
||||
@@ -109,8 +107,8 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
}
|
||||
|
||||
internal var isSmartbarKeyboardView: Boolean = false
|
||||
private var isPreviewMode: Boolean = false
|
||||
private var isLoadingPlaceholderKeyboard: Boolean = false
|
||||
internal var isPreviewMode: Boolean = false
|
||||
internal var isLoadingPlaceholderKeyboard: Boolean = false
|
||||
|
||||
private var keyHintConfiguration: KeyHintConfiguration = KeyHintConfiguration.HINTS_DISABLED
|
||||
private val pointerMap: PointerMap<TouchPointer> = PointerMap { TouchPointer() }
|
||||
@@ -129,21 +127,12 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
private var fadingGlideRadius: Float = 0.0f
|
||||
|
||||
val desiredKey: TextKey = TextKey(data = TextKeyData.UNSPECIFIED)
|
||||
private val desiredKeyView: TextKeyView = TextKeyView(context).also {
|
||||
it.key = desiredKey
|
||||
}
|
||||
private var keyMarginH: Int = 0
|
||||
private var keyMarginV: Int = 0
|
||||
|
||||
private var keyBackgroundPaint = Paint().also {
|
||||
it.isAntiAlias = true
|
||||
it.style = Paint.Style.FILL
|
||||
}
|
||||
private var keyShadowBackgroundPaint = Paint().also {
|
||||
it.isAntiAlias = true
|
||||
it.style = Paint.Style.STROKE
|
||||
it.strokeCap = Paint.Cap.ROUND
|
||||
it.strokeWidth = 6.0f
|
||||
}
|
||||
private val keyBackgroundCornerSize: Float = ViewUtils.dp2px(6.0f)
|
||||
|
||||
private var backgroundDrawable: PaintDrawable = PaintDrawable()
|
||||
private val baselineTextSize = resources.getDimension(R.dimen.key_textSize)
|
||||
var fontSizeMultiplier: Double = 1.0
|
||||
@@ -151,21 +140,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
private val glideTrailPaint: Paint = Paint()
|
||||
private var labelPaintTextSize: Float = resources.getDimension(R.dimen.key_textSize)
|
||||
private var labelPaintSpaceTextSize: Float = resources.getDimension(R.dimen.key_textSize)
|
||||
private val labelPaint: Paint = Paint().also {
|
||||
it.isAntiAlias = true
|
||||
it.isFakeBoldText = false
|
||||
it.textAlign = Paint.Align.CENTER
|
||||
it.textSize = labelPaintTextSize
|
||||
it.typeface = Typeface.DEFAULT
|
||||
}
|
||||
private var hintedLabelPaintTextSize: Float = resources.getDimension(R.dimen.key_textHintSize)
|
||||
private val hintedLabelPaint: Paint = Paint().also {
|
||||
it.isAntiAlias = true
|
||||
it.isFakeBoldText = false
|
||||
it.textAlign = Paint.Align.CENTER
|
||||
it.textSize = hintedLabelPaintTextSize
|
||||
it.typeface = Typeface.MONOSPACE
|
||||
}
|
||||
private val tempRect: Rect = Rect()
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
@@ -186,6 +161,10 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
popupManager = PopupManager(this, popupLayerView)
|
||||
swipeGestureDetector.isEnabled = !isSmartbarKeyboardView
|
||||
|
||||
if (isPreviewMode) {
|
||||
background = backgroundDrawable
|
||||
}
|
||||
|
||||
setWillNotDraw(false)
|
||||
}
|
||||
|
||||
@@ -195,6 +174,17 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
|
||||
fun setComputedKeyboard(keyboard: TextKeyboard) {
|
||||
flogInfo(LogTopic.TEXT_KEYBOARD_VIEW) { keyboard.mode.toString() }
|
||||
val renderViewDiff = keyboard.keyCount - childCount
|
||||
if (renderViewDiff > 0) {
|
||||
// We have more keys than render views, add abs(diff) views
|
||||
for (n in 0 until abs(renderViewDiff)) {
|
||||
addView(TextKeyView(context))
|
||||
}
|
||||
} else if (renderViewDiff < 0) {
|
||||
// We have more render views than keys, remove abs(diff) views
|
||||
val n = abs(renderViewDiff)
|
||||
removeViews(childCount - n, n)
|
||||
}
|
||||
computedKeyboard = keyboard
|
||||
initGlideClassifier(keyboard)
|
||||
if (isMeasured) {
|
||||
@@ -212,7 +202,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
override fun onUpdateKeyboardState(newState: KeyboardState) {
|
||||
flogInfo(LogTopic.TEXT_KEYBOARD_VIEW) { computedKeyboard?.mode?.toString() ?: "" }
|
||||
if (isMeasured) {
|
||||
if (newState != cachedState) {
|
||||
if (cachedState.isDifferentTo(newState)) {
|
||||
// Something within the defined interest has changed
|
||||
cachedState.reset(newState)
|
||||
computeKeyboard()
|
||||
@@ -333,7 +323,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
pointer.longPressJob = null
|
||||
pointer.hasTriggeredGestureMove = true
|
||||
pointer.activeKey?.let { activeKey ->
|
||||
activeKey.setPressed(false) { invalidate() }
|
||||
activeKey.setPressed(false) { invalidate(activeKey) }
|
||||
florisboard!!.textInputManager.inputEventDispatcher.let { dispatcher ->
|
||||
if (dispatcher.isPressed(activeKey.computedData.code)) {
|
||||
dispatcher.send(InputKeyEvent.cancel(activeKey.computedData))
|
||||
@@ -351,6 +341,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
val pointerId = event.getPointerId(pointerIndex)
|
||||
val pointer = pointerMap.findById(pointerId)
|
||||
if (pointer != null) {
|
||||
pointer.index = pointerIndex
|
||||
if (swipeGestureDetector.onTouchUp(event, pointer) || pointer.hasTriggeredGestureMove || pointer.shouldBlockNextUp) {
|
||||
if (pointer.hasTriggeredGestureMove && pointer.initialKey?.computedData?.code == KeyCode.DELETE) {
|
||||
florisboard!!.textInputManager.isGlidePostEffect = false
|
||||
@@ -420,7 +411,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
}
|
||||
florisboard!!.keyPressVibrate()
|
||||
florisboard!!.keyPressSound(key.computedData)
|
||||
key.setPressed(true) { invalidate() }
|
||||
key.setPressed(true) { invalidate(key) }
|
||||
if (pointer.initialKey == null) {
|
||||
pointer.initialKey = key
|
||||
}
|
||||
@@ -502,7 +493,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
val initialKey = pointer.initialKey
|
||||
val activeKey = pointer.activeKey
|
||||
if (initialKey != null && activeKey != null) {
|
||||
activeKey.setPressed(false) { invalidate() }
|
||||
activeKey.setPressed(false) { invalidate(activeKey) }
|
||||
florisboard!!.textInputManager.inputEventDispatcher.let { dispatcher ->
|
||||
if (popupManager.isSuitableForPopups(activeKey)) {
|
||||
val retData = popupManager.getActiveKeyData(activeKey, keyHintConfiguration)
|
||||
@@ -545,7 +536,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
|
||||
val activeKey = pointer.activeKey
|
||||
if (activeKey != null) {
|
||||
activeKey.setPressed(false) { invalidate() }
|
||||
activeKey.setPressed(false) { invalidate(activeKey) }
|
||||
florisboard.textInputManager.inputEventDispatcher.let { dispatcher ->
|
||||
dispatcher.send(InputKeyEvent.cancel(activeKey.computedData))
|
||||
}
|
||||
@@ -734,7 +725,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
val desiredHeight = if (isSmartbarKeyboardView || isPreviewMode) {
|
||||
MeasureSpec.getSize(heightMeasureSpec).toFloat()
|
||||
} else {
|
||||
(florisboard?.inputView?.desiredTextKeyboardViewHeight ?: MeasureSpec.getSize(heightMeasureSpec).toFloat())
|
||||
(florisboard?.uiBinding?.inputView?.desiredTextKeyboardViewHeight ?: MeasureSpec.getSize(heightMeasureSpec).toFloat())
|
||||
} * if (isPreviewMode) {
|
||||
0.90f
|
||||
} else {
|
||||
@@ -749,7 +740,6 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
flogInfo(LogTopic.TEXT_KEYBOARD_VIEW) { computedKeyboard?.mode?.toString() ?: "" }
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
computeDesiredDimensions()
|
||||
computeKeyboard()
|
||||
}
|
||||
@@ -767,7 +757,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
isSmartbarKeyboardView -> {
|
||||
measuredHeight
|
||||
}
|
||||
florisboard?.inputView?.shouldGiveAdditionalSpace == true -> {
|
||||
florisboard?.uiBinding?.inputView?.shouldGiveAdditionalSpace == true -> {
|
||||
(measuredHeight / (keyboard.rowCount + 0.5f).coerceAtMost(5.0f)).toInt()
|
||||
}
|
||||
else -> {
|
||||
@@ -793,23 +783,23 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
TextKeyboard.layoutLabelBounds(desiredKey)
|
||||
|
||||
setTextSizeFor(
|
||||
labelPaint,
|
||||
desiredKeyView.labelPaint,
|
||||
desiredKey.visibleLabelBounds.width().toFloat(),
|
||||
desiredKey.visibleLabelBounds.height().toFloat(),
|
||||
"X",
|
||||
fontSizeMultiplier
|
||||
)
|
||||
labelPaintTextSize = labelPaint.textSize
|
||||
labelPaintSpaceTextSize = labelPaint.textSize.coerceAtMost(resources.getDimension(R.dimen.key_space_textSize))
|
||||
labelPaintTextSize = desiredKeyView.labelPaint.textSize
|
||||
labelPaintSpaceTextSize = desiredKeyView.labelPaint.textSize.coerceAtMost(resources.getDimension(R.dimen.key_space_textSize))
|
||||
|
||||
setTextSizeFor(
|
||||
hintedLabelPaint,
|
||||
desiredKeyView.hintedLabelPaint,
|
||||
desiredKey.visibleBounds.width() * 1.0f / 5.0f,
|
||||
desiredKey.visibleBounds.height() * 1.0f / 5.0f,
|
||||
"X",
|
||||
fontSizeMultiplier
|
||||
)
|
||||
hintedLabelPaintTextSize = hintedLabelPaint.textSize
|
||||
hintedLabelPaintTextSize = desiredKeyView.hintedLabelPaint.textSize
|
||||
}
|
||||
|
||||
private fun computeKeyboard() {
|
||||
@@ -820,6 +810,117 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
computeLabelsAndDrawables(key, keyHintConfiguration)
|
||||
}
|
||||
keyboard.layout(this)
|
||||
val theme = cachedTheme ?: themeManager?.activeTheme ?: Theme.BASE_THEME
|
||||
val isBorderless = !theme.getAttr(Theme.Attr.KEY_SHOW_BORDER).toOnOff().state
|
||||
keyboard.keys().withIndex().forEach { (n, key) ->
|
||||
getChildAt(n)?.let { rv ->
|
||||
if (rv is TextKeyView) {
|
||||
rv.key = key
|
||||
layoutRenderView(rv, key, isBorderless)
|
||||
prepareKey(key, theme, rv)
|
||||
rv.invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun layoutRenderView(rv: TextKeyView, key: TextKey, isBorderless: Boolean) {
|
||||
rv.layout(
|
||||
key.visibleBounds.left,
|
||||
if (isBorderless) {
|
||||
(key.visibleBounds.top + key.visibleBounds.height() * 0.12).toInt()
|
||||
} else {
|
||||
key.visibleBounds.top
|
||||
},
|
||||
key.visibleBounds.right,
|
||||
if (isBorderless) {
|
||||
(key.visibleBounds.bottom - key.visibleBounds.height() * 0.12).toInt()
|
||||
} else {
|
||||
key.visibleBounds.bottom
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun prepareKey(key: TextKey, theme: Theme, renderView: TextKeyView) {
|
||||
val keyBackground: ThemeValue
|
||||
val keyForeground: ThemeValue
|
||||
val shouldShowBorder: Boolean
|
||||
val themeLabel = key.computedData.asString(isForDisplay = false)
|
||||
when {
|
||||
isLoadingPlaceholderKeyboard -> {
|
||||
shouldShowBorder = theme.getAttr(Theme.Attr.KEY_SHOW_BORDER, themeLabel).toOnOff().state
|
||||
if (key.isPressed && key.isEnabled) {
|
||||
keyBackground = theme.getAttr(Theme.Attr.KEY_BACKGROUND_PRESSED, themeLabel)
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND_PRESSED, themeLabel)
|
||||
} else {
|
||||
keyBackground = if (shouldShowBorder) {
|
||||
theme.getAttr(Theme.Attr.KEY_BACKGROUND, themeLabel)
|
||||
} else {
|
||||
theme.getAttr(Theme.Attr.SMARTBAR_BUTTON_BACKGROUND, themeLabel)
|
||||
}
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND, themeLabel)
|
||||
}
|
||||
}
|
||||
isSmartbarKeyboardView -> {
|
||||
shouldShowBorder = false
|
||||
if (key.isPressed && key.isEnabled) {
|
||||
keyBackground = theme.getAttr(Theme.Attr.SMARTBAR_BUTTON_BACKGROUND)
|
||||
keyForeground = theme.getAttr(Theme.Attr.SMARTBAR_FOREGROUND)
|
||||
} else {
|
||||
keyBackground = theme.getAttr(Theme.Attr.SMARTBAR_BACKGROUND)
|
||||
keyForeground = if (!key.isEnabled) {
|
||||
theme.getAttr(Theme.Attr.SMARTBAR_FOREGROUND_ALT)
|
||||
} else {
|
||||
theme.getAttr(Theme.Attr.SMARTBAR_FOREGROUND)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val capsSpecific = when {
|
||||
cachedState.capsLock -> {
|
||||
"capslock"
|
||||
}
|
||||
cachedState.caps -> {
|
||||
"caps"
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
shouldShowBorder = theme.getAttr(Theme.Attr.KEY_SHOW_BORDER, themeLabel, capsSpecific).toOnOff().state
|
||||
if (key.isPressed && key.isEnabled) {
|
||||
keyBackground = theme.getAttr(Theme.Attr.KEY_BACKGROUND_PRESSED, themeLabel, capsSpecific)
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND_PRESSED, themeLabel, capsSpecific)
|
||||
} else {
|
||||
keyBackground = theme.getAttr(Theme.Attr.KEY_BACKGROUND, themeLabel, capsSpecific)
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND, themeLabel, capsSpecific)
|
||||
}
|
||||
}
|
||||
}
|
||||
renderView.let { rv ->
|
||||
rv.elevation = if (shouldShowBorder) 4.0f else 0.0f
|
||||
rv.bgDrawable.paint.color = keyBackground.toSolidColor().color
|
||||
rv.labelPaint.let {
|
||||
it.color = keyForeground.toSolidColor().color
|
||||
if (computedKeyboard?.mode == KeyboardMode.CHARACTERS && key.computedData.code == KeyCode.SPACE) {
|
||||
it.alpha = 120
|
||||
}
|
||||
it.textSize = when (key.computedData.code) {
|
||||
KeyCode.SPACE -> labelPaintSpaceTextSize
|
||||
KeyCode.VIEW_CHARACTERS,
|
||||
KeyCode.VIEW_SYMBOLS,
|
||||
KeyCode.VIEW_SYMBOLS2 -> labelPaintTextSize * 0.80f
|
||||
KeyCode.VIEW_NUMERIC,
|
||||
KeyCode.VIEW_NUMERIC_ADVANCED -> labelPaintTextSize * 0.55f
|
||||
else -> labelPaintTextSize
|
||||
}
|
||||
}
|
||||
rv.hintedLabelPaint.let {
|
||||
it.color = keyForeground.toSolidColor().color
|
||||
it.alpha = 170
|
||||
it.textSize = hintedLabelPaintTextSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -882,160 +983,34 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
} else {
|
||||
glideTrailPaint.color = theme.getAttr(Theme.Attr.GLIDE_TRAIL_COLOR).toSolidColor().color
|
||||
}
|
||||
keyShadowBackgroundPaint.color = Color.argb(32, 0, 0, 0)
|
||||
invalidate()
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas?) {
|
||||
super.onDraw(canvas)
|
||||
if (!isVisible) return
|
||||
if (canvas == null) {
|
||||
flogWarning(LogTopic.TEXT_KEYBOARD_VIEW) { "${computedKeyboard?.mode} Cannot draw: 'canvas' is null!" }
|
||||
return
|
||||
} else {
|
||||
flogInfo(LogTopic.TEXT_KEYBOARD_VIEW) { computedKeyboard?.mode.toString() }
|
||||
}
|
||||
if (isPreviewMode) {
|
||||
backgroundDrawable.let {
|
||||
it.setBounds(0, 0, measuredWidth, measuredHeight)
|
||||
it.draw(canvas)
|
||||
val isBorderless = !theme.getAttr(Theme.Attr.KEY_SHOW_BORDER).toOnOff().state
|
||||
for (n in 0 until childCount) {
|
||||
val rv = getChildAt(n) as? TextKeyView
|
||||
if (rv?.key != null) {
|
||||
layoutRenderView(rv, rv.key!!, isBorderless)
|
||||
prepareKey(rv.key!!, cachedTheme ?: themeManager?.activeTheme ?: Theme.BASE_THEME, rv)
|
||||
rv.invalidate()
|
||||
}
|
||||
}
|
||||
onDrawComputedKeyboard(canvas)
|
||||
}
|
||||
|
||||
private fun onDrawComputedKeyboard(canvas: Canvas) {
|
||||
flogInfo(LogTopic.TEXT_KEYBOARD_VIEW) { computedKeyboard?.mode.toString() }
|
||||
val keyboard = computedKeyboard ?: return
|
||||
|
||||
// SUPER JANK nyi message implementation for the editing layout
|
||||
if (keyboard.mode == KeyboardMode.EDITING) {
|
||||
val msg = "The Editing layout is currently not available, see #216."
|
||||
val msg2 = "Will be re-implemented in a later stage."
|
||||
labelPaint.apply {
|
||||
textSize = 30.0f
|
||||
private fun invalidate(key: TextKey) {
|
||||
for (n in 0 until childCount) {
|
||||
val rv = getChildAt(n) as? TextKeyView
|
||||
if (rv != null && rv.key == key) {
|
||||
prepareKey(key, cachedTheme ?: themeManager?.activeTheme ?: Theme.BASE_THEME, rv)
|
||||
rv.invalidate()
|
||||
break
|
||||
}
|
||||
canvas.drawText(msg, measuredWidth / 2.0f, 100.0f, labelPaint)
|
||||
canvas.drawText(msg2, measuredWidth / 2.0f, 200.0f, labelPaint)
|
||||
return
|
||||
}
|
||||
|
||||
val theme = cachedTheme ?: themeManager?.activeTheme ?: Theme.BASE_THEME
|
||||
val isBorderless = !theme.getAttr(Theme.Attr.KEY_SHOW_BORDER).toOnOff().state &&
|
||||
Color.alpha(theme.getAttr(Theme.Attr.KEY_BACKGROUND).toSolidColor().color) <= 0x0F
|
||||
for (key in keyboard.keys()) {
|
||||
onDrawComputedKey(canvas, key, theme, isBorderless)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onDrawComputedKey(canvas: Canvas, key: TextKey, theme: Theme, isBorderless: Boolean) {
|
||||
fun onDrawComputedKey(canvas: Canvas, key: TextKey, renderView: TextKeyView) {
|
||||
if (!key.isVisible) return
|
||||
|
||||
val keyBackground: ThemeValue
|
||||
val keyForeground: ThemeValue
|
||||
val shouldShowBorder: Boolean
|
||||
val themeLabel = key.computedData.asString(isForDisplay = false)
|
||||
when {
|
||||
isLoadingPlaceholderKeyboard -> {
|
||||
shouldShowBorder = theme.getAttr(Theme.Attr.KEY_SHOW_BORDER, themeLabel).toOnOff().state
|
||||
if (key.isPressed && key.isEnabled) {
|
||||
keyBackground = theme.getAttr(Theme.Attr.KEY_BACKGROUND_PRESSED, themeLabel)
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND_PRESSED, themeLabel)
|
||||
} else {
|
||||
keyBackground = if (shouldShowBorder) {
|
||||
theme.getAttr(Theme.Attr.KEY_BACKGROUND, themeLabel)
|
||||
} else {
|
||||
theme.getAttr(Theme.Attr.SMARTBAR_BUTTON_BACKGROUND, themeLabel)
|
||||
}
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND, themeLabel)
|
||||
}
|
||||
}
|
||||
isSmartbarKeyboardView -> {
|
||||
shouldShowBorder = false
|
||||
if (key.isPressed && key.isEnabled) {
|
||||
keyBackground = theme.getAttr(Theme.Attr.SMARTBAR_BUTTON_BACKGROUND)
|
||||
keyForeground = theme.getAttr(Theme.Attr.SMARTBAR_FOREGROUND)
|
||||
} else {
|
||||
keyBackground = theme.getAttr(Theme.Attr.SMARTBAR_BACKGROUND)
|
||||
keyForeground = if (!key.isEnabled) {
|
||||
theme.getAttr(Theme.Attr.SMARTBAR_FOREGROUND_ALT)
|
||||
} else {
|
||||
theme.getAttr(Theme.Attr.SMARTBAR_FOREGROUND)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val capsSpecific = when {
|
||||
cachedState.capsLock -> {
|
||||
"capslock"
|
||||
}
|
||||
cachedState.caps -> {
|
||||
"caps"
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
shouldShowBorder = theme.getAttr(Theme.Attr.KEY_SHOW_BORDER, themeLabel, capsSpecific).toOnOff().state
|
||||
if (key.isPressed && key.isEnabled) {
|
||||
keyBackground = theme.getAttr(Theme.Attr.KEY_BACKGROUND_PRESSED, themeLabel, capsSpecific)
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND_PRESSED, themeLabel, capsSpecific)
|
||||
} else {
|
||||
keyBackground = theme.getAttr(Theme.Attr.KEY_BACKGROUND, themeLabel, capsSpecific)
|
||||
keyForeground = theme.getAttr(Theme.Attr.KEY_FOREGROUND, themeLabel, capsSpecific)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val bgBoundsLeft = key.visibleBounds.left.toFloat()
|
||||
val bgBoundsTop = (if (isBorderless) {
|
||||
(key.visibleBounds.top + key.visibleBounds.height() * 0.12).toInt()
|
||||
} else {
|
||||
key.visibleBounds.top
|
||||
}).toFloat()
|
||||
val bgBoundsRight = key.visibleBounds.right.toFloat()
|
||||
val bgBoundsBottom = (if (isBorderless) {
|
||||
(key.visibleBounds.bottom - key.visibleBounds.height() * 0.12).toInt()
|
||||
} else {
|
||||
key.visibleBounds.bottom
|
||||
}).toFloat()
|
||||
|
||||
if (shouldShowBorder) {
|
||||
keyShadowBackgroundPaint.let {
|
||||
canvas.drawRoundRect(
|
||||
bgBoundsLeft, bgBoundsTop, bgBoundsRight, bgBoundsBottom,
|
||||
keyBackgroundCornerSize,
|
||||
keyBackgroundCornerSize,
|
||||
it
|
||||
)
|
||||
}
|
||||
}
|
||||
keyBackgroundPaint.let {
|
||||
it.color = keyBackground.toSolidColor().color
|
||||
canvas.drawRoundRect(
|
||||
bgBoundsLeft, bgBoundsTop, bgBoundsRight, bgBoundsBottom,
|
||||
keyBackgroundCornerSize,
|
||||
keyBackgroundCornerSize,
|
||||
it
|
||||
)
|
||||
}
|
||||
|
||||
val label = key.label
|
||||
if (label != null) {
|
||||
labelPaint.let {
|
||||
it.color = keyForeground.toSolidColor().color
|
||||
if (computedKeyboard?.mode == KeyboardMode.CHARACTERS && key.computedData.code == KeyCode.SPACE) {
|
||||
it.alpha = 120
|
||||
}
|
||||
it.textSize = when (key.computedData.code) {
|
||||
KeyCode.SPACE -> labelPaintSpaceTextSize
|
||||
KeyCode.VIEW_CHARACTERS,
|
||||
KeyCode.VIEW_SYMBOLS,
|
||||
KeyCode.VIEW_SYMBOLS2 -> labelPaintTextSize * 0.80f
|
||||
KeyCode.VIEW_NUMERIC,
|
||||
KeyCode.VIEW_NUMERIC_ADVANCED -> labelPaintTextSize * 0.55f
|
||||
else -> labelPaintTextSize
|
||||
}
|
||||
renderView.labelPaint.let {
|
||||
val centerX = key.visibleLabelBounds.exactCenterX()
|
||||
val centerY = key.visibleLabelBounds.exactCenterY() + (it.textSize - it.descent()) / 2
|
||||
if (label.contains("\n")) {
|
||||
@@ -1052,10 +1027,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
|
||||
val hintedLabel = key.hintedLabel
|
||||
if (hintedLabel != null) {
|
||||
hintedLabelPaint.let {
|
||||
it.color = keyForeground.toSolidColor().color
|
||||
it.alpha = 170
|
||||
it.textSize = hintedLabelPaintTextSize
|
||||
renderView.hintedLabelPaint.let {
|
||||
val centerX = key.visibleBounds.left + key.visibleBounds.width() * 5.0f / 6.0f
|
||||
val centerY = key.visibleBounds.top + key.visibleBounds.height() * 1.0f / 6.0f + (it.textSize - it.descent()) / 2
|
||||
canvas.drawText(hintedLabel, centerX, centerY, it)
|
||||
@@ -1066,7 +1038,7 @@ class TextKeyboardView : KeyboardView, SwipeGesture.Listener, GlideTypingGesture
|
||||
if (foregroundDrawableId != null) {
|
||||
iconSet?.withDrawable(foregroundDrawableId) {
|
||||
bounds = key.visibleDrawableBounds
|
||||
setTint(keyForeground.toSolidColor().color)
|
||||
setTint(renderView.labelPaint.color)
|
||||
draw(canvas)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ class CandidateView : View, ThemeManager.OnThemeUpdatedListener {
|
||||
recomputeCandidates()
|
||||
}
|
||||
|
||||
fun setEventListener(listener: SmartbarView.EventListener) {
|
||||
fun setEventListener(listener: SmartbarView.EventListener?) {
|
||||
eventListener = WeakReference(listener)
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
binding = SmartbarBinding.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by Android when this view has been attached to a window. At this point we can be
|
||||
* certain that all children have been instantiated and that we can begin working with them.
|
||||
@@ -96,8 +101,6 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
|
||||
super.onAttachedToWindow()
|
||||
|
||||
binding = SmartbarBinding.bind(this)
|
||||
|
||||
for (view in binding.actionStartArea.children) {
|
||||
indexedActionStartArea.add(view.id)
|
||||
}
|
||||
@@ -156,21 +159,12 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
eventListener.get()?.onSmartbarQuickActionPressed(it.id)
|
||||
}
|
||||
|
||||
configureFeatureVisibility(
|
||||
actionStartAreaVisible = false,
|
||||
actionStartAreaId = null,
|
||||
mainAreaId = null,
|
||||
actionEndAreaVisible = false,
|
||||
actionEndAreaId = null
|
||||
)
|
||||
configureFeatureVisibility()
|
||||
|
||||
themeManager.registerOnThemeUpdatedListener(this)
|
||||
|
||||
florisboard?.textInputManager?.registerSmartbarView(this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
florisboard?.textInputManager?.unregisterSmartbarView(this)
|
||||
themeManager.unregisterOnThemeUpdatedListener(this)
|
||||
super.onDetachedFromWindow()
|
||||
}
|
||||
@@ -220,6 +214,12 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
binding.actionEndArea.displayedChild =
|
||||
indexedActionEndArea.indexOf(actionEndAreaId).coerceAtLeast(0)
|
||||
}
|
||||
|
||||
cachedActionStartAreaVisible = actionStartAreaVisible
|
||||
cachedActionStartAreaId = actionStartAreaId
|
||||
cachedMainAreaId = mainAreaId
|
||||
cachedActionEndAreaVisible = actionEndAreaVisible
|
||||
cachedActionEndAreaId = actionEndAreaId
|
||||
}
|
||||
|
||||
override fun onInterceptUpdateKeyboardState(newState: KeyboardState): Boolean {
|
||||
@@ -228,14 +228,12 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
|
||||
override fun onUpdateKeyboardState(newState: KeyboardState) {
|
||||
flogInfo(LogTopic.SMARTBAR)
|
||||
if (newState != cachedState) {
|
||||
if (cachedState.isDifferentTo(newState)) {
|
||||
cachedState.reset(newState)
|
||||
if (this::binding.isInitialized) {
|
||||
updateUi()
|
||||
when (cachedMainAreaId) {
|
||||
R.id.clipboard_cursor_row -> binding.clipboardCursorRow.updateKeyboardState(newState)
|
||||
R.id.number_row -> binding.numberRow.updateKeyboardState(newState)
|
||||
}
|
||||
updateUi()
|
||||
when (cachedMainAreaId) {
|
||||
R.id.clipboard_cursor_row -> binding.clipboardCursorRow.updateKeyboardState(newState)
|
||||
R.id.number_row -> binding.numberRow.updateKeyboardState(newState)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,15 +263,13 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
cachedState.keyVariation == KeyVariation.PASSWORD -> {
|
||||
if (!prefs.keyboard.numberRow) R.id.number_row else null
|
||||
}
|
||||
else -> when (florisboard.textInputManager.getActiveKeyboardMode()) {
|
||||
else -> when (cachedState.keyboardMode) {
|
||||
KeyboardMode.EDITING -> null
|
||||
KeyboardMode.NUMERIC,
|
||||
KeyboardMode.PHONE,
|
||||
KeyboardMode.PHONE2 -> R.id.clipboard_cursor_row
|
||||
else -> when {
|
||||
florisboard.activeEditorInstance.isComposingEnabled &&
|
||||
florisboard.activeEditorInstance.selection.isCursorMode
|
||||
-> R.id.candidates
|
||||
cachedState.isComposingEnabled && cachedState.isCursorMode -> R.id.candidates
|
||||
else -> R.id.clipboard_cursor_row
|
||||
}
|
||||
}
|
||||
@@ -362,7 +358,7 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
binding.inlineSuggestionsStrip.removeAllViews()
|
||||
val florisboard = florisboard ?: return
|
||||
if (suggestionViews.isEmpty()) {
|
||||
florisboard.activeState.isQuickActionsVisible = false
|
||||
florisboard.activeState.isShowingInlineSuggestions = false
|
||||
return
|
||||
} else {
|
||||
for (suggestionView in suggestionViews) {
|
||||
@@ -371,7 +367,7 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
}
|
||||
binding.inlineSuggestionsStrip.addView(suggestionView)
|
||||
}
|
||||
florisboard.activeState.isQuickActionsVisible = true
|
||||
florisboard.activeState.isShowingInlineSuggestions = true
|
||||
}
|
||||
updateKeyboardState(florisboard.activeState)
|
||||
}
|
||||
@@ -386,11 +382,11 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
}
|
||||
MeasureSpec.AT_MOST -> {
|
||||
// Can't be bigger than...
|
||||
(florisboard?.inputView?.desiredSmartbarHeight ?: resources.getDimension(R.dimen.smartbar_baseHeight)).coerceAtMost(heightSize)
|
||||
(florisboard?.uiBinding?.inputView?.desiredSmartbarHeight ?: resources.getDimension(R.dimen.smartbar_baseHeight)).coerceAtMost(heightSize)
|
||||
}
|
||||
else -> {
|
||||
// Be whatever you want
|
||||
florisboard?.inputView?.desiredSmartbarHeight ?: resources.getDimension(R.dimen.smartbar_baseHeight)
|
||||
florisboard?.uiBinding?.inputView?.desiredSmartbarHeight ?: resources.getDimension(R.dimen.smartbar_baseHeight)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +398,7 @@ class SmartbarView : ConstraintLayout, KeyboardState.OnUpdateStateListener, Them
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setEventListener(listener: EventListener) {
|
||||
fun setEventListener(listener: EventListener?) {
|
||||
eventListener = WeakReference(listener)
|
||||
binding.candidates.setEventListener(listener)
|
||||
}
|
||||
|
||||
@@ -91,6 +91,8 @@ class ThemeEditorActivity : AppCompatActivity() {
|
||||
|
||||
binding.themeNameEditBtn.setOnClickListener { showMetaEditDialog() }
|
||||
|
||||
binding.keyboardPreview.sync()
|
||||
|
||||
val toolbar = findViewById<Toolbar>(R.id.toolbar)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ class ThemeManagerActivity : FlorisActivity<ThemeManagerActivityBinding>() {
|
||||
textKeyboardIconSet = TextKeyboardIconSet.new(this)
|
||||
binding.keyboardPreview.setIconSet(textKeyboardIconSet)
|
||||
binding.keyboardPreview.setComputingEvaluator(textComputingEvaluator)
|
||||
binding.keyboardPreview.sync()
|
||||
|
||||
buildUi()
|
||||
}
|
||||
@@ -182,11 +183,18 @@ class ThemeManagerActivity : FlorisActivity<ThemeManagerActivityBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
// Normally the selection should already be applied to the prefs, but just to make sure we
|
||||
// apply it here again.
|
||||
setThemeRefInPrefs(selectedRef)
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
super.finish()
|
||||
// Normally the selection should already be applied to the prefs, but just to make sure we
|
||||
// apply it here again.
|
||||
setThemeRefInPrefs(selectedRef)
|
||||
}
|
||||
|
||||
private fun evaluateSelectedRef(ignorePrefs: Boolean = false): AssetRef? {
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
<dev.patrickgold.florisboard.ime.core.InputWindowView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/florisboard"
|
||||
android:id="@+id/input_window_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
android:layoutDirection="ltr">
|
||||
android:layoutDirection="ltr"
|
||||
android:hapticFeedbackEnabled="true">
|
||||
|
||||
<dev.patrickgold.florisboard.ime.core.InputView
|
||||
android:id="@+id/inner_input_view_container"
|
||||
android:id="@+id/input_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
@@ -53,11 +54,11 @@
|
||||
android:layout_weight="1"
|
||||
android:measureAllChildren="false">
|
||||
|
||||
<include layout="@layout/text_input_layout"/>
|
||||
<include android:id="@+id/text" layout="@layout/text_input_layout"/>
|
||||
|
||||
<include layout="@layout/media_input_layout"/>
|
||||
<include android:id="@+id/media" layout="@layout/media_input_layout"/>
|
||||
|
||||
<include layout="@layout/clipboard_layout"/>
|
||||
<include android:id="@+id/clipboard" layout="@layout/clipboard_layout"/>
|
||||
|
||||
</dev.patrickgold.florisboard.common.FlorisViewFlipper>
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<dev.patrickgold.florisboard.ime.text.smartbar.SmartbarView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/smartbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
|
||||
@@ -4,29 +4,12 @@
|
||||
android:id="@+id/text_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:alpha="0.9">
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/smartbar"/>
|
||||
<include android:id="@+id/smartbar" layout="@layout/smartbar"/>
|
||||
|
||||
<!-- KeyboardViews will be inserted in ViewFlipper below dynamically -->
|
||||
<!--<dev.patrickgold.florisboard.app.FlorisViewFlipper
|
||||
android:id="@+id/text_input_view_flipper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:measureAllChildren="true">
|
||||
|
||||
<dev.patrickgold.florisboard.ime.text.keyboard.KeyboardView
|
||||
android:id="@+id/keyboard_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:isLoadingPlaceholderKeyboard="true"/>
|
||||
|
||||
<include layout="@layout/editing_layout"/>
|
||||
|
||||
</dev.patrickgold.florisboard.app.FlorisViewFlipper>-->
|
||||
<dev.patrickgold.florisboard.ime.text.keyboard.TextKeyboardView
|
||||
android:id="@+id/text_input_keyboard_view"
|
||||
android:id="@+id/main_keyboard_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<string name="smartbar__quick_action__redo" comment="Content-description for the redo quick action in Smartbar">زر الإعادة لعكس آخر إلغاء</string>
|
||||
<string name="smartbar__quick_action__private_mode" comment="Content-description for the private mode button in Smartbar">إذا كان مرئيًا، يشير إلى أن الوضع الخاص نشط. عند النقر فوقه، يظهر معلومات حول الوضع الخاص.</string>
|
||||
<!-- Settings UI strings -->
|
||||
<string name="settings__title" comment="Title of Settings">الاعدادات</string>
|
||||
<string name="settings__title" comment="Title of Settings">الإعدادات</string>
|
||||
<string name="settings__menu" comment="Hint of top-right three-dot icon in Settings">المزيد من الخيارات</string>
|
||||
<string name="settings__menu_help" comment="Three-dot menu entry for Help and Feedback web link">المساعدة والملاحظات</string>
|
||||
<string name="settings__help" comment="General label for help buttons in Settings">مساعدة</string>
|
||||
|
||||
@@ -202,6 +202,20 @@
|
||||
<string name="pref__keyboard__sound_enabled__label" comment="Preference title">So en prémer la tecla</string>
|
||||
<string name="pref__keyboard__sound_volume__label" comment="Preference title">Volum del so en prémer la tecla</string>
|
||||
<string name="pref__keyboard__vibration_enabled__label" comment="Preference title">Vibrar al prémer la tecla</string>
|
||||
<string name="pref__keyboard__vibration_duration__label" comment="Preference title">Durada de la vibració en prémer la tecla</string>
|
||||
<string name="pref__keyboard__vibration_strength__label" comment="Preference title">Força de vibració en prémer la tecla</string>
|
||||
<string name="pref__keyboard__popup_visible__label" comment="Preference title">Visibilitat de la finestra emergent</string>
|
||||
<string name="pref__keyboard__popup_visible__summary" comment="Preference summary">Mostra una finestra emergent quan premeu una tecla</string>
|
||||
<string name="pref__keyboard__long_press_delay__label" comment="Preference title">Retard de la premuda de tecla llarga</string>
|
||||
<string name="pref__keyboard__space_bar_switches_to_characters__label" comment="Preference title">La barra espaiadora canvia a la disposició de caràcters</string>
|
||||
<string name="pref__keyboard__space_bar_switches_to_characters__summary" comment="Preference summary">En prémer la barra d\'espai, es torna automàticament als caràcters quan estan en símbols o numèrics</string>
|
||||
<string name="pref__smartbar__enabled__label" comment="Preference title">Habilita la barra intel·ligent</string>
|
||||
<string name="pref__smartbar__enabled__summary" comment="Preference summary">Es mostrarà a la part superior del teclat</string>
|
||||
<string name="pref__suggestion__title" comment="Preference group title">Suggeriments</string>
|
||||
<string name="pref__dictionary__title" comment="Preference group title">Diccionari</string>
|
||||
<string name="pref__dictionary__enable_system_user_dictionary__label" comment="Preference title">Habilita el diccionari d\'usuari del sistema</string>
|
||||
<string name="pref__dictionary__enable_system_user_dictionary__summary" comment="Preference summary">Suggereix paraules emmagatzemades al diccionari d\'usuari del sistema</string>
|
||||
<string name="pref__dictionary__manage_system_user_dictionary__label" comment="Preference title">Gestiona el diccionari d\'usuari del sistema</string>
|
||||
<string name="pref__correction__title" comment="Preference group title">Correccions</string>
|
||||
<string name="pref__correction__auto_capitalization__label" comment="Preference title">Majúscules automàtiques</string>
|
||||
<!-- About UI strings -->
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<!-- Settings UI strings -->
|
||||
<string name="settings__title" comment="Title of Settings">Nastavení</string>
|
||||
<string name="settings__menu" comment="Hint of top-right three-dot icon in Settings">Více možností</string>
|
||||
<string name="settings__menu_help" comment="Three-dot menu entry for Help and Feedback web link">Pomoc & odezva</string>
|
||||
<string name="settings__menu_help" comment="Three-dot menu entry for Help and Feedback web link">Nápověda & zpětná vazba</string>
|
||||
<string name="settings__help" comment="General label for help buttons in Settings">Nápověda</string>
|
||||
<string name="settings__navigation__home" comment="Long-press hint of bottom nav item Home in Settings">Domov</string>
|
||||
<string name="settings__navigation__keyboard" comment="Long-press hint of bottom nav item Keyboard in Settings">Klávesnice</string>
|
||||
@@ -73,7 +73,7 @@
|
||||
<string name="settings__localization__subtype_phone2_layout" comment="Label for layout dropdown in subtype dialog">Sekundární telefonní rozložení</string>
|
||||
<string name="settings__localization__subtype_error_already_exists" comment="Error message shown in subtype dialog when a subtype to add already exists">Tento podtyp již existuje!</string>
|
||||
<string name="settings__theme__title" comment="Title of the Theme fragment">Motiv klávesnice</string>
|
||||
<string name="settings__theme__undefined" comment="General string for an undefined preference value">Definován</string>
|
||||
<string name="settings__theme__undefined" comment="General string for an undefined preference value">Nedefinováno</string>
|
||||
<string name="pref__theme__mode__label" comment="Label of the theme mode preference">Režim motivu</string>
|
||||
<string name="pref__theme__mode__always_day" comment="Preference value for theme mode">Vždy denní</string>
|
||||
<string name="pref__theme__mode__always_night" comment="Preference value for theme mode">Vždy noční</string>
|
||||
@@ -108,14 +108,14 @@
|
||||
<string name="settings__theme_editor__value_type_reference" comment="Theme value type">Odkaz</string>
|
||||
<string name="settings__theme_editor__value_type_reference_group" comment="Theme value type sub-field">Skupina</string>
|
||||
<string name="settings__theme_editor__value_type_reference_attr" comment="Theme value type sub-field">Atribut</string>
|
||||
<string name="settings__theme_editor__value_type_solid_color" comment="Theme value type">Jednolitá barva</string>
|
||||
<string name="settings__theme_editor__value_type_solid_color" comment="Theme value type">Plná barva</string>
|
||||
<string name="settings__theme_editor__value_type_lin_grad" comment="Theme value type">Lineární přechod</string>
|
||||
<string name="settings__theme_editor__value_type_rad_grad" comment="Theme value type">Radiální přechod</string>
|
||||
<string name="settings__theme_editor__value_type_on_off" comment="Theme value type">Přepínač</string>
|
||||
<string name="settings__theme_editor__value_type_on_off_state" comment="Theme value type sub-field">Stav</string>
|
||||
<string name="settings__theme_editor__value_type_other" comment="Theme value type">Ostatní</string>
|
||||
<string name="settings__theme_editor__value_type_other_text" comment="Theme value type sub-field">Text</string>
|
||||
<string name="settings__theme_editor__value_preview_content_description" comment="Theme value preview content description">Náhled této hodnoty tématu</string>
|
||||
<string name="settings__theme_editor__value_preview_content_description" comment="Theme value preview content description">Náhled této hodnoty motivu</string>
|
||||
<string name="settings__theme_editor__error_theme_label_empty" comment="Error text for an empty theme label">Zadejte prosím název motivu.</string>
|
||||
<string name="settings__theme_editor__error_group_name" comment="Error text for an invalid group name">Prosím, zadejte název skupiny který používá pouze písmena (a-z a/nebo A-Z), dvojtečku (:) pro podskupiny a navíc číslice (0-9), vlnovku (~) a podtržítko (_) pro název klíče.</string>
|
||||
<string name="settings__theme_editor__error_group_name_empty" comment="Error text for an empty group name">Zadejte název skupiny.</string>
|
||||
@@ -171,13 +171,13 @@
|
||||
<string name="pref__keyboard__utility_key_action__dynamic_switch_language_emojis" comment="Preference value">Dynamicky: Přepnout na emoji / Přepnout jazyk</string>
|
||||
<string name="pref__keyboard__merge_hint_popups_enabled__label">Ukazovat vyskakovací symboly</string>
|
||||
<string name="pref__keyboard_merge_hint_popups_enabled__summary">Přidat vyskakovací symboly do základního rozpoložení</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Multiplikátor velikosti písma (portrét)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Multiplikátor velikosti písma (Krajina)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Multiplikátor velikosti písma (na výšku)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Multiplikátor velikosti písma (na šířku)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Rozložení</string>
|
||||
<string name="pref__keyboard__one_handed_mode__label" comment="Preference title">Režim s jednou rukou</string>
|
||||
<string name="pref__keyboard__one_handed_mode__off" comment="Preference value">Z</string>
|
||||
<string name="pref__keyboard__one_handed_mode__right" comment="Preference value">Režim pravé ruky</string>
|
||||
<string name="pref__keyboard__one_handed_mode__left" comment="Preference value">Režim levé ruky</string>
|
||||
<string name="pref__keyboard__one_handed_mode__label" comment="Preference title">Režim jedné ruky</string>
|
||||
<string name="pref__keyboard__one_handed_mode__off" comment="Preference value">Vypnuto</string>
|
||||
<string name="pref__keyboard__one_handed_mode__right" comment="Preference value">Režim pro praváky</string>
|
||||
<string name="pref__keyboard__one_handed_mode__left" comment="Preference value">Režim pro leváky</string>
|
||||
<string name="pref__keyboard__one_handed_mode_scale_factor__label" comment="Preference title">Šířka klávesnice v režimu jedné ruky</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__label" comment="Preference value">Vstupní okno v celoobrazovkovém režimu na šířku</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__never_show" comment="Preference value">Nikdy nezobrazovat</string>
|
||||
@@ -192,7 +192,7 @@
|
||||
<string name="pref__keyboard__height_factor__tall" comment="Preference value">Vysoká</string>
|
||||
<string name="pref__keyboard__height_factor__extra_tall" comment="Preference value">Extra vysoká</string>
|
||||
<string name="pref__keyboard__height_factor__custom" comment="Preference value">Vlastní</string>
|
||||
<string name="pref__keyboard__height_factor_custom__label" comment="Preference title">Vlastní hodnota výšky klávesnice</string>
|
||||
<string name="pref__keyboard__height_factor_custom__label" comment="Preference title">Hodnota vlastní výšky klávesnice</string>
|
||||
<string name="pref__keyboard__bottom_offset_portrait__label" comment="Preference title">Spodní odsazení (na výšku)</string>
|
||||
<string name="pref__keyboard__bottom_offset_landscape__label" comment="Preference title">Spodní odsazení (na šířku)</string>
|
||||
<string name="pref__keyboard__key_spacing_vertical__label" comment="Preference title">Mezery mezi klávesami (na výšku)</string>
|
||||
@@ -201,25 +201,25 @@
|
||||
<string name="pref__keyboard__sound_enabled__label" comment="Preference title">Zvuk při stisku klávesy</string>
|
||||
<string name="pref__keyboard__sound_volume__label" comment="Preference title">Hlasitost zvuku při stisku klávesy</string>
|
||||
<string name="pref__keyboard__vibration_enabled__label" comment="Preference title">Vibrace při stisku klávesy</string>
|
||||
<string name="pref__keyboard__vibration_duration__label" comment="Preference title">Trvání vibrací při stisknutí tlačítka</string>
|
||||
<string name="pref__keyboard__vibration_strength__label" comment="Preference title">Síla vibrací na stisknutí tlačítka</string>
|
||||
<string name="pref__keyboard__popup_visible__label" comment="Preference title">Vyskakovací Viditelnost</string>
|
||||
<string name="pref__keyboard__popup_visible__summary" comment="Preference summary">Zobrazit vyskakovací okno, když stisknete klávesu</string>
|
||||
<string name="pref__keyboard__long_press_delay__label" comment="Preference title">Dlouhé zpoždění stisknutí tlačítka</string>
|
||||
<string name="pref__keyboard__vibration_duration__label" comment="Preference title">Trvání vibrací při stisku klávesy</string>
|
||||
<string name="pref__keyboard__vibration_strength__label" comment="Preference title">Síla vibrací při stisku klávesy</string>
|
||||
<string name="pref__keyboard__popup_visible__label" comment="Preference title">Viditelnost vyskakovacího okna</string>
|
||||
<string name="pref__keyboard__popup_visible__summary" comment="Preference summary">Zobrazit vyskakovací okno při stisku klávesy</string>
|
||||
<string name="pref__keyboard__long_press_delay__label" comment="Preference title">Délka dlouhého stisku</string>
|
||||
<string name="pref__keyboard__space_bar_switches_to_characters__label" comment="Preference title">Mezerník přepne znovu do písmenného rozložení</string>
|
||||
<string name="pref__keyboard__space_bar_switches_to_characters__summary" comment="Preference summary">Stisknutím mezerníku se automaticky vrátíte z nabídky čísel/symbolů ke klasické klávesnici</string>
|
||||
<string name="settings__typing__title" comment="Title of Typing experience fragment">Psaní zkušenosti</string>
|
||||
<string name="settings__typing__title" comment="Title of Typing experience fragment">Zážitek z psaní</string>
|
||||
<string name="pref__smartbar__enabled__label" comment="Preference title">Povolit chytrou lištu</string>
|
||||
<string name="pref__smartbar__enabled__summary" comment="Preference summary">Zobrazí se na vrchu klávesnice</string>
|
||||
<string name="pref__suggestion__title" comment="Preference group title">Návrh</string>
|
||||
<string name="pref__smartbar__enabled__summary" comment="Preference summary">Zobrazí se v horní části klávesnice</string>
|
||||
<string name="pref__suggestion__title" comment="Preference group title">Návrhy</string>
|
||||
<string name="pref__dictionary__title" comment="Preference group title">Slovník</string>
|
||||
<string name="pref__correction__title" comment="Preference group title">Oprava</string>
|
||||
<string name="pref__correction__auto_capitalization__label" comment="Preference title">Automatická kapitalizace</string>
|
||||
<string name="pref__correction__auto_capitalization__summary" comment="Preference summary">Vydělávejte slova na základě aktuálního vstupního kontextu</string>
|
||||
<string name="pref__correction__remember_caps_lock_state__label" comment="Preference title">Pamatovat caps lock stav</string>
|
||||
<string name="pref__correction__remember_caps_lock_state__summary" comment="Preference summary">Caps lock zůstane při přesunu do jiného textového pole</string>
|
||||
<string name="pref__correction__double_space_period__label" comment="Preference title">Doba dvojitého prostoru</string>
|
||||
<string name="pref__correction__double_space_period__summary" comment="Preference summary">Poklepáním dvakrát na mezerník vloží období následuje prostor</string>
|
||||
<string name="pref__correction__auto_capitalization__summary" comment="Preference summary">Kapitalizovat slova na základě aktuálního vstupního kontextu</string>
|
||||
<string name="pref__correction__remember_caps_lock_state__label" comment="Preference title">Pamatovat stav caps locku</string>
|
||||
<string name="pref__correction__remember_caps_lock_state__summary" comment="Preference summary">Caps lock zůstane aktivní při přesunu do jiného textového pole</string>
|
||||
<string name="pref__correction__double_space_period__label" comment="Preference title">Tečka dovjitou mezerou</string>
|
||||
<string name="pref__correction__double_space_period__summary" comment="Preference summary">Dvojité poklepání na mezerník vloží tečku a mezeru</string>
|
||||
<string name="settings__udm__word_summary_freq" comment="Summary label for a word entry. The decimal placeholder inserts the frequency for the word it summarizes.">Frekvence: %d</string>
|
||||
<string name="settings__udm__word_summary_freq_shortcut" comment="Summary label for a word entry. The first placeholder inserts the frequency for the word it summarizes, the second placeholder the shortcut defined.">Frekvence: %d | Zkratka: %s</string>
|
||||
<string name="settings__udm__all_languages" comment="Label of the For all languages entry in the language list">Pro všechny jazyky</string>
|
||||
@@ -229,10 +229,10 @@
|
||||
<string name="settings__udm__dialog__word_error_empty" comment="Error label for the word in the user dictionary add/edit dialog">Zadejte prosím slovo!</string>
|
||||
<string name="settings__udm__dialog__word_error_invalid" comment="Error label for the word in the user dictionary add/edit dialog">Toto slovo obsahuje neplatné znaky.</string>
|
||||
<string name="settings__udm__dialog__freq_label" comment="Label for the frequency in the user dictionary add/edit dialog. The two decimal placeholders are the minimum and maximum frequency, both inclusive.">Frekvence (mezi %d a %d)</string>
|
||||
<string name="settings__gestures__title" comment="Title of Gestures fragment">Gesta & Glide psan</string>
|
||||
<string name="pref__glide__title" comment="Preference group title">Glide psan</string>
|
||||
<string name="settings__gestures__title" comment="Title of Gestures fragment">Gesta & Psaní tahem</string>
|
||||
<string name="pref__glide__title" comment="Preference group title">Psaní tahem</string>
|
||||
<string name="pref__glide__enabled__label" comment="Preference title">Povolit psaní tahem</string>
|
||||
<string name="pref__glide__enabled__summary" comment="Preference summary">Zadejte slovo posunutím prstu jeho písmeny</string>
|
||||
<string name="pref__glide__enabled__summary" comment="Preference summary">Zadejte slovo posouváním přes jeho písmena</string>
|
||||
<string name="pref__glide__show_trail__label" comment="Preference title">Zobrazit stopu tahu</string>
|
||||
<string name="pref__glide__show_trail__summary" comment="Preference summary">Zmizí po každém slově</string>
|
||||
<string name="pref__gestures__general_title" comment="Preference group title">Obecná gesta</string>
|
||||
@@ -254,50 +254,56 @@
|
||||
<string name="pref__gestures__swipe_action__move_cursor_end_of_line" comment="Preference value for swipe action">Přesunout kurzor na konec řádku</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_start_of_page" comment="Preference value for swipe action">Přesunout kurzor na začátek stránky</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_end_of_page" comment="Preference value for swipe action">Přesunout kurzor na konec stránky</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_clipboard_context" comment="Preference value for swipe action">Otevřít správce schránky / historie</string>
|
||||
<string name="pref__gestures__swipe_action__shift" comment="Preference value for swipe action">Posun</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_clipboard_context" comment="Preference value for swipe action">Otevřít správce schránky / historii</string>
|
||||
<string name="pref__gestures__swipe_action__shift" comment="Preference value for swipe action">Přepnout shift</string>
|
||||
<string name="pref__gestures__swipe_action__redo" comment="Preference value for swipe action">Vpřed</string>
|
||||
<string name="pref__gestures__swipe_action__undo" comment="Preference value for swipe action">Zpět</string>
|
||||
<string name="pref__gestures__swipe_action__show_input_method_picker" comment="Preference value for swipe action">Zobrazit výběr metody zadávání</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_prev_keyboard" comment="Preference value for swipe action">Přepnout na předchozí klávesnici</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_prev_subtype" comment="Preference value for swipe action">Přepněte na předchozí podtyp</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_next_subtype" comment="Preference value for swipe action">Přepněte na další podtyp</string>
|
||||
<string name="pref__gestures__swipe_up__label" comment="Preference title">Přejeďte nahoru</string>
|
||||
<string name="pref__gestures__swipe_down__label" comment="Preference title">Přejet</string>
|
||||
<string name="pref__gestures__swipe_left__label" comment="Preference title">Přejeďte doleva</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_prev_subtype" comment="Preference value for swipe action">Přepnout na předchozí podtyp</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_next_subtype" comment="Preference value for swipe action">Přepnout na další podtyp</string>
|
||||
<string name="pref__gestures__swipe_up__label" comment="Preference title">Přejetí nahoru</string>
|
||||
<string name="pref__gestures__swipe_down__label" comment="Preference title">Přejetí dolů</string>
|
||||
<string name="pref__gestures__swipe_left__label" comment="Preference title">Přejetí doleva</string>
|
||||
<string name="pref__gestures__swipe_right__label" comment="Preference title">Přejeďte prstem doprava</string>
|
||||
<string name="pref__gestures__space_bar_swipe_up__label" comment="Preference title">Přejetí nahoru přes mezerník</string>
|
||||
<string name="pref__gestures__space_bar_swipe_left__label" comment="Preference title">Mezerník přejeďte doleva</string>
|
||||
<string name="pref__gestures__space_bar_swipe_right__label" comment="Preference title">Mezerník přejeďte doprava</string>
|
||||
<string name="pref__gestures__space_bar_swipe_left__label" comment="Preference title">Přejetí vlevo přes mezerník</string>
|
||||
<string name="pref__gestures__space_bar_swipe_right__label" comment="Preference title">Přejetí vpravo přes mezerník</string>
|
||||
<string name="pref__gestures__space_bar_long_press__label" comment="Preference title">Dlouhý stisk mezerníku</string>
|
||||
<string name="pref__gestures__delete_key_swipe_left__label" comment="Preference title">Odstranit klíč přejeďte doleva</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__label" comment="Preference title">Práh rychlosti přejetí prstem</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__very_slow" comment="Preference value for swipe velocity threshold">Velmi pomalé</string>
|
||||
<string name="pref__gestures__delete_key_swipe_left__label" comment="Preference title">Přejetí doleva na klávese mazání</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__label" comment="Preference title">Práh rychlosti přejetí</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__very_slow" comment="Preference value for swipe velocity threshold">Velmi pomalý</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__slow" comment="Preference value for swipe velocity threshold">Pomalý</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__normal" comment="Preference value for swipe velocity threshold">Normální</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__fast" comment="Preference value for swipe velocity threshold">Rychlý</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__very_fast" comment="Preference value for swipe velocity threshold">Velmi rychle</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__label" comment="Preference title">Práh vzdálenosti přejetím prstem</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_short" comment="Preference value for swipe distance threshold">Velmi krátká</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__very_fast" comment="Preference value for swipe velocity threshold">Velmi rychlý</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__label" comment="Preference title">Práh vzdálenosti přejetí</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_short" comment="Preference value for swipe distance threshold">Velmi krátký</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__short" comment="Preference value for swipe distance threshold">Krátký</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__normal" comment="Preference value for swipe distance threshold">Normální</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__long" comment="Preference value for swipe distance threshold">Dlouhý</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_long" comment="Preference value for swipe distance threshold">Dlouhý</string>
|
||||
<string name="settings__advanced__title" comment="Title of Advanced settings activity">Upřesnit</string>
|
||||
<string name="pref__advanced__settings_theme__label" comment="Label of Settings theme preference in Advanced">Téma nastavení</string>
|
||||
<string name="pref__advanced__settings_theme__light" comment="Possible value of Settings theme preference in Advanced">Světlo</string>
|
||||
<string name="pref__advanced__settings_theme__dark" comment="Possible value of Settings theme preference in Advanced">Tma</string>
|
||||
<string name="pref__advanced__show_app_icon__label" comment="Label of Show app icon preference in Advanced">Zobrazit ikonu aplikace v launcher</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_long" comment="Preference value for swipe distance threshold">Velmi dlouhý</string>
|
||||
<string name="settings__advanced__title" comment="Title of Advanced settings activity">Pokročilé</string>
|
||||
<string name="pref__advanced__settings_theme__label" comment="Label of Settings theme preference in Advanced">Motiv nastavení</string>
|
||||
<string name="pref__advanced__settings_theme__light" comment="Possible value of Settings theme preference in Advanced">Světlý</string>
|
||||
<string name="pref__advanced__settings_theme__dark" comment="Possible value of Settings theme preference in Advanced">Tmavý</string>
|
||||
<string name="pref__advanced__show_app_icon__label" comment="Label of Show app icon preference in Advanced">Zobrazit ikonu aplikace na domovské obrazovce</string>
|
||||
<string name="pref__advanced__force_private_mode__label" comment="Label of Force private mode preference in Advanced">Vynutit soukromý režim</string>
|
||||
<string name="pref__advanced__force_private_mode__summary" comment="Summary of Force private mode preference in Advanced">Dočasně vypne všechny funkce, které pracují se vstupními daty</string>
|
||||
<!-- About UI strings -->
|
||||
<string name="about__title" comment="Title of About activity">O</string>
|
||||
<string name="about__title" comment="Title of About activity">O aplikaci</string>
|
||||
<string name="about__app_icon_content_description" comment="Content description of app icon in About">Ikona aplikace FlorisBoard</string>
|
||||
<string name="about__view_licenses" comment="Label of View licenses button in About">Open source licence</string>
|
||||
<string name="about__view_privacy_policy" comment="Label of View privacy policy button in About">Soukromí</string>
|
||||
<string name="about__view_source_code" comment="Label of View source code button in About">Kód</string>
|
||||
<string name="about__view_source_code" comment="Label of View source code button in About">Zdrojový kód</string>
|
||||
<string name="about__license__title" comment="Title of Open-source licenses dialog">Open-source licence</string>
|
||||
<!-- Assets strings -->
|
||||
<plurals name="assets__file__authors">
|
||||
<item quantity="one">Autor</item>
|
||||
<item quantity="few">Autoři</item>
|
||||
<item quantity="many">Autorů</item>
|
||||
<item quantity="other">Autorů</item>
|
||||
</plurals>
|
||||
<string name="assets__file__name">Název</string>
|
||||
<string name="assets__file__source">Zdroj</string>
|
||||
<string name="assets__action__add">Přidat</string>
|
||||
@@ -318,32 +324,32 @@
|
||||
<string name="assets__error__invalid">Neplatné</string>
|
||||
<string name="assets__error__snackbar_message">Něco se pokazilo</string>
|
||||
<!-- Setup UI strings -->
|
||||
<string name="setup__title" comment="Title of Setup">Nastavení</string>
|
||||
<string name="setup__prev_button" comment="Label of Previous button in Setup (try to find a short translation due to limited space in UI)">Náhled</string>
|
||||
<string name="setup__title" comment="Title of Setup">Prvotní nastavení</string>
|
||||
<string name="setup__prev_button" comment="Label of Previous button in Setup (try to find a short translation due to limited space in UI)">Předchozí</string>
|
||||
<string name="setup__cancel_button" comment="Label of Cancel button in Setup">Zrušit</string>
|
||||
<string name="setup__next_button" comment="Label of Next button in Setup (try to find a short translation due to limited space in UI)">Další</string>
|
||||
<string name="setup__finish_button" comment="Label of Finish button in Setup">Dokončit</string>
|
||||
<string name="setup__ok_button" comment="Label of OK button in Setup">OK</string>
|
||||
<string name="setup__welcome__title" comment="Title of Welcome fragment in Setup">Vítejte!</string>
|
||||
<string name="setup__welcome__intro" comment="Paragraph in Welcome fragment in Setup">Díky za vyzkoušení FlorisBoard! Než jej začnete používat, musíme udělat obvyklé věci a povolit je v nastavení systému, nastavit preferovaný jazyk/rozvržení atd.... ale bez obav - průvodce nastavením vás provede tímto!</string>
|
||||
<string name="setup__welcome__intro" comment="Paragraph in Welcome fragment in Setup">Díky za vyzkoušení aplikace FlorisBoard! Než ji začnete používat, musíme ji povolit v nastavení systému, zvolit preferovaný jazyk/rozvržení atd… ale bez obav - průvodce nastavením vás tímto provede!</string>
|
||||
<string name="setup__welcome__privacy" comment="Paragraph in Welcome fragment in Setup">FlorisBoard plně respektuje vaše soukromí a neshromažďuje žádná uživatelská data. Pro více informací viz zde:</string>
|
||||
<string name="setup__welcome__trust" comment="Paragraph in Welcome fragment in Setup">Zdrojový kód pro FlorisBoard je veřejně přístupný pro každého, takže můžete snadno zkontrolovat, co FlorisBoard dělá na pozadí. Podívejte se na odkaz úložiště níže.</string>
|
||||
<string name="setup__welcome__contribute" comment="Paragraph in Welcome fragment in Setup">Jedna poslední věc, než začnete nastavení - pokud narazíte na nějaké chyby/pády/problémy s FlorisBoard, nebo máte požadavek na funkci - přes hlavu na GitHub úložiště google níže a soubor problém. To pomáhá při zlepšování zkušeností pro všechny uživatele!</string>
|
||||
<string name="setup__welcome__outro" comment="Paragraph in Welcome fragment in Setup">Chcete-li spustit nastavení, klikněte na <i>další</i>.</string>
|
||||
<string name="setup__welcome__trust" comment="Paragraph in Welcome fragment in Setup">Zdrojový kód aplikace FlorisBoard je veřejně přístupný pro každého, takže můžete snadno zkontrolovat, co FlorisBoard dělá na pozadí. Podívejte se na odkaz repozitáře níže.</string>
|
||||
<string name="setup__welcome__contribute" comment="Paragraph in Welcome fragment in Setup">Poslední věc, než začnete s nastavováním - pokud narazíte na nějaké chyby/pády/problémy s FlorisBoard, nebo máte požadavek na funkci - navštivte repozitář na GitHubu odkazovaný níže a vytvořte issue. To pomáhá se zlepšováním zážitku pro všechny uživatele!</string>
|
||||
<string name="setup__welcome__outro" comment="Paragraph in Welcome fragment in Setup">Chcete-li spustit prvotní nastavení, klikněte na <i>další</i>.</string>
|
||||
<string name="setup__enable_ime__title" comment="Title of Enable IME fragment in Setup">Povolit FlorisBoard</string>
|
||||
<string name="setup__enable_ime__text_before_enabled" comment="Description of state in Enable IME fragment before user enabled">Android vyžaduje, abyste před použitím mohli každou vlastní klávesnici ručně povolit. Kliknutím na tlačítko níže přejděte do nabídky <i> Jazyk & Zadejte </i> nastavení a nezapomeňte zkontrolovat „<i> FlorisBoard </i>“.</string>
|
||||
<string name="setup__enable_ime__text_before_enabled" comment="Description of state in Enable IME fragment before user enabled">Android vyžaduje ruční povolení vlastní klávesnice před jejím použitím. Kliknutím na tlačítko níže přejděte do nabídky nastavení<i> Jazyk & Zadávání</i> a povolte „<i> FlorisBoard </i>“.</string>
|
||||
<string name="setup__enable_ime__text_after_enabled" comment="Description of state in Enable IME fragment after user enabled">FlorisBoard byl úspěšně povolen. Chcete-li pokračovat, klikněte na <i>další</i>!</string>
|
||||
<string name="setup__enable_ime__text_button_language_and_input" comment="Label of language and input button in Enable IME fragment">Otevřený Jazyk & Nastavení vstupu</string>
|
||||
<string name="setup__make_default__title" comment="Title of Make IME default fragment in Setup">Aby FlorisBoard výchozí</string>
|
||||
<string name="setup__make_default__text_before_switch" comment="Description of state in Make IME default fragment before user switched">FlorisBoard je nyní povolen ve vašem systému. Chcete-li ji aktivně používat, přepněte na FlorisBoard výběrem v dialogu pro výběr vstupu!</string>
|
||||
<string name="setup__make_default__text_after_switch" comment="Description of state in Make IME default fragment after user switched">Úspěšně přepnul výchozí klávesnici na FlorisBoard!</string>
|
||||
<string name="setup__enable_ime__text_button_language_and_input" comment="Label of language and input button in Enable IME fragment">Otevřít nastavení Jazyk & Zadávání</string>
|
||||
<string name="setup__make_default__title" comment="Title of Make IME default fragment in Setup">Nastavit FlorisBoard jako výchozí</string>
|
||||
<string name="setup__make_default__text_before_switch" comment="Description of state in Make IME default fragment before user switched">FlorisBoard je nyní povolen. Chcete-li ji aktivně používat, přepněte na FlorisBoard zvolením v dialogu pro výběr vstupu!</string>
|
||||
<string name="setup__make_default__text_after_switch" comment="Description of state in Make IME default fragment after user switched">Úspěšné zvolení FlorisBoard jako výchozí klávesnice!</string>
|
||||
<string name="setup__make_default__text_switch_button" comment="Label of switch button in Make IME default fragment">Přepnout klávesnici</string>
|
||||
<string name="setup__finish__title" comment="Title of Setup finished fragment in Setup">Nastavení dokončeno!</string>
|
||||
<string name="setup__finish__title" comment="Title of Setup finished fragment in Setup">Prvorní nastavení dokončeno!</string>
|
||||
<!-- Crash Dialog strings -->
|
||||
<string name="crash_dialog__title" comment="Title of crash dialog">Zpráva o chybě florisboardu</string>
|
||||
<string name="crash_dialog__close" comment="Label of Close button in crash dialog">Uzavřít</string>
|
||||
<string name="crash_notification_channel__title" comment="Title of crash notification channel">FlorisBoard chybové hlášení</string>
|
||||
<string name="crash_once_notification__title" comment="Title of the notification for a single crash">FlorisBoard přestal fungovat…</string>
|
||||
<string name="crash_dialog__close" comment="Label of Close button in crash dialog">Zavřít</string>
|
||||
<string name="crash_notification_channel__title" comment="Title of crash notification channel">FlorisBoard chybová hlášení</string>
|
||||
<string name="crash_once_notification__title" comment="Title of the notification for a single crash">FlorisBoard přestal pracovat…</string>
|
||||
<string name="crash_once_notification__body" comment="Body of the notification for a single crash">Klepnutím zobrazíte podrobnosti o chybě</string>
|
||||
<string name="crash_multiple_notification__title" comment="Title of the notification for consecutive crashes">Zdá se, že FlorisBoard přestal opakovaně pracovat…</string>
|
||||
<string name="crash_multiple_notification__body" comment="Body of the notification for consecutive crashes">Vrácení zpět na předchozí klávesnici pro zastavení nekonečného crash loopu. Klepnutím zobrazíte podrobnosti o chybě</string>
|
||||
|
||||
@@ -86,7 +86,10 @@
|
||||
<string name="settings__theme__attr_textColor" comment="Theme attribute label">Tekstfarve</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Tastatur præferencer</string>
|
||||
<string name="pref__keyboard__hint_mode__disabled" comment="Preference value">Deaktiveret</string>
|
||||
<string name="pref__keyboard__utility_key_action__switch_language" comment="Preference value">Skift sprog</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__never_show" comment="Preference value">Vis aldrig</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__always_show" comment="Preference value">Vis altid</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__dynamically_show" comment="Preference value">Vis dynamisk</string>
|
||||
<string name="pref__keyboard__height_factor__extra_short" comment="Preference value">Ekstra kort</string>
|
||||
<string name="pref__keyboard__height_factor__short" comment="Preference value">Kort</string>
|
||||
<string name="pref__keyboard__height_factor__normal" comment="Preference value">Normal</string>
|
||||
@@ -118,6 +121,8 @@
|
||||
<string name="settings__udm__word_summary_freq" comment="Summary label for a word entry. The decimal placeholder inserts the frequency for the word it summarizes.">Frekvens: %d</string>
|
||||
<string name="settings__udm__all_languages" comment="Label of the For all languages entry in the language list">For alle sprog</string>
|
||||
<string name="settings__udm__dialog__word_label" comment="Label for the word in the user dictionary add/edit dialog">Ord</string>
|
||||
<string name="settings__udm__dialog__word_error_empty" comment="Error label for the word in the user dictionary add/edit dialog">Indtast venligst et ord!</string>
|
||||
<string name="settings__udm__dialog__shortcut_label" comment="Label for the shortcut in the user dictionary add/edit dialog">Genvej (valgfri)</string>
|
||||
<string name="settings__gestures__title" comment="Title of Gestures fragment">Bevægelser & Strygeskrivning</string>
|
||||
<string name="pref__glide__title" comment="Preference group title">Strygeskrivning</string>
|
||||
<string name="pref__glide__enabled__summary" comment="Preference summary">Skriv ord ved at stryge fingeren igennem bogstaver</string>
|
||||
@@ -133,16 +138,25 @@
|
||||
<string name="pref__gestures__swipe_action__move_cursor_right" comment="Preference value for swipe action">Flyt musen højre</string>
|
||||
<string name="pref__gestures__swipe_action__undo" comment="Preference value for swipe action">Fortryd</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_prev_keyboard" comment="Preference value for swipe action">Skift til forrige tastatur</string>
|
||||
<string name="pref__gestures__swipe_up__label" comment="Preference title">Stryg opad</string>
|
||||
<string name="pref__gestures__swipe_down__label" comment="Preference title">Stryg nedad</string>
|
||||
<string name="pref__gestures__swipe_left__label" comment="Preference title">Stryg til venstre</string>
|
||||
<string name="pref__gestures__swipe_right__label" comment="Preference title">Swipe til højre</string>
|
||||
<string name="pref__gestures__space_bar_swipe_up__label" comment="Preference title">Space bar knalde op</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__slow" comment="Preference value for swipe velocity threshold">Langsom</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__normal" comment="Preference value for swipe velocity threshold">Normal</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__fast" comment="Preference value for swipe velocity threshold">Hurtig</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__very_fast" comment="Preference value for swipe velocity threshold">Meget hurtig</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_short" comment="Preference value for swipe distance threshold">Meget kort</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__short" comment="Preference value for swipe distance threshold">Kort</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__normal" comment="Preference value for swipe distance threshold">Normal</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__long" comment="Preference value for swipe distance threshold">Lang</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_long" comment="Preference value for swipe distance threshold">Meget lang</string>
|
||||
<string name="settings__advanced__title" comment="Title of Advanced settings activity">Avanceret</string>
|
||||
<string name="pref__advanced__settings_theme__light" comment="Possible value of Settings theme preference in Advanced">Lys</string>
|
||||
<string name="pref__advanced__settings_theme__dark" comment="Possible value of Settings theme preference in Advanced">Mørk</string>
|
||||
<!-- About UI strings -->
|
||||
<string name="about__view_privacy_policy" comment="Label of View privacy policy button in About">Privatlivspolitik</string>
|
||||
<!-- Assets strings -->
|
||||
<string name="assets__file__name">Navn</string>
|
||||
<string name="assets__action__add">Tilføj</string>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
<string name="settings__localization__subtype_characters_layout" comment="Label for layout dropdown in subtype dialog">Διάταξη χαρακτήρων</string>
|
||||
<string name="settings__localization__subtype_symbols_layout" comment="Label for layout dropdown in subtype dialog">Πρωτεύουσα διάταξη συμβόλων</string>
|
||||
<string name="settings__localization__subtype_symbols2_layout" comment="Label for layout dropdown in subtype dialog">Δευτερεύουσα διάταξη συμβόλων</string>
|
||||
<string name="settings__localization__subtype_composer" comment="Label for composer dropdown in subtype dialog.">Συνθέτης</string>
|
||||
<string name="settings__localization__subtype_currency_set" comment="Label for currency set dropdown in subtype dialog. 'set' is used as a noun here and can be compared to a group of elements (in this case currency symbols).">Σύνολο συναλλαγμάτων</string>
|
||||
<string name="settings__localization__subtype_numeric_layout" comment="Label for layout dropdown in subtype dialog">Αριθμητική διάταξη</string>
|
||||
<string name="settings__localization__subtype_numeric_advanced_layout" comment="Label for layout dropdown in subtype dialog">(Προχωρημένη) αριθμητική διάταξη</string>
|
||||
|
||||
@@ -1,18 +1,241 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">FlorisBoard</string>
|
||||
<!-- One-handed strings -->
|
||||
<string name="one_handed__close_btn_content_description" comment="Content description for the one-handed close button">Tutup mode satu-tangan.</string>
|
||||
<string name="one_handed__move_start_btn_content_description" comment="Content description for the one-handed move to left button">Pindahkan papan ketik ke kiri.</string>
|
||||
<string name="one_handed__move_end_btn_content_description" comment="Content description for the one-handed move to right button">Pindahkan papan ketik ke kanan.</string>
|
||||
<!-- Private mode info dialog strings -->
|
||||
<string name="private_mode_dialog__title" comment="Title of the private mode dialog">Mode pribadi</string>
|
||||
<!--
|
||||
<string name="private_mode_dialog__text" comment="Text of the private mode dialog">The icon you just clicked at indicates that FlorisBoard works in the private mode. This means that all features which require to process and temporarily save your input stop working. This applies at minimum to the following features (if they\'ve been turned on previously):\n\n - Next word algorithm adjustments\n\n - Clipboard paste suggestions\n\n - Clipboard history\n\nFlorisBoard enters this mode either if an app requests it or if it was specifically enabled in the advanced settings.</string>
|
||||
-->
|
||||
<!-- Media strings -->
|
||||
<string name="media__tab__emojis" comment="Tab description for emojis in the media UI">Emoji</string>
|
||||
<string name="media__tab__kaomoji" comment="Tab description for kaomoji in the media UI">Kaomoji</string>
|
||||
<!-- Emoji strings -->
|
||||
<string name="emoji__category__people_body" comment="Emoji category name">Orang & Badan</string>
|
||||
<string name="emoji__category__animals_nature" comment="Emoji category name">Hewan & Alam</string>
|
||||
<string name="emoji__category__food_drink" comment="Emoji category name">Makanan & Minuman</string>
|
||||
<string name="emoji__category__travel_places" comment="Emoji category name">Perjalanan & Tempat</string>
|
||||
<string name="emoji__category__activities" comment="Emoji category name">Aktivitas</string>
|
||||
<string name="emoji__category__objects" comment="Emoji category name">Obyek</string>
|
||||
<string name="emoji__category__symbols" comment="Emoji category name">Simbol</string>
|
||||
<string name="emoji__category__flags" comment="Emoji category name">Bendera</string>
|
||||
<!-- Smartbar strings -->
|
||||
<string name="smartbar__quick_action__open_settings" comment="Content-description for the settings quick action in Smartbar">Buka pengaturan.</string>
|
||||
<string name="smartbar__quick_action__private_mode" comment="Content-description for the private mode button in Smartbar">Jika terlihat, menandakan bahwa mode pribadi aktif. Jika diklik, menampilkan informasi tentang mode pribadi.</string>
|
||||
<!-- Settings UI strings -->
|
||||
<string name="settings__title" comment="Title of Settings">Pengaturan</string>
|
||||
<string name="settings__menu" comment="Hint of top-right three-dot icon in Settings">Opsi lainnya</string>
|
||||
<string name="settings__menu_help" comment="Three-dot menu entry for Help and Feedback web link">Dukungan & masukan</string>
|
||||
<string name="settings__help" comment="General label for help buttons in Settings">Bantuan</string>
|
||||
<string name="settings__navigation__home" comment="Long-press hint of bottom nav item Home in Settings">Beranda</string>
|
||||
<string name="settings__navigation__keyboard" comment="Long-press hint of bottom nav item Keyboard in Settings">Papan Ketik</string>
|
||||
<string name="settings__navigation__typing" comment="Long-press hint of bottom nav item Typing in Settings">Mengetik</string>
|
||||
<string name="settings__navigation__theme" comment="Long-press hint of bottom nav item Theme in Settings">Tema</string>
|
||||
<string name="settings__navigation__gestures" comment="Long-press hint of bottom nav item Gestures in Settings">Gestur</string>
|
||||
<string name="settings__default" comment="General string which is used when a preference has the default value set">Default</string>
|
||||
<string name="settings__system_default" comment="General string which is used when a preference has the system default value set">Default sistem</string>
|
||||
<string name="settings__home__title" comment="Title of the Home fragment">Selamat datang di %s</string>
|
||||
<string name="settings__home__contribute" comment="Contributing message shown in Home fragment">Terima kasih telah mencoba FlorisBoard! Proyek ini masih dalam versi alpha dan karena itu banyak fitur belum ada. Jika Anda menemukan sebuah bug atau ingin memberikan saran, harap periksa repositori di GitHub dan membuat sebuah masalah (issue). Ini membantu membuat FlorisBoard lebih baik. Terima kasih!</string>
|
||||
<string name="settings__localization__title" comment="Title of languages and layout box in the Typing fragment">Bahasa & Tata letak papan ketik</string>
|
||||
<string name="settings__localization__subtype_add" comment="Subtype dialog add button">Tambahkan</string>
|
||||
<string name="settings__localization__subtype_apply" comment="Subtype dialog apply button">Terapkan</string>
|
||||
<string name="settings__localization__subtype_cancel" comment="Subtype dialog cancel button">Batal</string>
|
||||
<string name="settings__localization__subtype_delete" comment="Subtype dialog delete button">Hapus</string>
|
||||
<string name="settings__localization__subtype_characters_layout" comment="Label for layout dropdown in subtype dialog">Tata letak karakter</string>
|
||||
<string name="settings__localization__subtype_currency_set" comment="Label for currency set dropdown in subtype dialog. 'set' is used as a noun here and can be compared to a group of elements (in this case currency symbols).">Set mata uang</string>
|
||||
<string name="settings__theme__title" comment="Title of the Theme fragment">Tema papan ketik</string>
|
||||
<string name="settings__theme__undefined" comment="General string for an undefined preference value">Tidak ditetapkan</string>
|
||||
<string name="pref__theme__mode__label" comment="Label of the theme mode preference">Mode tema</string>
|
||||
<string name="pref__theme__mode__always_day" comment="Preference value for theme mode">Selalu siang</string>
|
||||
<string name="pref__theme__mode__always_night" comment="Preference value for theme mode">Selalu malam</string>
|
||||
<string name="pref__theme__mode__follow_system" comment="Preference value for theme mode">Ikuti sistem</string>
|
||||
<string name="pref__theme__mode__follow_time" comment="Preference value for theme mode">Ikuti waktu</string>
|
||||
<string name="pref__theme__sunrise_time__label" comment="Label of the sunrise time preference">Waktu matahari terbit</string>
|
||||
<string name="pref__theme__sunset_time__label" comment="Label of the sunset time preference">Waktu matahari terbenam</string>
|
||||
<string name="pref__theme__day" comment="Label of the day group (day means light theme)">Tema siang</string>
|
||||
<string name="pref__theme__night" comment="Label of the night group (night means dark theme)">Tema malam</string>
|
||||
<string name="pref__theme__any_theme__label" comment="Label of the theme selector preference">Tema yang dipilih</string>
|
||||
<string name="pref__theme__source_assets" comment="Label for the theme source field">Aset Aplikasi FlorisBoard</string>
|
||||
<string name="pref__theme__source_internal" comment="Label for the theme source field">Penyimpanan Internal</string>
|
||||
<string name="settings__theme_manager__create_empty" comment="Label of the Create empty FAB action">Buat tema kosong</string>
|
||||
<string name="settings__theme_manager__create_from_selected" comment="Label of the Create from selected FAB action">Buat dari tema yang dipilih</string>
|
||||
<string name="settings__theme_manager__theme_custom_title" comment="Title template for a custom theme">Kustom (berdasarkan %s)</string>
|
||||
<string name="settings__theme_manager__theme_new_title" comment="Title template for a new theme">Tema baru</string>
|
||||
<string name="settings__theme_manager__theme_import_success" comment="Message for theme import success">Tema berhasil diimpor!</string>
|
||||
<string name="settings__theme_manager__theme_export_success" comment="Message for theme export success">Tema berhasil diekspor!</string>
|
||||
<string name="settings__theme_editor__title" comment="Title of the edit theme activity">Sunting tema</string>
|
||||
<string name="settings__theme_editor__name_label" comment="Label of name input">Nama</string>
|
||||
<string name="settings__theme_editor__type_label" comment="Label of type input">Jenis</string>
|
||||
<string name="settings__theme_editor__add_group_dialog_title" comment="Title of the add group dialog in the theme editor">Tambahkan kelompok</string>
|
||||
<string name="settings__theme_editor__edit_group_dialog_title" comment="Title of the edit group dialog in the theme editor">Sunting kelompok</string>
|
||||
<string name="settings__theme_editor__add_attr_dialog_title" comment="Title of the add attribute dialog in the theme editor">Tambahkan atribut</string>
|
||||
<string name="settings__theme_editor__edit_attr_dialog_title" comment="Title of the edit attribute dialog in the theme editor">Sunting atribut</string>
|
||||
<string name="settings__theme_editor__edit_theme_name_dialog_title" comment="Title of the edit theme name dialog in the theme editor">Sunting nama tema</string>
|
||||
<string name="settings__theme_editor__value_type_reference_group" comment="Theme value type sub-field">Kelompok</string>
|
||||
<string name="settings__theme_editor__value_type_reference_attr" comment="Theme value type sub-field">Atribut</string>
|
||||
<string name="settings__theme_editor__value_type_other" comment="Theme value type">Lainnya</string>
|
||||
<string name="settings__theme_editor__value_type_other_text" comment="Theme value type sub-field">Teka</string>
|
||||
<string name="settings__theme_editor__error_theme_label_empty" comment="Error text for an empty theme label">Harap masukkan nama tema.</string>
|
||||
<string name="settings__theme_editor__error_group_name_empty" comment="Error text for an empty group name">Harap masukkan nama kelompok.</string>
|
||||
<string name="settings__theme_editor__error_attr_name" comment="Error text for an invalid attribute name">Harap masukkan nama atribut yang hanya mengandung huruf a-z dan/atau A-Z.</string>
|
||||
<string name="settings__theme_editor__error_attr_name_empty" comment="Error text for an empty attribute name">Harap masukkan nama atribut.</string>
|
||||
<string name="settings__theme__group_keyboard" comment="Theme group label">Papan ketik</string>
|
||||
<string name="settings__theme__group_oneHanded" comment="Theme group label">Satu-tangan</string>
|
||||
<string name="settings__theme__group_privateMode" comment="Theme group label">Mode pribadi</string>
|
||||
<string name="settings__theme__attr_background" comment="Theme attribute label">Warna latar belakang</string>
|
||||
<string name="settings__theme__attr_backgroundActive" comment="Theme attribute label">Warna latar belakang (aktif)</string>
|
||||
<string name="settings__theme__attr_colorPrimary" comment="Theme attribute label">Warna utama</string>
|
||||
<string name="settings__theme__attr_colorPrimaryDark" comment="Theme attribute label">Warna utama (gelap)</string>
|
||||
<string name="settings__theme__attr_navBarColor" comment="Theme attribute label">Warna bilah navigasi</string>
|
||||
<string name="settings__theme__attr_textColor" comment="Theme attribute label">Warna teks</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Preferensi Papan Ketik</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">Baris angka</string>
|
||||
<string name="pref__keyboard__hint_mode__disabled" comment="Preference value">Nonaktif</string>
|
||||
<string name="pref__keyboard__utility_key_action__switch_to_emojis" comment="Preference value">Beralih ke emoji</string>
|
||||
<string name="pref__keyboard__utility_key_action__switch_language" comment="Preference value">Beralih bahasa</string>
|
||||
<string name="pref__keyboard__utility_key_action__switch_keyboard_app" comment="Preference value">Beralih aplikasi papan ketik</string>
|
||||
<string name="pref__keyboard__utility_key_action__dynamic_switch_language_emojis" comment="Preference value">Dinamis: Beralih ke emoji / Beralih bahasa</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Tata letak</string>
|
||||
<string name="pref__keyboard__one_handed_mode__label" comment="Preference title">Mode satu-tangan</string>
|
||||
<string name="pref__keyboard__one_handed_mode__off" comment="Preference value">Mati</string>
|
||||
<string name="pref__keyboard__one_handed_mode__right" comment="Preference value">Mode tangan kanan</string>
|
||||
<string name="pref__keyboard__one_handed_mode__left" comment="Preference value">Mode tangan kiri</string>
|
||||
<string name="pref__keyboard__height_factor__label" comment="Preference title">Tinggi papan ketik</string>
|
||||
<string name="pref__keyboard__height_factor__extra_short" comment="Preference value">Ekstra-rendah</string>
|
||||
<string name="pref__keyboard__height_factor__short" comment="Preference value">Rendah</string>
|
||||
<string name="pref__keyboard__height_factor__normal" comment="Preference value">Normal</string>
|
||||
<string name="pref__keyboard__height_factor__tall" comment="Preference value">Tinggi</string>
|
||||
<string name="pref__keyboard__height_factor__extra_tall" comment="Preference value">Ekstra-tinggi</string>
|
||||
<string name="settings__typing__title" comment="Title of Typing experience fragment">Pengalaman mengetik</string>
|
||||
<string name="pref__smartbar__enabled__summary" comment="Preference summary">Akan tampil di atas papan ketik</string>
|
||||
<string name="pref__suggestion__title" comment="Preference group title">Saran</string>
|
||||
<string name="pref__dictionary__title" comment="Preference group title">Kamus</string>
|
||||
<string name="pref__correction__auto_capitalization__label" comment="Preference title">Kapitalisasi otomatis</string>
|
||||
<string name="pref__correction__double_space_period__summary" comment="Preference summary">Mengetuk batang spasi dua kali memasukkan titik yang diikuti oleh sebuah spasi</string>
|
||||
<string name="settings__udm__word_summary_freq" comment="Summary label for a word entry. The decimal placeholder inserts the frequency for the word it summarizes.">Frekuensi: %d</string>
|
||||
<string name="settings__udm__all_languages" comment="Label of the For all languages entry in the language list">Untuk semua bahasa</string>
|
||||
<string name="settings__udm__dictionary_import_success" comment="Message for dictionary import success">Kamus pengguna berhasil diimpor!</string>
|
||||
<string name="settings__udm__dictionary_export_success" comment="Message for dictionary export success">Kamus pengguna berhasil diekspor!</string>
|
||||
<string name="settings__udm__dialog__word_label" comment="Label for the word in the user dictionary add/edit dialog">Kata</string>
|
||||
<string name="settings__udm__dialog__word_error_empty" comment="Error label for the word in the user dictionary add/edit dialog">Harap masukkan sebuah kata!</string>
|
||||
<string name="settings__udm__dialog__word_error_invalid" comment="Error label for the word in the user dictionary add/edit dialog">Kata ini mengandung karakter yang tidak valid.</string>
|
||||
<string name="settings__udm__dialog__freq_label" comment="Label for the frequency in the user dictionary add/edit dialog. The two decimal placeholders are the minimum and maximum frequency, both inclusive.">Frekuensi (diantara %d dan %d)</string>
|
||||
<string name="settings__udm__dialog__locale_label" comment="Label for the language code in the user dictionary add/edit dialog">Kode bahasa (opsional)</string>
|
||||
<string name="pref__glide__enabled__summary" comment="Preference summary">Ketik sebuah kata dengan menggeser jari Anda melewati huruf-huruf nya</string>
|
||||
<string name="pref__glide__show_trail__summary" comment="Preference summary">Akan menghilang setelah setiap kata</string>
|
||||
<string name="pref__gestures__general_title" comment="Preference group title">Gestur umum</string>
|
||||
<string name="pref__gestures__space_bar_title" comment="Preference group title">Gestur batang spasi</string>
|
||||
<string name="pref__gestures__swipe_action__no_action" comment="Preference value for swipe action">Tidak ada tindakan</string>
|
||||
<string name="pref__gestures__swipe_action__delete_word" comment="Preference value for swipe action">Hapus kata saat ini</string>
|
||||
<string name="pref__gestures__swipe_action__hide_keyboard" comment="Preference value for swipe action">Sembunyikan papan ketik</string>
|
||||
<string name="pref__gestures__swipe_action__insert_space" comment="Preference value for swipe action">Masukkan spasi</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_up" comment="Preference value for swipe action">Pindahkan kursor ke atas</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_down" comment="Preference value for swipe action">Pindahkan kursor ke bawah</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_left" comment="Preference value for swipe action">Pindahkan kursor ke kiri</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_right" comment="Preference value for swipe action">Pindahkan kursor ke kanan</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_start_of_line" comment="Preference value for swipe action">Pindahkan kursor ke awal baris</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_end_of_line" comment="Preference value for swipe action">Pindahkan kursor ke akhir baris</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_start_of_page" comment="Preference value for swipe action">Pindahkan kursor ke awal halaman</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_end_of_page" comment="Preference value for swipe action">Pindahkan kursor ke akhir halaman</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_clipboard_context" comment="Preference value for swipe action">Buka pengelola/riwayat papan klip</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_prev_keyboard" comment="Preference value for swipe action">Beralih ke papan ketik sebelumnya</string>
|
||||
<string name="pref__gestures__swipe_up__label" comment="Preference title">Geser ke atas</string>
|
||||
<string name="pref__gestures__swipe_down__label" comment="Preference title">Geser ke bawah</string>
|
||||
<string name="pref__gestures__swipe_left__label" comment="Preference title">Geser ke kiri</string>
|
||||
<string name="pref__gestures__swipe_right__label" comment="Preference title">Geser ke kanan</string>
|
||||
<string name="pref__gestures__space_bar_swipe_up__label" comment="Preference title">Geser batang spasi ke atas</string>
|
||||
<string name="pref__gestures__space_bar_swipe_left__label" comment="Preference title">Geser batang spasi ke kiri</string>
|
||||
<string name="pref__gestures__space_bar_swipe_right__label" comment="Preference title">Geser batang spasi ke kanan</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__very_slow" comment="Preference value for swipe velocity threshold">Sangat lambat</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__slow" comment="Preference value for swipe velocity threshold">Lambat</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__normal" comment="Preference value for swipe velocity threshold">Normal</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__fast" comment="Preference value for swipe velocity threshold">Cepat</string>
|
||||
<string name="pref__gestures__swipe_velocity_threshold__very_fast" comment="Preference value for swipe velocity threshold">Sangat cepat</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_short" comment="Preference value for swipe distance threshold">Sangat singkat</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__short" comment="Preference value for swipe distance threshold">Singkat</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__normal" comment="Preference value for swipe distance threshold">Normal</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__long" comment="Preference value for swipe distance threshold">Panjang</string>
|
||||
<string name="pref__gestures__swipe_distance_threshold__very_long" comment="Preference value for swipe distance threshold">Sangat panjang</string>
|
||||
<string name="pref__advanced__settings_theme__label" comment="Label of Settings theme preference in Advanced">Tema pengaturan</string>
|
||||
<string name="pref__advanced__settings_theme__light" comment="Possible value of Settings theme preference in Advanced">Cerah</string>
|
||||
<string name="pref__advanced__settings_theme__dark" comment="Possible value of Settings theme preference in Advanced">Gelap</string>
|
||||
<string name="pref__advanced__show_app_icon__label" comment="Label of Show app icon preference in Advanced">Tampilkan ikon aplikasi pada peluncur</string>
|
||||
<string name="pref__advanced__force_private_mode__label" comment="Label of Force private mode preference in Advanced">Paksa mode pribadi</string>
|
||||
<string name="pref__devtools__enabled__label" comment="Label of Enable developer tools in Advanced">Aktifkan alat pengembang</string>
|
||||
<!-- About UI strings -->
|
||||
<string name="about__title" comment="Title of About activity">Tentang</string>
|
||||
<string name="about__app_icon_content_description" comment="Content description of app icon in About">Ikon aplikasi FlorisBoard</string>
|
||||
<string name="about__view_privacy_policy" comment="Label of View privacy policy button in About">Kebijakan privasi</string>
|
||||
<string name="about__view_source_code" comment="Label of View source code button in About">Kode sumber</string>
|
||||
<string name="about__version_copied__title" comment="Title of the toast for copying the version string">Versi disalin ke papan klip</string>
|
||||
<!-- Assets strings -->
|
||||
<plurals name="assets__file__authors">
|
||||
<item quantity="other">Penulis</item>
|
||||
</plurals>
|
||||
<string name="assets__file__name">Nama</string>
|
||||
<string name="assets__file__source">Sumber</string>
|
||||
<string name="assets__action__add">Tambahkan</string>
|
||||
<string name="assets__action__apply">Terapkan</string>
|
||||
<string name="assets__action__cancel">Batal</string>
|
||||
<string name="assets__action__cancel_confirm_title">Konfirmasi pembatalan</string>
|
||||
<string name="assets__action__cancel_confirm_message">Apakah Anda yakin ingin membuang perubahan yang belum disimpan? Tindakan ini tidak dapat dibatalkan setelah dieksekusi.</string>
|
||||
<string name="assets__action__delete">Hapus</string>
|
||||
<string name="assets__action__delete_confirm_title">Konfirmasi penghapusan</string>
|
||||
<string name="assets__action__delete_confirm_message">Apakah Anda yakin ingin menghapus \"%s\"? Tindakan ini tidak dapat dibatalkan setelah dieksekusi.</string>
|
||||
<string name="assets__action__edit">Sunting</string>
|
||||
<string name="assets__action__export">Ekspor</string>
|
||||
<string name="assets__action__import">Impor</string>
|
||||
<string name="assets__action__no">Tidak</string>
|
||||
<string name="assets__action__save">Simpan</string>
|
||||
<string name="assets__action__yes">Ya</string>
|
||||
<string name="assets__error__details">Keterangan</string>
|
||||
<string name="assets__error__invalid">Tidak valid</string>
|
||||
<string name="assets__error__snackbar_message">Terjadi kesalahan</string>
|
||||
<!-- Setup UI strings -->
|
||||
<string name="setup__title" comment="Title of Setup">Persiapan</string>
|
||||
<string name="setup__prev_button" comment="Label of Previous button in Setup (try to find a short translation due to limited space in UI)">Seb</string>
|
||||
<string name="setup__cancel_button" comment="Label of Cancel button in Setup">Batal</string>
|
||||
<string name="setup__next_button" comment="Label of Next button in Setup (try to find a short translation due to limited space in UI)">Lanjut</string>
|
||||
<string name="setup__finish_button" comment="Label of Finish button in Setup">Selesai</string>
|
||||
<string name="setup__ok_button" comment="Label of OK button in Setup">Oke</string>
|
||||
<string name="setup__welcome__title" comment="Title of Welcome fragment in Setup">Selamat datang!</string>
|
||||
<string name="setup__welcome__privacy" comment="Paragraph in Welcome fragment in Setup">FlorisBoard sepenuhnya menghormati privasi Anda dan tidak mengumpulkan data pengguna apapun. Untuk informasi lebih lanjut lihat di sini:</string>
|
||||
<string name="setup__welcome__trust" comment="Paragraph in Welcome fragment in Setup">Kode sumber FlorisBoard dapat diakses oleh siapapun, sehingga Anda dapat memeriksa apa yang FlorisBoard lakukan di belakang. Cek tautan repositori nya berikut ini.</string>
|
||||
<string name="setup__welcome__outro" comment="Paragraph in Welcome fragment in Setup">Untuk memulai persiapan, klik <i>LANJUT</i>.</string>
|
||||
<string name="setup__enable_ime__title" comment="Title of Enable IME fragment in Setup">Aktifkan FlorisBoard</string>
|
||||
<string name="setup__enable_ime__text_after_enabled" comment="Description of state in Enable IME fragment after user enabled">FlorisBoard berhasil diaktifkan. Untuk melanjutkan klik <i>LANJUT</i>!</string>
|
||||
<string name="setup__enable_ime__text_button_language_and_input" comment="Label of language and input button in Enable IME fragment">Buka pengaturan Bahasa & Masukan</string>
|
||||
<string name="setup__make_default__text_after_switch" comment="Description of state in Make IME default fragment after user switched">Berhasil mengalihkan papan ketik default menjadi FlorisBoard!</string>
|
||||
<string name="setup__make_default__text_switch_button" comment="Label of switch button in Make IME default fragment">Beralih papan ketik</string>
|
||||
<string name="setup__finish__title" comment="Title of Setup finished fragment in Setup">Persiapan selesai!</string>
|
||||
<!-- Crash Dialog strings -->
|
||||
<string name="crash_dialog__title" comment="Title of crash dialog">Laporan kesalahan FlorisBoard</string>
|
||||
<string name="crash_dialog__copy_to_clipboard" comment="Label of Copy to clipboard button in crash dialog">Salin ke papan klip sistem</string>
|
||||
<string name="crash_dialog__copy_to_clipboard_success" comment="Label of Copy to clipboard success message in crash dialog">Disalin ke papan klip sistem</string>
|
||||
<string name="crash_dialog__close" comment="Label of Close button in crash dialog">Tutup</string>
|
||||
<string name="crash_once_notification__title" comment="Title of the notification for a single crash">FlorisBoard berhenti bekerja…</string>
|
||||
<string name="crash_once_notification__body" comment="Body of the notification for a single crash">Ketuk untuk melihat keterangan kesalahan</string>
|
||||
<string name="crash_multiple_notification__title" comment="Title of the notification for consecutive crashes">FlorisBoard kelihatannya berhenti bekerja berulang kali…</string>
|
||||
<!-- clipboard strings -->
|
||||
<string name="clip__context_header">Riwayat papan klip</string>
|
||||
<string name="clip__clear_history">Hapus riwayat</string>
|
||||
<string name="clip__delete_item">Hapus</string>
|
||||
<string name="clip__paste_item">Tempel</string>
|
||||
<string name="clip__cant_paste">Aplikasi ini tidak mengizinkan untuk menempel konten ini.</string>
|
||||
<string name="pref__clipboard__clipboard_category__label">Papan klip</string>
|
||||
<string name="pref__clipboard__use_internal_clipboard___label">Gunakan papan klip internal</string>
|
||||
<string name="pref__clipboard__sync_from_system_clipboard__label">Sinkronkan dari papan klip sistem</string>
|
||||
<string name="pref__clipboard__keyboard_sync_from_system_clipboard__summary">Pembaruan papan klip sistem juga memperbarui papan klip Floris</string>
|
||||
<string name="pref__clipboard__sync_to_system_clipboard__label">Sinkronkan ke papan klip sistem</string>
|
||||
<string name="pref__clipboard__sync_to_system_clipboard__summary">Pembaruan papan klip Floris juga memperbarui papan klip sistem</string>
|
||||
<string name="pref__clipboard__enable_clipboard_history__label">Aktifkan riwayat papan klip</string>
|
||||
<string name="pref__clipboard__clean_up_old_clipboard_items__label">Bersihkan item-item lama</string>
|
||||
<string name="pref__clipboard__clean_up_old_after__label">Bersihkan item lama setelah</string>
|
||||
<string name="pref__unit_minutes">" menit"</string>
|
||||
<string name="pref__clipboard__limit_history_size__label">Batasi ukuran riwayat</string>
|
||||
<string name="pref__unit_items">" item"</string>
|
||||
<!-- glide strings -->
|
||||
</resources>
|
||||
|
||||
@@ -61,6 +61,13 @@
|
||||
<string name="settings__localization__subtype_delete" comment="Subtype dialog delete button">מחק</string>
|
||||
<string name="settings__localization__subtype_edit_title" comment="Title of subtype dialog when editing an existing subtype">ערוך תת-סוג</string>
|
||||
<string name="settings__localization__subtype_locale" comment="Label for locale dropdown in subtype dialog">שפה</string>
|
||||
<string name="settings__localization__subtype_symbols_layout" comment="Label for layout dropdown in subtype dialog">סמלים פריסה ראשית</string>
|
||||
<string name="settings__localization__subtype_symbols2_layout" comment="Label for layout dropdown in subtype dialog">סמלים פריסה משנית</string>
|
||||
<string name="settings__localization__subtype_composer" comment="Label for composer dropdown in subtype dialog.">מחבר</string>
|
||||
<string name="settings__localization__subtype_currency_set" comment="Label for currency set dropdown in subtype dialog. 'set' is used as a noun here and can be compared to a group of elements (in this case currency symbols).">הגדרות מטבע</string>
|
||||
<string name="settings__localization__subtype_numeric_layout" comment="Label for layout dropdown in subtype dialog">פריסה מספרית</string>
|
||||
<string name="settings__localization__subtype_numeric_advanced_layout" comment="Label for layout dropdown in subtype dialog">פריסה מספרית (מתקדם)</string>
|
||||
<string name="settings__localization__subtype_numeric_row_layout" comment="Label for layout dropdown in subtype dialog">פריסת שורת מספרים</string>
|
||||
<string name="settings__localization__subtype_error_already_exists" comment="Error message shown in subtype dialog when a subtype to add already exists">תת הסוג הזה כבר קיים!</string>
|
||||
<string name="settings__theme__title" comment="Title of the Theme fragment">ערכת נושא של המקלדת</string>
|
||||
<string name="settings__theme__undefined" comment="General string for an undefined preference value">לא מוגדר</string>
|
||||
@@ -120,6 +127,8 @@
|
||||
<string name="settings__theme__group_privateMode" comment="Theme group label">מצב פרטיות</string>
|
||||
<string name="settings__theme__group_smartbar" comment="Theme group label">שורה חכמה</string>
|
||||
<string name="settings__theme__group_smartbarButton" comment="Theme group label">כפתור שורה חכמה</string>
|
||||
<string name="settings__theme__group_extractEditLayout" comment="Theme group label">פריסת מסך מלא לרוחב</string>
|
||||
<string name="settings__theme__group_extractActionButton" comment="Theme group label">כפתור פעולה מסך מלא לרוחב</string>
|
||||
<string name="settings__theme__group_custom" comment="Theme group label (%s is custom group name)">קבוצה מותאמת אישית (%s)</string>
|
||||
<string name="settings__theme__attr_background" comment="Theme attribute label">צבע רקע</string>
|
||||
<string name="settings__theme__attr_backgroundActive" comment="Theme attribute label">צבע רקע (מופעל)</string>
|
||||
@@ -153,6 +162,7 @@
|
||||
<string name="pref__keyboard__utility_key_action__switch_language" comment="Preference value">החלף שפה</string>
|
||||
<string name="pref__keyboard__utility_key_action__switch_keyboard_app" comment="Preference value">החלף אפליקציית מקלדת</string>
|
||||
<string name="pref__keyboard__utility_key_action__dynamic_switch_language_emojis" comment="Preference value">דינמי: עבור לאימוג\'ים / החלף שפה</string>
|
||||
<string name="pref__keyboard__merge_hint_popups_enabled__label">הראה גם חלונות קופצים של סמל</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">מכפלת גודל גופן (אנכי)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">מכפלת גודל גופן (אופקי)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">אופן תצוגה</string>
|
||||
@@ -160,6 +170,9 @@
|
||||
<string name="pref__keyboard__one_handed_mode__off" comment="Preference value">כבה</string>
|
||||
<string name="pref__keyboard__one_handed_mode__right" comment="Preference value">מצב ליד ימין</string>
|
||||
<string name="pref__keyboard__one_handed_mode__left" comment="Preference value">מצב לשמאליים</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__never_show" comment="Preference value">לעולם אל תציג</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__always_show" comment="Preference value">הצג תמיד</string>
|
||||
<string name="pref__keyboard__landscape_input_ui_mode__dynamically_show" comment="Preference value">להציג באופן דינמי</string>
|
||||
<string name="pref__keyboard__height_factor__label" comment="Preference title">גובה המקלדת</string>
|
||||
<string name="pref__keyboard__height_factor__extra_short" comment="Preference value">קצר במיוחד</string>
|
||||
<string name="pref__keyboard__height_factor__short" comment="Preference value">קצר</string>
|
||||
@@ -170,18 +183,31 @@
|
||||
<string name="pref__keyboard__height_factor__extra_tall" comment="Preference value">גבוה במיוחד</string>
|
||||
<string name="pref__keyboard__height_factor__custom" comment="Preference value">מותאם אישית</string>
|
||||
<string name="pref__keyboard__height_factor_custom__label" comment="Preference title">גובה מקלדת מותאם אישית</string>
|
||||
<string name="pref__keyboard__bottom_offset_portrait__label" comment="Preference title">קיזוז תחתון (דיוקן)</string>
|
||||
<string name="pref__keyboard__key_spacing_vertical__label" comment="Preference title">ריווח מקשים (אנכי)</string>
|
||||
<string name="pref__keyboard__key_spacing_horizontal__label" comment="Preference title">ריווח מקשים (אופקי)</string>
|
||||
<string name="pref__keyboard__group_keypress__label" comment="Preference group title">לחיצת מקש</string>
|
||||
<string name="pref__keyboard__sound_enabled__label" comment="Preference title">שמע בעת לחיצה על מקש</string>
|
||||
<string name="pref__keyboard__sound_volume__label" comment="Preference title">השמע צליל בעת לחיצה על מקש</string>
|
||||
<string name="pref__keyboard__vibration_enabled__label" comment="Preference title">הפעל רטט בעת לחיצה על מקש</string>
|
||||
<string name="pref__keyboard__vibration_duration__label" comment="Preference title">משך הרטט בלחיצת מקש</string>
|
||||
<string name="pref__keyboard__vibration_strength__label" comment="Preference title">עוצמת רטט בעת לחיצה על מקש</string>
|
||||
<string name="pref__keyboard__popup_visible__label" comment="Preference title">תצוגת חלונית</string>
|
||||
<string name="pref__keyboard__popup_visible__summary" comment="Preference summary">הצד חלונית בעת לחיצה על מקש</string>
|
||||
<string name="pref__keyboard__long_press_delay__label" comment="Preference title">השהיית לחיצה מקש ארוכה</string>
|
||||
<string name="pref__keyboard__space_bar_switches_to_characters__label" comment="Preference title">סרגל רווח עובר חזרה לפריסת התווים</string>
|
||||
<string name="pref__keyboard__space_bar_switches_to_characters__summary" comment="Preference summary">לחיצה על סרגל הרווח מחזירה אוטומטית לתווים כאשר היא נמצאת בסמלים או במספרים</string>
|
||||
<string name="settings__typing__title" comment="Title of Typing experience fragment">חווית הקלדה</string>
|
||||
<string name="pref__smartbar__enabled__label" comment="Preference title">הפעל שורה חכמה</string>
|
||||
<string name="pref__smartbar__enabled__summary" comment="Preference summary">יהיה ממוקם מעל המקלדת</string>
|
||||
<string name="pref__suggestion__title" comment="Preference group title">הצעות</string>
|
||||
<string name="pref__dictionary__title" comment="Preference group title">מילון</string>
|
||||
<string name="pref__dictionary__enable_system_user_dictionary__label" comment="Preference title">אפשר מילון משתמשי מערכת</string>
|
||||
<string name="pref__dictionary__enable_system_user_dictionary__summary" comment="Preference summary">הצע מילים המאוחסנות במילון משתמשי המערכת</string>
|
||||
<string name="pref__dictionary__manage_system_user_dictionary__label" comment="Preference title">נהל את מילון משתמשי המערכת</string>
|
||||
<string name="pref__dictionary__manage_system_user_dictionary__summary" comment="Preference summary">הוסף, הצג והסר ערכים עבור מילון המשתמשים במערכת</string>
|
||||
<string name="pref__dictionary__enable_internal_user_dictionary__label" comment="Preference title">אפשר מילון משתמשים פנימי</string>
|
||||
<string name="pref__dictionary__enable_internal_user_dictionary__summary" comment="Preference summary">הצע מילים המאוחסנות במילון המשתמש הפנימי</string>
|
||||
<string name="pref__correction__title" comment="Preference group title">תיקונים</string>
|
||||
<string name="pref__correction__auto_capitalization__label" comment="Preference title">שימוש אוטומטי באותיות גדולות</string>
|
||||
<string name="pref__correction__auto_capitalization__summary" comment="Preference summary">הפוך אותיות לגדולות בהתחשב בהקשר של הקלט הנכוחי</string>
|
||||
@@ -189,6 +215,12 @@
|
||||
<string name="pref__correction__remember_caps_lock_state__summary" comment="Preference summary">Caps lock ישאר פעיל גם כאשר תעבור לשדה טקסט אחר</string>
|
||||
<string name="pref__correction__double_space_period__label" comment="Preference title">רווח-כפול סוף משפט</string>
|
||||
<string name="pref__correction__double_space_period__summary" comment="Preference summary">לחיצה על מקש הרווח פעמים תכניס נקודה ואחריה רווח</string>
|
||||
<string name="settings__udm__title_floris" comment="Title of the User Dictionary Manager activity for internal">מילון משתמשים פנימי</string>
|
||||
<string name="settings__udm__title_system" comment="Title of the User Dictionary Manager activity for system">מילון משתמשי מערכת</string>
|
||||
<string name="settings__udm__dictionary_import_success" comment="Message for dictionary import success">מילון המשתמש יובא בהצלחה!</string>
|
||||
<string name="settings__udm__dictionary_export_success" comment="Message for dictionary export success">מילון משתמשים מיוצא בהצלחה!</string>
|
||||
<string name="settings__udm__dialog__title_add" comment="Label for the title (when in adding mode) in the user dictionary add/edit dialog">הוסף ערך מילים</string>
|
||||
<string name="settings__udm__dialog__title_edit" comment="Label for the title (when in editing mode) in the user dictionary add/edit dialog">ערוך הזנת מילים</string>
|
||||
<string name="settings__gestures__title" comment="Title of Gestures fragment">מחוות & הקלדה גולשת</string>
|
||||
<string name="pref__glide__title" comment="Preference group title">הקלדה גולשת</string>
|
||||
<string name="pref__glide__enabled__summary" comment="Preference summary">הקלד מילה באמצעות החלקה של האצבע בין האותיות</string>
|
||||
@@ -209,6 +241,8 @@
|
||||
<string name="pref__gestures__swipe_action__move_cursor_start_of_line" comment="Preference value for swipe action">הזז את הסמן לתחילת השורה</string>
|
||||
<string name="pref__gestures__swipe_action__move_cursor_end_of_line" comment="Preference value for swipe action">העבר את הסמן לסוף השורה</string>
|
||||
<string name="pref__gestures__swipe_action__shift" comment="Preference value for swipe action">Shift</string>
|
||||
<string name="pref__gestures__swipe_action__redo" comment="Preference value for swipe action">בצע שוב</string>
|
||||
<string name="pref__gestures__swipe_action__undo" comment="Preference value for swipe action">ביטול</string>
|
||||
<string name="pref__gestures__swipe_action__show_input_method_picker" comment="Preference value for swipe action">הצג בורר שיטות קלט</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_prev_keyboard" comment="Preference value for swipe action">החלפה למקלדת הקודמת</string>
|
||||
<string name="pref__gestures__swipe_action__switch_to_prev_subtype" comment="Preference value for swipe action">החלף לתת-סוג הקודם</string>
|
||||
@@ -241,6 +275,9 @@
|
||||
<string name="pref__advanced__show_app_icon__label" comment="Label of Show app icon preference in Advanced">הצד את סמל האפליקציה בLauncher</string>
|
||||
<string name="pref__advanced__force_private_mode__label" comment="Label of Force private mode preference in Advanced">כפה מצב פרטיות</string>
|
||||
<string name="pref__advanced__force_private_mode__summary" comment="Summary of Force private mode preference in Advanced">יבטל כל תכולה אשר חייבת להשתמש בצורה זמנית בקלט שלך</string>
|
||||
<string name="pref__devtools__enabled__label" comment="Label of Enable developer tools in Advanced">אפשר כלי מפתח</string>
|
||||
<string name="pref__devtools__enabled__summary" comment="Summary of Enable developer tools in Advanced">כלים שתוכננו במיוחד לצורך איתור באגים ופתרון בעיות</string>
|
||||
<string name="pref__devtools__show_heap_memory_stats__label" comment="Label of Show heap memory stats in Advanced">הראה נתונים סטטיסטיים של זיכרון ערימה</string>
|
||||
<!-- About UI strings -->
|
||||
<string name="about__title" comment="Title of About activity">אודות</string>
|
||||
<string name="about__app_icon_content_description" comment="Content description of app icon in About">סמל האפליקציה של FlorisBoard</string>
|
||||
@@ -248,6 +285,7 @@
|
||||
<string name="about__view_privacy_policy" comment="Label of View privacy policy button in About">מדיניות פרטיות</string>
|
||||
<string name="about__view_source_code" comment="Label of View source code button in About">קוד מקור</string>
|
||||
<string name="about__license__title" comment="Title of Open-source licenses dialog">רישיונות קוד פתוח</string>
|
||||
<string name="about__version_copied__title" comment="Title of the toast for copying the version string">הגרסה הועתקה ללוח</string>
|
||||
<!-- Assets strings -->
|
||||
<plurals name="assets__file__authors">
|
||||
<item quantity="one">יוצר</item>
|
||||
@@ -258,6 +296,7 @@
|
||||
<string name="assets__file__name">שם</string>
|
||||
<string name="assets__file__source">מקור</string>
|
||||
<string name="assets__action__add">הוסף</string>
|
||||
<string name="assets__action__apply">החל</string>
|
||||
<string name="assets__action__cancel">ביטול</string>
|
||||
<string name="assets__action__cancel_confirm_title">אשר ביטול</string>
|
||||
<string name="assets__action__cancel_confirm_message">האם אתה בטוח שברצונך לבטל שינויים שלא נשמרו? לא ניתן לבטל פעולה זו לאחר ביצועה.</string>
|
||||
@@ -270,7 +309,9 @@
|
||||
<string name="assets__action__no">לא</string>
|
||||
<string name="assets__action__save">שמור</string>
|
||||
<string name="assets__action__yes">כן</string>
|
||||
<string name="assets__error__details">פרטים</string>
|
||||
<string name="assets__error__invalid">לא תקין</string>
|
||||
<string name="assets__error__snackbar_message">משהו השתבש</string>
|
||||
<!-- Setup UI strings -->
|
||||
<string name="setup__title" comment="Title of Setup">הגדרות</string>
|
||||
<string name="setup__prev_button" comment="Label of Previous button in Setup (try to find a short translation due to limited space in UI)">הקודם</string>
|
||||
@@ -295,6 +336,8 @@
|
||||
<string name="setup__finish__title" comment="Title of Setup finished fragment in Setup">ההתקנה הושלמה!</string>
|
||||
<!-- Crash Dialog strings -->
|
||||
<string name="crash_dialog__title" comment="Title of crash dialog">FlorisBoard דוח שגיאה</string>
|
||||
<string name="crash_dialog__description" comment="Description of crash dialog">מצטער על אי הנוחות, אך FlorisBoard קרס בגלל שגיאה לא צפויה.</string>
|
||||
<string name="crash_dialog__copy_to_clipboard" comment="Label of Copy to clipboard button in crash dialog">העתק ללוח המערכת</string>
|
||||
<string name="crash_dialog__close" comment="Label of Close button in crash dialog">סגור</string>
|
||||
<string name="crash_notification_channel__title" comment="Title of crash notification channel">FlorisBoard דוח שגיאה</string>
|
||||
<string name="crash_once_notification__title" comment="Title of the notification for a single crash">FlorisBoard הפסיק לעבוד…</string>
|
||||
@@ -302,5 +345,20 @@
|
||||
<string name="crash_multiple_notification__title" comment="Title of the notification for consecutive crashes">נראה שFlorisBoard מפסיק לעבוד שוב שוב…</string>
|
||||
<string name="crash_multiple_notification__body" comment="Body of the notification for consecutive crashes">המקדלת הקומדת הוחזרה כדי למנוע לולאת קריסה אינסופית. לחץ כדי לראות את פרטי השגיאה</string>
|
||||
<!-- clipboard strings -->
|
||||
<string name="clip__clear_history">נקה היסטוריה</string>
|
||||
<string name="clip__unpin_item">ביטול הצמדה של פריט</string>
|
||||
<string name="clip__delete_item">מחק</string>
|
||||
<string name="clip__paste_item">הדבק</string>
|
||||
<string name="clip__back_to_text_input">חזרה להזנת טקסט</string>
|
||||
<string name="clip__cant_paste">אפליקציה זו אינה מאפשרת הדבקת תוכן זה.</string>
|
||||
<string name="pref__clipboard__enable_clipboard_history__label">אפשר היסטוריה של הלוח</string>
|
||||
<string name="pref__clipboard__enable_clipboard_history__summary">שמור פריטי לוח</string>
|
||||
<string name="pref__clipboard__clean_up_old_clipboard_items__label">נקה פריטים ישנים</string>
|
||||
<string name="pref__clipboard__clean_up_old_after__label">נקה פריטים ישנים אחרי</string>
|
||||
<string name="pref__unit_minutes">" דקות"</string>
|
||||
<string name="pref__clipboard__limit_history_size__label">הגבל את גודל ההיסטוריה</string>
|
||||
<string name="pref__clipboard__max_history_size__label">גודל היסטוריה מקסימלי</string>
|
||||
<string name="pref__unit_items">" פריטים"</string>
|
||||
<!-- glide strings -->
|
||||
<string name="pref__glide_preview_refresh_delay">תצוגה מקדימה של עיכוב רענון</string>
|
||||
</resources>
|
||||
|
||||
@@ -2,4 +2,15 @@
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:settingsActivity="dev.patrickgold.florisboard.settings.SettingsMainActivity"
|
||||
android:supportsInlineSuggestions="true"
|
||||
android:supportsSwitchingToNextInputMethod="true"/>
|
||||
android:supportsSwitchingToNextInputMethod="true">
|
||||
|
||||
<!-- Add default system subtype so we can properly set the icon and label -->
|
||||
<subtype
|
||||
android:label="@string/floris_app_name"
|
||||
android:icon="@mipmap/floris_app_icon"
|
||||
android:imeSubtypeMode="keyboard"
|
||||
android:imeSubtypeExtraValue="AsciiCapable"
|
||||
android:isAsciiCapable="true"
|
||||
android:overridesImplicitlyEnabledSubtype="true"/>
|
||||
|
||||
</input-method>
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:settingsActivity="dev.patrickgold.florisboard.settings.SettingsMainActivity"
|
||||
android:supportsSwitchingToNextInputMethod="true"/>
|
||||
android:supportsSwitchingToNextInputMethod="true">
|
||||
|
||||
<!-- Add default system subtype so we can properly set the icon and label -->
|
||||
<subtype
|
||||
android:label="@string/floris_app_name"
|
||||
android:icon="@mipmap/floris_app_icon"
|
||||
android:imeSubtypeMode="keyboard"
|
||||
android:imeSubtypeExtraValue="AsciiCapable"
|
||||
android:isAsciiCapable="true"
|
||||
android:overridesImplicitlyEnabledSubtype="true"/>
|
||||
|
||||
</input-method>
|
||||
|
||||
6
fastlane/metadata/androidbeta/en-US/changelogs/47.txt
Normal file
6
fastlane/metadata/androidbeta/en-US/changelogs/47.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
- Added Halmak keyboard layout (#982, thanks @dessalines)
|
||||
- Keyboard rendering and performance (#992)
|
||||
- Duplicates in the clipboard view are now discarded (#991, thanks @Luensche)
|
||||
- Smartbar not showing sometimes (#987)
|
||||
|
||||
Detailed changelog: https://github.com/florisboard/florisboard/releases/tag/v0.3.13-beta04
|
||||
Reference in New Issue
Block a user