Skip to content

Commit

Permalink
refactors: always pass the copy of the active theme to the views ...
Browse files Browse the repository at this point in the history
... and related managers, therefore the stuffs in the scope can always get the initialized and unique Theme instance.
  • Loading branch information
WhiredPlanck committed Oct 8, 2024
1 parent c5b1c51 commit 7ecec44
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 197 deletions.
15 changes: 6 additions & 9 deletions app/src/main/java/com/osfans/trime/data/theme/ColorManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import timber.log.Timber
import java.io.File

object ColorManager {
private val theme get() = ThemeManager.activeTheme
private lateinit var theme: Theme
private val prefs = AppPrefs.defaultInstance().theme
private val backgroundFolder get() = theme.generalStyle.backgroundFolder

Expand Down Expand Up @@ -81,7 +81,7 @@ object ColorManager {
} ?: mapOf()

fun interface OnColorChangeListener {
fun onColorChange()
fun onColorChange(theme: Theme)
}

private val onChangeListeners = WeakHashSet<OnColorChangeListener>()
Expand All @@ -95,16 +95,11 @@ object ColorManager {
}

private fun fireChange() {
onChangeListeners.forEach { it.onColorChange() }
onChangeListeners.forEach { it.onColorChange(theme) }
}

fun init(configuration: Configuration) {
isNightMode = configuration.isNightMode()
runCatching {
ThemeManager.init()
}.getOrElse {
Timber.e(it, "Setting up theme failed!")
}
}

fun onSystemNightModeChange(isNight: Boolean) {
Expand All @@ -115,10 +110,12 @@ object ColorManager {
}

/** 每次切换主题后,都要调用此函数,初始化配色 */
fun refresh() {
fun resetCache(theme: Theme) {
lastDarkColorSchemeId = null
lastLightColorSchemeId = null

this.theme = theme

val selected = prefs.selectedColor
val fromStyle = theme.generalStyle.colorScheme
val default = "default" // 主題中的 default 配色
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ object EventManager {
return event
}

fun refresh() = eventCache.clear()
fun resetCache() = eventCache.clear()
}
11 changes: 7 additions & 4 deletions app/src/main/java/com/osfans/trime/data/theme/FontManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import timber.log.Timber
import java.io.File

object FontManager {
private lateinit var theme: Theme

private enum class FontKey {
HANB_FONT,
LATIN_FONT,
Expand All @@ -28,16 +30,17 @@ object FontManager {
}

private val fontDir get() = File(DataManager.userDataDir, "fonts")
var hanBFont: Typeface = getTypefaceOrDefault(FontKey.HANB_FONT.name)
lateinit var hanBFont: Typeface
private set
var latinFont: Typeface = getTypefaceOrDefault(FontKey.LATIN_FONT.name)
lateinit var latinFont: Typeface
private set
private val typefaceCache = mutableMapOf<String, Typeface>()
private val fontFamilyCache = mutableMapOf<String, FontFamily>()

fun refresh() {
fun resetCache(theme: Theme) {
typefaceCache.clear()
fontFamilyCache.clear()
this.theme = theme
hanBFont = getTypefaceOrDefault(FontKey.HANB_FONT.name)
latinFont = getTypefaceOrDefault(FontKey.LATIN_FONT.name)
}
Expand Down Expand Up @@ -96,7 +99,7 @@ object FontManager {
}

private fun getFontFromStyle(key: String): List<String>? {
val style = ThemeManager.activeTheme.generalStyle
val style = theme.generalStyle
return when (FontKey.entries.firstOrNull { it.name == key.uppercase() }) {
FontKey.HANB_FONT -> style.hanbFont
FontKey.LATIN_FONT -> style.latinFont
Expand Down
13 changes: 6 additions & 7 deletions app/src/main/java/com/osfans/trime/data/theme/ThemeManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ object ThemeManager {
userThemes.clear()
sharedThemes.addAll(listThemes(DataManager.sharedDataDir))
userThemes.addAll(listThemes(DataManager.userDataDir))
setNormalTheme(prefs.selectedTheme)
}

// 在初始化 ColorManager 时会被赋值
lateinit var activeTheme: Theme
private set

Expand All @@ -60,14 +60,13 @@ object ThemeManager {
fun setNormalTheme(name: String) {
Theme(name).let {
if (::activeTheme.isInitialized) {
if (it == activeTheme) return
if (activeTheme == it) return
}
EventManager.resetCache()
FontManager.resetCache(it)
ColorManager.resetCache(it)
TabManager.resetCache(it)
activeTheme = it
// 由于这里的顺序不能打乱,不适合使用 listener
EventManager.refresh()
FontManager.refresh()
ColorManager.refresh()
TabManager.refresh()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.ScaleXSpan
import android.text.style.UnderlineSpan
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
Expand All @@ -31,7 +30,7 @@ import com.osfans.trime.core.RimeProto
import com.osfans.trime.data.theme.ColorManager
import com.osfans.trime.data.theme.EventManager
import com.osfans.trime.data.theme.FontManager
import com.osfans.trime.data.theme.ThemeManager
import com.osfans.trime.data.theme.Theme
import com.osfans.trime.data.theme.model.CompositionComponent
import com.osfans.trime.ime.core.TrimeInputMethodService
import com.osfans.trime.ime.keyboard.Event
Expand All @@ -46,10 +45,9 @@ import kotlin.math.absoluteValue
@SuppressLint("AppCompatCustomView")
class Composition(
context: Context,
attrs: AttributeSet?,
) : TextView(context, attrs) {
private val theme: Theme,
) : TextView(context) {
private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
private val theme = ThemeManager.activeTheme

private val keyTextSize = theme.generalStyle.keyTextSize
private val labelTextSize = theme.generalStyle.labelTextSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import android.os.Build.VERSION_CODES
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
Expand All @@ -25,15 +24,17 @@ import com.osfans.trime.daemon.launchOnReady
import com.osfans.trime.data.prefs.AppPrefs
import com.osfans.trime.data.theme.ColorManager
import com.osfans.trime.data.theme.Theme
import com.osfans.trime.data.theme.ThemeManager
import com.osfans.trime.databinding.CompositionRootBinding
import com.osfans.trime.ime.bar.QuickBar
import com.osfans.trime.ime.broadcast.InputBroadcastReceiver
import com.osfans.trime.ime.dependency.InputScope
import com.osfans.trime.ime.enums.PopupPosition
import com.osfans.trime.ime.keyboard.CommonKeyboardActionListener
import me.tatarka.inject.annotations.Inject
import splitties.dimensions.dp
import splitties.views.dsl.core.add
import splitties.views.dsl.core.horizontalLayout
import splitties.views.dsl.core.lParams
import splitties.views.dsl.core.wrapContent
import timber.log.Timber

@InputScope
Expand All @@ -50,18 +51,22 @@ class CompositionPopupWindow(
AppPrefs.defaultInstance().keyboard.popupWindowEnabled &&
theme.generalStyle.window.isNotEmpty()

val binding =
CompositionRootBinding.inflate(LayoutInflater.from(ctx)).apply {
root.visibility = if (isPopupWindowEnabled) View.VISIBLE else View.GONE
composition.run {
setOnActionMoveListener { x, y ->
updatePopupWindow(x.toInt(), y.toInt())
}
setOnSelectCandidateListener { idx ->
rime.launchOnReady { it.selectCandidate(idx) }
}
setKeyboardActionListener(commonKeyboardActionListener.listener)
val composition =
Composition(ctx, theme).apply {
setOnActionMoveListener { x, y ->
updatePopupWindow(x.toInt(), y.toInt())
}
setOnSelectCandidateListener { idx ->
rime.launchOnReady { it.selectCandidate(idx) }
}
setKeyboardActionListener(commonKeyboardActionListener.listener)
}

val root =
ctx.horizontalLayout {
layoutParams = ViewGroup.LayoutParams(wrapContent, wrapContent)
visibility = if (isPopupWindowEnabled) View.VISIBLE else View.GONE
add(composition, lParams(wrapContent, wrapContent))
}

// 悬浮窗口是否可移動
Expand All @@ -80,7 +85,7 @@ class CompositionPopupWindow(
private var popupWindowPos = PopupPosition.fromString(theme.generalStyle.layout.position)

private val mPopupWindow =
PopupWindow(binding.root).apply {
PopupWindow(root).apply {
isClippingEnabled = false
inputMethodMode = PopupWindow.INPUT_METHOD_NOT_NEEDED
if (Build.VERSION.SDK_INT >= VERSION_CODES.M) {
Expand Down Expand Up @@ -219,14 +224,14 @@ class CompositionPopupWindow(

private fun updateCompositionView() {
if (isPopupWindowMovable == "once") {
popupWindowPos = PopupPosition.fromString(ThemeManager.activeTheme.generalStyle.layout.position)
popupWindowPos = PopupPosition.fromString(theme.generalStyle.layout.position)
}
binding.root.measure(
root.measure(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
mPopupWindow.width = binding.root.measuredWidth
mPopupWindow.height = binding.root.measuredHeight
mPopupWindow.width = root.measuredWidth
mPopupWindow.height = root.measuredHeight
mPopupHandler.post(mPopupTimer)
}

Expand Down
17 changes: 8 additions & 9 deletions app/src/main/java/com/osfans/trime/ime/core/InputView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import com.osfans.trime.core.RimeResponse
import com.osfans.trime.daemon.RimeSession
import com.osfans.trime.data.prefs.AppPrefs
import com.osfans.trime.data.theme.ColorManager
import com.osfans.trime.data.theme.ThemeManager
import com.osfans.trime.data.theme.Theme
import com.osfans.trime.ime.bar.QuickBar
import com.osfans.trime.ime.candidates.CompactCandidateModule
import com.osfans.trime.ime.composition.CompositionPopupWindow
Expand Down Expand Up @@ -67,10 +67,10 @@ import splitties.views.imageDrawable
*/
@SuppressLint("ViewConstructor")
class InputView(
val service: TrimeInputMethodService,
val rime: RimeSession,
private val service: TrimeInputMethodService,
private val rime: RimeSession,
private val theme: Theme,
) : ConstraintLayout(service) {
private val theme get() = ThemeManager.activeTheme
private var shouldUpdateNavbarForeground = false
private var shouldUpdateNavbarBackground = false
private val navbarBackground get() = AppPrefs.defaultInstance().theme.navbarBackground
Expand All @@ -83,17 +83,17 @@ class InputView(

private val leftPaddingSpace =
view(::View) {
setOnClickListener { placeholderListener }
setOnClickListener(placeholderListener)
}

private val rightPaddingSpace =
view(::View) {
setOnClickListener { placeholderListener }
setOnClickListener(placeholderListener)
}

private val bottomPaddingSpace =
view(::View) {
setOnClickListener { placeholderListener }
setOnClickListener(placeholderListener)
}

private val notificationHandlerJob: Job
Expand Down Expand Up @@ -353,7 +353,7 @@ class InputView(
val previous = ctx.menu.run { pageSize * pageNumber }
val highlightedIdx = ctx.menu.highlightedCandidateIndex
if (composition.isPopupWindowEnabled) {
val sticky = composition.binding.composition.update(ctx)
val sticky = composition.composition.update(ctx)
compactCandidate.adapter.updateCandidates(candidates, isLastPage, previous, highlightedIdx, sticky)
} else {
compactCandidate.adapter.updateCandidates(candidates, isLastPage, previous, highlightedIdx)
Expand All @@ -376,7 +376,6 @@ class InputView(
false
}.also { composition.isCursorUpdated = it }
}
keyboardWindow.mainKeyboardView.invalidateComposingKeys()
}

fun updateSelection(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import com.osfans.trime.data.prefs.AppPrefs
import com.osfans.trime.data.schema.SchemaManager
import com.osfans.trime.data.theme.ColorManager
import com.osfans.trime.data.theme.EventManager
import com.osfans.trime.data.theme.Theme
import com.osfans.trime.data.theme.ThemeManager
import com.osfans.trime.ime.broadcast.IntentReceiver
import com.osfans.trime.ime.enums.FullscreenMode
Expand Down Expand Up @@ -105,7 +106,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
private val onColorChangeListener =
ColorManager.OnColorChangeListener {
lifecycleScope.launch(Dispatchers.Main) {
recreateInputView()
recreateInputView(it)
}
}

Expand Down Expand Up @@ -221,6 +222,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
handleRimeResponse(it)
}
}
ColorManager.addOnChangedListener(onColorChangeListener)
super.onCreate()
instance = this
// MUST WRAP all code within Service onCreate() in try..catch to prevent any crash loops
Expand All @@ -229,13 +231,13 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
// could crash
// and lead to a crash loop
Timber.d("onCreate")
ColorManager.addOnChangedListener(onColorChangeListener)
mIntentReceiver =
IntentReceiver().also {
it.registerReceiver(this)
}
postRimeJob {
ColorManager.init(resources.configuration)
ThemeManager.init()
InputFeedbackManager.init()
restartSystemStartTimingSync()
shouldUpdateRimeOption = true
Expand Down Expand Up @@ -265,7 +267,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
private fun handleRimeNotification(notification: RimeNotification<*>) {
if (notification is RimeNotification.SchemaNotification) {
SchemaManager.init(notification.value.id)
recreateInputView()
recreateInputView(ThemeManager.activeTheme)
} else if (notification is RimeNotification.OptionNotification) {
val value = notification.value.value
when (val option = notification.value.option) {
Expand Down Expand Up @@ -310,11 +312,10 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
/** Must be called on the UI thread
*
* 重置鍵盤、候選條、狀態欄等 !!注意,如果其中調用Rime.setOption,切換方案會卡住 */
fun recreateInputView() {
inputView = InputView(this, rime)
fun recreateInputView(theme: Theme) {
shouldUpdateRimeOption = true // 不能在Rime.onMessage中調用set_option,會卡死
updateComposing() // 切換主題時刷新候選
setInputView(inputView!!)
setInputView(InputView(this, rime, theme).also { inputView = it })
initializationUi = null
}

Expand Down Expand Up @@ -413,7 +414,7 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
override fun onCreateInputView(): View {
Timber.d("onCreateInputView")
postRimeJob(Dispatchers.Main) {
recreateInputView()
recreateInputView(ThemeManager.activeTheme)
}
initializationUi = InitializationUi(this)
return initializationUi!!.root
Expand Down
Loading

0 comments on commit 7ecec44

Please sign in to comment.