From ba9d0d88d83896a21db3487c733575c702c52deb Mon Sep 17 00:00:00 2001 From: WhiredPlanck Date: Fri, 12 Apr 2024 10:18:20 +0800 Subject: [PATCH] refactor: enhance lifecycle management of Rime Migrate the abilities of RimeWrapper to RimeDaemon, the real Rime instance will be kept in RimeDaemon and shared via RimeSession --- .../main/java/com/osfans/trime/core/Rime.kt | 77 +++++++----- .../java/com/osfans/trime/core/RimeApi.kt | 4 + .../com/osfans/trime/core/RimeLifecycle.kt | 94 ++++++++++++++ .../com/osfans/trime/daemon/RimeDaemon.kt | 32 ++++- .../com/osfans/trime/daemon/RimeSession.kt | 18 ++- .../trime/ime/broadcast/IntentReceiver.kt | 8 +- .../com/osfans/trime/ime/core/RimeWrapper.kt | 119 ------------------ .../trime/ime/core/TrimeInputMethodService.kt | 23 ++-- .../trime/ui/fragments/ProfileFragment.kt | 5 +- .../com/osfans/trime/ui/main/MainViewModel.kt | 8 ++ .../java/com/osfans/trime/ui/main/Pickers.kt | 4 +- .../osfans/trime/ui/main/PrefMainActivity.kt | 17 ++- .../com/osfans/trime/util/ShortcutUtils.kt | 4 +- 13 files changed, 228 insertions(+), 185 deletions(-) create mode 100644 app/src/main/java/com/osfans/trime/core/RimeLifecycle.kt delete mode 100644 app/src/main/java/com/osfans/trime/ime/core/RimeWrapper.kt diff --git a/app/src/main/java/com/osfans/trime/core/Rime.kt b/app/src/main/java/com/osfans/trime/core/Rime.kt index 9d13bcc238..e82caeef6d 100644 --- a/app/src/main/java/com/osfans/trime/core/Rime.kt +++ b/app/src/main/java/com/osfans/trime/core/Rime.kt @@ -21,6 +21,8 @@ import com.osfans.trime.data.AppPrefs import com.osfans.trime.data.DataManager import com.osfans.trime.data.opencc.OpenCCDictManager import com.osfans.trime.data.schema.SchemaManager +import com.osfans.trime.util.appContext +import com.osfans.trime.util.isStorageAvailable import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow @@ -32,19 +34,57 @@ import kotlin.system.measureTimeMillis * * @see [librime](https://github.com/rime/librime) */ -class Rime(fullCheck: Boolean) : RimeApi { +class Rime : RimeApi, RimeLifecycleOwner { + private val lifecycleImpl = RimeLifecycleImpl() + override val lifecycle get() = lifecycleImpl + override val notificationFlow = notificationFlow_.asSharedFlow() + override val stateFlow = lifecycle.stateFlow + + override val isReady: Boolean + get() = lifecycle.stateFlow.value == RimeLifecycle.State.READY + + fun startup(fullCheck: Boolean) { + if (lifecycle.stateFlow.value != RimeLifecycle.State.STOPPED) { + Timber.w("Skip starting rime: not at stopped state!") + return + } + if (appContext.isStorageAvailable()) { + isHandlingRimeNotification = false - init { - startup(fullCheck) + DataManager.dirFireChange() + DataManager.sync() + + val sharedDataDir = AppPrefs.defaultInstance().profile.sharedDataDir + val userDataDir = AppPrefs.defaultInstance().profile.userDataDir + + lifecycleImpl.emitState(RimeLifecycle.State.STARTING) + Timber.i("Starting up Rime APIs ...") + startupRime(sharedDataDir, userDataDir, fullCheck) + + Timber.i("Initializing schema stuffs after starting up ...") + SchemaManager.init(getCurrentRimeSchema()) + updateStatus() + OpenCCDictManager.buildOpenCCDict() + lifecycleImpl.emitState(RimeLifecycle.State.READY) + } + } + + fun finalize() { + if (lifecycle.stateFlow.value != RimeLifecycle.State.READY) { + Timber.w("Skip stopping rime: not at ready state!") + return + } + exitRime() + lifecycleImpl.emitState(RimeLifecycle.State.STOPPED) } companion object { private var instance: Rime? = null @JvmStatic - fun getInstance(fullCheck: Boolean = false): Rime { - if (instance == null) instance = Rime(fullCheck) + fun getInstance(): Rime { + if (instance == null) instance = Rime() return instance!! } @@ -61,33 +101,6 @@ class Rime(fullCheck: Boolean) : RimeApi { System.loadLibrary("rime_jni") } - private fun startup(fullCheck: Boolean) { - isHandlingRimeNotification = false - - DataManager.sync() - - val sharedDataDir = AppPrefs.defaultInstance().profile.sharedDataDir - val userDataDir = AppPrefs.defaultInstance().profile.userDataDir - - Timber.i("Starting up Rime APIs ...") - startupRime(sharedDataDir, userDataDir, fullCheck) - - Timber.i("Initializing schema stuffs after starting up ...") - SchemaManager.init(getCurrentRimeSchema()) - updateStatus() - } - - fun destroy() { - exitRime() - instance = null - } - - fun deploy() { - destroy() - getInstance(true) - OpenCCDictManager.buildOpenCCDict() - } - fun updateStatus() { SchemaManager.updateSwitchOptions() measureTimeMillis { diff --git a/app/src/main/java/com/osfans/trime/core/RimeApi.kt b/app/src/main/java/com/osfans/trime/core/RimeApi.kt index 8dc036efae..c772ad874c 100644 --- a/app/src/main/java/com/osfans/trime/core/RimeApi.kt +++ b/app/src/main/java/com/osfans/trime/core/RimeApi.kt @@ -4,4 +4,8 @@ import kotlinx.coroutines.flow.SharedFlow interface RimeApi { val notificationFlow: SharedFlow> + + val stateFlow: SharedFlow + + val isReady: Boolean } diff --git a/app/src/main/java/com/osfans/trime/core/RimeLifecycle.kt b/app/src/main/java/com/osfans/trime/core/RimeLifecycle.kt new file mode 100644 index 0000000000..2da170ef06 --- /dev/null +++ b/app/src/main/java/com/osfans/trime/core/RimeLifecycle.kt @@ -0,0 +1,94 @@ +package com.osfans.trime.core + +import android.os.Handler +import android.os.Looper +import androidx.core.os.HandlerCompat +import kotlinx.coroutines.Job +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import java.util.Collections + +class RimeLifecycleImpl : RimeLifecycle { + private val _stateFlow = MutableStateFlow(RimeLifecycle.State.STOPPED) + override val stateFlow = _stateFlow.asStateFlow() + + override val handler = HandlerCompat.createAsync(Looper.getMainLooper()) + override val runnableList: MutableList = Collections.synchronizedList(mutableListOf()) + + fun emitState(state: RimeLifecycle.State) { + when (state) { + RimeLifecycle.State.STARTING -> { + checkAtState(RimeLifecycle.State.STOPPED) + _stateFlow.value = RimeLifecycle.State.STARTING + } + RimeLifecycle.State.READY -> { + checkAtState(RimeLifecycle.State.STARTING) + _stateFlow.value = RimeLifecycle.State.READY + } + RimeLifecycle.State.STOPPED -> { + checkAtState(RimeLifecycle.State.READY) + _stateFlow.value = RimeLifecycle.State.STOPPED + } + } + } + + private fun checkAtState(state: RimeLifecycle.State) = + takeIf { (_stateFlow.value == state) } + ?: throw IllegalStateException("Currently not at $state! Actual state is ${_stateFlow.value}") +} + +interface RimeLifecycle { + val stateFlow: StateFlow + val handler: Handler + val runnableList: MutableList + + enum class State { + STARTING, + READY, + STOPPED, + } +} + +interface RimeLifecycleOwner { + val lifecycle: RimeLifecycle + val handler get() = lifecycle.handler +} + +fun RimeLifecycle.whenAtState( + state: RimeLifecycle.State, + block: () -> Unit, +) { + runnableList.add(Runnable { block() }) + if (stateFlow.value == state) { + handler.post(runnableList.removeFirst()) + } else { + StateDelegate(this, state).run(block) + } +} + +inline fun RimeLifecycle.whenReady(noinline block: () -> Unit) = whenAtState(RimeLifecycle.State.READY, block) + +private class StateDelegate(val lifecycle: RimeLifecycle, val state: RimeLifecycle.State) { + private var job: Job? = null + + init { + job = + lifecycle.stateFlow.onEach { + if (it == state) { + while (lifecycle.runnableList.isNotEmpty()) { + lifecycle.handler.post(lifecycle.runnableList.removeFirst()) + } + } + }.launchIn(MainScope()) + } + + fun run(block: () -> T): T { + job?.cancel() + job = null + return block() + } +} diff --git a/app/src/main/java/com/osfans/trime/daemon/RimeDaemon.kt b/app/src/main/java/com/osfans/trime/daemon/RimeDaemon.kt index 4178182c92..134a5f315d 100644 --- a/app/src/main/java/com/osfans/trime/daemon/RimeDaemon.kt +++ b/app/src/main/java/com/osfans/trime/daemon/RimeDaemon.kt @@ -2,12 +2,14 @@ package com.osfans.trime.daemon import com.osfans.trime.core.Rime import com.osfans.trime.core.RimeApi +import com.osfans.trime.core.RimeLifecycle +import com.osfans.trime.core.whenReady import kotlinx.coroutines.runBlocking import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock object RimeDaemon { - private val realRime by lazy { Rime.getInstance() } + private val realRime by lazy { Rime() } private val rimeImpl by lazy { object : RimeApi by realRime {} } @@ -28,6 +30,20 @@ object RimeDaemon { ensureEstablished { runBlocking { block(rimeImpl) } } + + override fun runOnReady(block: RimeApi.() -> Unit) { + ensureEstablished { + realRime.lifecycle.whenReady { block(rimeImpl) } + } + } + + override fun runIfReady(block: RimeApi.() -> Unit) { + ensureEstablished { + if (realRime.isReady) { + realRime.lifecycle.handler.post { block(rimeImpl) } + } + } + } } fun createSession(name: String): RimeSession = @@ -35,6 +51,9 @@ object RimeDaemon { if (name in sessions) { return@withLock sessions.getValue(name) } + if (realRime.lifecycle.stateFlow.value == RimeLifecycle.State.STOPPED) { + realRime.startup(false) + } val session = establish(name) sessions[name] = session return@withLock session @@ -47,7 +66,16 @@ object RimeDaemon { } sessions -= name if (sessions.isEmpty()) { - Rime.destroy() + realRime.finalize() } } + + /** + * Restart Rime instance to deploy while keep the session + */ + fun restartRime(fullCheck: Boolean = false) = + lock.withLock { + realRime.finalize() + realRime.startup(fullCheck) + } } diff --git a/app/src/main/java/com/osfans/trime/daemon/RimeSession.kt b/app/src/main/java/com/osfans/trime/daemon/RimeSession.kt index f6991eba27..41418754b6 100644 --- a/app/src/main/java/com/osfans/trime/daemon/RimeSession.kt +++ b/app/src/main/java/com/osfans/trime/daemon/RimeSession.kt @@ -3,10 +3,9 @@ package com.osfans.trime.daemon import com.osfans.trime.core.RimeApi /** - * A Interface to run different operations on RimeApi + * A interface to run different operations on RimeApi */ interface RimeSession { - /** * Run an operation immediately * The suspended [block] will be executed in caller's thread. @@ -14,4 +13,19 @@ interface RimeSession { * accessing [RimeApi.notificationFlow]. */ fun run(block: suspend RimeApi.() -> T): T + + /** + * Run an operation immediately if rime is at ready state. + * Otherwise, caller will be suspended until rime is ready and operation is done. + * The [block] will be executed in main thread. + * Client should use this function in most cases. + */ + fun runOnReady(block: RimeApi.() -> Unit) + + /** + * Run an operation if rime is at ready state. + * Otherwise, do nothing. + * The [block] will be executed in main thread. + */ + fun runIfReady(block: RimeApi.() -> Unit) } diff --git a/app/src/main/java/com/osfans/trime/ime/broadcast/IntentReceiver.kt b/app/src/main/java/com/osfans/trime/ime/broadcast/IntentReceiver.kt index a0511c53f6..b3bcfa2d69 100644 --- a/app/src/main/java/com/osfans/trime/ime/broadcast/IntentReceiver.kt +++ b/app/src/main/java/com/osfans/trime/ime/broadcast/IntentReceiver.kt @@ -30,8 +30,8 @@ import androidx.core.content.ContextCompat import com.blankj.utilcode.util.ToastUtils import com.osfans.trime.R import com.osfans.trime.core.Rime +import com.osfans.trime.daemon.RimeDaemon import com.osfans.trime.data.AppPrefs -import com.osfans.trime.ime.core.RimeWrapper import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.MainScope @@ -55,7 +55,7 @@ class IntentReceiver : BroadcastReceiver(), CoroutineScope by MainScope() { COMMAND_DEPLOY -> launch { withContext(Dispatchers.IO) { - RimeWrapper.deploy() + RimeDaemon.restartRime() } ToastUtils.showLong(R.string.deploy_finish) } @@ -63,7 +63,7 @@ class IntentReceiver : BroadcastReceiver(), CoroutineScope by MainScope() { launch { withContext(Dispatchers.IO) { Rime.syncRimeUserData() - RimeWrapper.deploy() + RimeDaemon.restartRime() } } COMMAND_TIMING_SYNC -> @@ -106,7 +106,7 @@ class IntentReceiver : BroadcastReceiver(), CoroutineScope by MainScope() { } Rime.syncRimeUserData() - RimeWrapper.deploy() + RimeDaemon.restartRime() wakeLock.release() // 释放唤醒锁 } } diff --git a/app/src/main/java/com/osfans/trime/ime/core/RimeWrapper.kt b/app/src/main/java/com/osfans/trime/ime/core/RimeWrapper.kt deleted file mode 100644 index 153c9688f4..0000000000 --- a/app/src/main/java/com/osfans/trime/ime/core/RimeWrapper.kt +++ /dev/null @@ -1,119 +0,0 @@ -package com.osfans.trime.ime.core - -import android.os.Looper -import androidx.core.os.HandlerCompat -import com.osfans.trime.core.Rime -import com.osfans.trime.data.DataManager -import com.osfans.trime.util.appContext -import com.osfans.trime.util.isStorageAvailable -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Runnable -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import timber.log.Timber -import java.util.Collections -import kotlin.system.measureTimeMillis - -object RimeWrapper { - private var mainThreadHandler = HandlerCompat.createAsync(Looper.getMainLooper()) - private val mutex = Mutex() - private val myThreadSafeList = Collections.synchronizedList(mutableListOf()) - private val _statusStateFlow = MutableStateFlow(Status.UN_INIT) - val statusStateFlow = _statusStateFlow.asStateFlow() - - fun startup(r: Runnable? = null) { - r.let { - myThreadSafeList.add(it) - } - if (appContext.isStorageAvailable()) { - if (mutex.tryLock()) { - if (_statusStateFlow.value == Status.UN_INIT) { - Timber.d("Starting in a thread") - _statusStateFlow.value = Status.IN_PROGRESS - mutex.unlock() - - val scope = CoroutineScope(Dispatchers.IO) - scope.launch { - measureTimeMillis { - Rime.getInstance(false) - }.also { - Timber.d("Startup completed. It takes ${it / 1000} seconds") - } - - mutex.withLock { - _statusStateFlow.value = Status.READY - } - - notifyUnlock() - } - } else { - mutex.unlock() - } - } - } else { - Timber.d("RimeWrapper shall not be started") - } - } - - suspend fun deploy(): Boolean { - if (mutex.tryLock()) { - if (_statusStateFlow.value != Status.IN_PROGRESS) { - _statusStateFlow.value = Status.IN_PROGRESS - mutex.unlock() - - DataManager.dirFireChange() - - Rime.deploy() - - mutex.withLock { - _statusStateFlow.value = Status.READY - } - Timber.d("Rime Deployed") - - return true - } else { - mutex.unlock() - } - } - return false - } - - private fun notifyUnlock() { - Timber.d("notifying unlock") - while (myThreadSafeList.isNotEmpty()) { - myThreadSafeList.removeFirstOrNull()?.let { - mainThreadHandler.post(it) - } - } - Timber.d("Unlock Run Completed") - } - - fun runCheck() { - when (_statusStateFlow.value) { - Status.UN_INIT -> startup() - Status.READY -> notifyUnlock() - else -> return - } - } - - @JvmStatic - fun isReady(): Boolean { - return _statusStateFlow.value == Status.READY - } - - @JvmStatic - fun runAfterStarted(r: Runnable) { - myThreadSafeList.add(r) - runCheck() - } -} - -enum class Status { - UN_INIT, - IN_PROGRESS, - READY, -} diff --git a/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt b/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt index 6bc419f9a1..a3143a8edb 100644 --- a/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt +++ b/app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt @@ -142,11 +142,13 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { } else { Timber.i("onWindowShown...") } - if (RimeWrapper.isReady() && currentInputEditorInfo != null) { - isWindowShown = true - updateComposing() - for (listener in eventListeners) { - listener.onWindowShown() + rime.runIfReady { + if (currentInputEditorInfo != null) { + isWindowShown = true + updateComposing() + for (listener in eventListeners) { + listener.onWindowShown() + } } } } @@ -235,11 +237,11 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { // and lead to a crash loop Timber.d("onCreate") ColorManager.addOnChangedListener(onColorChangeListener) - RimeWrapper.startup { + rime.runOnReady { Timber.d("Running Trime.onCreate") ColorManager.init(resources.configuration) textInputManager = TextInputManager.getInstance() - InputFeedbackManager.init(this) + InputFeedbackManager.init(this@TrimeInputMethodService) restartSystemStartTimingSync() try { for (listener in eventListeners) { @@ -434,7 +436,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { } override fun onCreateInputView(): View { - RimeWrapper.runAfterStarted { + rime.runOnReady { recreateInputView() } initializationUi = InitializationUi(this) @@ -467,7 +469,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { restarting: Boolean, ) { Timber.d("onStartInputView: restarting=%s", restarting) - RimeWrapper.runAfterStarted { + rime.runOnReady { InputFeedbackManager.loadSoundEffects() InputFeedbackManager.resetPlayProgress() for (listener in eventListeners) { @@ -545,12 +547,11 @@ open class TrimeInputMethodService : LifecycleInputMethodService() { } } } - RimeWrapper.runCheck() } override fun onFinishInputView(finishingInput: Boolean) { super.onFinishInputView(finishingInput) - if (RimeWrapper.isReady()) { + rime.runIfReady { if (normalTextEditor) { DraftHelper.onInputEventChanged() } diff --git a/app/src/main/java/com/osfans/trime/ui/fragments/ProfileFragment.kt b/app/src/main/java/com/osfans/trime/ui/fragments/ProfileFragment.kt index d59bbf721e..e3a433cbac 100644 --- a/app/src/main/java/com/osfans/trime/ui/fragments/ProfileFragment.kt +++ b/app/src/main/java/com/osfans/trime/ui/fragments/ProfileFragment.kt @@ -21,9 +21,9 @@ import com.blankj.utilcode.util.ToastUtils import com.blankj.utilcode.util.UriUtils import com.osfans.trime.R import com.osfans.trime.core.Rime +import com.osfans.trime.daemon.RimeDaemon import com.osfans.trime.data.AppPrefs import com.osfans.trime.data.DataManager -import com.osfans.trime.ime.core.RimeWrapper import com.osfans.trime.ui.components.FolderPickerPreference import com.osfans.trime.ui.components.PaddingPreferenceFragment import com.osfans.trime.ui.main.MainViewModel @@ -75,7 +75,8 @@ class ProfileFragment : lifecycleScope.launch { this@ProfileFragment.context?.rimeActionWithResultDialog("rime.trime", "W", 1) { Rime.syncRimeUserData() - RimeWrapper.deploy() + RimeDaemon.restartRime() + true } } true diff --git a/app/src/main/java/com/osfans/trime/ui/main/MainViewModel.kt b/app/src/main/java/com/osfans/trime/ui/main/MainViewModel.kt index fa08f5401b..75dfadaf8f 100644 --- a/app/src/main/java/com/osfans/trime/ui/main/MainViewModel.kt +++ b/app/src/main/java/com/osfans/trime/ui/main/MainViewModel.kt @@ -2,12 +2,16 @@ package com.osfans.trime.ui.main import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import com.osfans.trime.daemon.RimeDaemon +import com.osfans.trime.daemon.RimeSession class MainViewModel : ViewModel() { val toolbarTitle = MutableLiveData() val topOptionsMenu = MutableLiveData() + val rime: RimeSession = RimeDaemon.createSession(javaClass.name) + fun setToolbarTitle(title: String) { toolbarTitle.value = title } @@ -19,4 +23,8 @@ class MainViewModel : ViewModel() { fun disableTopOptionsMenu() { topOptionsMenu.value = false } + + override fun onCleared() { + RimeDaemon.destroySession(javaClass.name) + } } diff --git a/app/src/main/java/com/osfans/trime/ui/main/Pickers.kt b/app/src/main/java/com/osfans/trime/ui/main/Pickers.kt index c8c9044361..3da19a7857 100644 --- a/app/src/main/java/com/osfans/trime/ui/main/Pickers.kt +++ b/app/src/main/java/com/osfans/trime/ui/main/Pickers.kt @@ -8,12 +8,12 @@ import androidx.lifecycle.lifecycleScope import com.osfans.trime.R import com.osfans.trime.core.Rime import com.osfans.trime.core.SchemaListItem +import com.osfans.trime.daemon.RimeDaemon import com.osfans.trime.data.AppPrefs import com.osfans.trime.data.sound.SoundEffect import com.osfans.trime.data.sound.SoundEffectManager import com.osfans.trime.data.theme.ColorManager import com.osfans.trime.data.theme.ThemeManager -import com.osfans.trime.ime.core.RimeWrapper import com.osfans.trime.ui.components.CoroutineChoiceDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -87,7 +87,7 @@ fun Context.schemaPicker( .toTypedArray(), ) withContext(Dispatchers.Default) { - RimeWrapper.deploy() + RimeDaemon.restartRime() } } } diff --git a/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt b/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt index 2732f11745..a30c89c025 100644 --- a/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt +++ b/app/src/main/java/com/osfans/trime/ui/main/PrefMainActivity.kt @@ -26,11 +26,11 @@ import androidx.navigation.ui.setupWithNavController import com.hjq.permissions.Permission import com.hjq.permissions.XXPermissions import com.osfans.trime.R +import com.osfans.trime.core.RimeLifecycle +import com.osfans.trime.daemon.RimeDaemon import com.osfans.trime.data.AppPrefs import com.osfans.trime.data.sound.SoundEffectManager import com.osfans.trime.databinding.ActivityPrefBinding -import com.osfans.trime.ime.core.RimeWrapper -import com.osfans.trime.ime.core.Status import com.osfans.trime.ui.setup.SetupActivity import com.osfans.trime.util.isStorageAvailable import com.osfans.trime.util.progressBarDialogIndeterminate @@ -112,19 +112,17 @@ class PrefMainActivity : AppCompatActivity() { lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { - RimeWrapper.statusStateFlow.collect { state -> + viewModel.rime.run { stateFlow }.collect { state -> when (state) { - Status.IN_PROGRESS -> { + RimeLifecycle.State.STARTING -> { loadingDialog?.dismiss() loadingDialog = progressBarDialogIndeterminate(R.string.deploy_progress).create().apply { show() } } - Status.UN_INIT -> { - RimeWrapper.startup() - } - else -> loadingDialog?.dismiss() + RimeLifecycle.State.READY -> loadingDialog?.dismiss() + else -> return@collect } } } @@ -156,7 +154,8 @@ class PrefMainActivity : AppCompatActivity() { private fun deploy() { lifecycleScope.launch { rimeActionWithResultDialog("rime.trime", "W", 1) { - RimeWrapper.deploy() + RimeDaemon.restartRime() + true } } } diff --git a/app/src/main/java/com/osfans/trime/util/ShortcutUtils.kt b/app/src/main/java/com/osfans/trime/util/ShortcutUtils.kt index a2f17b2e19..e15c5b1376 100644 --- a/app/src/main/java/com/osfans/trime/util/ShortcutUtils.kt +++ b/app/src/main/java/com/osfans/trime/util/ShortcutUtils.kt @@ -15,8 +15,8 @@ import android.view.KeyEvent import com.blankj.utilcode.util.ActivityUtils import com.blankj.utilcode.util.IntentUtils import com.osfans.trime.core.Rime +import com.osfans.trime.daemon.RimeDaemon import com.osfans.trime.data.AppPrefs -import com.osfans.trime.ime.core.RimeWrapper import com.osfans.trime.ime.core.TrimeInputMethodService import com.osfans.trime.ime.enums.SymbolKeyboardType import com.osfans.trime.ui.main.LiquidKeyboardEditActivity @@ -140,7 +140,7 @@ object ShortcutUtils { val prefs = AppPrefs.defaultInstance() prefs.profile.lastBackgroundSync = Date().time.toString() CoroutineScope(Dispatchers.IO).launch { - prefs.profile.lastSyncStatus = Rime.syncRimeUserData().also { RimeWrapper.deploy() } + prefs.profile.lastSyncStatus = Rime.syncRimeUserData().also { RimeDaemon.restartRime() } } }