Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactors 20241007 #1481

Merged
merged 4 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions app/src/main/java/com/osfans/trime/core/RimeProto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,29 @@ class RimeProto {
val composition: Composition,
val menu: Menu,
val input: String,
val caretPos: Int,
private val _caretPos: Int,
) {
/**
* Same with [Composition.cursorPos], just directly assign to it.
*/
val caretPos = composition.cursorPos

data class Composition(
val length: Int = 0,
val cursorPos: Int = 0,
private val _length: Int = 0,
private val _cursorPos: Int = 0,
private val _selStart: Int = 0,
private val _selEnd: Int = 0,
val preedit: String? = null,
val commitTextPreview: String? = null,
) {
/**
* Actually we can directly use [String.length] on [preedit], but
* we add it here for the sake of completeness as it is semantically correct
*/
val length: Int = preedit.run { if (isNullOrEmpty()) 0 else String(toByteArray(), 0, _length).length }

val cursorPos: Int = preedit.run { if (isNullOrEmpty()) 0 else String(toByteArray(), 0, _cursorPos).length }

val selStart: Int = preedit.run { if (isNullOrEmpty()) 0 else String(toByteArray(), 0, _selStart).length }

val selEnd: Int = preedit.run { if (isNullOrEmpty()) 0 else String(toByteArray(), 0, _selEnd).length }
Expand Down
19 changes: 8 additions & 11 deletions app/src/main/java/com/osfans/trime/data/prefs/AppPrefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import com.osfans.trime.ime.enums.FullscreenMode
import com.osfans.trime.ime.enums.InlinePreeditMode
import com.osfans.trime.util.appContext
import java.lang.ref.WeakReference
import java.util.Calendar

/**
* Helper class for an organized access to the shared preferences.
Expand Down Expand Up @@ -198,19 +197,17 @@ class AppPrefs(
) : PreferenceDelegateOwner(shared) {
companion object {
const val USER_DATA_DIR = "profile_user_data_dir"
const val SYNC_BACKGROUND_ENABLED = "profile_sync_in_background"
const val TIMING_SYNC_ENABLED = "profile_timing_sync"
const val TIMING_SYNC_TRIGGER_TIME = "profile_timing_sync_trigger_time"
const val LAST_SYNC_STATUS = "profile_last_sync_status"
const val LAST_BACKGROUND_SYNC = "profile_last_background_sync"
const val TIMING_BACKGROUND_SYNC_ENABLED = "profile_timing_background_sync"
const val TIMING_BACKGROUND_SYNC_SET_TIME = "profile_timing_background_sync_set_time"
const val LAST_BACKGROUND_SYNC_STATUS = "profile_last_background_sync_status"
const val LAST_BACKGROUND_SYNC_TIME = "profile_last_background_sync_time"
}

var userDataDir by string(USER_DATA_DIR, DataManager.defaultDataDirectory.path)
var syncBackgroundEnabled by bool(SYNC_BACKGROUND_ENABLED, false)
var timingSyncEnabled by bool(TIMING_SYNC_ENABLED, false)
var timingSyncTriggerTime by long(TIMING_SYNC_TRIGGER_TIME, Calendar.getInstance().timeInMillis + 1200000L)
var lastSyncStatus by bool(LAST_SYNC_STATUS, false)
var lastBackgroundSync by string(LAST_BACKGROUND_SYNC, "")
var timingBackgroundSyncEnabled by bool(TIMING_BACKGROUND_SYNC_ENABLED, false)
var timingBackgroundSyncSetTime by long(TIMING_BACKGROUND_SYNC_SET_TIME, System.currentTimeMillis())
var lastSyncStatus by bool(LAST_BACKGROUND_SYNC_STATUS, false)
var lastBackgroundSyncTime by long(LAST_BACKGROUND_SYNC_TIME, 0L)
}

class Clipboard(
Expand Down
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
3 changes: 0 additions & 3 deletions app/src/main/java/com/osfans/trime/data/theme/Theme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package com.osfans.trime.data.theme

import com.osfans.trime.core.Rime
import com.osfans.trime.data.prefs.AppPrefs
import com.osfans.trime.data.theme.mapper.GeneralStyleMapper
import com.osfans.trime.data.theme.model.GeneralStyle
import com.osfans.trime.util.config.Config
Expand All @@ -32,7 +31,6 @@ class Theme(
private set

companion object {
private val prefs = AppPrefs.defaultInstance().theme
private const val VERSION_KEY = "config_version"
private const val DEFAULT_THEME_NAME = "trime"

Expand Down Expand Up @@ -70,7 +68,6 @@ class Theme(
presetColorSchemes = config.getMap("preset_color_schemes")
presetKeyboards = config.getMap("preset_keyboards")
Timber.i("The theme is initialized")
prefs.selectedTheme = name
}

private fun mapToGeneralStyle(config: Config): GeneralStyle {
Expand Down
51 changes: 39 additions & 12 deletions app/src/main/java/com/osfans/trime/data/theme/ThemeManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.annotation.Keep
import com.osfans.trime.data.base.DataManager
import com.osfans.trime.data.prefs.AppPrefs
import com.osfans.trime.ime.symbol.TabManager
import com.osfans.trime.util.WeakHashSet
import java.io.File

object ThemeManager {
Expand Down Expand Up @@ -47,27 +48,53 @@ object ThemeManager {
userThemes.clear()
sharedThemes.addAll(listThemes(DataManager.sharedDataDir))
userThemes.addAll(listThemes(DataManager.userDataDir))
setNormalTheme(prefs.selectedTheme)
}

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

var activeTheme: Theme
get() = _activeTheme
set(value) {
if (::_activeTheme.isInitialized && _activeTheme == value) return
_activeTheme = value
fireChange()
}

private val onChangeListeners = WeakHashSet<OnThemeChangeListener>()

fun addOnChangedListener(listener: OnThemeChangeListener) {
onChangeListeners.add(listener)
}

fun removeOnChangedListener(listener: OnThemeChangeListener) {
onChangeListeners.remove(listener)
}

private fun fireChange() {
onChangeListeners.forEach { it.onThemeChange(_activeTheme) }
}

private val prefs = AppPrefs.defaultInstance().theme

fun init() = setNormalTheme(prefs.selectedTheme)
fun init() {
Theme(prefs.selectedTheme).let {
EventManager.resetCache()
FontManager.resetCache(it)
ColorManager.resetCache(it)
TabManager.resetCache(it)
_activeTheme = it
}
}

fun setNormalTheme(name: String) {
Theme(name).let {
if (::activeTheme.isInitialized) {
if (it == activeTheme) return
}
EventManager.resetCache()
FontManager.resetCache(it)
ColorManager.resetCache(it)
TabManager.resetCache(it)
activeTheme = it
// 由于这里的顺序不能打乱,不适合使用 listener
EventManager.refresh()
FontManager.refresh()
ColorManager.refresh()
TabManager.refresh()
}
prefs.selectedTheme = name
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class IntentReceiver :
wakeLock.acquire(600000) // 10分钟超时
val cal = Calendar.getInstance()
val triggerTime = cal.timeInMillis + TimeUnit.DAYS.toMillis(1) // 下次同步时间
AppPrefs.defaultInstance().profile.timingSyncTriggerTime =
AppPrefs.defaultInstance().profile.timingBackgroundSyncSetTime =
triggerTime // 更新定时同步偏好值
// 设置待发送的同步事件
val pendingIntent =
Expand Down
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
Loading
Loading