Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe6930fb76 | ||
|
|
6a10f0a01a | ||
|
|
30717eeb90 | ||
|
|
a664ab18c9 | ||
|
|
f50983d7ab | ||
|
|
be858802c5 | ||
|
|
1ba690e53a | ||
|
|
e16f81d350 | ||
|
|
0de2039d72 | ||
|
|
50b6a63468 | ||
|
|
8cb644b418 | ||
|
|
f138124670 | ||
|
|
0f76d7f9df | ||
|
|
27b9ec4628 | ||
|
|
ac733ed1dc | ||
|
|
6d15708f95 | ||
|
|
4377f3e41c | ||
|
|
1e690018d7 | ||
|
|
93bb5d2714 | ||
|
|
ad2b08a342 | ||
|
|
9e6508cee4 | ||
|
|
f735c138fb | ||
|
|
d663947fec | ||
|
|
c800617e26 | ||
|
|
f47c7abaf3 | ||
|
|
faf06ee234 | ||
|
|
07c41f9c27 | ||
|
|
80a0d9edab | ||
|
|
cd943a9d4a | ||
|
|
c3d3107b12 | ||
|
|
b91fac8e76 | ||
|
|
e2c784f4cf | ||
|
|
f83bdd8a28 |
32
.github/workflows/android.yml
vendored
Normal file
32
.github/workflows/android.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: FlorisBoard CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew clean assemble
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: app-debug.apk
|
||||
path: app/build/outputs/apk/debug/app-debug.apk
|
||||
@@ -1,7 +1,7 @@
|
||||
<img align="left" width="80" height="80"
|
||||
src="fastlane/metadata/android/en-US/images/icon.png" alt="App icon">
|
||||
|
||||
# FlorisBoard [](https://github.com/florisboard/florisboard/releases) [](https://crowdin.florisboard.patrickgold.dev)
|
||||
# FlorisBoard [](https://github.com/florisboard/florisboard/releases) [](https://crowdin.florisboard.patrickgold.dev) 
|
||||
|
||||
**FlorisBoard** is a free and open-source keyboard for Android 6.0+
|
||||
devices. It aims at being modern, user-friendly and customizable while
|
||||
|
||||
@@ -10,8 +10,8 @@ android {
|
||||
applicationId "dev.patrickgold.florisboard"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 20
|
||||
versionName "0.3.1"
|
||||
versionCode 21
|
||||
versionName "0.3.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@@ -53,4 +53,5 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7"
|
||||
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
"esperanto": "Esperanto",
|
||||
"esperanto_with_hx": "Esperanto with 'ĥ'",
|
||||
"colemak": "Colemak",
|
||||
"dvorak": "Dvorak"
|
||||
"dvorak": "Dvorak",
|
||||
"canadian_french": "Canadian French (QWERTY)"
|
||||
},
|
||||
"defaultSubtypes": [
|
||||
{
|
||||
@@ -64,7 +65,7 @@
|
||||
{
|
||||
"id": 302,
|
||||
"languageTag": "fr-CA",
|
||||
"preferredLayout": "qwerty"
|
||||
"preferredLayout": "canadian_french"
|
||||
},
|
||||
{
|
||||
"id": 303,
|
||||
|
||||
40
app/src/main/assets/ime/text/characters/canadian_french.json
Normal file
40
app/src/main/assets/ime/text/characters/canadian_french.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"type": "characters",
|
||||
"name": "canadian_french",
|
||||
"direction": "ltr",
|
||||
"arrangement": [
|
||||
[
|
||||
{ "code": 113, "label": "q" },
|
||||
{ "code": 119, "label": "w" },
|
||||
{ "code": 101, "label": "e" },
|
||||
{ "code": 114, "label": "r" },
|
||||
{ "code": 116, "label": "t" },
|
||||
{ "code": 121, "label": "y" },
|
||||
{ "code": 117, "label": "u" },
|
||||
{ "code": 105, "label": "i" },
|
||||
{ "code": 111, "label": "o" },
|
||||
{ "code": 112, "label": "p" },
|
||||
{ "code": 232, "label": "è" }
|
||||
], [
|
||||
{ "code": 97, "label": "a" },
|
||||
{ "code": 115, "label": "s" },
|
||||
{ "code": 100, "label": "d" },
|
||||
{ "code": 102, "label": "f" },
|
||||
{ "code": 103, "label": "g" },
|
||||
{ "code": 104, "label": "h" },
|
||||
{ "code": 106, "label": "j" },
|
||||
{ "code": 107, "label": "k" },
|
||||
{ "code": 108, "label": "l" },
|
||||
{ "code": 233, "label": "é" },
|
||||
{ "code": 224, "label": "à" }
|
||||
], [
|
||||
{ "code": 122, "label": "z" },
|
||||
{ "code": 120, "label": "x" },
|
||||
{ "code": 99, "label": "c" },
|
||||
{ "code": 118, "label": "v" },
|
||||
{ "code": 98, "label": "b" },
|
||||
{ "code": 110, "label": "n" },
|
||||
{ "code": 109, "label": "m" }
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -15,7 +15,10 @@
|
||||
{ "code": 163, "label": "£" },
|
||||
{ "code": 165, "label": "¥" }
|
||||
] },
|
||||
{ "code": 95, "label": "_", "popup": [] },
|
||||
{ "code": 37, "label": "%", "popup": [
|
||||
{ "code": 8240, "label": "‰" },
|
||||
{ "code": 8453, "label": "℅" }
|
||||
] },
|
||||
{ "code": 38, "label": "&", "popup": [] },
|
||||
{ "code": 45, "label": "-", "popup": [
|
||||
{ "code": 8212, "label": "—" },
|
||||
|
||||
@@ -54,10 +54,7 @@
|
||||
] },
|
||||
{ "code": 92, "label": "\\", "popup": [] }
|
||||
], [
|
||||
{ "code": 37, "label": "%", "popup": [
|
||||
{ "code": 8240, "label": "‰" },
|
||||
{ "code": 8453, "label": "℅" }
|
||||
] },
|
||||
{ "code": 95, "label": "_", "popup": [] },
|
||||
{ "code": 169, "label": "©", "popup": [] },
|
||||
{ "code": 174, "label": "®", "popup": [] },
|
||||
{ "code": 8482, "label": "™", "popup": [] },
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
"oneHandedButton": {
|
||||
"fgColor": "#424242"
|
||||
},
|
||||
"privateMode": {
|
||||
"bgColor": "#A000FF",
|
||||
"fgColor": "#FFFFFF"
|
||||
},
|
||||
"smartbar": {
|
||||
"bgColor": "transparent",
|
||||
"fgColor": "@window/textColor",
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
"oneHandedButton": {
|
||||
"fgColor": "#EEEEEE"
|
||||
},
|
||||
"privateMode": {
|
||||
"bgColor": "#A000FF",
|
||||
"fgColor": "#FFFFFF"
|
||||
},
|
||||
"smartbar": {
|
||||
"bgColor": "transparent",
|
||||
"fgColor": "@window/textColor",
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.util.Log
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.system.exitProcess
|
||||
@@ -49,7 +50,6 @@ abstract class CrashUtility private constructor() {
|
||||
private const val NOTIFICATION_ID = 0xFBAD0100
|
||||
|
||||
private const val UNHANDLED_STACKTRACE_FILE_EXT = "stacktrace"
|
||||
private const val TAG = "CrashUtility"
|
||||
|
||||
private var lastActivityCreated: WeakReference<Activity?> = WeakReference(null)
|
||||
|
||||
@@ -63,15 +63,14 @@ abstract class CrashUtility private constructor() {
|
||||
*/
|
||||
fun install(context: Context?): Boolean {
|
||||
if (context == null) {
|
||||
Log.e(
|
||||
TAG,
|
||||
Timber.e(
|
||||
"install($context): Can't install crash handler with a null Context object, doing nothing!"
|
||||
)
|
||||
return false
|
||||
}
|
||||
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
|
||||
if (oldHandler is UncaughtExceptionHandler) {
|
||||
Log.i(TAG, "install($context): Crash handler is already installed, doing nothing!")
|
||||
Timber.i("install($context): Crash handler is already installed, doing nothing!")
|
||||
} else {
|
||||
val application = context.applicationContext
|
||||
if (application != null && application is Application) {
|
||||
@@ -83,19 +82,16 @@ abstract class CrashUtility private constructor() {
|
||||
application.filesDir.absolutePath
|
||||
)
|
||||
)
|
||||
Log.i(
|
||||
TAG,
|
||||
Timber.i(
|
||||
"install($context): Successfully installed crash handler for this application!"
|
||||
)
|
||||
} catch (e: SecurityException) {
|
||||
Log.e(
|
||||
TAG,
|
||||
Timber.e(
|
||||
"install($context): Failed to install crash handler, probably due to missing runtime permission 'setDefaultUncaughtExceptionHandler':\n$e"
|
||||
)
|
||||
return false
|
||||
} catch (e: Exception) {
|
||||
Log.e(
|
||||
TAG,
|
||||
Timber.e(
|
||||
"install($context): Failed to install crash handler due to an unspecified error:\n$e"
|
||||
)
|
||||
return false
|
||||
@@ -130,20 +126,17 @@ abstract class CrashUtility private constructor() {
|
||||
)
|
||||
notificationManager.createNotificationChannel(notificationChannel)
|
||||
}
|
||||
Log.i(
|
||||
TAG,
|
||||
Timber.i(
|
||||
"install($context): Successfully created crash handler notification channel!"
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(
|
||||
TAG,
|
||||
Timber.e(
|
||||
"install($context): Failed to create crash handler notification channel due to an unspecified error:\n$e"
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e(
|
||||
TAG,
|
||||
Timber.e(
|
||||
"install($context): Can't install crash handler with a null Application object, doing nothing!"
|
||||
)
|
||||
return false
|
||||
@@ -168,7 +161,7 @@ abstract class CrashUtility private constructor() {
|
||||
pathname.name.endsWith(".$UNHANDLED_STACKTRACE_FILE_EXT")
|
||||
})?.forEach { file ->
|
||||
val newLine = System.lineSeparator()
|
||||
Log.i(TAG, "Reading unhandled stacktrace: ${file.name}")
|
||||
Timber.i("Reading unhandled stacktrace: ${file.name}")
|
||||
retString.append("~~~ ${file.name} ~~~$newLine$newLine")
|
||||
retString.append(readFile(file))
|
||||
file.delete()
|
||||
@@ -355,7 +348,7 @@ abstract class CrashUtility private constructor() {
|
||||
private val path: String
|
||||
) : Thread.UncaughtExceptionHandler {
|
||||
override fun uncaughtException(thread: Thread?, throwable: Throwable?) {
|
||||
Log.e(TAG, "Detected application crash, executing custom crash handler.")
|
||||
Timber.e("Detected application crash, executing custom crash handler.")
|
||||
thread ?: return
|
||||
throwable ?: return
|
||||
val timestamp = System.currentTimeMillis()
|
||||
|
||||
@@ -23,10 +23,13 @@ import android.content.Context
|
||||
import android.inputmethodservice.InputMethodService
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.SystemClock
|
||||
import android.text.InputType
|
||||
import android.view.KeyCharacterMap
|
||||
import android.view.KeyEvent
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.ExtractedTextRequest
|
||||
import android.view.inputmethod.InputConnection
|
||||
import android.view.inputmethod.InputContentInfo
|
||||
import androidx.annotation.RequiresApi
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
@@ -89,6 +92,7 @@ class EditorInstance private constructor(private val ims: InputMethodService?) {
|
||||
}
|
||||
var isNewSelectionInBoundsOfOld: Boolean = false
|
||||
private set
|
||||
var isPrivateMode: Boolean = false
|
||||
var isRawInputEditor: Boolean = true
|
||||
private set
|
||||
var packageName: String = "undefined"
|
||||
@@ -254,24 +258,19 @@ class EditorInstance private constructor(private val ims: InputMethodService?) {
|
||||
*/
|
||||
fun deleteBackwards(): Boolean {
|
||||
val ic = ims?.currentInputConnection ?: return false
|
||||
if (isRawInputEditor) {
|
||||
return sendSystemKeyEvent(KeyEvent.KEYCODE_DEL)
|
||||
return if (isRawInputEditor) {
|
||||
sendSystemKeyEvent(KeyEvent.KEYCODE_DEL)
|
||||
} else {
|
||||
ic.beginBatchEdit()
|
||||
markComposingRegion(null)
|
||||
if (selection.isCursorMode && selection.start > 0) {
|
||||
val length = detectLastUnicodeCharacterLengthBeforeCursor()
|
||||
ic.deleteSurroundingText(length, 0)
|
||||
} else if (selection.isSelectionMode) {
|
||||
ic.commitText("", 1)
|
||||
}
|
||||
sendSystemKeyEvent(KeyEvent.KEYCODE_DEL)
|
||||
updateEditorState()
|
||||
reevaluateCurrentWord()
|
||||
if (isComposingEnabled) {
|
||||
markComposingRegion(currentWord)
|
||||
}
|
||||
ic.endBatchEdit()
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,21 +286,89 @@ class EditorInstance private constructor(private val ims: InputMethodService?) {
|
||||
*/
|
||||
fun deleteWordsBeforeCursor(n: Int): Boolean {
|
||||
val ic = ims?.currentInputConnection ?: return false
|
||||
return if (n < 1 || isRawInputEditor) {
|
||||
return if (n < 1 || isRawInputEditor || !selection.isValid || !selection.isCursorMode) {
|
||||
false
|
||||
} else {
|
||||
ic.beginBatchEdit()
|
||||
markComposingRegion(null)
|
||||
if (currentWord.isValid) {
|
||||
ic.setSelection(currentWord.start, currentWord.end)
|
||||
ic.commitText("", 1)
|
||||
|
||||
getWordsInString(cachedText.substring(0, selection.start)).run {
|
||||
get(size - n.coerceAtLeast(0)).range
|
||||
}.run {
|
||||
ic.setSelection(first, selection.start)
|
||||
}
|
||||
|
||||
ic.commitText("", 1)
|
||||
|
||||
updateEditorState()
|
||||
reevaluateCurrentWord()
|
||||
ic.endBatchEdit()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all words in the given string with the correct regex for current subtype.
|
||||
* TODO: currently only supports en-US
|
||||
*
|
||||
* @param string String to select words from
|
||||
* @return Words in [string] as a List of [MatchResult]
|
||||
*/
|
||||
private fun getWordsInString(string: String):List<MatchResult>{
|
||||
val wordRegexPattern = "[\\p{L}]+".toRegex()
|
||||
return wordRegexPattern.findAll(
|
||||
string
|
||||
).toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Undoes the last action
|
||||
*
|
||||
* @return True on success, false if an error occurred or the input connection is invalid.
|
||||
*/
|
||||
fun performUndo(): Boolean{
|
||||
val ic = ims?.currentInputConnection ?: return false
|
||||
return if (isRawInputEditor) {
|
||||
sendSystemKeyEventCtrl(KeyEvent.KEYCODE_Z)
|
||||
true
|
||||
} else {
|
||||
ic.beginBatchEdit()
|
||||
markComposingRegion(null)
|
||||
sendSystemKeyEventCtrl(KeyEvent.KEYCODE_Z)
|
||||
updateEditorState()
|
||||
reevaluateCurrentWord()
|
||||
if (isComposingEnabled) {
|
||||
markComposingRegion(currentWord)
|
||||
}
|
||||
ic.endBatchEdit()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redoes the last Undo action
|
||||
*
|
||||
* @return True on success, false if an error occurred or the input connection is invalid.
|
||||
*/
|
||||
fun performRedo(): Boolean{
|
||||
val ic = ims?.currentInputConnection ?: return false
|
||||
return if (isRawInputEditor) {
|
||||
sendSystemKeyEventCtrlShift(KeyEvent.KEYCODE_Z)
|
||||
true
|
||||
} else {
|
||||
ic.beginBatchEdit()
|
||||
markComposingRegion(null)
|
||||
sendSystemKeyEventCtrlShift(KeyEvent.KEYCODE_Z)
|
||||
updateEditorState()
|
||||
reevaluateCurrentWord()
|
||||
if (isComposingEnabled) {
|
||||
markComposingRegion(currentWord)
|
||||
}
|
||||
ic.endBatchEdit()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets [n] characters after the cursor's current position. The resulting string may be any
|
||||
* length ranging from 0 to n.
|
||||
@@ -379,19 +446,21 @@ class EditorInstance private constructor(private val ims: InputMethodService?) {
|
||||
* @return True on success, false if an error occurred or the input connection is invalid.
|
||||
*/
|
||||
fun performClipboardPaste(): Boolean {
|
||||
val clipData: ClipData? = clipboardManager?.primaryClip
|
||||
val item: ClipData.Item? = clipData?.getItemAt(0)
|
||||
return when {
|
||||
item?.text != null -> {
|
||||
commitText(item.text.toString())
|
||||
}
|
||||
item?.uri != null -> {
|
||||
commitContent(item.uri, clipData.description)
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
// val clipData: ClipData? = clipboardManager?.primaryClip
|
||||
// val item: ClipData.Item? = clipData?.getItemAt(0)
|
||||
// return when {
|
||||
// item?.text != null -> {
|
||||
// commitText(item.text.toString())
|
||||
// }
|
||||
// item?.uri != null -> {
|
||||
// commitContent(item.uri, clipData.description)
|
||||
// }
|
||||
// else -> {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
sendSystemKeyEventCtrl(KeyEvent.KEYCODE_V)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -453,6 +522,66 @@ class EditorInstance private constructor(private val ims: InputMethodService?) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a given [keyCode] with Ctrl pressed with [sendDownUpKeyEvents]
|
||||
*
|
||||
* @param keyCode The key code to send, use a key code defined in Android's [KeyEvent], not in
|
||||
* [KeyCode] or this call may send a weird character, as this key codes do not match!!
|
||||
*/
|
||||
fun sendSystemKeyEventCtrl(keyCode: Int) {
|
||||
val ic = ims?.currentInputConnection ?: return
|
||||
sendDownUpKeyEvents(keyCode, KeyEvent.META_CTRL_ON)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a given [keyCode] with Ctrl and Shift pressed with [sendDownUpKeyEvents]
|
||||
*
|
||||
* @param keyCode The key code to send, use a key code defined in Android's [KeyEvent], not in
|
||||
* [KeyCode] or this call may send a weird character, as this key codes do not match!!
|
||||
*/
|
||||
fun sendSystemKeyEventCtrlShift(keyCode: Int) {
|
||||
val ic = ims?.currentInputConnection ?: return
|
||||
sendDownUpKeyEvents(keyCode, KeyEvent.META_SHIFT_ON or KeyEvent.META_CTRL_ON)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as [InputMethodService.sendDownUpKeyEvents] but also allows to set metaStae
|
||||
*
|
||||
* @param keyEventCode The key code to send, use a key code defined in Android's [KeyEvent]
|
||||
* @param metaState Flags indicating which meta keys are currently pressed.
|
||||
*/
|
||||
fun sendDownUpKeyEvents(keyEventCode: Int, metaState: Int) {
|
||||
val ic = ims?.currentInputConnection ?: return
|
||||
val eventTime = SystemClock.uptimeMillis()
|
||||
ic.sendKeyEvent(
|
||||
KeyEvent(
|
||||
eventTime,
|
||||
eventTime,
|
||||
KeyEvent.ACTION_DOWN,
|
||||
keyEventCode,
|
||||
0,
|
||||
metaState,
|
||||
KeyCharacterMap.VIRTUAL_KEYBOARD,
|
||||
0,
|
||||
KeyEvent.FLAG_SOFT_KEYBOARD or KeyEvent.FLAG_KEEP_TOUCH_MODE
|
||||
)
|
||||
)
|
||||
ic.sendKeyEvent(
|
||||
KeyEvent(
|
||||
eventTime,
|
||||
SystemClock.uptimeMillis(),
|
||||
KeyEvent.ACTION_UP,
|
||||
keyEventCode,
|
||||
0,
|
||||
metaState,
|
||||
KeyCharacterMap.VIRTUAL_KEYBOARD,
|
||||
0,
|
||||
KeyEvent.FLAG_SOFT_KEYBOARD or KeyEvent.FLAG_KEEP_TOUCH_MODE
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selection region of this instance and notifies the input connection.
|
||||
*
|
||||
@@ -478,6 +607,44 @@ class EditorInstance private constructor(private val ims: InputMethodService?) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*Adds one word on the left of selection to it
|
||||
*
|
||||
* @return True on success, false if no new words are selected
|
||||
*/
|
||||
fun leftAppendWordToSelection(): Boolean{
|
||||
// no words left to select
|
||||
if (selection.start <= 0)
|
||||
return false
|
||||
val stringBeforeSelection = cachedText.substring(
|
||||
0,
|
||||
selection.start
|
||||
)
|
||||
getWordsInString(stringBeforeSelection).last().range.apply {
|
||||
setSelection(first, selection.end)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
*Removes one word on the left from the selection
|
||||
*
|
||||
* @return True on success, false if no new words are deselected
|
||||
*/
|
||||
fun leftPopWordFromSelection(): Boolean{
|
||||
// no words left to pop
|
||||
if (selection.start >= selection.end)
|
||||
return false
|
||||
val stringInsideSelection = cachedText.substring(
|
||||
selection.start,
|
||||
selection.end
|
||||
)
|
||||
getWordsInString(stringInsideSelection).first().range.apply {
|
||||
setSelection(selection.start + last + 1, selection.end)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects the length of the character before the cursor, as many Unicode characters nowadays
|
||||
* are longer than 1 Java char and thus the length has to be calculated in order to avoid
|
||||
@@ -675,7 +842,7 @@ class ImeOptions private constructor(imeOptions: Int) {
|
||||
PREVIOUS -> EditorInfo.IME_ACTION_PREVIOUS
|
||||
SEARCH -> EditorInfo.IME_ACTION_SEARCH
|
||||
SEND -> EditorInfo.IME_ACTION_SEND
|
||||
UNSPECIFIED-> EditorInfo.IME_ACTION_UNSPECIFIED
|
||||
UNSPECIFIED -> EditorInfo.IME_ACTION_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
package dev.patrickgold.florisboard.ime.core
|
||||
|
||||
import android.app.Application
|
||||
import dev.patrickgold.florisboard.BuildConfig
|
||||
import dev.patrickgold.florisboard.crashutility.CrashUtility
|
||||
import timber.log.Timber
|
||||
|
||||
class FlorisApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
CrashUtility.install(this)
|
||||
if (BuildConfig.DEBUG)
|
||||
Timber.plant(Timber.DebugTree())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import dev.patrickgold.florisboard.ime.text.key.KeyData
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
|
||||
import dev.patrickgold.florisboard.settings.SettingsMainActivity
|
||||
import dev.patrickgold.florisboard.util.*
|
||||
import timber.log.Timber
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
@@ -94,16 +95,15 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
companion object {
|
||||
private const val IME_ID: String = "dev.patrickgold.florisboard/.ime.core.FlorisBoard"
|
||||
private const val IME_ID_DEBUG: String = "dev.patrickgold.florisboard.debug/dev.patrickgold.florisboard.ime.core.FlorisBoard"
|
||||
private val TAG: String? = FlorisBoard::class.simpleName
|
||||
|
||||
fun checkIfImeIsEnabled(context: Context): Boolean {
|
||||
val activeImeIds = Settings.Secure.getString(
|
||||
context.contentResolver,
|
||||
Settings.Secure.ENABLED_INPUT_METHODS
|
||||
)
|
||||
Timber.i("List of active IMEs: $activeImeIds")
|
||||
return when {
|
||||
BuildConfig.DEBUG -> {
|
||||
Log.i(FlorisBoard::class.simpleName, "List of active IMEs: $activeImeIds")
|
||||
activeImeIds.split(":").contains(IME_ID_DEBUG)
|
||||
}
|
||||
else -> {
|
||||
@@ -117,9 +117,9 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
context.contentResolver,
|
||||
Settings.Secure.DEFAULT_INPUT_METHOD
|
||||
)
|
||||
Timber.i("Selected IME: $selectedImeId")
|
||||
return when {
|
||||
BuildConfig.DEBUG -> {
|
||||
Log.i(FlorisBoard::class.simpleName, "Selected IME: $selectedImeId")
|
||||
selectedImeId == IME_ID_DEBUG
|
||||
}
|
||||
else -> {
|
||||
@@ -165,7 +165,7 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
.build()
|
||||
)
|
||||
}
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onCreate()")
|
||||
Timber.i("onCreate()")
|
||||
|
||||
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
@@ -191,7 +191,7 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
override fun onCreateInputView(): View? {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onCreateInputView()")
|
||||
Timber.i("onCreateInputView()")
|
||||
|
||||
baseContext.setTheme(currentThemeResId)
|
||||
|
||||
@@ -203,7 +203,7 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
}
|
||||
|
||||
fun registerInputView(inputView: InputView) {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "registerInputView($inputView)")
|
||||
Timber.i("registerInputView($inputView)")
|
||||
|
||||
this.inputView = inputView
|
||||
initializeOneHandedEnvironment()
|
||||
@@ -215,7 +215,7 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onDestroy()")
|
||||
Timber.i("onDestroy()")
|
||||
|
||||
clipboardManager?.removePrimaryClipChangedListener(this)
|
||||
osHandler.removeCallbacksAndMessages(null)
|
||||
@@ -227,15 +227,15 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
}
|
||||
|
||||
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onStartInput($attribute, $restarting)")
|
||||
Timber.i("onStartInput($attribute, $restarting)")
|
||||
|
||||
super.onStartInput(attribute, restarting)
|
||||
currentInputConnection?.requestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE)
|
||||
}
|
||||
|
||||
override fun onStartInputView(info: EditorInfo?, restarting: Boolean) {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onStartInputView($info, $restarting)")
|
||||
Log.i(TAG, "onStartInputView: " + info?.debugSummarize())
|
||||
Timber.i("onStartInputView($info, $restarting)")
|
||||
Timber.i("onStartInputView: ${info?.debugSummarize()}")
|
||||
|
||||
super.onStartInputView(info, restarting)
|
||||
activeEditorInstance = EditorInstance.from(info, this)
|
||||
@@ -245,7 +245,7 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
}
|
||||
|
||||
override fun onFinishInputView(finishingInput: Boolean) {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onFinishInputView($finishingInput)")
|
||||
Timber.i( "onFinishInputView($finishingInput)")
|
||||
|
||||
if (finishingInput) {
|
||||
activeEditorInstance = EditorInstance.default()
|
||||
@@ -256,14 +256,14 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
}
|
||||
|
||||
override fun onFinishInput() {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onFinishInput()")
|
||||
Timber.i("onFinishInput()")
|
||||
|
||||
super.onFinishInput()
|
||||
currentInputConnection?.requestCursorUpdates(0)
|
||||
}
|
||||
|
||||
override fun onWindowShown() {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onWindowShown()")
|
||||
Timber.i("onWindowShown()")
|
||||
|
||||
prefs.sync()
|
||||
val newIsNumberRowVisible = prefs.keyboard.numberRow
|
||||
@@ -282,14 +282,14 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
}
|
||||
|
||||
override fun onWindowHidden() {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onWindowHidden()")
|
||||
Timber.i("onWindowHidden()")
|
||||
|
||||
super.onWindowHidden()
|
||||
eventListeners.toList().forEach { it?.get()?.onWindowHidden() }
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onConfigurationChanged($newConfig)")
|
||||
Timber.i("onConfigurationChanged($newConfig)")
|
||||
if (isInputViewShown) {
|
||||
updateOneHandedPanelVisibility()
|
||||
}
|
||||
@@ -302,7 +302,7 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
newSelStart: Int, newSelEnd: Int,
|
||||
candidatesStart: Int, candidatesEnd: Int
|
||||
) {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onUpdateSelection($oldSelStart, $oldSelEnd, $newSelStart, $newSelEnd, $candidatesStart, $candidatesEnd)")
|
||||
Timber.i("onUpdateSelection($oldSelStart, $oldSelEnd, $newSelStart, $newSelEnd, $candidatesStart, $candidatesEnd)")
|
||||
|
||||
super.onUpdateSelection(
|
||||
oldSelStart, oldSelEnd,
|
||||
@@ -361,14 +361,12 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
inputView?.setBackgroundColor(prefs.theme.keyboardBgColor)
|
||||
inputView?.oneHandedCtrlPanelStart?.setBackgroundColor(prefs.theme.oneHandedBgColor)
|
||||
inputView?.oneHandedCtrlPanelEnd?.setBackgroundColor(prefs.theme.oneHandedBgColor)
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_move_start)
|
||||
?.imageTintList = ColorStateList.valueOf(prefs.theme.oneHandedButtonFgColor)
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_move_end)
|
||||
?.imageTintList = ColorStateList.valueOf(prefs.theme.oneHandedButtonFgColor)
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_close_start)
|
||||
?.imageTintList = ColorStateList.valueOf(prefs.theme.oneHandedButtonFgColor)
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_close_end)
|
||||
?.imageTintList = ColorStateList.valueOf(prefs.theme.oneHandedButtonFgColor)
|
||||
ColorStateList.valueOf(prefs.theme.oneHandedButtonFgColor).also {
|
||||
inputView?.oneHandedCtrlMoveStart?.imageTintList = it
|
||||
inputView?.oneHandedCtrlMoveEnd?.imageTintList = it
|
||||
inputView?.oneHandedCtrlCloseStart?.imageTintList = it
|
||||
inputView?.oneHandedCtrlCloseEnd?.imageTintList = it
|
||||
}
|
||||
eventListeners.toList().forEach { it?.get()?.onApplyThemeAttributes() }
|
||||
}
|
||||
|
||||
@@ -517,14 +515,12 @@ class FlorisBoard : InputMethodService(), ClipboardManager.OnPrimaryClipChangedL
|
||||
}
|
||||
|
||||
private fun initializeOneHandedEnvironment() {
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_move_start)
|
||||
?.setOnClickListener { v -> onOneHandedPanelButtonClick(v) }
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_move_end)
|
||||
?.setOnClickListener { v -> onOneHandedPanelButtonClick(v) }
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_close_start)
|
||||
?.setOnClickListener { v -> onOneHandedPanelButtonClick(v) }
|
||||
inputView?.findViewById<ImageButton>(R.id.one_handed_ctrl_close_end)
|
||||
?.setOnClickListener { v -> onOneHandedPanelButtonClick(v) }
|
||||
{ v:View -> onOneHandedPanelButtonClick(v) }.also {
|
||||
inputView?.oneHandedCtrlMoveStart?.setOnClickListener(it)
|
||||
inputView?.oneHandedCtrlMoveEnd?.setOnClickListener(it)
|
||||
inputView?.oneHandedCtrlCloseStart?.setOnClickListener(it)
|
||||
inputView?.oneHandedCtrlCloseEnd?.setOnClickListener(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onOneHandedPanelButtonClick(v: View) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.res.Configuration
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ViewFlipper
|
||||
import dev.patrickgold.florisboard.BuildConfig
|
||||
@@ -28,6 +29,7 @@ import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyVariation
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
|
||||
import dev.patrickgold.florisboard.util.ViewLayoutUtils
|
||||
import timber.log.Timber
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
@@ -52,6 +54,14 @@ class InputView : LinearLayout {
|
||||
private set
|
||||
var oneHandedCtrlPanelEnd: LinearLayout? = null
|
||||
private set
|
||||
var oneHandedCtrlMoveStart: ImageButton? = null
|
||||
private set
|
||||
var oneHandedCtrlMoveEnd: ImageButton? = null
|
||||
private set
|
||||
var oneHandedCtrlCloseStart: ImageButton? = null
|
||||
private set
|
||||
var oneHandedCtrlCloseEnd: ImageButton? = null
|
||||
private set
|
||||
|
||||
constructor(context: Context) : this(context, null)
|
||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||
@@ -62,13 +72,17 @@ class InputView : LinearLayout {
|
||||
)
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
if (BuildConfig.DEBUG) Log.i(this::class.simpleName, "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)
|
||||
oneHandedCtrlMoveStart = findViewById(R.id.one_handed_ctrl_move_start)
|
||||
oneHandedCtrlMoveEnd = findViewById(R.id.one_handed_ctrl_move_end)
|
||||
oneHandedCtrlCloseStart = findViewById(R.id.one_handed_ctrl_close_start)
|
||||
oneHandedCtrlCloseEnd = findViewById(R.id.one_handed_ctrl_close_end)
|
||||
|
||||
florisboard.registerInputView(this)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.text.gestures.DistanceThreshold
|
||||
import dev.patrickgold.florisboard.ime.text.gestures.SwipeAction
|
||||
import dev.patrickgold.florisboard.ime.text.gestures.VelocityThreshold
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyHintMode
|
||||
import dev.patrickgold.florisboard.util.VersionName
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
@@ -166,6 +167,7 @@ class PrefHelper(
|
||||
companion object {
|
||||
const val SETTINGS_THEME = "advanced__settings_theme"
|
||||
const val SHOW_APP_ICON = "advanced__show_app_icon"
|
||||
const val FORCE_PRIVATE_MODE = "advanced__force_private_mode"
|
||||
}
|
||||
|
||||
var settingsTheme: String = ""
|
||||
@@ -174,6 +176,9 @@ class PrefHelper(
|
||||
var showAppIcon: Boolean = false
|
||||
get() = prefHelper.getPref(SHOW_APP_ICON, true)
|
||||
private set
|
||||
var forcePrivateMode: Boolean
|
||||
get() = prefHelper.getPref(FORCE_PRIVATE_MODE, false)
|
||||
set(v) = prefHelper.setPref(FORCE_PRIVATE_MODE, v)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,8 +312,8 @@ class PrefHelper(
|
||||
const val FONT_SIZE_MULTIPLIER_LANDSCAPE = "keyboard__font_size_multiplier_landscape"
|
||||
const val HEIGHT_FACTOR = "keyboard__height_factor"
|
||||
const val HEIGHT_FACTOR_CUSTOM = "keyboard__height_factor_custom"
|
||||
const val HINTED_NUMBER_ROW = "keyboard__hinted_number_row"
|
||||
const val HINTED_SYMBOLS = "keyboard__hinted_symbols"
|
||||
const val HINTED_NUMBER_ROW_MODE = "keyboard__hinted_number_row_mode"
|
||||
const val HINTED_SYMBOLS_MODE = "keyboard__hinted_symbols_mode"
|
||||
const val LONG_PRESS_DELAY = "keyboard__long_press_delay"
|
||||
const val NUMBER_ROW = "keyboard__number_row"
|
||||
const val ONE_HANDED_MODE = "keyboard__one_handed_mode"
|
||||
@@ -334,12 +339,12 @@ class PrefHelper(
|
||||
var heightFactorCustom: Int
|
||||
get() = prefHelper.getPref(HEIGHT_FACTOR_CUSTOM, 100)
|
||||
set(v) = prefHelper.setPref(HEIGHT_FACTOR_CUSTOM, v)
|
||||
var hintedNumberRow: Boolean
|
||||
get() = prefHelper.getPref(HINTED_NUMBER_ROW, true)
|
||||
set(v) = prefHelper.setPref(HINTED_NUMBER_ROW, v)
|
||||
var hintedSymbols: Boolean
|
||||
get() = prefHelper.getPref(HINTED_SYMBOLS, true)
|
||||
set(v) = prefHelper.setPref(HINTED_SYMBOLS, v)
|
||||
var hintedNumberRowMode: KeyHintMode
|
||||
get() = KeyHintMode.fromString(prefHelper.getPref(HINTED_NUMBER_ROW_MODE, KeyHintMode.ENABLED_ACCENT_PRIORITY.toString()))
|
||||
set(v) = prefHelper.setPref(HINTED_NUMBER_ROW_MODE, v)
|
||||
var hintedSymbolsMode: KeyHintMode
|
||||
get() = KeyHintMode.fromString(prefHelper.getPref(HINTED_SYMBOLS_MODE, KeyHintMode.ENABLED_ACCENT_PRIORITY.toString()))
|
||||
set(v) = prefHelper.setPref(HINTED_SYMBOLS_MODE, v)
|
||||
var longPressDelay: Int = 0
|
||||
get() = prefHelper.getPref(LONG_PRESS_DELAY, 300)
|
||||
private set
|
||||
@@ -447,6 +452,8 @@ class PrefHelper(
|
||||
const val MEDIA_FG_COLOR_ALT = "theme__media_fgColorAlt"
|
||||
const val ONE_HANDED_BG_COLOR = "theme__oneHanded_bgColor"
|
||||
const val ONE_HANDED_BUTTON_FG_COLOR = "theme__oneHandedButton_fgColor"
|
||||
const val PRIVATE_MODE_BG_COLOR = "theme__privateMode_bgColor"
|
||||
const val PRIVATE_MODE_FG_COLOR = "theme__privateMode_fgColor"
|
||||
const val SMARTBAR_BG_COLOR = "theme__smartbar_bgColor"
|
||||
const val SMARTBAR_FG_COLOR = "theme__smartbar_fgColor"
|
||||
const val SMARTBAR_FG_COLOR_ALT = "theme__smartbar_fgColorAlt"
|
||||
@@ -523,6 +530,12 @@ class PrefHelper(
|
||||
var oneHandedButtonFgColor: Int
|
||||
get() = prefHelper.getPref(ONE_HANDED_BUTTON_FG_COLOR, 0)
|
||||
set(v) = prefHelper.setPref(ONE_HANDED_BUTTON_FG_COLOR, v)
|
||||
var privateModeBgColor: Int
|
||||
get() = prefHelper.getPref(PRIVATE_MODE_BG_COLOR, 0)
|
||||
set(v) = prefHelper.setPref(PRIVATE_MODE_BG_COLOR, v)
|
||||
var privateModeFgColor: Int
|
||||
get() = prefHelper.getPref(PRIVATE_MODE_FG_COLOR, 0)
|
||||
set(v) = prefHelper.setPref(PRIVATE_MODE_FG_COLOR, v)
|
||||
var smartbarBgColor: Int
|
||||
get() = prefHelper.getPref(SMARTBAR_BG_COLOR, 0)
|
||||
set(v) = prefHelper.setPref(SMARTBAR_BG_COLOR, v)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package dev.patrickgold.florisboard.ime.media
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Handler
|
||||
import android.util.Log
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
@@ -34,7 +35,10 @@ import dev.patrickgold.florisboard.ime.media.emoticon.EmoticonKeyboardView
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyData
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyType
|
||||
import dev.patrickgold.florisboard.util.cancelAll
|
||||
import dev.patrickgold.florisboard.util.postAtScheduledRate
|
||||
import kotlinx.coroutines.*
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -56,7 +60,7 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
|
||||
private var activeTab: Tab? = null
|
||||
private var mediaViewFlipper: ViewFlipper? = null
|
||||
private var osTimer: Timer? = null
|
||||
private var repeatedKeyPressHandler: Handler? = null
|
||||
private var tabLayout: TabLayout? = null
|
||||
private val tabViews = EnumMap<Tab, LinearLayout>(Tab::class.java)
|
||||
|
||||
@@ -78,6 +82,11 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
florisboard.addEventListener(this)
|
||||
}
|
||||
|
||||
override fun onCreateInputView() {
|
||||
super.onCreateInputView()
|
||||
repeatedKeyPressHandler = Handler(florisboard.context.mainLooper)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new input view has been registered. Used to initialize all media-relevant
|
||||
* views and layouts.
|
||||
@@ -85,7 +94,7 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onRegisterInputView(inputView: InputView) {
|
||||
if (BuildConfig.DEBUG) Log.i(this::class.simpleName, "onRegisterInputView(inputView)")
|
||||
Timber.i("onRegisterInputView(inputView)")
|
||||
|
||||
launch(Dispatchers.Default) {
|
||||
mediaViewGroup = inputView.findViewById(R.id.media_input)
|
||||
@@ -126,7 +135,7 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
* Clean-up of resources and stopping all coroutines.
|
||||
*/
|
||||
override fun onDestroy() {
|
||||
if (BuildConfig.DEBUG) Log.i(this::class.simpleName, "onDestroy()")
|
||||
Timber.i("onDestroy()")
|
||||
|
||||
cancel()
|
||||
instance = null
|
||||
@@ -151,17 +160,14 @@ class MediaInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
florisboard.keyPressVibrate()
|
||||
florisboard.keyPressSound(data)
|
||||
if (data?.code == KeyCode.DELETE && data.type == KeyType.ENTER_EDITING) {
|
||||
osTimer = Timer()
|
||||
osTimer?.scheduleAtFixedRate(object : TimerTask() {
|
||||
override fun run() {
|
||||
florisboard.textInputManager.sendKeyPress(data)
|
||||
}
|
||||
}, 500, 50)
|
||||
val delayMillis = florisboard.prefs.keyboard.longPressDelay.toLong()
|
||||
repeatedKeyPressHandler?.postAtScheduledRate(delayMillis, 25) {
|
||||
florisboard.textInputManager.sendKeyPress(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
osTimer?.cancel()
|
||||
osTimer = null
|
||||
repeatedKeyPressHandler?.cancelAll()
|
||||
if (event.actionMasked != MotionEvent.ACTION_CANCEL && data != null) {
|
||||
florisboard.textInputManager.sendKeyPress(data)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.graphics.Paint
|
||||
import android.graphics.Typeface
|
||||
import android.util.Log
|
||||
import androidx.core.graphics.PaintCompat
|
||||
import timber.log.Timber
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
@@ -171,13 +172,13 @@ fun parseRawEmojiSpecsFile(
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.e("EmojiLayoutDataMap", "parseRawEmojiSpecsFile(): $e")
|
||||
Timber.e("parseRawEmojiSpecsFile(): $e")
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close()
|
||||
} catch (e: IOException) {
|
||||
Log.e("EmojiLayoutDataMap", "parseRawEmojiSpecsFile(): $e")
|
||||
Timber.e("parseRawEmojiSpecsFile(): $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyData
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyView
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardView
|
||||
import dev.patrickgold.florisboard.util.ViewLayoutUtils
|
||||
|
||||
/**
|
||||
* Manages the creation and dismissal of key popups as well as the checks if the pointer moved
|
||||
@@ -146,11 +147,13 @@ class KeyPopupManager<T_KBD: View, T_KV: View>(private val keyboardView: T_KBD)
|
||||
* @return A new [PopupWindow] already preconfigured and ready-to-go.
|
||||
*/
|
||||
private fun createPopupWindow(view: View): PopupWindow {
|
||||
return PopupWindow(keyboardView.context).apply {
|
||||
return PopupWindow(view.context).apply {
|
||||
animationStyle = 0
|
||||
contentView = view
|
||||
elevation = ViewLayoutUtils.convertDpToPixel(2.0f, view.context)
|
||||
enterTransition = null
|
||||
exitTransition = null
|
||||
isAttachedInDecor = false
|
||||
isClippingEnabled = false
|
||||
isFocusable = false
|
||||
isTouchable = false
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.inputmethod.*
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import android.widget.ViewFlipper
|
||||
import dev.patrickgold.florisboard.BuildConfig
|
||||
import dev.patrickgold.florisboard.R
|
||||
@@ -37,6 +38,7 @@ import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardView
|
||||
import dev.patrickgold.florisboard.ime.text.layout.LayoutManager
|
||||
import dev.patrickgold.florisboard.ime.text.smartbar.SmartbarView
|
||||
import kotlinx.coroutines.*
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -82,7 +84,6 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
private var isManualSelectionModeRight: Boolean = false
|
||||
|
||||
companion object {
|
||||
private val TAG: String? = TextInputManager::class.simpleName
|
||||
private var instance: TextInputManager? = null
|
||||
|
||||
@Synchronized
|
||||
@@ -103,7 +104,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
* background).
|
||||
*/
|
||||
override fun onCreate() {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onCreate()")
|
||||
Timber.i("onCreate()")
|
||||
|
||||
var subtypes = florisboard.subtypeManager.subtypes
|
||||
if (subtypes.isEmpty()) {
|
||||
@@ -129,7 +130,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
* Sets up the newly registered input view.
|
||||
*/
|
||||
override fun onRegisterInputView(inputView: InputView) {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onRegisterInputView(inputView)")
|
||||
Timber.i("onRegisterInputView(inputView)")
|
||||
|
||||
launch(Dispatchers.Default) {
|
||||
textViewGroup = inputView.findViewById(R.id.text_input)
|
||||
@@ -158,7 +159,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
* Cancels all coroutines and cleans up.
|
||||
*/
|
||||
override fun onDestroy() {
|
||||
if (BuildConfig.DEBUG) Log.i(TAG, "onDestroy()")
|
||||
Timber.i("onDestroy()")
|
||||
|
||||
cancel()
|
||||
osHandler.removeCallbacksAndMessages(null)
|
||||
@@ -206,14 +207,18 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
KeyboardMode.CHARACTERS
|
||||
}
|
||||
}
|
||||
instance.isComposingEnabled = when (keyboardMode) {
|
||||
KeyboardMode.NUMERIC,
|
||||
KeyboardMode.PHONE,
|
||||
KeyboardMode.PHONE2 -> false
|
||||
else -> keyVariation != KeyVariation.PASSWORD &&
|
||||
florisboard.prefs.suggestion.enabled// &&
|
||||
//!instance.inputAttributes.flagTextAutoComplete &&
|
||||
//!instance.inputAttributes.flagTextNoSuggestions
|
||||
instance.apply {
|
||||
isComposingEnabled = when (keyboardMode) {
|
||||
KeyboardMode.NUMERIC,
|
||||
KeyboardMode.PHONE,
|
||||
KeyboardMode.PHONE2 -> false
|
||||
else -> keyVariation != KeyVariation.PASSWORD &&
|
||||
florisboard.prefs.suggestion.enabled// &&
|
||||
//!instance.inputAttributes.flagTextAutoComplete &&
|
||||
//!instance.inputAttributes.flagTextNoSuggestions
|
||||
}
|
||||
isPrivateMode = florisboard.prefs.advanced.forcePrivateMode ||
|
||||
imeOptions.flagNoPersonalizedLearning
|
||||
}
|
||||
if (!florisboard.prefs.correction.rememberCapsLockState) {
|
||||
capsLock = false
|
||||
@@ -323,6 +328,10 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
setActiveKeyboardMode(KeyboardMode.CHARACTERS)
|
||||
}
|
||||
|
||||
override fun onSmartbarPrivateModeButtonClicked() {
|
||||
Toast.makeText(florisboard.context, R.string.private_mode_dialog__title, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onSmartbarQuickActionPressed(quickActionId: Int) {
|
||||
when (quickActionId) {
|
||||
R.id.quick_action_switch_to_editing_context -> {
|
||||
@@ -335,11 +344,27 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
R.id.quick_action_switch_to_media_context -> florisboard.setActiveInput(R.id.media_input)
|
||||
R.id.quick_action_open_settings -> florisboard.launchSettings()
|
||||
R.id.quick_action_one_handed_toggle -> florisboard.toggleOneHandedMode()
|
||||
R.id.quick_action_undo -> {
|
||||
handleUndo()
|
||||
return
|
||||
}
|
||||
R.id.quick_action_redo -> {
|
||||
handleRedo()
|
||||
return
|
||||
}
|
||||
}
|
||||
smartbarView?.isQuickActionsVisible = false
|
||||
smartbarView?.updateSmartbarState()
|
||||
}
|
||||
|
||||
private fun handleUndo(){
|
||||
activeEditorInstance.performUndo()
|
||||
}
|
||||
|
||||
private fun handleRedo(){
|
||||
activeEditorInstance.performRedo()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a [KeyCode.DELETE] event.
|
||||
*/
|
||||
@@ -653,7 +678,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Log.e(TAG,"sendKeyPress(keyData): Received unknown key: $keyData")
|
||||
Timber.e("sendKeyPress(keyData): Received unknown key: $keyData")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.res.Configuration
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Typeface
|
||||
import android.os.Handler
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.widget.Button
|
||||
@@ -32,7 +33,8 @@ import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
import dev.patrickgold.florisboard.ime.core.PrefHelper
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyCode
|
||||
import dev.patrickgold.florisboard.ime.text.key.KeyData
|
||||
import java.util.*
|
||||
import dev.patrickgold.florisboard.util.cancelAll
|
||||
import dev.patrickgold.florisboard.util.postAtScheduledRate
|
||||
|
||||
/**
|
||||
* View class for managing and rendering an editing key.
|
||||
@@ -42,7 +44,7 @@ class EditingKeyView : AppCompatImageButton {
|
||||
private val prefs: PrefHelper = PrefHelper.getDefaultInstance(context)
|
||||
private val data: KeyData
|
||||
private var isKeyPressed: Boolean = false
|
||||
private var osTimer: Timer? = null
|
||||
private val repeatedKeyPressHandler: Handler = Handler(context.mainLooper)
|
||||
|
||||
private var label: String? = null
|
||||
private var labelPaint: Paint = Paint().apply {
|
||||
@@ -100,23 +102,20 @@ class EditingKeyView : AppCompatImageButton {
|
||||
KeyCode.ARROW_RIGHT,
|
||||
KeyCode.ARROW_UP,
|
||||
KeyCode.DELETE -> {
|
||||
osTimer = Timer()
|
||||
osTimer?.scheduleAtFixedRate(object : TimerTask() {
|
||||
override fun run() {
|
||||
val delayMillis = prefs.keyboard.longPressDelay.toLong()
|
||||
repeatedKeyPressHandler.postAtScheduledRate(delayMillis, 25) {
|
||||
if (isKeyPressed) {
|
||||
florisboard?.textInputManager?.sendKeyPress(data)
|
||||
if (!isKeyPressed) {
|
||||
osTimer?.cancel()
|
||||
osTimer = null
|
||||
}
|
||||
} else {
|
||||
repeatedKeyPressHandler.cancelAll()
|
||||
}
|
||||
}, 500, 50)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
isKeyPressed = false
|
||||
osTimer?.cancel()
|
||||
osTimer = null
|
||||
repeatedKeyPressHandler.cancelAll()
|
||||
if (event.actionMasked != MotionEvent.ACTION_CANCEL) {
|
||||
florisboard?.textInputManager?.sendKeyPress(data)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Patrick Goldinger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.key
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Enum for the key hint modes.
|
||||
*/
|
||||
enum class KeyHintMode {
|
||||
DISABLED,
|
||||
ENABLED_HINT_PRIORITY,
|
||||
ENABLED_ACCENT_PRIORITY,
|
||||
ENABLED_SMART_PRIORITY;
|
||||
|
||||
companion object {
|
||||
fun fromString(string: String): KeyHintMode {
|
||||
return valueOf(string.toUpperCase(Locale.ROOT))
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return super.toString().toLowerCase(Locale.ROOT)
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,9 @@ import dev.patrickgold.florisboard.ime.text.gestures.SwipeAction
|
||||
import dev.patrickgold.florisboard.ime.text.gestures.SwipeGesture
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
|
||||
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardView
|
||||
import dev.patrickgold.florisboard.util.cancelAll
|
||||
import dev.patrickgold.florisboard.util.postAtScheduledRate
|
||||
import dev.patrickgold.florisboard.util.postDelayed
|
||||
import dev.patrickgold.florisboard.util.setBackgroundTintColor2
|
||||
import java.util.*
|
||||
|
||||
@@ -61,8 +64,8 @@ class KeyView(
|
||||
updateKeyPressedBackground()
|
||||
}
|
||||
private var hasTriggeredGestureMove: Boolean = false
|
||||
private var osHandler: Handler? = null
|
||||
private var osTimer: Timer? = null
|
||||
private val longKeyPressHandler: Handler = Handler(context.mainLooper)
|
||||
private val repeatedKeyPressHandler: Handler = Handler(context.mainLooper)
|
||||
private val prefs: PrefHelper = PrefHelper.getDefaultInstance(context)
|
||||
private var shouldBlockNextKeyCode: Boolean = false
|
||||
|
||||
@@ -143,19 +146,26 @@ class KeyView(
|
||||
elevation = 4.0f
|
||||
|
||||
var hintKeyData: KeyData? = null
|
||||
var hintKeyMode: KeyHintMode = KeyHintMode.DISABLED
|
||||
val hintedNumber = data.hintedNumber
|
||||
if (prefs.keyboard.hintedNumberRow && hintedNumber != null) {
|
||||
if (prefs.keyboard.hintedNumberRowMode != KeyHintMode.DISABLED && hintedNumber != null) {
|
||||
hintKeyData = hintedNumber
|
||||
hintKeyMode = prefs.keyboard.hintedNumberRowMode
|
||||
}
|
||||
val hintedSymbol = data.hintedSymbol
|
||||
if (prefs.keyboard.hintedSymbols && hintedSymbol != null) {
|
||||
if (prefs.keyboard.hintedSymbolsMode != KeyHintMode.DISABLED && hintedSymbol != null) {
|
||||
hintKeyData = hintedSymbol
|
||||
hintKeyMode = prefs.keyboard.hintedSymbolsMode
|
||||
}
|
||||
dataPopupWithHint = if (hintKeyData == null) {
|
||||
data.popup.toMutableList()
|
||||
} else {
|
||||
val popupList = data.popup.toMutableList()
|
||||
popupList.add(hintKeyData)
|
||||
if (hintKeyMode == KeyHintMode.ENABLED_HINT_PRIORITY) {
|
||||
popupList.add(0, hintKeyData)
|
||||
} else {
|
||||
popupList.add(hintKeyData)
|
||||
}
|
||||
popupList
|
||||
}
|
||||
|
||||
@@ -210,14 +220,14 @@ class KeyView(
|
||||
if (event == null || !isEnabled) return false
|
||||
if (swipeGestureDetector.onTouchEvent(event)) {
|
||||
isKeyPressed = false
|
||||
osHandler?.removeCallbacksAndMessages(null)
|
||||
osTimer?.cancel()
|
||||
osTimer = null
|
||||
longKeyPressHandler.cancelAll()
|
||||
repeatedKeyPressHandler.cancelAll()
|
||||
keyboardView.popupManager.hide()
|
||||
return true
|
||||
}
|
||||
when (event.actionMasked) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
val delayMillis = prefs.keyboard.longPressDelay.toLong()
|
||||
hasTriggeredGestureMove = false
|
||||
shouldBlockNextKeyCode = false
|
||||
florisboard?.prefs?.keyboard?.let {
|
||||
@@ -228,23 +238,22 @@ class KeyView(
|
||||
isKeyPressed = true
|
||||
florisboard?.keyPressVibrate()
|
||||
florisboard?.keyPressSound(data)
|
||||
if (data.code == KeyCode.DELETE && data.type == KeyType.ENTER_EDITING) {
|
||||
osTimer = Timer()
|
||||
osTimer?.scheduleAtFixedRate(object : TimerTask() {
|
||||
override fun run() {
|
||||
florisboard?.textInputManager?.sendKeyPress(data)
|
||||
if (!isKeyPressed) {
|
||||
osTimer?.cancel()
|
||||
osTimer = null
|
||||
when (data.code) {
|
||||
KeyCode.ARROW_DOWN,
|
||||
KeyCode.ARROW_LEFT,
|
||||
KeyCode.ARROW_RIGHT,
|
||||
KeyCode.ARROW_UP,
|
||||
KeyCode.DELETE -> {
|
||||
repeatedKeyPressHandler.postAtScheduledRate(delayMillis, 25) {
|
||||
if (isKeyPressed) {
|
||||
florisboard?.textInputManager?.sendKeyPress(data)
|
||||
} else {
|
||||
repeatedKeyPressHandler.cancelAll()
|
||||
}
|
||||
}
|
||||
}, 500, 50)
|
||||
}
|
||||
}
|
||||
val delayMillis = prefs.keyboard.longPressDelay
|
||||
if (osHandler == null) {
|
||||
osHandler = Handler()
|
||||
}
|
||||
osHandler?.postDelayed({
|
||||
longKeyPressHandler.postDelayed(delayMillis) {
|
||||
if (dataPopupWithHint.isNotEmpty()) {
|
||||
keyboardView.popupManager.extend(this)
|
||||
}
|
||||
@@ -257,7 +266,7 @@ class KeyView(
|
||||
)
|
||||
shouldBlockNextKeyCode = true
|
||||
}
|
||||
}, delayMillis.toLong())
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
if (keyboardView.popupManager.isShowingExtendedPopup) {
|
||||
@@ -281,9 +290,8 @@ class KeyView(
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
isKeyPressed = false
|
||||
osHandler?.removeCallbacksAndMessages(null)
|
||||
osTimer?.cancel()
|
||||
osTimer = null
|
||||
longKeyPressHandler.cancelAll()
|
||||
repeatedKeyPressHandler.cancelAll()
|
||||
if (hasTriggeredGestureMove && data.code == KeyCode.DELETE) {
|
||||
hasTriggeredGestureMove = false
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
@@ -296,7 +304,6 @@ class KeyView(
|
||||
keyboardView.popupManager.hide()
|
||||
if (event.actionMasked != MotionEvent.ACTION_CANCEL && !shouldBlockNextKeyCode && retData != null) {
|
||||
florisboard?.textInputManager?.sendKeyPress(retData)
|
||||
performClick()
|
||||
} else {
|
||||
shouldBlockNextKeyCode = false
|
||||
}
|
||||
@@ -327,6 +334,15 @@ class KeyView(
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
}
|
||||
SwipeAction.DELETE_WORDS_PRECISELY -> {
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
leftAppendWordToSelection()
|
||||
}
|
||||
|
||||
hasTriggeredGestureMove = true
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
SwipeGesture.Direction.RIGHT -> when (prefs.gestures.deleteKeySwipeLeft) {
|
||||
@@ -340,6 +356,14 @@ class KeyView(
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
}
|
||||
|
||||
SwipeAction.DELETE_WORDS_PRECISELY -> {
|
||||
florisboard?.activeEditorInstance?.apply {
|
||||
leftPopWordFromSelection()
|
||||
}
|
||||
shouldBlockNextKeyCode = true
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
else -> false
|
||||
@@ -629,11 +653,11 @@ class KeyView(
|
||||
) {
|
||||
label = getComputedLetter()
|
||||
val hintedNumber = data.hintedNumber
|
||||
if (prefs.keyboard.hintedNumberRow && hintedNumber != null) {
|
||||
if (prefs.keyboard.hintedNumberRowMode != KeyHintMode.DISABLED && hintedNumber != null) {
|
||||
hintedLabel = getComputedLetter(hintedNumber)
|
||||
}
|
||||
val hintedSymbol = data.hintedSymbol
|
||||
if (prefs.keyboard.hintedSymbols && hintedSymbol != null) {
|
||||
if (prefs.keyboard.hintedSymbolsMode != KeyHintMode.DISABLED && hintedSymbol != null) {
|
||||
hintedLabel = getComputedLetter(hintedSymbol)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package dev.patrickgold.florisboard.ime.text.smartbar
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.util.AttributeSet
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.ime.core.PrefHelper
|
||||
import dev.patrickgold.florisboard.util.setBackgroundTintColor2
|
||||
|
||||
@@ -52,7 +53,12 @@ class SmartbarQuickActionButton : androidx.appcompat.widget.AppCompatImageButton
|
||||
}
|
||||
|
||||
private fun updateTheme() {
|
||||
setBackgroundTintColor2(this, prefs.theme.smartbarButtonBgColor)
|
||||
setColorFilter(prefs.theme.smartbarButtonFgColor)
|
||||
if (id == R.id.private_mode_button) {
|
||||
setBackgroundTintColor2(this, prefs.theme.privateModeBgColor)
|
||||
setColorFilter(prefs.theme.privateModeFgColor)
|
||||
} else {
|
||||
setBackgroundTintColor2(this, prefs.theme.smartbarButtonBgColor)
|
||||
setColorFilter(prefs.theme.smartbarButtonFgColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,11 @@ package dev.patrickgold.florisboard.ime.text.smartbar
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.children
|
||||
import dev.patrickgold.florisboard.BuildConfig
|
||||
import dev.patrickgold.florisboard.R
|
||||
import dev.patrickgold.florisboard.databinding.SmartbarBinding
|
||||
import dev.patrickgold.florisboard.ime.core.FlorisBoard
|
||||
@@ -38,6 +36,7 @@ import dev.patrickgold.florisboard.util.setDrawableTintColor2
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -83,7 +82,7 @@ class SmartbarView : ConstraintLayout {
|
||||
* TextInputManager, which then starts working together with this view.
|
||||
*/
|
||||
override fun onAttachedToWindow() {
|
||||
if (BuildConfig.DEBUG) Log.i(this::class.simpleName, "onAttachedToWindow()")
|
||||
Timber.i("onAttachedToWindow()")
|
||||
|
||||
super.onAttachedToWindow()
|
||||
|
||||
@@ -141,6 +140,10 @@ class SmartbarView : ConstraintLayout {
|
||||
}
|
||||
}
|
||||
|
||||
binding.privateModeButton.setOnClickListener {
|
||||
eventListener?.get()?.onSmartbarPrivateModeButtonClicked()
|
||||
}
|
||||
|
||||
for (quickAction in binding.quickActions.children) {
|
||||
if (quickAction is SmartbarQuickActionButton) {
|
||||
quickAction.setOnClickListener { eventListener?.get()?.onSmartbarQuickActionPressed(quickAction.id) }
|
||||
@@ -258,15 +261,19 @@ class SmartbarView : ConstraintLayout {
|
||||
KeyVariation.PASSWORD -> false
|
||||
else -> true
|
||||
},
|
||||
actionEndAreaId = null
|
||||
actionEndAreaId = when {
|
||||
florisboard.activeEditorInstance.isPrivateMode -> R.id.private_mode_button
|
||||
else -> null
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onPrimaryClipChanged() {
|
||||
if (prefs.suggestion.enabled && prefs.suggestion.suggestClipboardContent) {
|
||||
if (prefs.suggestion.enabled && prefs.suggestion.suggestClipboardContent &&
|
||||
florisboard?.activeEditorInstance?.isPrivateMode == false) {
|
||||
shouldSuggestClipboardContents = true
|
||||
val item = florisboard?.clipboardManager?.primaryClip?.getItemAt(0)
|
||||
val item = florisboard.clipboardManager?.primaryClip?.getItemAt(0)
|
||||
when {
|
||||
item?.text != null -> {
|
||||
binding.clipboardSuggestion.text = item.text
|
||||
@@ -283,10 +290,8 @@ class SmartbarView : ConstraintLayout {
|
||||
}
|
||||
|
||||
fun resetClipboardSuggestion() {
|
||||
if (prefs.suggestion.enabled && prefs.suggestion.suggestClipboardContent) {
|
||||
shouldSuggestClipboardContents = false
|
||||
updateSmartbarState()
|
||||
}
|
||||
shouldSuggestClipboardContents = false
|
||||
updateSmartbarState()
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
@@ -333,6 +338,7 @@ class SmartbarView : ConstraintLayout {
|
||||
fun onSmartbarBackButtonPressed() {}
|
||||
//fun onSmartbarCandidatePressed() {}
|
||||
//fun onSmartbarCandidateLongPressed() {}
|
||||
fun onSmartbarPrivateModeButtonClicked() {}
|
||||
fun onSmartbarQuickActionPressed(@IdRes quickActionId: Int) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +162,9 @@ data class Theme(
|
||||
|
||||
prefs.theme.oneHandedButtonFgColor = theme.getAttr("oneHandedButton/fgColor", "#424242")
|
||||
|
||||
prefs.theme.privateModeBgColor = theme.getAttr("privateMode/bgColor", "#A000FF")
|
||||
prefs.theme.privateModeFgColor = theme.getAttr("privateMode/fgColor", "#FFFFFF")
|
||||
|
||||
prefs.theme.smartbarBgColor = theme.getAttr("smartbar/bgColor", "#E0E0E0")
|
||||
prefs.theme.smartbarFgColor = theme.getAttr("smartbar/fgColor", "#000000")
|
||||
prefs.theme.smartbarFgColorAlt = theme.getAttr("smartbar/fgColorAlt", "#4A000000")
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.patrickgold.florisboard.util
|
||||
|
||||
import android.os.Handler
|
||||
|
||||
fun Handler.postAtScheduledRate(delayMillis: Long, periodMillis: Long, r: Runnable) {
|
||||
val internalRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
this@postAtScheduledRate.postDelayed(this, periodMillis)
|
||||
r.run()
|
||||
}
|
||||
}
|
||||
this.postDelayed(internalRunnable, delayMillis)
|
||||
}
|
||||
|
||||
fun Handler.postDelayed(delayMillis: Long, r: Runnable) {
|
||||
this.postDelayed(r, delayMillis)
|
||||
}
|
||||
|
||||
fun Handler.cancelAll() {
|
||||
this.removeCallbacksAndMessages(null)
|
||||
}
|
||||
9
app/src/main/res/drawable/ic_redo.xml
Normal file
9
app/src/main/res/drawable/ic_redo.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18.4,10.6C16.55,8.99 14.15,8 11.5,8c-4.65,0 -8.58,3.03 -9.96,7.22L3.9,16c1.05,-3.19 4.05,-5.5 7.6,-5.5 1.95,0 3.73,0.72 5.12,1.88L13,16h9V7l-3.6,3.6z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/ic_security.xml
Normal file
5
app/src/main/res/drawable/ic_security.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,1L3,5v6c0,5.55 3.84,10.74 9,12 5.16,-1.26 9,-6.45 9,-12L21,5l-9,-4zM12,11.99h7c-0.53,4.12 -3.28,7.79 -7,8.94L12,12L5,12L5,6.3l7,-3.11v8.8z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_undo.xml
Normal file
9
app/src/main/res/drawable/ic_undo.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12.5,8c-2.65,0 -5.05,0.99 -6.9,2.6L2,7v9h9l-3.62,-3.62c1.39,-1.16 3.16,-1.88 5.12,-1.88 3.54,0 6.55,2.31 7.6,5.5l2.37,-0.78C21.08,11.03 17.15,8 12.5,8z"/>
|
||||
</vector>
|
||||
@@ -1,13 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape>
|
||||
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp"/>
|
||||
<solid android:color="#CDAFAFAF"/>
|
||||
<corners android:radius="@dimen/key_borderRadius"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/white"/>
|
||||
|
||||
@@ -79,6 +79,18 @@
|
||||
android:id="@+id/quick_actions"
|
||||
style="@style/SmartbarContainer">
|
||||
|
||||
<dev.patrickgold.florisboard.ime.text.smartbar.SmartbarQuickActionButton
|
||||
android:id="@+id/quick_action_undo"
|
||||
style="@style/SmartbarQuickAction"
|
||||
android:contentDescription="@string/smartbar__quick_action__undo"
|
||||
android:src="@drawable/ic_undo"/>
|
||||
|
||||
<dev.patrickgold.florisboard.ime.text.smartbar.SmartbarQuickActionButton
|
||||
android:id="@+id/quick_action_redo"
|
||||
style="@style/SmartbarQuickAction"
|
||||
android:contentDescription="@string/smartbar__quick_action__redo"
|
||||
android:src="@drawable/ic_redo"/>
|
||||
|
||||
<dev.patrickgold.florisboard.ime.text.smartbar.SmartbarQuickActionButton
|
||||
android:id="@+id/quick_action_switch_to_media_context"
|
||||
style="@style/SmartbarQuickAction"
|
||||
@@ -128,14 +140,11 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<!-- Placeholder on the right which reserves the space for a second button -->
|
||||
<dev.patrickgold.florisboard.ime.text.smartbar.SmartbarQuickActionButton
|
||||
android:id="@+id/placeholder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="@dimen/smartbar_button_margin"
|
||||
android:clickable="false"
|
||||
android:visibility="invisible"/>
|
||||
android:id="@+id/private_mode_button"
|
||||
style="@style/SmartbarQuickAction.PrivateModeButton"
|
||||
android:contentDescription="@string/smartbar__quick_action__private_mode"
|
||||
android:src="@drawable/ic_security"/>
|
||||
|
||||
</dev.patrickgold.florisboard.ime.core.FlorisViewFlipper>
|
||||
|
||||
|
||||
@@ -93,10 +93,6 @@
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">المفاتيح</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">صف الأعداد</string>
|
||||
<string name="pref__keyboard__number_row__summary" comment="Preference summary">إظهار صف الأعداد فوق تخطيط الحروف</string>
|
||||
<string name="pref__keyboard__hinted_number_row__label" comment="Preference title">تلميح لصف الأعداد</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">الصف الأول لتخطيط الحروف يشير إلى صف الأرقام</string>
|
||||
<string name="pref__keyboard__hinted_symbols__label" comment="Preference title">تلميح للرموز</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">الصف الثاني و الثالث لتخطيط الحروف يشير إلى الرموز</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>
|
||||
|
||||
@@ -91,8 +91,6 @@
|
||||
<string name="pref__theme__navBarIsLight_summary" comment="Summary of Nav bar is light theme preference">Nastavte na Zapnuto pro tmavé nebo vypnuté pro světlé popředí.</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Předvolby Klávesnice</string>
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Šipka</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">První řádek rozvržení znaků naznačuje číslo řádku</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Druhá a třetí řada znakových symbolů nápovědy</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__group_layout__label" comment="Preference group title">Rozložení</string>
|
||||
|
||||
@@ -91,8 +91,6 @@
|
||||
<string name="pref__theme__navBarIsLight_summary" comment="Summary of Nav bar is light theme preference">EIN für dunklen oder AUS für hellen Vordergrund.</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Tastatur-Einstellungen</string>
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Tasten</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">Erste Reihe der Tastatur deutet Zahlenreihe im Hintergrund an</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Zweite und dritte Reihe der Tastatur deuten Symbole im Hintergrund an</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Schriftgröße anpassen (Hochformat)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Schriftgröße anpassen (Querformat)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Layout</string>
|
||||
|
||||
@@ -91,8 +91,6 @@
|
||||
<string name="pref__theme__navBarIsLight_summary" comment="Summary of Nav bar is light theme preference">Ορίστε ΕΝΕΡΓΟΠΟΙΗΜΈΝΟ για σκούρο ή ΑΠΕΝΕΡΓΟΠΟΙΗΜΈΝΟ για φωτεινό προσκήνιο.</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Προτιμήσεις Πληκτρολογίου</string>
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Πλήκτρα</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">Η πρώτη σειρά χαρακτήρων υπονοεί τη σειρά αριθμών</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Η δεύτερη και τρίτη σειρά διάταξης χαρακτήρων υπονοούν σύμβολα</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>
|
||||
|
||||
@@ -43,10 +43,6 @@
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">کلیدها</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">ردیف عدد</string>
|
||||
<string name="pref__keyboard__number_row__summary" comment="Preference summary">ردیف عددی که بالای چیدمان کاراکتر ها نمایش داده می شود</string>
|
||||
<string name="pref__keyboard__hinted_number_row__label" comment="Preference title">ردیف عددی همیار</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">اولین ردیف از چیدمان کاراکتر ها به ردیف عدد اشاره می کند</string>
|
||||
<string name="pref__keyboard__hinted_symbols__label" comment="Preference title">نشانه های همیار</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">دومین و سویم ردیف از کاراکتر ها در چیدمان به نماد ها اشاره می کند</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>
|
||||
|
||||
@@ -91,8 +91,6 @@
|
||||
<string name="pref__theme__navBarIsLight_summary" comment="Summary of Nav bar is light theme preference">Aseta päälle tummia tai pois päältä vaaleita painikkeita varten.</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Näppäimistön asetukset</string>
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Painikkeet</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">Numerot ensimmäisen näppäinrivin painikkeilla</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Symbolit toisen ja kolmannen näppäinrivin painikkeilla</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Fonttikoon kerroin (pystysuunnassa)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Fonttikoon kerroin (vaakasuunnassa)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Ulkoasu</string>
|
||||
|
||||
@@ -93,10 +93,6 @@
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Touches</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">Rangée de numéros</string>
|
||||
<string name="pref__keyboard__number_row__summary" comment="Preference summary">Afficher la rangée de numéros au dessus de la disposition des caractères</string>
|
||||
<string name="pref__keyboard__hinted_number_row__label" comment="Preference title">Rangée de numéros subtile</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">Première rangée de la configuration des caractères indique la rangée des numéros</string>
|
||||
<string name="pref__keyboard__hinted_symbols__label" comment="Preference title">Astuce des symboles</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Deuxième et troisième rangées de la configuration des caractères indique des symboles</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Multiplicateur de la taille de la police (portrait)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Multiplicateur de la taille de la police (paysage)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Disposition</string>
|
||||
|
||||
@@ -93,8 +93,6 @@
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Billentyűk</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">Számsor</string>
|
||||
<string name="pref__keyboard__number_row__summary" comment="Preference summary">Számsor megjelenítése a karakterelrendezés felett</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">A karakterelrendezés első sora utal a számsorra</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Második és harmadik sor karakter elrendezés tipp szimbólumok</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Betűméret szorzó (álló)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Betűméret szorzó (fekvő)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Elrendezés</string>
|
||||
|
||||
@@ -91,8 +91,6 @@
|
||||
<string name="pref__theme__navBarIsLight_summary" comment="Summary of Nav bar is light theme preference">Imposta a ON per un colore di primo piano scuro e OFF per uno chiaro.</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Tastiera preferenze</string>
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Tasti</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">Prima riga dei tasti contiene suggerimenti per i numeri</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">La seconda e terza riga suggeriscono simboli</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Moltiplicatore della dimensione del testo (ritratto)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Moltiplicatore della dimensione del testo (panorama)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Layout</string>
|
||||
|
||||
@@ -91,8 +91,6 @@
|
||||
<string name="pref__theme__navBarIsLight_summary" comment="Summary of Nav bar is light theme preference">Start op voor donker of uit voor lichte voorgrond.</string>
|
||||
<string name="settings__keyboard__title" comment="Title of Keyboard preferences fragment">Toetsenbordvoorkeuren</string>
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Toets</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">Eerste rij tekenopmaak geeft nummer rij</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Tweede en derde rij tekenopmaak hint symbolen</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Lettergrootte multiplier (portret)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Lettergrootte multiplier (landschap)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Lay</string>
|
||||
|
||||
@@ -93,10 +93,6 @@
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Teclas</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">Linha de números</string>
|
||||
<string name="pref__keyboard__number_row__summary" comment="Preference summary">Mostrar linha de números em cima do teclado</string>
|
||||
<string name="pref__keyboard__hinted_number_row__label" comment="Preference title">Sugerir linha de números</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">A primeira linha de letras sugere números</string>
|
||||
<string name="pref__keyboard__hinted_symbols__label" comment="Preference title">Sugerir símbolos</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">As segunda e terceira linhas de letras sugere símbolos</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Multiplicador de tamanho da fonte (retrato)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Multiplicador de tamanho da fonte (paisagem)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Layout</string>
|
||||
|
||||
@@ -93,8 +93,6 @@
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Teclas</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">Linha de números</string>
|
||||
<string name="pref__keyboard__number_row__summary" comment="Preference summary">Mostrar linha de números em cima do teclado</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">Mostrar números na primeira linha do teclado</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Mostrar símbolos na segunda e na terceira linha do teclado</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Multiplicador do tipo de letra (vertical)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Multiplicador do tipo de letra (horizontal)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Disposição</string>
|
||||
|
||||
@@ -21,6 +21,20 @@
|
||||
<item>custom</item>
|
||||
</string-array>
|
||||
|
||||
<!-- TODO: implement smart priority -->
|
||||
<string-array name="pref__keyboard__hint_mode__entries">
|
||||
<item>@string/pref__keyboard__hint_mode__disabled</item>
|
||||
<item>@string/pref__keyboard__hint_mode__enabled_hint_priority</item>
|
||||
<item>@string/pref__keyboard__hint_mode__enabled_accent_priority</item>
|
||||
<!--<item>@string/pref__keyboard__hint_mode__enabled_smart_priority</item>-->
|
||||
</string-array>
|
||||
<string-array name="pref__keyboard__hint_mode__values">
|
||||
<item>disabled</item>
|
||||
<item>enabled_hint_priority</item>
|
||||
<item>enabled_accent_priority</item>
|
||||
<!--<item>enabled_smart_priority</item>-->
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref__keyboard__one_handed_mode__entries">
|
||||
<item>@string/pref__keyboard__one_handed_mode__off</item>
|
||||
<item>@string/pref__keyboard__one_handed_mode__right</item>
|
||||
@@ -66,18 +80,17 @@
|
||||
<item>switch_to_next_subtype</item>
|
||||
</string-array>
|
||||
|
||||
<!-- TODO: Implement precise word deleting -->
|
||||
<string-array name="pref__gestures__swipe_action_delete__entries">
|
||||
<item>@string/pref__gestures__swipe_action__no_action</item>
|
||||
<item>@string/pref__gestures__swipe_action__delete_characters_precisely</item>
|
||||
<item>@string/pref__gestures__swipe_action__delete_word</item>
|
||||
<!--<item>@string/pref__gestures__swipe_action__delete_words_precisely</item>-->
|
||||
<item>@string/pref__gestures__swipe_action__delete_words_precisely</item>
|
||||
</string-array>
|
||||
<string-array name="pref__gestures__swipe_action_delete__values">
|
||||
<item>no_action</item>
|
||||
<item>delete_characters_precisely</item>
|
||||
<item>delete_word</item>
|
||||
<!--<item>delete_words_precisely</item>-->
|
||||
<item>delete_words_precisely</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="pref__gestures__swipe_velocity_threshold__entries">
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
<string name="one_handed__move_start_btn_content_description" comment="Content description for the one-handed move to left button">Move keyboard to the left.</string>
|
||||
<string name="one_handed__move_end_btn_content_description" comment="Content description for the one-handed move to right button">Move keyboard to the right.</string>
|
||||
|
||||
<!-- Private mode info dialog strings -->
|
||||
<string name="private_mode_dialog__title" comment="Title of the private mode dialog">Private mode</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">Emojis</string>
|
||||
<string name="media__tab__emoticons" comment="Tab description for emoticons in the media UI">Emoticons</string>
|
||||
@@ -31,6 +37,9 @@
|
||||
<string name="smartbar__quick_action__open_settings" comment="Content-description for the settings quick action in Smartbar">Open settings.</string>
|
||||
<string name="smartbar__quick_action__switch_to_editing_context" comment="Content-description for the editing quick action in Smartbar">Switch to text editing panel.</string>
|
||||
<string name="smartbar__quick_action__switch_to_media_context" comment="Content-description for the media quick action in Smartbar">Switch to media input view.</string>
|
||||
<string name="smartbar__quick_action__undo" comment="Content-description for the undo quick action in Smartbar">Undo button to reverse the last action</string>
|
||||
<string name="smartbar__quick_action__redo" comment="Content-description for the redo quick action in Smartbar">Redo button to reverse the last Undo</string>
|
||||
<string name="smartbar__quick_action__private_mode" comment="Content-description for the private mode button in Smartbar">If visible, indicates that private mode is active. When clicked, shows info about the private mode.</string>
|
||||
|
||||
<!-- Settings UI strings -->
|
||||
<string name="settings__title" comment="Title of Settings">Settings</string>
|
||||
@@ -86,6 +95,7 @@
|
||||
<string name="settings__theme__group_media" comment="Theme group label">Media context</string>
|
||||
<string name="settings__theme__group_one_handed" comment="Theme group label">One-handed</string>
|
||||
<string name="settings__theme__group_one_handed_button" comment="Theme group label">One-handed button</string>
|
||||
<string name="settings__theme__group_private_mode" comment="Theme group label">Private mode</string>
|
||||
<string name="settings__theme__group_smartbar" comment="Theme group label">Smartbar</string>
|
||||
<string name="settings__theme__group_smartbar_button" comment="Theme group label">Smartbar button</string>
|
||||
<string name="pref__theme__colorPrimary_title" comment="Title of Color primary theme preference">Primary color</string>
|
||||
@@ -103,10 +113,12 @@
|
||||
<string name="pref__keyboard__group_keys__label" comment="Preference group title">Keys</string>
|
||||
<string name="pref__keyboard__number_row__label" comment="Preference title">Number row</string>
|
||||
<string name="pref__keyboard__number_row__summary" comment="Preference summary">Show number row on top of character layout</string>
|
||||
<string name="pref__keyboard__hinted_number_row__label" comment="Preference title">Hinted number row</string>
|
||||
<string name="pref__keyboard__hinted_number_row__summary" comment="Preference summary">First row of character layout hints number row</string>
|
||||
<string name="pref__keyboard__hinted_symbols__label" comment="Preference title">Hinted symbols</string>
|
||||
<string name="pref__keyboard__hinted_symbols__summary" comment="Preference summary">Second and third row of character layout hint symbols</string>
|
||||
<string name="pref__keyboard__hinted_number_row_mode__label" comment="Preference title">Hinted number row</string>
|
||||
<string name="pref__keyboard__hinted_symbols_mode__label" comment="Preference title">Hinted symbols</string>
|
||||
<string name="pref__keyboard__hint_mode__disabled" comment="Preference value">Disabled</string>
|
||||
<string name="pref__keyboard__hint_mode__enabled_hint_priority" comment="Preference value">Enabled (Hint is prioritized)</string>
|
||||
<string name="pref__keyboard__hint_mode__enabled_accent_priority" comment="Preference value">Enabled (Accent is prioritized)</string>
|
||||
<string name="pref__keyboard__hint_mode__enabled_smart_priority" comment="Preference value">Enabled (Smart prioritization)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_portrait__label" comment="Preference title">Font size multiplier (portrait)</string>
|
||||
<string name="pref__keyboard__font_size_multiplier_landscape__label" comment="Preference title">Font size multiplier (landscape)</string>
|
||||
<string name="pref__keyboard__group_layout__label" comment="Preference group title">Layout</string>
|
||||
@@ -196,6 +208,8 @@
|
||||
<string name="pref__advanced__settings_theme__light" comment="Possible value of Settings theme preference in Advanced">Light</string>
|
||||
<string name="pref__advanced__settings_theme__dark" comment="Possible value of Settings theme preference in Advanced">Dark</string>
|
||||
<string name="pref__advanced__show_app_icon__label" comment="Label of Show app icon preference in Advanced">Show app icon in launcher</string>
|
||||
<string name="pref__advanced__force_private_mode__label" comment="Label of Force private mode preference in Advanced">Force private mode</string>
|
||||
<string name="pref__advanced__force_private_mode__summary" comment="Summary of Force private mode preference in Advanced">Will disable any features which have to temporarily work with your input data</string>
|
||||
|
||||
<!-- About UI strings -->
|
||||
<string name="about__title" comment="Title of About activity">About</string>
|
||||
|
||||
@@ -72,6 +72,10 @@
|
||||
<item name="android:autoMirrored">true</item>
|
||||
</style>
|
||||
|
||||
<style name="SmartbarQuickAction.PrivateModeButton">
|
||||
<item name="android:background">@drawable/shape_rect_rounded</item>
|
||||
</style>
|
||||
|
||||
<style name="TextEditingButton" parent="Widget.AppCompat.Button.Borderless">
|
||||
<item name="android:layout_width">0dp</item>
|
||||
<item name="android:layout_height">0dp</item>
|
||||
|
||||
@@ -18,4 +18,12 @@
|
||||
app:title="@string/pref__advanced__show_app_icon__label"
|
||||
app:useSimpleSummaryProvider="true"/>
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
app:key="advanced__force_private_mode"
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/pref__advanced__force_private_mode__label"
|
||||
app:summary="@string/pref__advanced__force_private_mode__summary"
|
||||
app:useSimpleSummaryProvider="true"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -13,19 +13,23 @@
|
||||
app:title="@string/pref__keyboard__number_row__label"
|
||||
app:summary="@string/pref__keyboard__number_row__summary"/>
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="keyboard__hinted_number_row"
|
||||
<ListPreference
|
||||
android:defaultValue="enabled_accent_priority"
|
||||
app:entries="@array/pref__keyboard__hint_mode__entries"
|
||||
app:entryValues="@array/pref__keyboard__hint_mode__values"
|
||||
app:key="keyboard__hinted_number_row_mode"
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/pref__keyboard__hinted_number_row__label"
|
||||
app:summary="@string/pref__keyboard__hinted_number_row__summary"/>
|
||||
app:title="@string/pref__keyboard__hinted_number_row_mode__label"
|
||||
app:useSimpleSummaryProvider="true"/>
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="keyboard__hinted_symbols"
|
||||
<ListPreference
|
||||
android:defaultValue="enabled_accent_priority"
|
||||
app:entries="@array/pref__keyboard__hint_mode__entries"
|
||||
app:entryValues="@array/pref__keyboard__hint_mode__values"
|
||||
app:key="keyboard__hinted_symbols_mode"
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/pref__keyboard__hinted_symbols__label"
|
||||
app:summary="@string/pref__keyboard__hinted_symbols__summary"/>
|
||||
app:title="@string/pref__keyboard__hinted_symbols_mode__label"
|
||||
app:useSimpleSummaryProvider="true"/>
|
||||
|
||||
<dev.patrickgold.florisboard.settings.components.DialogSeekBarPreference
|
||||
app:allowDividerAbove="false"
|
||||
|
||||
@@ -182,6 +182,24 @@
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
app:title="@string/settings__theme__group_private_mode"
|
||||
app:iconSpaceReserved="false">
|
||||
|
||||
<com.jaredrummler.android.colorpicker.ColorPreferenceCompat
|
||||
android:defaultValue="0xFFA000FF"
|
||||
android:key="theme__privateMode_bgColor"
|
||||
android:title="@string/settings__theme__background"
|
||||
app:iconSpaceReserved="false"/>
|
||||
|
||||
<com.jaredrummler.android.colorpicker.ColorPreferenceCompat
|
||||
android:defaultValue="0xFFFFFFFF"
|
||||
android:key="theme__privateMode_fgColor"
|
||||
android:title="@string/settings__theme__foreground"
|
||||
app:iconSpaceReserved="false"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
app:title="@string/settings__theme__group_smartbar"
|
||||
app:iconSpaceReserved="false">
|
||||
|
||||
7
fastlane/metadata/android/en-US/changelogs/20.txt
Normal file
7
fastlane/metadata/android/en-US/changelogs/20.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
- Complete rework of the Smartbar + new features (see PR #91 for more details)
|
||||
- Add Colemak keyboard layout (#72)
|
||||
- Add Dvorak keyboard layout (#72)
|
||||
- Add Esperanto keyboard layout (thanks @jeremiah-miller)
|
||||
- Add Hungarian keyboard layout (thanks @zoli111)
|
||||
- Fix event listener NullPointerException (#73, #81)
|
||||
- Other bug fixes and improvements
|
||||
9
fastlane/metadata/android/en-US/changelogs/21.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/21.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
- Add option to prioritize hints in the extended popups (#39)
|
||||
- Add private mode (#106)
|
||||
- Add precise word deletion (#25) (thanks @yashx)
|
||||
- Add undo/redo for pasting (#70) (thanks @yashx)
|
||||
- Add Canadian-French keyboard layout (thanks @The-Quantum-Alpha)
|
||||
- Improve delete key behavior (thanks @yashx)
|
||||
- Improve input UX and performance
|
||||
- Fix delete key crash on holding down
|
||||
- Other bug fixes and improvements
|
||||
Reference in New Issue
Block a user