Skip to content

Commit

Permalink
refactor: merge notification flow and response flow as callback flow
Browse files Browse the repository at this point in the history
  • Loading branch information
WhiredPlanck committed Oct 17, 2024
1 parent 7b71c6f commit bde2c47
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 130 deletions.
77 changes: 28 additions & 49 deletions app/src/main/java/com/osfans/trime/core/Rime.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class Rime :
private val lifecycleImpl = RimeLifecycleImpl()
override val lifecycle get() = lifecycleImpl

override val notificationFlow = notificationFlow_.asSharedFlow()
override val responseFlow = responseFlow_.asSharedFlow()
override val callbackFlow = callbackFlow_.asSharedFlow()

override val stateFlow get() = lifecycle.currentStateFlow

override val isReady: Boolean
Expand Down Expand Up @@ -147,7 +147,7 @@ class Rime :
getRimeCandidates(startIndex, limit) ?: emptyArray()
}

private fun handleRimeNotification(it: RimeNotification<*>) {
private fun handleRimeCallback(it: RimeCallback) {
when (it) {
is RimeNotification.SchemaNotification -> {
schemaItemCached = it.value
Expand All @@ -165,22 +165,21 @@ class Rime :
"start" -> OpenCCDictManager.buildOpenCCDict()
}
}
else -> {}
}
}

private fun handleRimeResponse(response: RimeResponse) {
response.status?.let {
val status = InputStatus.fromStatus(it)
inputStatusCached = status
inputStatus = it // for compatibility
is RimeResponse -> {
it.status?.let {
val status = InputStatus.fromStatus(it)
inputStatusCached = status
inputStatus = it // for compatibility

val item = SchemaItem.fromStatus(it)
if (item != schemaItemCached) {
schemaItemCached = item
val item = SchemaItem.fromStatus(it)
if (item != schemaItemCached) {
schemaItemCached = item
}
}
it.context?.let { inputContext = it } // for compatibility
}
else -> {}
}
response.context?.let { inputContext = it } // for compatibility
}

fun startup(fullCheck: Boolean) {
Expand All @@ -189,8 +188,7 @@ class Rime :
return
}
if (appContext.isStorageAvailable()) {
registerRimeNotificationHandler(::handleRimeNotification)
registerRimeResponseHandler(::handleRimeResponse)
registerRimeCallbackHandler(::handleRimeCallback)
lifecycleImpl.emitState(RimeLifecycle.State.STARTING)
dispatcher.start(fullCheck)
}
Expand All @@ -209,28 +207,19 @@ class Rime :
}
}
lifecycleImpl.emitState(RimeLifecycle.State.STOPPED)
unregisterRimeNotificationHandler(::handleRimeNotification)
unregisterRimeResponseHandler(::handleRimeResponse)
unregisterRimeCallbackHandler(::handleRimeCallback)
}

companion object {
private var inputContext: RimeProto.Context? = null
private var inputStatus: RimeProto.Status? = null
private val notificationFlow_ =
MutableSharedFlow<RimeNotification<*>>(
private val callbackFlow_ =
MutableSharedFlow<RimeCallback>(
extraBufferCapacity = 15,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
)

private val responseFlow_ =
MutableSharedFlow<RimeResponse>(
extraBufferCapacity = 15,
onBufferOverflow = BufferOverflow.DROP_LATEST,
)

private val notificationHandlers = ArrayList<(RimeNotification<*>) -> Unit>()

private val responseHandlers = ArrayList<(RimeResponse) -> Unit>()
private val callbackHandlers = ArrayList<(RimeCallback) -> Unit>()

init {
System.loadLibrary("rime_jni")
Expand Down Expand Up @@ -489,33 +478,23 @@ class Rime :
) {
val notification = RimeNotification.create(messageType, messageValue)
Timber.d("Handling Rime notification: $notification")
notificationHandlers.forEach { it.invoke(notification) }
notificationFlow_.tryEmit(notification)
callbackHandlers.forEach { it.invoke(notification) }
callbackFlow_.tryEmit(notification)
}

private fun registerRimeNotificationHandler(handler: (RimeNotification<*>) -> Unit) {
if (notificationHandlers.contains(handler)) return
notificationHandlers.add(handler)
private fun registerRimeCallbackHandler(handler: (RimeCallback) -> Unit) {
if (callbackHandlers.contains(handler)) return
callbackHandlers.add(handler)
}

private fun unregisterRimeNotificationHandler(handler: (RimeNotification<*>) -> Unit) {
notificationHandlers.remove(handler)
private fun unregisterRimeCallbackHandler(handler: (RimeCallback) -> Unit) {
callbackHandlers.remove(handler)
}

fun requestRimeResponse() {
val response = RimeResponse(getRimeCommit(), getRimeContext(), getRimeStatus())
Timber.d("Got Rime response: $response")
responseHandlers.forEach { it.invoke(response) }
responseFlow_.tryEmit(response)
}

private fun registerRimeResponseHandler(handler: (RimeResponse) -> Unit) {
if (responseHandlers.contains(handler)) return
responseHandlers.add(handler)
}

private fun unregisterRimeResponseHandler(handler: (RimeResponse) -> Unit) {
responseHandlers.remove(handler)
callbackFlow_.tryEmit(response)
}
}
}
4 changes: 1 addition & 3 deletions app/src/main/java/com/osfans/trime/core/RimeApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ package com.osfans.trime.core
import kotlinx.coroutines.flow.SharedFlow

interface RimeApi {
val notificationFlow: SharedFlow<RimeNotification<*>>

val responseFlow: SharedFlow<RimeResponse>
val callbackFlow: SharedFlow<RimeCallback>

val stateFlow: SharedFlow<RimeLifecycle.State>

Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/osfans/trime/core/RimeCallback.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2015 - 2024 Rime community
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package com.osfans.trime.core

sealed interface RimeCallback
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package com.osfans.trime.core

sealed class RimeNotification<T>(
open val value: T,
) {
) : RimeCallback {
abstract val messageType: MessageType

data class SchemaNotification(
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/osfans/trime/core/RimeResponse.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ data class RimeResponse(
val commit: RimeProto.Commit?,
val context: RimeProto.Context?,
val status: RimeProto.Status?,
)
) : RimeCallback
2 changes: 1 addition & 1 deletion app/src/main/java/com/osfans/trime/daemon/RimeSession.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface RimeSession {
* Run an operation immediately
* The suspended [block] will be executed in caller's thread.
* Use this function only for non-blocking operations like
* accessing [RimeApi.notificationFlow].
* accessing [RimeApi.callbackFlow].
*/
fun <T> run(block: suspend RimeApi.() -> T): T

Expand Down
60 changes: 26 additions & 34 deletions app/src/main/java/com/osfans/trime/ime/core/InputView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import com.osfans.trime.core.CandidateItem
import com.osfans.trime.core.RimeCallback
import com.osfans.trime.core.RimeNotification
import com.osfans.trime.core.RimeResponse
import com.osfans.trime.daemon.RimeSession
Expand Down Expand Up @@ -97,8 +98,7 @@ class InputView(
setOnClickListener(placeholderListener)
}

private val notificationHandlerJob: Job
private val responseHandlerJob: Job
private val callbackHandlerJob: Job

private val themedContext = context.withTheme(android.R.style.Theme_DeviceDefault_Settings)
private val inputComponent = InputComponent::class.create(this, themedContext, theme, service, rime)
Expand Down Expand Up @@ -144,17 +144,10 @@ class InputView(
init {
addBroadcastReceivers()

notificationHandlerJob =
callbackHandlerJob =
service.lifecycleScope.launch {
rime.run { notificationFlow }.collect {
handleRimeNotification(it)
}
}

responseHandlerJob =
service.lifecycleScope.launch {
rime.run { responseFlow }.collect {
handleRimeResponse(it)
rime.run { callbackFlow }.collect {
handleRimeCallback(it)
}
}

Expand Down Expand Up @@ -324,7 +317,7 @@ class InputView(
}
}

private fun handleRimeNotification(it: RimeNotification<*>) {
private fun handleRimeCallback(it: RimeCallback) {
when (it) {
is RimeNotification.SchemaNotification -> {
broadcaster.onRimeSchemaUpdated(it.value)
Expand All @@ -341,27 +334,26 @@ class InputView(
}
}
}
else -> {}
}
}

private fun handleRimeResponse(response: RimeResponse) {
val ctx = response.context
if (ctx != null) {
broadcaster.onInputContextUpdate(ctx)
val candidates = ctx.menu.candidates.map { CandidateItem(it.comment ?: "", it.text) }
val isLastPage = ctx.menu.isLastPage
val previous = ctx.menu.run { pageSize * pageNumber }
val highlightedIdx = ctx.menu.highlightedCandidateIndex
if (composition.isPopupWindowEnabled) {
val sticky = composition.composition.update(ctx)
compactCandidate.adapter.updateCandidates(candidates, isLastPage, previous, highlightedIdx, sticky)
} else {
compactCandidate.adapter.updateCandidates(candidates, isLastPage, previous, highlightedIdx)
}
if (candidates.isEmpty()) {
compactCandidate.refreshUnrolled()
is RimeResponse -> {
val ctx = it.context
if (ctx != null) {
broadcaster.onInputContextUpdate(ctx)
val candidates = ctx.menu.candidates.map { CandidateItem(it.comment ?: "", it.text) }
val isLastPage = ctx.menu.isLastPage
val previous = ctx.menu.run { pageSize * pageNumber }
val highlightedIdx = ctx.menu.highlightedCandidateIndex
if (composition.isPopupWindowEnabled) {
val sticky = composition.composition.update(ctx)
compactCandidate.adapter.updateCandidates(candidates, isLastPage, previous, highlightedIdx, sticky)
} else {
compactCandidate.adapter.updateCandidates(candidates, isLastPage, previous, highlightedIdx)
}
if (candidates.isEmpty()) {
compactCandidate.refreshUnrolled()
}
}
}
else -> {}
}
}

Expand Down Expand Up @@ -420,7 +412,7 @@ class InputView(
composition.hideCompositionView()
// cancel the notification job and clear all broadcast receivers,
// implies that InputView should not be attached again after detached.
notificationHandlerJob.cancel()
callbackHandlerJob.cancel()
broadcaster.clear()
super.onDetachedFromWindow()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.osfans.trime.core.KeyModifiers
import com.osfans.trime.core.KeyValue
import com.osfans.trime.core.Rime
import com.osfans.trime.core.RimeApi
import com.osfans.trime.core.RimeCallback
import com.osfans.trime.core.RimeKeyMapping
import com.osfans.trime.core.RimeNotification
import com.osfans.trime.core.RimeProto
Expand Down Expand Up @@ -206,13 +207,8 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
jobs.consumeEach { it.join() }
}
lifecycleScope.launch {
rime.run { notificationFlow }.collect {
handleRimeNotification(it)
}
}
lifecycleScope.launch {
rime.run { responseFlow }.collect {
handleRimeResponse(it)
rime.run { callbackFlow }.collect {
handleRimeCallback(it)
}
}
ThemeManager.addOnChangedListener(onThemeChangeListener)
Expand Down Expand Up @@ -258,46 +254,50 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
}
}

private fun handleRimeNotification(notification: RimeNotification<*>) {
if (notification is RimeNotification.SchemaNotification) {
recreateInputView(ThemeManager.activeTheme)
} else if (notification is RimeNotification.OptionNotification) {
val value = notification.value.value
when (val option = notification.value.option) {
"ascii_mode" -> {
InputFeedbackManager.ttsLanguage =
locales[if (value) 1 else 0]
private fun handleRimeCallback(it: RimeCallback) {
when (it) {
is RimeNotification.SchemaNotification -> {
recreateInputView(ThemeManager.activeTheme)
}

is RimeNotification.OptionNotification -> {
val value = it.value.value
when (val option = it.value.option) {
"ascii_mode" -> {
InputFeedbackManager.ttsLanguage =
locales[if (value) 1 else 0]
}
"_hide_bar",
"_hide_candidate",
-> {
setCandidatesViewShown(isComposable && !value)
}
else ->
if (option.startsWith("_key_") && option.length > 5 && value) {
shouldUpdateRimeOption = false // 防止在 handleRimeNotification 中 setOption
val key = option.substring(5)
inputView
?.commonKeyboardActionListener
?.listener
?.onEvent(EventManager.getEvent(key))
shouldUpdateRimeOption = true
}
}
"_hide_bar",
"_hide_candidate",
-> {
setCandidatesViewShown(isComposable && !value)
}
is RimeResponse -> {
val (commit, ctx) = it
if (commit?.text?.isNotEmpty() == true) {
commitText(commit.text)
}
else ->
if (option.startsWith("_key_") && option.length > 5 && value) {
shouldUpdateRimeOption = false // 防止在 handleRimeNotification 中 setOption
val key = option.substring(5)
inputView
?.commonKeyboardActionListener
?.listener
?.onEvent(EventManager.getEvent(key))
shouldUpdateRimeOption = true
}
if (ctx != null) {
updateComposingText(ctx)
}
updateComposing()
}
else -> {}
}
}

private fun handleRimeResponse(response: RimeResponse) {
val (commit, ctx, _) = response
if (commit != null && !commit.text.isNullOrEmpty()) {
commitText(commit.text)
}
if (ctx != null) {
updateComposingText(ctx)
}
updateComposing()
}

fun pasteByChar() {
commitTextByChar(checkNotNull(ShortcutUtils.pasteFromClipboard(this)).toString())
}
Expand Down

0 comments on commit bde2c47

Please sign in to comment.