gioser

sergio/humanoid

HTML 13TOML 10 Sutichaykuna

⎇ e3dd167a16e071c181b3d4f3bc77664f9cf053ab keyboard/src/main/java/com/rizoma/trazo/TrazoImeService.kt 112 siq'ikuna · 4.3 KB Ñawpa willay ch'uya

Trazo: teclado MessagEase remasterizado (IME v0.1) e3dd167a1 · sergio ·

1package com.rizoma.trazo
2
3import android.inputmethodservice.InputMethodService
4import android.text.InputType
5import android.view.KeyEvent
6import android.view.View
7import android.view.inputmethod.EditorInfo
8import androidx.compose.ui.platform.ComposeView
9import androidx.lifecycle.Lifecycle
10import androidx.lifecycle.LifecycleOwner
11import androidx.lifecycle.LifecycleRegistry
12import androidx.lifecycle.ViewModelStore
13import androidx.lifecycle.ViewModelStoreOwner
14import androidx.lifecycle.setViewTreeLifecycleOwner
15import androidx.lifecycle.setViewTreeViewModelStoreOwner
16import androidx.savedstate.SavedStateRegistry
17import androidx.savedstate.SavedStateRegistryController
18import androidx.savedstate.SavedStateRegistryOwner
19import androidx.savedstate.setViewTreeSavedStateRegistryOwner
20import com.rizoma.trazo.ime.ImeHost
21import com.rizoma.trazo.ime.KeyboardController
22import com.rizoma.trazo.ui.KeyboardScreen
23import com.rizoma.trazo.ui.theme.TrazoTheme
24
25/**
26 * Trazo IME. Hospeda un teclado Compose dentro del InputMethodService, para lo cual
27 * el servicio actúa como Lifecycle/ViewModelStore/SavedState owner del ComposeView.
28 */
29class TrazoImeService : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner {
30
31    private val lifecycleRegistry = LifecycleRegistry(this)
32    override val lifecycle: Lifecycle get() = lifecycleRegistry
33
34    private val store = ViewModelStore()
35    override val viewModelStore: ViewModelStore get() = store
36
37    private val savedStateController = SavedStateRegistryController.create(this)
38    override val savedStateRegistry: SavedStateRegistry get() = savedStateController.savedStateRegistry
39
40    private var editorInputType: Int = InputType.TYPE_CLASS_TEXT
41
42    private val host = object : ImeHost {
43        override fun commit(text: String) {
44            currentInputConnection?.commitText(text, 1)
45        }
46
47        override fun backspace() {
48            val ic = currentInputConnection ?: return
49            val selected = ic.getSelectedText(0)
50            if (selected.isNullOrEmpty()) ic.deleteSurroundingText(1, 0) else ic.commitText("", 1)
51        }
52
53        override fun newline() {
54            val action = currentInputEditorInfo?.imeOptions ?: 0
55            val opt = action and EditorInfo.IME_MASK_ACTION
56            if (opt != EditorInfo.IME_ACTION_NONE && opt != EditorInfo.IME_ACTION_UNSPECIFIED &&
57                (action and EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0
58            ) {
59                currentInputConnection?.performEditorAction(opt)
60            } else {
61                currentInputConnection?.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER))
62                currentInputConnection?.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER))
63            }
64        }
65
66        override fun textBeforeCursor(n: Int): CharSequence =
67            currentInputConnection?.getTextBeforeCursor(n, 0) ?: ""
68
69        override fun cursorCapsMode(): Int =
70            currentInputConnection?.getCursorCapsMode(editorInputType) ?: 0
71    }
72
73    private val controller = KeyboardController(host)
74
75    override fun onCreate() {
76        super.onCreate()
77        savedStateController.performRestore(null)
78        lifecycleRegistry.currentState = Lifecycle.State.CREATED
79    }
80
81    override fun onCreateInputView(): View {
82        val view = ComposeView(this).apply {
83            setViewTreeLifecycleOwner(this@TrazoImeService)
84            setViewTreeViewModelStoreOwner(this@TrazoImeService)
85            setViewTreeSavedStateRegistryOwner(this@TrazoImeService)
86            setContent {
87                TrazoTheme {
88                    KeyboardScreen(controller)
89                }
90            }
91        }
92        return view
93    }
94
95    override fun onStartInputView(info: EditorInfo?, restarting: Boolean) {
96        super.onStartInputView(info, restarting)
97        editorInputType = info?.inputType ?: InputType.TYPE_CLASS_TEXT
98        lifecycleRegistry.currentState = Lifecycle.State.RESUMED
99        controller.syncAutoShift()
100    }
101
102    override fun onFinishInputView(finishingInput: Boolean) {
103        super.onFinishInputView(finishingInput)
104        lifecycleRegistry.currentState = Lifecycle.State.CREATED
105    }
106
107    override fun onDestroy() {
108        lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
109        store.clear()
110        super.onDestroy()
111    }
112}