代码优化
This commit is contained in:
@@ -3,9 +3,10 @@ package io.legado.app.help.rhino
|
|||||||
import com.script.rhino.JavaObjectWrapFactory
|
import com.script.rhino.JavaObjectWrapFactory
|
||||||
import org.mozilla.javascript.NativeJavaObject
|
import org.mozilla.javascript.NativeJavaObject
|
||||||
import org.mozilla.javascript.Scriptable
|
import org.mozilla.javascript.Scriptable
|
||||||
|
import org.mozilla.javascript.lc.type.TypeInfoFactory
|
||||||
|
|
||||||
class NativeBaseSource(scope: Scriptable?, javaObject: Any, staticType: Class<*>?) :
|
class NativeBaseSource(scope: Scriptable?, javaObject: Any, staticType: Class<*>?) :
|
||||||
NativeJavaObject(scope, javaObject, staticType) {
|
NativeJavaObject(scope, javaObject, staticType?.let { TypeInfoFactory.GLOBAL.create(it) }) {
|
||||||
|
|
||||||
override fun has(name: String, start: Scriptable): Boolean {
|
override fun has(name: String, start: Scriptable): Boolean {
|
||||||
if (name != "setVariable" && name.length > 3 && name.startsWith("set")) {
|
if (name != "setVariable" && name.length > 3 && name.startsWith("set")) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package io.legado.app.ui.config
|
|||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
@@ -21,9 +22,14 @@ import kotlin.properties.ReadWriteProperty
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
interface PrefDelegate<T> : ReadWriteProperty<Any?, T> {
|
interface PrefDelegate<T> : ReadWriteProperty<Any?, T> {
|
||||||
|
val state: State<T>
|
||||||
fun dispose()
|
fun dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PrefStateDelegate<T>(private val delegate: PrefDelegate<T>) : ReadWriteProperty<Any?, T> by delegate {
|
||||||
|
val state: State<T> get() = delegate.state
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> prefDelegate(
|
fun <T> prefDelegate(
|
||||||
key: String,
|
key: String,
|
||||||
defaultValue: T,
|
defaultValue: T,
|
||||||
@@ -32,6 +38,7 @@ fun <T> prefDelegate(
|
|||||||
): PrefDelegate<T> {
|
): PrefDelegate<T> {
|
||||||
return object : PrefDelegate<T>, SharedPreferences.OnSharedPreferenceChangeListener, DefaultLifecycleObserver {
|
return object : PrefDelegate<T>, SharedPreferences.OnSharedPreferenceChangeListener, DefaultLifecycleObserver {
|
||||||
private var _value: MutableState<T> = mutableStateOf(readInitialValue())
|
private var _value: MutableState<T> = mutableStateOf(readInitialValue())
|
||||||
|
override val state: State<T> get() = _value
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (lifecycleOwner != null) {
|
if (lifecycleOwner != null) {
|
||||||
@@ -98,4 +105,14 @@ fun <T> prefDelegate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> prefStateDelegate(
|
||||||
|
key: String,
|
||||||
|
defaultValue: T,
|
||||||
|
lifecycleOwner: LifecycleOwner? = null,
|
||||||
|
onValueChange: ((T) -> Unit)? = null
|
||||||
|
): PrefStateDelegate<T> {
|
||||||
|
val delegate = prefDelegate(key, defaultValue, lifecycleOwner, onValueChange)
|
||||||
|
return PrefStateDelegate(delegate)
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
package io.legado.app.ui.config.bookshelfConfig
|
package io.legado.app.ui.config.bookshelfConfig
|
||||||
|
|
||||||
|
import androidx.compose.runtime.State
|
||||||
import io.legado.app.constant.EventBus
|
import io.legado.app.constant.EventBus
|
||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.data.entities.BookGroup
|
import io.legado.app.data.entities.BookGroup
|
||||||
import io.legado.app.ui.config.prefDelegate
|
import io.legado.app.ui.config.prefStateDelegate
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,213 +15,295 @@ object BookshelfConfig {
|
|||||||
/**
|
/**
|
||||||
* 书架分组样式: 0: Tab, 1:隐藏Tab, 2:文件夹
|
* 书架分组样式: 0: Tab, 1:隐藏Tab, 2:文件夹
|
||||||
*/
|
*/
|
||||||
var bookGroupStyle by prefDelegate(PreferKey.bookGroupStyle, 0) {
|
private val _bookGroupStyle = prefStateDelegate(PreferKey.bookGroupStyle, 0) {
|
||||||
postEvent(EventBus.NOTIFY_MAIN, false)
|
postEvent(EventBus.NOTIFY_MAIN, false)
|
||||||
}
|
}
|
||||||
|
var bookGroupStyle by _bookGroupStyle
|
||||||
|
val bookGroupStyleState: State<Int> get() = _bookGroupStyle.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架排序方式
|
* 书架排序方式
|
||||||
*/
|
*/
|
||||||
var bookshelfSort by prefDelegate(PreferKey.bookshelfSort, 0)
|
private val _bookshelfSort = prefStateDelegate(PreferKey.bookshelfSort, 0)
|
||||||
|
var bookshelfSort by _bookshelfSort
|
||||||
|
val bookshelfSortState: State<Int> get() = _bookshelfSort.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架排序顺序
|
* 书架排序顺序
|
||||||
*/
|
*/
|
||||||
var bookshelfSortOrder by prefDelegate(PreferKey.bookshelfSortOrder, 1)
|
private val _bookshelfSortOrder = prefStateDelegate(PreferKey.bookshelfSortOrder, 1)
|
||||||
|
var bookshelfSortOrder by _bookshelfSortOrder
|
||||||
|
val bookshelfSortOrderState: State<Int> get() = _bookshelfSortOrder.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示未读标志
|
* 是否显示未读标志
|
||||||
*/
|
*/
|
||||||
var showUnread by prefDelegate(PreferKey.showUnread, true)
|
private val _showUnread = prefStateDelegate(PreferKey.showUnread, true)
|
||||||
|
var showUnread by _showUnread
|
||||||
|
val showUnreadState: State<Boolean> get() = _showUnread.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示新未读标志(小圆点)
|
* 是否显示新未读标志(小圆点)
|
||||||
*/
|
*/
|
||||||
var showUnreadNew by prefDelegate(PreferKey.showUnreadNew, true)
|
private val _showUnreadNew = prefStateDelegate(PreferKey.showUnreadNew, true)
|
||||||
|
var showUnreadNew by _showUnreadNew
|
||||||
|
val showUnreadNewState: State<Boolean> get() = _showUnreadNew.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示更新提示
|
* 是否显示更新提示
|
||||||
*/
|
*/
|
||||||
var showTip by prefDelegate(PreferKey.showTip, false)
|
private val _showTip = prefStateDelegate(PreferKey.showTip, false)
|
||||||
|
var showTip by _showTip
|
||||||
|
val showTipState: State<Boolean> get() = _showTip.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 鏄惁鏄剧ず鍒嗙粍鍐呬功绫嶆暟閲?
|
* 鏄惁鏄剧ず鍒嗙粍鍐呬功绫嶆暟閲?
|
||||||
*/
|
*/
|
||||||
var showBookCount by prefDelegate(PreferKey.showBookCount, true)
|
private val _showBookCount = prefStateDelegate(PreferKey.showBookCount, true)
|
||||||
|
var showBookCount by _showBookCount
|
||||||
|
val showBookCountState: State<Boolean> get() = _showBookCount.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否在列表中显示最后更新时间
|
* 是否在列表中显示最后更新时间
|
||||||
*/
|
*/
|
||||||
var showLastUpdateTime by prefDelegate(PreferKey.showLastUpdateTime, false)
|
private val _showLastUpdateTime = prefStateDelegate(PreferKey.showLastUpdateTime, false)
|
||||||
|
var showLastUpdateTime by _showLastUpdateTime
|
||||||
|
val showLastUpdateTimeState: State<Boolean> get() = _showLastUpdateTime.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否在列表中显示书籍简介
|
* 是否在列表中显示书籍简介
|
||||||
*/
|
*/
|
||||||
var showBookIntro by prefDelegate(PreferKey.showBookIntro, false)
|
private val _showBookIntro = prefStateDelegate(PreferKey.showBookIntro, false)
|
||||||
|
var showBookIntro by _showBookIntro
|
||||||
|
val showBookIntroState: State<Boolean> get() = _showBookIntro.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示简介
|
* 是否显示简介
|
||||||
*/
|
*/
|
||||||
var bookshelfShowIntro by prefDelegate(PreferKey.bookshelfShowIntro, true)
|
private val _bookshelfShowIntro = prefStateDelegate(PreferKey.bookshelfShowIntro, true)
|
||||||
|
var bookshelfShowIntro by _bookshelfShowIntro
|
||||||
|
val bookshelfShowIntroState: State<Boolean> get() = _bookshelfShowIntro.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示标签
|
* 是否显示标签
|
||||||
*/
|
*/
|
||||||
var bookshelfShowTag by prefDelegate(PreferKey.bookshelfShowTag, true)
|
private val _bookshelfShowTag = prefStateDelegate(PreferKey.bookshelfShowTag, true)
|
||||||
|
var bookshelfShowTag by _bookshelfShowTag
|
||||||
|
val bookshelfShowTagState: State<Boolean> get() = _bookshelfShowTag.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 列表模式下简介显示行数 (0为显示全部)
|
* 列表模式下简介显示行数 (0为显示全部)
|
||||||
*/
|
*/
|
||||||
var bookshelfIntroMaxLines by prefDelegate(PreferKey.bookshelfIntroMaxLines, 0)
|
private val _bookshelfIntroMaxLines = prefStateDelegate(PreferKey.bookshelfIntroMaxLines, 0)
|
||||||
|
var bookshelfIntroMaxLines by _bookshelfIntroMaxLines
|
||||||
|
val bookshelfIntroMaxLinesState: State<Int> get() = _bookshelfIntroMaxLines.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示等待更新的书籍数量
|
* 是否显示等待更新的书籍数量
|
||||||
*/
|
*/
|
||||||
var showWaitUpCount by prefDelegate(PreferKey.showWaitUpCount, false)
|
private val _showWaitUpCount = prefStateDelegate(PreferKey.showWaitUpCount, false)
|
||||||
|
var showWaitUpCount by _showWaitUpCount
|
||||||
|
val showWaitUpCountState: State<Boolean> get() = _showWaitUpCount.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示书架快速滚动条
|
* 是否显示书架快速滚动条
|
||||||
*/
|
*/
|
||||||
var showBookshelfFastScroller by prefDelegate(PreferKey.showBookshelfFastScroller, false)
|
private val _showBookshelfFastScroller = prefStateDelegate(PreferKey.showBookshelfFastScroller, false)
|
||||||
|
var showBookshelfFastScroller by _showBookshelfFastScroller
|
||||||
|
val showBookshelfFastScrollerState: State<Boolean> get() = _showBookshelfFastScroller.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否在书架Tab处显示分类展开按钮
|
* 是否在书架Tab处显示分类展开按钮
|
||||||
*/
|
*/
|
||||||
var shouldShowExpandButton by prefDelegate(PreferKey.shouldShowExpandButton, false)
|
private val _shouldShowExpandButton = prefStateDelegate(PreferKey.shouldShowExpandButton, false)
|
||||||
|
var shouldShowExpandButton by _shouldShowExpandButton
|
||||||
|
val shouldShowExpandButtonState: State<Boolean> get() = _shouldShowExpandButton.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架同时更新书籍数量限制 (0为无限制)
|
* 书架同时更新书籍数量限制 (0为无限制)
|
||||||
*/
|
*/
|
||||||
var bookshelfRefreshingLimit by prefDelegate(PreferKey.bookshelfRefreshingLimit, 0)
|
private val _bookshelfRefreshingLimit = prefStateDelegate(PreferKey.bookshelfRefreshingLimit, 0)
|
||||||
|
var bookshelfRefreshingLimit by _bookshelfRefreshingLimit
|
||||||
|
val bookshelfRefreshingLimitState: State<Int> get() = _bookshelfRefreshingLimit.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 竖屏书架布局模式: 0:列表, 1:网格
|
* 竖屏书架布局模式: 0:列表, 1:网格
|
||||||
*/
|
*/
|
||||||
var bookshelfLayoutModePortrait by prefDelegate(PreferKey.bookshelfLayoutModePortrait, 1)
|
private val _bookshelfLayoutModePortrait = prefStateDelegate(PreferKey.bookshelfLayoutModePortrait, 1)
|
||||||
|
var bookshelfLayoutModePortrait by _bookshelfLayoutModePortrait
|
||||||
|
val bookshelfLayoutModePortraitState: State<Int> get() = _bookshelfLayoutModePortrait.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 竖屏书架网格列数
|
* 竖屏书架网格列数
|
||||||
*/
|
*/
|
||||||
var bookshelfLayoutGridPortrait by prefDelegate(PreferKey.bookshelfLayoutGridPortrait, 3)
|
private val _bookshelfLayoutGridPortrait = prefStateDelegate(PreferKey.bookshelfLayoutGridPortrait, 3)
|
||||||
|
var bookshelfLayoutGridPortrait by _bookshelfLayoutGridPortrait
|
||||||
|
val bookshelfLayoutGridPortraitState: State<Int> get() = _bookshelfLayoutGridPortrait.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 横屏书架布局模式: 0:列表, 1:网格
|
* 横屏书架布局模式: 0:列表, 1:网格
|
||||||
*/
|
*/
|
||||||
var bookshelfLayoutModeLandscape by prefDelegate(PreferKey.bookshelfLayoutModeLandscape, 1)
|
private val _bookshelfLayoutModeLandscape = prefStateDelegate(PreferKey.bookshelfLayoutModeLandscape, 1)
|
||||||
|
var bookshelfLayoutModeLandscape by _bookshelfLayoutModeLandscape
|
||||||
|
val bookshelfLayoutModeLandscapeState: State<Int> get() = _bookshelfLayoutModeLandscape.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 横屏书架网格列数
|
* 横屏书架网格列数
|
||||||
*/
|
*/
|
||||||
var bookshelfLayoutGridLandscape by prefDelegate(PreferKey.bookshelfLayoutGridLandscape, 7)
|
private val _bookshelfLayoutGridLandscape = prefStateDelegate(PreferKey.bookshelfLayoutGridLandscape, 7)
|
||||||
|
var bookshelfLayoutGridLandscape by _bookshelfLayoutGridLandscape
|
||||||
|
val bookshelfLayoutGridLandscapeState: State<Int> get() = _bookshelfLayoutGridLandscape.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 竖屏书架列表列数
|
* 竖屏书架列表列数
|
||||||
*/
|
*/
|
||||||
var bookshelfLayoutListPortrait by prefDelegate(PreferKey.bookshelfLayoutListPortrait, 1)
|
private val _bookshelfLayoutListPortrait = prefStateDelegate(PreferKey.bookshelfLayoutListPortrait, 1)
|
||||||
|
var bookshelfLayoutListPortrait by _bookshelfLayoutListPortrait
|
||||||
|
val bookshelfLayoutListPortraitState: State<Int> get() = _bookshelfLayoutListPortrait.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 横屏书架列表列数
|
* 横屏书架列表列数
|
||||||
*/
|
*/
|
||||||
var bookshelfLayoutListLandscape by prefDelegate(PreferKey.bookshelfLayoutListLandscape, 1)
|
private val _bookshelfLayoutListLandscape = prefStateDelegate(PreferKey.bookshelfLayoutListLandscape, 1)
|
||||||
|
var bookshelfLayoutListLandscape by _bookshelfLayoutListLandscape
|
||||||
|
val bookshelfLayoutListLandscapeState: State<Int> get() = _bookshelfLayoutListLandscape.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹竖屏布局模式: 0:列表, 1:网格
|
* 文件夹竖屏布局模式: 0:列表, 1:网格
|
||||||
*/
|
*/
|
||||||
var bookshelfFolderLayoutModePortrait by prefDelegate(PreferKey.bookshelfFolderLayoutModePortrait, 1)
|
private val _bookshelfFolderLayoutModePortrait = prefStateDelegate(PreferKey.bookshelfFolderLayoutModePortrait, 1)
|
||||||
|
var bookshelfFolderLayoutModePortrait by _bookshelfFolderLayoutModePortrait
|
||||||
|
val bookshelfFolderLayoutModePortraitState: State<Int> get() = _bookshelfFolderLayoutModePortrait.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹竖屏网格列数
|
* 文件夹竖屏网格列数
|
||||||
*/
|
*/
|
||||||
var bookshelfFolderLayoutGridPortrait by prefDelegate(PreferKey.bookshelfFolderLayoutGridPortrait, 3)
|
private val _bookshelfFolderLayoutGridPortrait = prefStateDelegate(PreferKey.bookshelfFolderLayoutGridPortrait, 3)
|
||||||
|
var bookshelfFolderLayoutGridPortrait by _bookshelfFolderLayoutGridPortrait
|
||||||
|
val bookshelfFolderLayoutGridPortraitState: State<Int> get() = _bookshelfFolderLayoutGridPortrait.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹横屏布局模式: 0:列表, 1:网格
|
* 文件夹横屏布局模式: 0:列表, 1:网格
|
||||||
*/
|
*/
|
||||||
var bookshelfFolderLayoutModeLandscape by prefDelegate(PreferKey.bookshelfFolderLayoutModeLandscape, 1)
|
private val _bookshelfFolderLayoutModeLandscape = prefStateDelegate(PreferKey.bookshelfFolderLayoutModeLandscape, 1)
|
||||||
|
var bookshelfFolderLayoutModeLandscape by _bookshelfFolderLayoutModeLandscape
|
||||||
|
val bookshelfFolderLayoutModeLandscapeState: State<Int> get() = _bookshelfFolderLayoutModeLandscape.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹横屏网格列数
|
* 文件夹横屏网格列数
|
||||||
*/
|
*/
|
||||||
var bookshelfFolderLayoutGridLandscape by prefDelegate(PreferKey.bookshelfFolderLayoutGridLandscape, 7)
|
private val _bookshelfFolderLayoutGridLandscape = prefStateDelegate(PreferKey.bookshelfFolderLayoutGridLandscape, 7)
|
||||||
|
var bookshelfFolderLayoutGridLandscape by _bookshelfFolderLayoutGridLandscape
|
||||||
|
val bookshelfFolderLayoutGridLandscapeState: State<Int> get() = _bookshelfFolderLayoutGridLandscape.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹竖屏列表列数
|
* 文件夹竖屏列表列数
|
||||||
*/
|
*/
|
||||||
var bookshelfFolderLayoutListPortrait by prefDelegate(PreferKey.bookshelfFolderLayoutListPortrait, 1)
|
private val _bookshelfFolderLayoutListPortrait = prefStateDelegate(PreferKey.bookshelfFolderLayoutListPortrait, 1)
|
||||||
|
var bookshelfFolderLayoutListPortrait by _bookshelfFolderLayoutListPortrait
|
||||||
|
val bookshelfFolderLayoutListPortraitState: State<Int> get() = _bookshelfFolderLayoutListPortrait.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹横屏列表列数
|
* 文件夹横屏列表列数
|
||||||
*/
|
*/
|
||||||
var bookshelfFolderLayoutListLandscape by prefDelegate(PreferKey.bookshelfFolderLayoutListLandscape, 1)
|
private val _bookshelfFolderLayoutListLandscape = prefStateDelegate(PreferKey.bookshelfFolderLayoutListLandscape, 1)
|
||||||
|
var bookshelfFolderLayoutListLandscape by _bookshelfFolderLayoutListLandscape
|
||||||
|
val bookshelfFolderLayoutListLandscapeState: State<Int> get() = _bookshelfFolderLayoutListLandscape.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网格模式布局样式: 0:标准, 1:紧凑, 2:仅封面
|
* 网格模式布局样式: 0:标准, 1:紧凑, 2:仅封面
|
||||||
*/
|
*/
|
||||||
var bookshelfGridLayout by prefDelegate(PreferKey.bookshelfGridLayout, 0)
|
private val _bookshelfGridLayout = prefStateDelegate(PreferKey.bookshelfGridLayout, 0)
|
||||||
|
var bookshelfGridLayout by _bookshelfGridLayout
|
||||||
|
val bookshelfGridLayoutState: State<Int> get() = _bookshelfGridLayout.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 紧凑模式
|
* 紧凑模式
|
||||||
*/
|
*/
|
||||||
var bookshelfLayoutCompact by prefDelegate(PreferKey.bookshelfLayoutCompact, false)
|
private val _bookshelfLayoutCompact = prefStateDelegate(PreferKey.bookshelfLayoutCompact, false)
|
||||||
|
var bookshelfLayoutCompact by _bookshelfLayoutCompact
|
||||||
|
val bookshelfLayoutCompactState: State<Boolean> get() = _bookshelfLayoutCompact.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否显示书架分隔线
|
* 是否显示书架分隔线
|
||||||
*/
|
*/
|
||||||
var bookshelfShowDivider by prefDelegate(PreferKey.bookshelfShowDivider, true)
|
private val _bookshelfShowDivider = prefStateDelegate(PreferKey.bookshelfShowDivider, true)
|
||||||
|
var bookshelfShowDivider by _bookshelfShowDivider
|
||||||
|
val bookshelfShowDividerState: State<Boolean> get() = _bookshelfShowDivider.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架标题小字体
|
* 书架标题小字体
|
||||||
*/
|
*/
|
||||||
var bookshelfTitleSmallFont by prefDelegate(PreferKey.bookshelfTitleSmallFont, false)
|
private val _bookshelfTitleSmallFont = prefStateDelegate(PreferKey.bookshelfTitleSmallFont, false)
|
||||||
|
var bookshelfTitleSmallFont by _bookshelfTitleSmallFont
|
||||||
|
val bookshelfTitleSmallFontState: State<Boolean> get() = _bookshelfTitleSmallFont.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架标题居中
|
* 书架标题居中
|
||||||
*/
|
*/
|
||||||
var bookshelfTitleCenter by prefDelegate(PreferKey.bookshelfTitleCenter, true)
|
private val _bookshelfTitleCenter = prefStateDelegate(PreferKey.bookshelfTitleCenter, true)
|
||||||
|
var bookshelfTitleCenter by _bookshelfTitleCenter
|
||||||
|
val bookshelfTitleCenterState: State<Boolean> get() = _bookshelfTitleCenter.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架标题最大行数
|
* 书架标题最大行数
|
||||||
*/
|
*/
|
||||||
var bookshelfTitleMaxLines by prefDelegate(PreferKey.bookshelfTitleMaxLines, 2)
|
private val _bookshelfTitleMaxLines = prefStateDelegate(PreferKey.bookshelfTitleMaxLines, 2)
|
||||||
|
var bookshelfTitleMaxLines by _bookshelfTitleMaxLines
|
||||||
|
val bookshelfTitleMaxLinesState: State<Int> get() = _bookshelfTitleMaxLines.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架封面阴影
|
* 书架封面阴影
|
||||||
*/
|
*/
|
||||||
var bookshelfCoverShadow by prefDelegate(PreferKey.bookshelfCoverShadow, false)
|
private val _bookshelfCoverShadow = prefStateDelegate(PreferKey.bookshelfCoverShadow, false)
|
||||||
|
var bookshelfCoverShadow by _bookshelfCoverShadow
|
||||||
|
val bookshelfCoverShadowState: State<Boolean> get() = _bookshelfCoverShadow.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架卡片背景颜色
|
* 书架卡片背景颜色
|
||||||
*/
|
*/
|
||||||
var bookshelfCardColor by prefDelegate(PreferKey.bookshelfCardColor, 0) {
|
private val _bookshelfCardColor = prefStateDelegate(PreferKey.bookshelfCardColor, 0) {
|
||||||
postEvent(EventBus.NOTIFY_MAIN, false)
|
postEvent(EventBus.NOTIFY_MAIN, false)
|
||||||
}
|
}
|
||||||
|
var bookshelfCardColor by _bookshelfCardColor
|
||||||
|
val bookshelfCardColorState: State<Int> get() = _bookshelfCardColor.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹在列表模式下的样式: 0: 默认, 2: 横排封面
|
* 文件夹在列表模式下的样式: 0: 默认, 2: 横排封面
|
||||||
*/
|
*/
|
||||||
var bookshelfGroupListStyle by prefDelegate(PreferKey.bookshelfGroupListStyle, 0)
|
private val _bookshelfGroupListStyle = prefStateDelegate(PreferKey.bookshelfGroupListStyle, 0)
|
||||||
|
var bookshelfGroupListStyle by _bookshelfGroupListStyle
|
||||||
|
val bookshelfGroupListStyleState: State<Int> get() = _bookshelfGroupListStyle.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件夹在列表模式下横排封面的数量
|
* 文件夹在列表模式下横排封面的数量
|
||||||
*/
|
*/
|
||||||
var bookshelfGroupCoverCount by prefDelegate(PreferKey.bookshelfGroupCoverCount, 4)
|
private val _bookshelfGroupCoverCount = prefStateDelegate(PreferKey.bookshelfGroupCoverCount, 4)
|
||||||
|
var bookshelfGroupCoverCount by _bookshelfGroupCoverCount
|
||||||
|
val bookshelfGroupCoverCountState: State<Int> get() = _bookshelfGroupCoverCount.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 书架搜索按钮是否直接跳转搜索页
|
* 书架搜索按钮是否直接跳转搜索页
|
||||||
*/
|
*/
|
||||||
var bookshelfSearchActionDirectToSearch by prefDelegate(
|
private val _bookshelfSearchActionDirectToSearch = prefStateDelegate(
|
||||||
PreferKey.bookshelfSearchActionDirectToSearch,
|
PreferKey.bookshelfSearchActionDirectToSearch,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
var bookshelfSearchActionDirectToSearch by _bookshelfSearchActionDirectToSearch
|
||||||
|
val bookshelfSearchActionDirectToSearchState: State<Boolean> get() = _bookshelfSearchActionDirectToSearch.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动时自动刷新书架
|
* 启动时自动刷新书架
|
||||||
*/
|
*/
|
||||||
var autoRefreshBook by prefDelegate(PreferKey.autoRefresh, false)
|
private val _autoRefreshBook = prefStateDelegate(PreferKey.autoRefresh, false)
|
||||||
|
var autoRefreshBook by _autoRefreshBook
|
||||||
|
val autoRefreshBookState: State<Boolean> get() = _autoRefreshBook.state
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存上次停留的分组Id
|
* 保存上次停留的分组Id
|
||||||
*/
|
*/
|
||||||
var saveTabPosition by prefDelegate(PreferKey.saveTabPosition, BookGroup.IdAll)
|
private val _saveTabPosition = prefStateDelegate(PreferKey.saveTabPosition, BookGroup.IdAll)
|
||||||
|
var saveTabPosition by _saveTabPosition
|
||||||
|
val saveTabPositionState: State<Long> get() = _saveTabPosition.state
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
|
import androidx.compose.ui.semantics.testTagsAsResourceId
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -241,7 +244,9 @@ fun MainScreen(
|
|||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
WideNavigationRailItem(
|
WideNavigationRailItem(
|
||||||
modifier = Modifier.testTag("nav_${destination.route}"),
|
modifier = Modifier.semantics(mergeDescendants = true) {
|
||||||
|
contentDescription = "nav_${destination.route}"
|
||||||
|
},
|
||||||
railExpanded = navState.targetValue == WideNavigationRailValue.Expanded,
|
railExpanded = navState.targetValue == WideNavigationRailValue.Expanded,
|
||||||
selected = selected,
|
selected = selected,
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -310,7 +315,9 @@ fun MainScreen(
|
|||||||
MainDestination.My -> ThemeConfig.navIconMy
|
MainDestination.My -> ThemeConfig.navIconMy
|
||||||
}
|
}
|
||||||
AppNavigationBarItem(
|
AppNavigationBarItem(
|
||||||
modifier = Modifier.testTag("nav_${destination.route}"),
|
modifier = Modifier.semantics(mergeDescendants = true) {
|
||||||
|
contentDescription = "nav_${destination.route}"
|
||||||
|
},
|
||||||
selected = selected,
|
selected = selected,
|
||||||
onClick = {
|
onClick = {
|
||||||
coroutineScope.launch { pagerState.animateScrollToPage(index) }
|
coroutineScope.launch { pagerState.animateScrollToPage(index) }
|
||||||
@@ -457,7 +464,11 @@ fun MainScreen(
|
|||||||
pagerState.animateScrollToPage(index)
|
pagerState.animateScrollToPage(index)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.defaultMinSize(minWidth = 76.dp)
|
modifier = Modifier
|
||||||
|
.defaultMinSize(minWidth = 76.dp)
|
||||||
|
.semantics(mergeDescendants = true) {
|
||||||
|
contentDescription = "nav_${destination.route}"
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
NavigationIcon(
|
NavigationIcon(
|
||||||
destination = destination,
|
destination = destination,
|
||||||
|
|||||||
@@ -83,7 +83,11 @@ import androidx.compose.ui.platform.LocalClipboard
|
|||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -123,6 +127,9 @@ import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
|||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||||
import io.legado.app.ui.widget.components.tabRow.AppTabRow
|
import io.legado.app.ui.widget.components.tabRow.AppTabRow
|
||||||
import io.legado.app.ui.widget.components.text.AppText
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -321,32 +328,38 @@ fun BookshelfScreen(
|
|||||||
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
val bookshelfLayoutMode by remember {
|
val bookshelfLayoutMode by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscape else BookshelfConfig.bookshelfLayoutModePortrait
|
if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfLayoutModePortraitState.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val bookshelfLayoutGrid by remember {
|
val bookshelfLayoutGrid by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (isLandscape) BookshelfConfig.bookshelfLayoutGridLandscape else BookshelfConfig.bookshelfLayoutGridPortrait
|
if (isLandscape) BookshelfConfig.bookshelfLayoutGridLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfLayoutGridPortraitState.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val bookshelfLayoutList by remember {
|
val bookshelfLayoutList by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscape else BookshelfConfig.bookshelfLayoutListPortrait
|
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfLayoutListPortraitState.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val bookshelfFolderLayoutMode by remember {
|
val bookshelfFolderLayoutMode by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutModeLandscape else BookshelfConfig.bookshelfFolderLayoutModePortrait
|
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutModeLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfFolderLayoutModePortraitState.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val bookshelfFolderLayoutGrid by remember {
|
val bookshelfFolderLayoutGrid by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutGridLandscape else BookshelfConfig.bookshelfFolderLayoutGridPortrait
|
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutGridLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfFolderLayoutGridPortraitState.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val bookshelfFolderLayoutList by remember {
|
val bookshelfFolderLayoutList by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutListLandscape else BookshelfConfig.bookshelfFolderLayoutListPortrait
|
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutListLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfFolderLayoutListPortraitState.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val currentMenuGroupId by remember {
|
val currentMenuGroupId by remember {
|
||||||
@@ -388,7 +401,7 @@ fun BookshelfScreen(
|
|||||||
backNavigationIcon = AppIcons.Close,
|
backNavigationIcon = AppIcons.Close,
|
||||||
showSearchAction = true,
|
showSearchAction = true,
|
||||||
onSearchToggle = { active ->
|
onSearchToggle = { active ->
|
||||||
if (BookshelfConfig.bookshelfSearchActionDirectToSearch) {
|
if (BookshelfConfig.bookshelfSearchActionDirectToSearchState.value) {
|
||||||
onNavigateToSearch(uiState.searchKey.trim())
|
onNavigateToSearch(uiState.searchKey.trim())
|
||||||
} else {
|
} else {
|
||||||
viewModel.setSearchMode(active)
|
viewModel.setSearchMode(active)
|
||||||
@@ -561,7 +574,8 @@ fun BookshelfScreen(
|
|||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (BookshelfConfig.shouldShowExpandButton) {
|
val showExpandButton by BookshelfConfig.shouldShowExpandButtonState
|
||||||
|
if (showExpandButton) {
|
||||||
Box(modifier = Modifier) {
|
Box(modifier = Modifier) {
|
||||||
SmallOutlinedIconToggleButton(
|
SmallOutlinedIconToggleButton(
|
||||||
checked = showGroupMenu,
|
checked = showGroupMenu,
|
||||||
@@ -716,12 +730,12 @@ fun BookshelfScreen(
|
|||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
horizontalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
||||||
showFastScroll = BookshelfConfig.showBookshelfFastScroller
|
showFastScroll = BookshelfConfig.showBookshelfFastScrollerState.value
|
||||||
) {
|
) {
|
||||||
itemsIndexed(
|
itemsIndexed(
|
||||||
uiState.groups,
|
uiState.groups,
|
||||||
key = { _, it -> it.groupId }) { index, group ->
|
key = { _, it -> it.groupId }) { index, group ->
|
||||||
val countText = if (BookshelfConfig.showBookCount) {
|
val countText = if (BookshelfConfig.showBookCountState.value) {
|
||||||
uiState.groupBookCounts[group.groupId]?.let {
|
uiState.groupBookCounts[group.groupId]?.let {
|
||||||
stringResource(R.string.book_count, it)
|
stringResource(R.string.book_count, it)
|
||||||
}
|
}
|
||||||
@@ -734,11 +748,11 @@ fun BookshelfScreen(
|
|||||||
previewBooks = uiState.groupPreviews[group.groupId]
|
previewBooks = uiState.groupPreviews[group.groupId]
|
||||||
?: emptyList(),
|
?: emptyList(),
|
||||||
countText = countText,
|
countText = countText,
|
||||||
isCompact = BookshelfConfig.bookshelfLayoutCompact,
|
isCompact = BookshelfConfig.bookshelfLayoutCompactState.value,
|
||||||
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFont,
|
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFontState.value,
|
||||||
titleCenter = BookshelfConfig.bookshelfTitleCenter,
|
titleCenter = BookshelfConfig.bookshelfTitleCenterState.value,
|
||||||
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLinesState.value,
|
||||||
coverShadow = BookshelfConfig.bookshelfCoverShadow,
|
coverShadow = BookshelfConfig.bookshelfCoverShadowState.value,
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch { pagerState.scrollToPage(index) }
|
scope.launch { pagerState.scrollToPage(index) }
|
||||||
viewModel.setInFolderRoot(false)
|
viewModel.setInFolderRoot(false)
|
||||||
@@ -754,11 +768,11 @@ fun BookshelfScreen(
|
|||||||
previewBooks = uiState.groupPreviews[group.groupId]
|
previewBooks = uiState.groupPreviews[group.groupId]
|
||||||
?: emptyList(),
|
?: emptyList(),
|
||||||
countText = countText,
|
countText = countText,
|
||||||
gridStyle = BookshelfConfig.bookshelfGridLayout,
|
gridStyle = BookshelfConfig.bookshelfGridLayoutState.value,
|
||||||
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFont,
|
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFontState.value,
|
||||||
titleCenter = BookshelfConfig.bookshelfTitleCenter,
|
titleCenter = BookshelfConfig.bookshelfTitleCenterState.value,
|
||||||
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLinesState.value,
|
||||||
coverShadow = BookshelfConfig.bookshelfCoverShadow,
|
coverShadow = BookshelfConfig.bookshelfCoverShadowState.value,
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch { pagerState.scrollToPage(index) }
|
scope.launch { pagerState.scrollToPage(index) }
|
||||||
viewModel.setInFolderRoot(false)
|
viewModel.setInFolderRoot(false)
|
||||||
@@ -810,7 +824,7 @@ fun BookshelfScreen(
|
|||||||
val isSelectedGroup = group.groupId == uiState.selectedGroupId
|
val isSelectedGroup = group.groupId == uiState.selectedGroupId
|
||||||
val books = uiState.allGroupBooks[group.groupId]
|
val books = uiState.allGroupBooks[group.groupId]
|
||||||
?: if (isSelectedGroup) uiState.items
|
?: if (isSelectedGroup) uiState.items
|
||||||
else emptyList()
|
else persistentListOf()
|
||||||
val canReorderBooks = isEditMode &&
|
val canReorderBooks = isEditMode &&
|
||||||
!uiState.isSearch &&
|
!uiState.isSearch &&
|
||||||
(group.bookSort.takeIf { it >= 0 }
|
(group.bookSort.takeIf { it >= 0 }
|
||||||
@@ -1155,17 +1169,17 @@ private data class BookshelfEditStickySummary(
|
|||||||
@Composable
|
@Composable
|
||||||
fun BookshelfPage(
|
fun BookshelfPage(
|
||||||
paddingValues: PaddingValues,
|
paddingValues: PaddingValues,
|
||||||
books: List<BookShelfItem>,
|
books: ImmutableList<BookShelfItem>,
|
||||||
uiState: BookshelfUiState,
|
uiState: BookshelfUiState,
|
||||||
selectedBookUrls: Set<String>,
|
selectedBookUrls: ImmutableSet<String>,
|
||||||
canReorderBooks: Boolean,
|
canReorderBooks: Boolean,
|
||||||
onToggleBookSelection: (BookShelfItem) -> Unit,
|
onToggleBookSelection: (BookShelfItem) -> Unit,
|
||||||
draggingBooks: List<BookShelfItem>?,
|
draggingBooks: ImmutableList<BookShelfItem>?,
|
||||||
pendingSavedBooks: List<BookShelfItem>?,
|
pendingSavedBooks: ImmutableList<BookShelfItem>?,
|
||||||
onDragStarted: (List<BookShelfItem>) -> Unit,
|
onDragStarted: (ImmutableList<BookShelfItem>) -> Unit,
|
||||||
onMoveBook: (fromIndex: Int, toIndex: Int, currentBooks: List<BookShelfItem>) -> Unit,
|
onMoveBook: (fromIndex: Int, toIndex: Int, currentBooks: ImmutableList<BookShelfItem>) -> Unit,
|
||||||
onDragFinished: () -> Unit,
|
onDragFinished: () -> Unit,
|
||||||
onSyncDragState: (books: List<BookShelfItem>, canReorderBooks: Boolean) -> Unit,
|
onSyncDragState: (books: ImmutableList<BookShelfItem>, canReorderBooks: Boolean) -> Unit,
|
||||||
onGlobalSearch: () -> Unit,
|
onGlobalSearch: () -> Unit,
|
||||||
onBookClick: (BookShelfItem) -> Unit,
|
onBookClick: (BookShelfItem) -> Unit,
|
||||||
onBookLongClick: (BookShelfItem) -> Unit,
|
onBookLongClick: (BookShelfItem) -> Unit,
|
||||||
@@ -1203,14 +1217,37 @@ fun BookshelfPage(
|
|||||||
|
|
||||||
val configuration = LocalConfiguration.current
|
val configuration = LocalConfiguration.current
|
||||||
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
val bookshelfLayoutMode =
|
val bookshelfLayoutMode by remember {
|
||||||
if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscape else BookshelfConfig.bookshelfLayoutModePortrait
|
derivedStateOf {
|
||||||
val bookshelfLayoutGrid =
|
if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscapeState.value
|
||||||
if (isLandscape) BookshelfConfig.bookshelfLayoutGridLandscape else BookshelfConfig.bookshelfLayoutGridPortrait
|
else BookshelfConfig.bookshelfLayoutModePortraitState.value
|
||||||
val bookshelfLayoutList =
|
}
|
||||||
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscape else BookshelfConfig.bookshelfLayoutListPortrait
|
}
|
||||||
val columns = if (bookshelfLayoutMode == 0) bookshelfLayoutList else bookshelfLayoutGrid
|
val bookshelfLayoutGrid by remember {
|
||||||
val isGridMode = bookshelfLayoutMode != 0
|
derivedStateOf {
|
||||||
|
if (isLandscape) BookshelfConfig.bookshelfLayoutGridLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfLayoutGridPortraitState.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val bookshelfLayoutList by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscapeState.value
|
||||||
|
else BookshelfConfig.bookshelfLayoutListPortraitState.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val columns by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
if (bookshelfLayoutMode == 0) bookshelfLayoutList else bookshelfLayoutGrid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val isGridMode by remember { derivedStateOf { bookshelfLayoutMode != 0 } }
|
||||||
|
val bookItemGridStyle by BookshelfConfig.bookshelfGridLayoutState
|
||||||
|
val bookItemIsCompact by BookshelfConfig.bookshelfLayoutCompactState
|
||||||
|
val bookItemTitleSmallFont by BookshelfConfig.bookshelfTitleSmallFontState
|
||||||
|
val bookItemTitleCenter by BookshelfConfig.bookshelfTitleCenterState
|
||||||
|
val bookItemTitleMaxLines by BookshelfConfig.bookshelfTitleMaxLinesState
|
||||||
|
val bookItemCoverShadow by BookshelfConfig.bookshelfCoverShadowState
|
||||||
|
val showFastScroll by BookshelfConfig.showBookshelfFastScrollerState
|
||||||
val totalHorizontalPadding =
|
val totalHorizontalPadding =
|
||||||
if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) 12.dp else 16.dp
|
if (ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)) 12.dp else 16.dp
|
||||||
val gridContentHorizontalPadding = totalHorizontalPadding / 2
|
val gridContentHorizontalPadding = totalHorizontalPadding / 2
|
||||||
@@ -1247,7 +1284,7 @@ fun BookshelfPage(
|
|||||||
state = gridState,
|
state = gridState,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.testTag("bookshelf_list")
|
.semantics(mergeDescendants = true) { contentDescription = "bookshelf_list" }
|
||||||
.then(
|
.then(
|
||||||
with(sharedTransitionScope) {
|
with(sharedTransitionScope) {
|
||||||
if (this != null) Modifier.skipToLookaheadSize() else Modifier
|
if (this != null) Modifier.skipToLookaheadSize() else Modifier
|
||||||
@@ -1260,7 +1297,7 @@ fun BookshelfPage(
|
|||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
horizontalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
||||||
showFastScroll = BookshelfConfig.showBookshelfFastScroller
|
showFastScroll = showFastScroll
|
||||||
) {
|
) {
|
||||||
items(displayBooks, key = { it.bookUrl }) { book ->
|
items(displayBooks, key = { it.bookUrl }) { book ->
|
||||||
val isSelected = selectedBookUrls.contains(book.bookUrl)
|
val isSelected = selectedBookUrls.contains(book.bookUrl)
|
||||||
@@ -1292,13 +1329,13 @@ fun BookshelfPage(
|
|||||||
),
|
),
|
||||||
layoutMode = bookshelfLayoutMode,
|
layoutMode = bookshelfLayoutMode,
|
||||||
isSelected = isSelected,
|
isSelected = isSelected,
|
||||||
gridStyle = BookshelfConfig.bookshelfGridLayout,
|
gridStyle = bookItemGridStyle,
|
||||||
isCompact = BookshelfConfig.bookshelfLayoutCompact,
|
isCompact = bookItemIsCompact,
|
||||||
isUpdating = uiState.updatingBooks.contains(book.bookUrl),
|
isUpdating = uiState.updatingBooks.contains(book.bookUrl),
|
||||||
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFont,
|
titleSmallFont = bookItemTitleSmallFont,
|
||||||
titleCenter = BookshelfConfig.bookshelfTitleCenter,
|
titleCenter = bookItemTitleCenter,
|
||||||
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
titleMaxLines = bookItemTitleMaxLines,
|
||||||
coverShadow = BookshelfConfig.bookshelfCoverShadow,
|
coverShadow = bookItemCoverShadow,
|
||||||
isSearchMode = uiState.isSearch,
|
isSearchMode = uiState.isSearch,
|
||||||
searchKey = uiState.searchKey,
|
searchKey = uiState.searchKey,
|
||||||
sharedTransitionScope = sharedTransitionScope,
|
sharedTransitionScope = sharedTransitionScope,
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ android {
|
|||||||
targetSdk = 37
|
targetSdk = 37
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE"
|
||||||
|
}
|
||||||
|
|
||||||
targetProjectPath = ":app"
|
targetProjectPath = ":app"
|
||||||
|
|
||||||
|
|||||||
+27
-22
@@ -30,36 +30,41 @@ class BaselineProfileGenerator {
|
|||||||
packageName = packageName,
|
packageName = packageName,
|
||||||
includeInStartupProfile = true
|
includeInStartupProfile = true
|
||||||
) {
|
) {
|
||||||
// 1. 启动应用
|
|
||||||
pressHome()
|
pressHome()
|
||||||
startActivityAndWait()
|
startActivityAndWait()
|
||||||
|
|
||||||
// 2. 等待书架加载 (我们在 BookshelfScreen 中添加了 ReportDrawnWhen)
|
val bookshelfSelector = By.desc("bookshelf_list")
|
||||||
// 等待书架列表 testTag 出现
|
device.wait(Until.hasObject(bookshelfSelector), 10000)
|
||||||
device.wait(Until.hasObject(By.res(packageName, "bookshelf_list")), 10000)
|
|
||||||
|
|
||||||
// 3. 模拟滑动书架 (优化列表渲染性能)
|
device.waitForIdle()
|
||||||
val bookshelf = device.findObject(By.res(packageName, "bookshelf_list"))
|
Thread.sleep(2000)
|
||||||
bookshelf?.apply {
|
|
||||||
setGestureMargin(device.displayWidth / 10)
|
val screenWidth = device.displayWidth
|
||||||
fling(Direction.DOWN)
|
val screenHeight = device.displayHeight
|
||||||
device.waitForIdle()
|
val startX = screenWidth / 2
|
||||||
fling(Direction.UP)
|
val startY = (screenHeight * 0.75).toInt()
|
||||||
device.waitForIdle()
|
val endY = (screenHeight * 0.25).toInt()
|
||||||
|
|
||||||
|
repeat(3) {
|
||||||
|
device.swipe(startX, startY, startX, endY, 25)
|
||||||
|
Thread.sleep(1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 遍历主要 Tab (优化 Compose 导航和各页面初始化)
|
repeat(2) {
|
||||||
val tabs = listOf("nav_explore", "nav_rss", "nav_my", "nav_bookshelf")
|
device.swipe(startX, endY, startX, startY, 10)
|
||||||
for (tabTag in tabs) {
|
Thread.sleep(1000)
|
||||||
val tab = device.findObject(By.res(packageName, tabTag))
|
}
|
||||||
|
|
||||||
|
// "nav_my"
|
||||||
|
/* val tabs = listOf("nav_explore", "nav_rss", "nav_bookshelf")
|
||||||
|
for (tabDesc in tabs) {
|
||||||
|
val tab = device.wait(Until.findObject(By.desc(tabDesc)), 5000)
|
||||||
if (tab != null) {
|
if (tab != null) {
|
||||||
tab.click()
|
val bounds = tab.visibleBounds
|
||||||
device.waitForIdle()
|
device.click(bounds.centerX(), bounds.centerY())
|
||||||
// 稍微等待页面加载
|
Thread.sleep(3000)
|
||||||
Thread.sleep(500)
|
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,21 +44,19 @@ class StartupBenchmarks {
|
|||||||
val rule = MacrobenchmarkRule()
|
val rule = MacrobenchmarkRule()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun startupCompilationNone() =
|
fun startupCompilationNone() = benchmark(CompilationMode.None())
|
||||||
benchmark(CompilationMode.None())
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun startupCompilationBaselineProfiles() =
|
fun startupCompilationBaselineProfiles() =
|
||||||
benchmark(CompilationMode.Partial(BaselineProfileMode.Require))
|
benchmark(CompilationMode.Partial(BaselineProfileMode.Require))
|
||||||
|
|
||||||
private fun benchmark(compilationMode: CompilationMode) {
|
private fun benchmark(compilationMode: CompilationMode) {
|
||||||
// The application id for the running build variant is read from the instrumentation arguments.
|
|
||||||
val packageName = InstrumentationRegistry.getArguments().getString("targetAppId")
|
val packageName = InstrumentationRegistry.getArguments().getString("targetAppId")
|
||||||
?: "io.legado.app"
|
?: "io.legado.app"
|
||||||
|
|
||||||
rule.measureRepeated(
|
rule.measureRepeated(
|
||||||
packageName = packageName,
|
packageName = packageName,
|
||||||
metrics = listOf(StartupTimingMetric(), FrameTimingMetric()),
|
metrics = listOf(StartupTimingMetric()),
|
||||||
compilationMode = compilationMode,
|
compilationMode = compilationMode,
|
||||||
startupMode = StartupMode.COLD,
|
startupMode = StartupMode.COLD,
|
||||||
iterations = 3,
|
iterations = 3,
|
||||||
@@ -67,18 +65,6 @@ class StartupBenchmarks {
|
|||||||
},
|
},
|
||||||
measureBlock = {
|
measureBlock = {
|
||||||
startActivityAndWait()
|
startActivityAndWait()
|
||||||
|
|
||||||
// 等待书架列表加载完成
|
|
||||||
// 我们在 BookshelfScreen 中添加了 testTag("bookshelf_list")
|
|
||||||
device.wait(Until.hasObject(By.res(packageName, "bookshelf_list")), 10000)
|
|
||||||
|
|
||||||
// 模拟交互:在书架上进行滑动,以确保 Profile 捕获到列表渲染和图片加载的路径
|
|
||||||
val bookshelfList = device.findObject(By.res(packageName, "bookshelf_list"))
|
|
||||||
bookshelfList?.apply {
|
|
||||||
setGestureMargin(device.displayWidth / 10)
|
|
||||||
fling(Direction.DOWN)
|
|
||||||
device.waitForIdle()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ adaptive = "1.3.0-beta01"
|
|||||||
adaptiveLayout = "1.3.0-beta01"
|
adaptiveLayout = "1.3.0-beta01"
|
||||||
adaptiveNavigation = "1.3.0-beta01"
|
adaptiveNavigation = "1.3.0-beta01"
|
||||||
animation = "1.11.1"
|
animation = "1.11.1"
|
||||||
biometric = "1.4.0-alpha06"
|
biometric = "1.4.0-alpha07"
|
||||||
coilCompose = "2.7.0"
|
coilCompose = "2.7.0"
|
||||||
composeBom = "2026.05.00"
|
composeBom = "2026.05.00"
|
||||||
constraintlayoutCompose = "1.1.1"
|
constraintlayoutCompose = "1.1.1"
|
||||||
coreSplashscreen = "1.2.0"
|
coreSplashscreen = "1.2.0"
|
||||||
datastorePreferences = "1.2.1"
|
datastorePreferences = "1.2.1"
|
||||||
foundation = "1.11.1"
|
foundation = "1.11.1"
|
||||||
kotlin = "2.3.10"
|
kotlin = "2.3.21"
|
||||||
kotlinxSerialization = "1.11.0"
|
kotlinxSerialization = "1.11.0"
|
||||||
kotlinxCoroutinesAndroid = "1.10.2"
|
kotlinxCoroutinesAndroid = "1.10.2"
|
||||||
kotlinxSerializationJson = "1.11.0"
|
kotlinxSerializationJson = "1.11.0"
|
||||||
@@ -35,8 +35,8 @@ hutool = "5.8.22"
|
|||||||
libarchive = "1.1.6"
|
libarchive = "1.1.6"
|
||||||
lifecycle = "2.10.0"
|
lifecycle = "2.10.0"
|
||||||
glide = "5.0.7"
|
glide = "5.0.7"
|
||||||
gson = "2.13.2"
|
gson = "2.14.0"
|
||||||
jsonPath = "2.10.0"
|
jsonPath = "3.0.0"
|
||||||
# issue #3811,不要更新版本,新版引入了一个破坏性变更(详见https://github.com/jhy/jsoup/pull/2017)
|
# issue #3811,不要更新版本,新版引入了一个破坏性变更(详见https://github.com/jhy/jsoup/pull/2017)
|
||||||
# 若要升级请确保相关代码不会受此变更影响(如AnalyzeByJSoup.kt、JsoupXpath库等)
|
# 若要升级请确保相关代码不会受此变更影响(如AnalyzeByJSoup.kt、JsoupXpath库等)
|
||||||
jsoup = "1.16.2"
|
jsoup = "1.16.2"
|
||||||
@@ -51,7 +51,7 @@ material = "1.14.0-rc01"
|
|||||||
material3 = "1.5.0-alpha19"
|
material3 = "1.5.0-alpha19"
|
||||||
material3IconsExtended = "1.7.8"
|
material3IconsExtended = "1.7.8"
|
||||||
materialKolor = "4.1.1"
|
materialKolor = "4.1.1"
|
||||||
media = "1.7.1"
|
media = "1.8.0"
|
||||||
media3 = "1.8.0"
|
media3 = "1.8.0"
|
||||||
nanoHttpd = "2.3.1"
|
nanoHttpd = "2.3.1"
|
||||||
navigationCompose = "2.9.8"
|
navigationCompose = "2.9.8"
|
||||||
@@ -62,7 +62,7 @@ protobufJavalite = "4.26.1"
|
|||||||
quickChineseTransfer = "0.2.16"
|
quickChineseTransfer = "0.2.16"
|
||||||
room = "2.8.4"
|
room = "2.8.4"
|
||||||
splitties = "3.0.0"
|
splitties = "3.0.0"
|
||||||
rhino = "1.8.1"
|
rhino = "1.9.1"
|
||||||
desugar = "2.1.5"
|
desugar = "2.1.5"
|
||||||
|
|
||||||
activity = "1.13.0"
|
activity = "1.13.0"
|
||||||
@@ -77,7 +77,7 @@ viewpager2 = "1.1.0"
|
|||||||
webkit = "1.16.0"
|
webkit = "1.16.0"
|
||||||
collection = "1.6.0"
|
collection = "1.6.0"
|
||||||
|
|
||||||
zxingLite = "3.3.0"
|
zxingLite = "3.4.1"
|
||||||
|
|
||||||
koin-bom = "4.2.1"
|
koin-bom = "4.2.1"
|
||||||
biometricKtx = "1.1.0"
|
biometricKtx = "1.1.0"
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package com.script.rhino
|
|||||||
|
|
||||||
import org.mozilla.javascript.NativeJavaObject
|
import org.mozilla.javascript.NativeJavaObject
|
||||||
import org.mozilla.javascript.Scriptable
|
import org.mozilla.javascript.Scriptable
|
||||||
|
import org.mozilla.javascript.lc.type.TypeInfoFactory
|
||||||
|
|
||||||
class ReadOnlyJavaObject(scope: Scriptable?, javaObject: Any, staticType: Class<*>?) :
|
class ReadOnlyJavaObject(scope: Scriptable?, javaObject: Any, staticType: Class<*>?) :
|
||||||
NativeJavaObject(scope, javaObject, staticType) {
|
NativeJavaObject(scope, javaObject, staticType?.let { TypeInfoFactory.GLOBAL.create(it) }) {
|
||||||
|
|
||||||
override fun has(name: String, start: Scriptable): Boolean {
|
override fun has(name: String, start: Scriptable): Boolean {
|
||||||
if (name.length > 3 && name.startsWith("set")) {
|
if (name.length > 3 && name.startsWith("set")) {
|
||||||
|
|||||||
@@ -1,20 +1,31 @@
|
|||||||
package com.script.rhino
|
package com.script.rhino
|
||||||
|
|
||||||
import org.mozilla.javascript.VMBridge
|
import org.mozilla.javascript.Context
|
||||||
|
import org.mozilla.javascript.ContextFactory
|
||||||
|
|
||||||
object VMBridgeReflect {
|
object VMBridgeReflect {
|
||||||
|
|
||||||
val instance: VMBridge by lazy {
|
|
||||||
VMBridge::class.java.getDeclaredField("instance").apply {
|
|
||||||
isAccessible = true
|
|
||||||
}.get(null) as VMBridge
|
|
||||||
}
|
|
||||||
|
|
||||||
val contextLocal: ThreadLocal<Any> by lazy {
|
val contextLocal: ThreadLocal<Any> by lazy {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
instance::class.java.getDeclaredField("contextLocal").apply {
|
try {
|
||||||
isAccessible = true
|
// Rhino 1.9.1+ uses threadContextLocal directly in Context class
|
||||||
}.get(null) as ThreadLocal<Any>
|
val field = Context::class.java.getDeclaredField("threadContextLocal")
|
||||||
|
field.isAccessible = true
|
||||||
|
field.get(null) as ThreadLocal<Any>
|
||||||
|
} catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
// Fallback for some versions or custom builds
|
||||||
|
val factory = ContextFactory.getGlobal()
|
||||||
|
val field = ContextFactory::class.java.getDeclaredField("localContext")
|
||||||
|
field.isAccessible = true
|
||||||
|
field.get(factory) as ThreadLocal<Any>
|
||||||
|
} catch (e2: Exception) {
|
||||||
|
// Older versions used threadContextHelper (Object) which held a ThreadLocal
|
||||||
|
val field = Context::class.java.getDeclaredField("threadContextHelper")
|
||||||
|
field.isAccessible = true
|
||||||
|
field.get(null) as ThreadLocal<Any>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,3 +54,4 @@ include ':app'
|
|||||||
include ':modules:book'
|
include ':modules:book'
|
||||||
include ':modules:rhino'
|
include ':modules:rhino'
|
||||||
include ':baselineprofile'
|
include ':baselineprofile'
|
||||||
|
project(':baselineprofile').projectDir = file('baselineProfile')
|
||||||
|
|||||||
Reference in New Issue
Block a user