diff --git a/build.gradle b/build.gradle
index 8e500f26a..6bd19e7c7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -144,12 +144,12 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
- implementation 'androidx.lifecycle:lifecycle-runtime:2.6.2'
- implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.6.2'
- implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
+ implementation 'androidx.lifecycle:lifecycle-runtime:2.7.0'
+ implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.7.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0'
implementation 'androidx.activity:activity-compose:1.8.2'
- implementation platform('androidx.compose:compose-bom:2022.10.00')
+ implementation platform('androidx.compose:compose-bom:2024.02.02')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
@@ -157,7 +157,7 @@ dependencies {
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
- implementation 'androidx.navigation:navigation-compose:2.7.6'
+ implementation 'androidx.navigation:navigation-compose:2.7.7'
implementation 'com.google.code.findbugs:jsr305:3.0.2'
diff --git a/java/res/values/strings-uix.xml b/java/res/values/strings-uix.xml
index 95f66c272..bc0dfda75 100644
--- a/java/res/values/strings-uix.xml
+++ b/java/res/values/strings-uix.xml
@@ -39,4 +39,5 @@
Blacklist
Blacklist \"%1$s\" from being suggested?
+ Try typing hereā¦
\ No newline at end of file
diff --git a/java/src/org/futo/inputmethod/latin/LatinIME.kt b/java/src/org/futo/inputmethod/latin/LatinIME.kt
index 2aca377cf..431426639 100644
--- a/java/src/org/futo/inputmethod/latin/LatinIME.kt
+++ b/java/src/org/futo/inputmethod/latin/LatinIME.kt
@@ -292,7 +292,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
key(legacyInputView) {
AndroidView(factory = {
legacyInputView!!
- }, update = { }, modifier = modifier)
+ }, modifier = modifier)
}
}
@@ -305,7 +305,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
latinIMELegacy.setComposeInputView(it)
}
- latinIMELegacy.setInputView(legacyInputView)
+ latinIMELegacy.setInputView(newView)
}
override fun setInputView(view: View?) {
diff --git a/java/src/org/futo/inputmethod/latin/uix/settings/SettingsActivity.kt b/java/src/org/futo/inputmethod/latin/uix/settings/SettingsActivity.kt
index 19627c2d1..d6e7a3851 100644
--- a/java/src/org/futo/inputmethod/latin/uix/settings/SettingsActivity.kt
+++ b/java/src/org/futo/inputmethod/latin/uix/settings/SettingsActivity.kt
@@ -1,9 +1,11 @@
package org.futo.inputmethod.latin.uix.settings
+import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Context.INPUT_METHOD_SERVICE
import android.content.Intent
+import android.content.pm.PackageManager
import android.os.Bundle
import android.provider.Settings
import android.view.inputmethod.InputMethodManager
@@ -27,9 +29,12 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.uix.THEME_KEY
+import org.futo.inputmethod.latin.uix.USE_SYSTEM_VOICE_INPUT
import org.futo.inputmethod.latin.uix.deferGetSetting
+import org.futo.inputmethod.latin.uix.getSetting
import org.futo.inputmethod.latin.uix.theme.StatusBarColorSetter
import org.futo.inputmethod.latin.uix.theme.ThemeOption
import org.futo.inputmethod.latin.uix.theme.ThemeOptions
@@ -68,10 +73,10 @@ class SettingsActivity : ComponentActivity() {
private val inputMethodEnabled = mutableStateOf(false)
private val inputMethodSelected = mutableStateOf(false)
+ private val micPermissionGrantedOrUsingSystem = mutableStateOf(false)
private var wasImeEverDisabled = false
-
private var fileBeingSaved: File? = null
fun updateFileBeingSaved(to: File) {
fileBeingSaved = to
@@ -82,12 +87,16 @@ class SettingsActivity : ComponentActivity() {
}
@OptIn(DelicateCoroutinesApi::class)
- private fun updateSystemState() {
+ fun updateSystemState() {
val inputMethodEnabled = isInputMethodEnabled()
val inputMethodSelected = isDefaultIMECurrent()
this.inputMethodEnabled.value = inputMethodEnabled
this.inputMethodSelected.value = inputMethodSelected
+ this.micPermissionGrantedOrUsingSystem.value = (checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) || runBlocking {
+ getSetting(USE_SYSTEM_VOICE_INPUT)
+ }
+
if(!inputMethodEnabled) {
wasImeEverDisabled = true
} else if(wasImeEverDisabled) {
@@ -138,7 +147,7 @@ class SettingsActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
- SetupOrMain(inputMethodEnabled.value, inputMethodSelected.value) {
+ SetupOrMain(inputMethodEnabled.value, inputMethodSelected.value, micPermissionGrantedOrUsingSystem.value) {
SettingsNavigator(navController = navController)
}
}
diff --git a/java/src/org/futo/inputmethod/latin/uix/settings/SettingsUtils.kt b/java/src/org/futo/inputmethod/latin/uix/settings/SettingsUtils.kt
index d15ec490c..603969868 100644
--- a/java/src/org/futo/inputmethod/latin/uix/settings/SettingsUtils.kt
+++ b/java/src/org/futo/inputmethod/latin/uix/settings/SettingsUtils.kt
@@ -9,11 +9,13 @@ import androidx.compose.runtime.Composable
import org.futo.inputmethod.latin.utils.UncachedInputMethodManagerUtils
@Composable
-fun SetupOrMain(inputMethodEnabled: Boolean, inputMethodSelected: Boolean, main: @Composable () -> Unit) {
+fun SetupOrMain(inputMethodEnabled: Boolean, inputMethodSelected: Boolean, micPermissionGrantedOrUsingSystem: Boolean, main: @Composable () -> Unit) {
if (!inputMethodEnabled) {
SetupEnableIME()
} else if (!inputMethodSelected) {
SetupChangeDefaultIME()
+ } else if (!micPermissionGrantedOrUsingSystem) {
+ SetupEnableMic()
} else {
main()
}
diff --git a/java/src/org/futo/inputmethod/latin/uix/settings/Setup.kt b/java/src/org/futo/inputmethod/latin/uix/settings/Setup.kt
index 620d6476d..ed829adeb 100644
--- a/java/src/org/futo/inputmethod/latin/uix/settings/Setup.kt
+++ b/java/src/org/futo/inputmethod/latin/uix/settings/Setup.kt
@@ -1,9 +1,13 @@
package org.futo.inputmethod.latin.uix.settings
+import android.Manifest
import android.content.Context
import android.content.Intent
+import android.net.Uri
import android.provider.Settings
import android.view.inputmethod.InputMethodManager
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -17,6 +21,10 @@ import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@@ -25,6 +33,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.futo.inputmethod.latin.R
+import org.futo.inputmethod.latin.uix.USE_SYSTEM_VOICE_INPUT
import org.futo.inputmethod.latin.uix.theme.Typography
@Composable
@@ -93,10 +102,10 @@ fun SetupEnableIME() {
SetupContainer {
Column {
- Step(fraction = 1.0f/3.0f, text = "Setup - Step 1 of 2")
+ Step(fraction = 1.0f/3.0f, text = "Setup - Step 1 of 3")
Text(
- "To use FUTO Keyboard, you must first enable FUTO Keyboard as an input method.",
+ "Welcome to FUTO Keyboard pre-alpha! Please keep in mind things may be rough. This is not a finished product in any way.\n\nFirst, enable FUTO Keyboard as an input method.",
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
@@ -123,14 +132,16 @@ fun SetupChangeDefaultIME() {
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showInputMethodPicker()
+
+ (context as SettingsActivity).updateSystemState()
}
SetupContainer {
Column {
- Step(fraction = 2.0f/3.0f, text = "Setup - Step 2 of 2")
+ Step(fraction = 2.0f/3.0f, text = "Setup - Step 2 of 3")
Text(
- "Next, select FUTO Keyboard as your active input method.",
+ "Please select FUTO Keyboard as your active input method.",
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
@@ -144,4 +155,70 @@ fun SetupChangeDefaultIME() {
}
}
}
-}
\ No newline at end of file
+}
+
+
+@Composable
+@Preview
+fun SetupEnableMic(onClick: () -> Unit = { }) {
+ val launcher = rememberLauncherForActivityResult(
+ ActivityResultContracts.RequestPermission()
+ ) { isGranted: Boolean ->
+ if(isGranted) { onClick() }
+ }
+
+ val context = LocalContext.current
+
+ var askedCount by remember { mutableStateOf(0) }
+ val askMicAccess = {
+ if (askedCount++ >= 2) {
+ val packageName = context.packageName
+ val myAppSettings = Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse(
+ "package:$packageName"
+ )
+ )
+ myAppSettings.addCategory(Intent.CATEGORY_DEFAULT)
+ myAppSettings.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ context.startActivity(myAppSettings)
+ } else {
+ launcher.launch(Manifest.permission.RECORD_AUDIO)
+ }
+ onClick()
+ }
+
+ val (useSystemVoiceInput, setUseSystemVoiceInput) = useDataStore(key = USE_SYSTEM_VOICE_INPUT.key, default = USE_SYSTEM_VOICE_INPUT.default)
+
+ SetupContainer {
+ Column {
+ Step(fraction = 0.9f, text = "Step 3 of 3")
+ Text(
+ "Choose whether you want to use built-in voice input, or the system voice input.",
+ textAlign = TextAlign.Center,
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ Button(
+ onClick = askMicAccess,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp)
+ ) {
+ Text("Use built-in (mic permission needed)")
+ }
+
+ Button(
+ onClick = {
+ setUseSystemVoiceInput(true)
+ (context as SettingsActivity).updateSystemState()
+ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp, 4.dp)
+ ) {
+ Text("Use system")
+ }
+ }
+ }
+}
+
diff --git a/java/src/org/futo/inputmethod/latin/uix/settings/pages/Home.kt b/java/src/org/futo/inputmethod/latin/uix/settings/pages/Home.kt
index 8d6e88152..0e932fd37 100644
--- a/java/src/org/futo/inputmethod/latin/uix/settings/pages/Home.kt
+++ b/java/src/org/futo/inputmethod/latin/uix/settings/pages/Home.kt
@@ -1,16 +1,26 @@
package org.futo.inputmethod.latin.uix.settings.pages
+import android.widget.EditText
+import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import org.futo.inputmethod.latin.BuildConfig
@@ -18,64 +28,90 @@ import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.uix.settings.NavigationItem
import org.futo.inputmethod.latin.uix.settings.NavigationItemStyle
import org.futo.inputmethod.latin.uix.settings.ScreenTitle
-import org.futo.inputmethod.latin.uix.settings.ScrollableList
import org.futo.inputmethod.latin.uix.settings.openLanguageSettings
import org.futo.inputmethod.latin.uix.theme.Typography
import org.futo.inputmethod.updates.ConditionalUpdate
+@Composable
+fun AndroidTextInput() {
+ val context = LocalContext.current
+ val bgColor = MaterialTheme.colorScheme.background
+ val fgColor = MaterialTheme.colorScheme.onBackground
+
+ if(!LocalInspectionMode.current) {
+ val editText = remember {
+ EditText(context).apply {
+ setHint(R.string.try_typing)
+ setBackgroundColor(bgColor.toArgb())
+ setTextColor(fgColor.toArgb())
+ setHintTextColor(fgColor.copy(alpha = 0.7f).toArgb())
+ }
+ }
+ AndroidView({ editText }, modifier = Modifier.fillMaxWidth().padding(8.dp))
+ }
+}
+
@Preview(showBackground = true)
@Composable
fun HomeScreen(navController: NavHostController = rememberNavController()) {
val context = LocalContext.current
- ScrollableList {
- Spacer(modifier = Modifier.height(24.dp))
- ScreenTitle("FUTO Keyboard Settings")
+ val scrollState = rememberScrollState()
+ Column {
+ Column(
+ modifier = Modifier
+ .weight(1.0f).fillMaxWidth()
+ .verticalScroll(scrollState)
+ ) {
+ Spacer(modifier = Modifier.height(24.dp))
+ ScreenTitle("FUTO Keyboard Settings")
- ConditionalUpdate(navController)
+ ConditionalUpdate(navController)
- NavigationItem(
- title = "Languages",
- style = NavigationItemStyle.HomePrimary,
- navigate = { context.openLanguageSettings() },
- icon = painterResource(id = R.drawable.globe)
- )
+ NavigationItem(
+ title = "Languages",
+ style = NavigationItemStyle.HomePrimary,
+ navigate = { context.openLanguageSettings() },
+ icon = painterResource(id = R.drawable.globe)
+ )
- NavigationItem(
- title = "Predictive Text",
- style = NavigationItemStyle.HomeSecondary,
- navigate = { navController.navigate("predictiveText") },
- icon = painterResource(id = R.drawable.shift)
- )
+ NavigationItem(
+ title = "Predictive Text",
+ style = NavigationItemStyle.HomeSecondary,
+ navigate = { navController.navigate("predictiveText") },
+ icon = painterResource(id = R.drawable.shift)
+ )
- NavigationItem(
- title = "Typing Preferences",
- style = NavigationItemStyle.HomeSecondary,
- navigate = { navController.navigate("typing") },
- icon = painterResource(id = R.drawable.delete)
- )
+ NavigationItem(
+ title = "Typing Preferences",
+ style = NavigationItemStyle.HomeSecondary,
+ navigate = { navController.navigate("typing") },
+ icon = painterResource(id = R.drawable.delete)
+ )
- NavigationItem(
- title = "Voice Input",
- style = NavigationItemStyle.HomeSecondary,
- navigate = { navController.navigate("voiceInput") },
- icon = painterResource(id = R.drawable.mic_fill)
- )
+ NavigationItem(
+ title = "Voice Input",
+ style = NavigationItemStyle.HomeSecondary,
+ navigate = { navController.navigate("voiceInput") },
+ icon = painterResource(id = R.drawable.mic_fill)
+ )
- NavigationItem(
- title = "Theme",
- style = NavigationItemStyle.HomeTertiary,
- navigate = { navController.navigate("themes") },
- icon = painterResource(id = R.drawable.eye)
- )
+ NavigationItem(
+ title = "Theme",
+ style = NavigationItemStyle.HomeTertiary,
+ navigate = { navController.navigate("themes") },
+ icon = painterResource(id = R.drawable.eye)
+ )
- Spacer(modifier = Modifier.height(32.dp))
- Text(
- "v${BuildConfig.VERSION_NAME}",
- style = Typography.labelSmall,
- modifier = Modifier.fillMaxWidth(),
- textAlign = TextAlign.Center
- )
- Spacer(modifier = Modifier.height(32.dp))
+ Spacer(modifier = Modifier.height(32.dp))
+ Text(
+ "v${BuildConfig.VERSION_NAME}",
+ style = Typography.labelSmall,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Center
+ )
+ Spacer(modifier = Modifier.height(32.dp))
+ }
+ AndroidTextInput()
}
}
\ No newline at end of file
diff --git a/voiceinput-shared/build.gradle b/voiceinput-shared/build.gradle
index e77e870b8..ddbff311c 100644
--- a/voiceinput-shared/build.gradle
+++ b/voiceinput-shared/build.gradle
@@ -41,12 +41,12 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
- implementation 'androidx.lifecycle:lifecycle-runtime:2.6.2'
- implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.6.2'
- implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
+ implementation 'androidx.lifecycle:lifecycle-runtime:2.7.0'
+ implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.7.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0'
implementation 'androidx.activity:activity-compose:1.8.2'
- implementation platform('androidx.compose:compose-bom:2022.10.00')
+ implementation platform('androidx.compose:compose-bom:2024.02.02')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
@@ -54,7 +54,7 @@ dependencies {
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
- implementation 'androidx.navigation:navigation-compose:2.7.6'
+ implementation 'androidx.navigation:navigation-compose:2.7.7'
implementation 'androidx.datastore:datastore-preferences:1.0.0'
implementation(name:'vad-release', ext:'aar')