[Rich text editor] Ensure keyboard opens for reply and text formatting modes (#1337)

This commit is contained in:
jonnyandrew
2023-09-16 08:40:56 +01:00
committed by GitHub
parent 8f519b614f
commit 7ba73aed2c
4 changed files with 84 additions and 13 deletions

1
changelog.d/1337.bugfix Normal file
View File

@@ -0,0 +1 @@
[Rich text editor] Ensure keyboard opens for reply and text formatting modes

View File

@@ -17,8 +17,11 @@
package io.element.android.libraries.androidutils.ui
import android.view.View
import android.view.ViewTreeObserver
import android.view.inputmethod.InputMethodManager
import androidx.core.content.getSystemService
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
fun View.hideKeyboard() {
val imm = context?.getSystemService<InputMethodManager>()
@@ -41,3 +44,24 @@ fun View.setHorizontalPadding(padding: Int) {
paddingBottom
)
}
suspend fun View.awaitWindowFocus() = suspendCancellableCoroutine { continuation ->
if (hasWindowFocus()) {
continuation.resume(Unit)
} else {
val listener = object : ViewTreeObserver.OnWindowFocusChangeListener {
override fun onWindowFocusChanged(hasFocus: Boolean) {
if (hasFocus) {
viewTreeObserver.removeOnWindowFocusChangeListener(this)
continuation.resume(Unit)
}
}
}
viewTreeObserver.addOnWindowFocusChangeListener(listener)
continuation.invokeOnCancellation {
viewTreeObserver.removeOnWindowFocusChangeListener(listener)
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* 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 io.element.android.libraries.textcomposer
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.viewinterop.AndroidView
import io.element.android.libraries.androidutils.ui.awaitWindowFocus
import io.element.android.libraries.androidutils.ui.showKeyboard
/**
* Shows the soft keyboard when a given key changes to meet the required condition.
*
* Uses [showKeyboard] to show the keyboard for compatibility with [AndroidView].
*
* @param T
* @param key The key to watch for changes.
* @param onRequestFocus A callback to request focus to the view that will receive the keyboard input.
* @param predicate The predicate that [key] must meet before showing the keyboard.
*/
@Composable
internal fun <T> SoftKeyboardEffect(
key: T,
onRequestFocus: () -> Unit,
predicate: (T) -> Boolean,
) {
val view = LocalView.current
LaunchedEffect(key) {
if (predicate(key)) {
// Await window focus in case returning from a dialog
view.awaitWindowFocus()
// Show the keyboard, temporarily using the root view for focus
view.showKeyboard(andRequestFocus = true)
// Refocus to the correct view
onRequestFocus()
}
}
}

View File

@@ -43,7 +43,6 @@ import androidx.compose.material.icons.filled.Close
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
@@ -52,7 +51,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextAlign
@@ -84,7 +82,6 @@ import io.element.android.wysiwyg.compose.RichTextEditor
import io.element.android.wysiwyg.compose.RichTextEditorDefaults
import io.element.android.wysiwyg.compose.RichTextEditorState
import io.element.android.wysiwyg.view.models.InlineFormat
import kotlinx.coroutines.android.awaitFrame
import uniffi.wysiwyg_composer.ActionState
import uniffi.wysiwyg_composer.ComposerAction
@@ -223,17 +220,11 @@ fun TextComposer(
}
}
// Request focus when changing mode, and show keyboard.
val keyboard = LocalSoftwareKeyboardController.current
LaunchedEffect(composerMode) {
if (composerMode is MessageComposerMode.Special) {
onRequestFocus()
keyboard?.let {
awaitFrame()
it.show()
}
}
SoftKeyboardEffect(composerMode, onRequestFocus) {
it is MessageComposerMode.Special
}
SoftKeyboardEffect(showTextFormatting, onRequestFocus) { it }
}
@Composable