[优化] 一些主题优化
This commit is contained in:
45 files changed
+352
-318
No files matched your search
@@ -10,7 +10,6 @@ import android.content.res.Configuration
|
|||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.graphics.scale
|
import androidx.core.graphics.scale
|
||||||
import coil.ImageLoader
|
|
||||||
import com.github.liuyueyi.quick.transfer.constants.TransType
|
import com.github.liuyueyi.quick.transfer.constants.TransType
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
import com.google.android.material.color.DynamicColorsOptions
|
import com.google.android.material.color.DynamicColorsOptions
|
||||||
@@ -44,9 +43,9 @@ import io.legado.app.help.LifecycleHelp
|
|||||||
import io.legado.app.help.RuleBigDataHelp
|
import io.legado.app.help.RuleBigDataHelp
|
||||||
import io.legado.app.help.book.BookHelp
|
import io.legado.app.help.book.BookHelp
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig.applyDayNightInit
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
|
||||||
import io.legado.app.help.config.ThemeConfig.applyDayNightInit
|
|
||||||
import io.legado.app.help.coroutine.Coroutine
|
import io.legado.app.help.coroutine.Coroutine
|
||||||
import io.legado.app.help.http.Cronet
|
import io.legado.app.help.http.Cronet
|
||||||
import io.legado.app.help.http.ObsoleteUrlFactory
|
import io.legado.app.help.http.ObsoleteUrlFactory
|
||||||
@@ -155,7 +154,7 @@ class App : Application() {
|
|||||||
BookHelp.clearInvalidCache()
|
BookHelp.clearInvalidCache()
|
||||||
Backup.clearCache()
|
Backup.clearCache()
|
||||||
ReadBookConfig.clearBgAndCache()
|
ReadBookConfig.clearBgAndCache()
|
||||||
ThemeConfig.clearBg()
|
OldThemeConfig.clearBg()
|
||||||
//初始化简繁转换引擎
|
//初始化简繁转换引擎
|
||||||
when (AppConfig.chineseConverterType) {
|
when (AppConfig.chineseConverterType) {
|
||||||
1 -> {
|
1 -> {
|
||||||
|
|||||||
@@ -27,9 +27,8 @@ import io.legado.app.constant.EventBus
|
|||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.constant.Theme
|
import io.legado.app.constant.Theme
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.lib.theme.primaryColor
|
import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.ui.theme.ThemeSyncer
|
|
||||||
import io.legado.app.utils.applyOpenTint
|
import io.legado.app.utils.applyOpenTint
|
||||||
import io.legado.app.utils.applyTint
|
import io.legado.app.utils.applyTint
|
||||||
import io.legado.app.utils.disableAutoFill
|
import io.legado.app.utils.disableAutoFill
|
||||||
@@ -232,7 +231,7 @@ abstract class BaseActivity<VB : ViewBinding>(
|
|||||||
open fun upBackgroundImage() {
|
open fun upBackgroundImage() {
|
||||||
if (imageBg) {
|
if (imageBg) {
|
||||||
try {
|
try {
|
||||||
ThemeConfig.getBgImage(this, windowManager.windowSize)?.let {
|
OldThemeConfig.getBgImage(this, windowManager.windowSize)?.let {
|
||||||
window.decorView.background = it.toDrawable(resources)
|
window.decorView.background = it.toDrawable(resources)
|
||||||
}
|
}
|
||||||
} catch (e: OutOfMemoryError) {
|
} catch (e: OutOfMemoryError) {
|
||||||
@@ -245,7 +244,6 @@ abstract class BaseActivity<VB : ViewBinding>(
|
|||||||
|
|
||||||
open fun observeLiveBus() {
|
open fun observeLiveBus() {
|
||||||
observeEvent<String>(EventBus.RECREATE) {
|
observeEvent<String>(EventBus.RECREATE) {
|
||||||
ThemeSyncer.syncAll()
|
|
||||||
recreate()
|
recreate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,8 @@ import androidx.core.graphics.drawable.toDrawable
|
|||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import io.legado.app.constant.EventBus
|
import io.legado.app.constant.EventBus
|
||||||
import io.legado.app.constant.Theme
|
import io.legado.app.constant.Theme
|
||||||
import io.legado.app.help.config.ThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.ui.theme.AppTheme
|
import io.legado.app.ui.theme.AppTheme
|
||||||
import io.legado.app.ui.theme.ThemeSyncer
|
|
||||||
import io.legado.app.utils.disableAutoFill
|
import io.legado.app.utils.disableAutoFill
|
||||||
import io.legado.app.utils.fullScreen
|
import io.legado.app.utils.fullScreen
|
||||||
import io.legado.app.utils.observeEvent
|
import io.legado.app.utils.observeEvent
|
||||||
@@ -66,7 +65,7 @@ abstract class BaseComposeActivity(
|
|||||||
|
|
||||||
open fun upBackgroundImage() {
|
open fun upBackgroundImage() {
|
||||||
try {
|
try {
|
||||||
ThemeConfig.getBgImage(this, windowManager.windowSize)?.let {
|
OldThemeConfig.getBgImage(this, windowManager.windowSize)?.let {
|
||||||
window.setBackgroundDrawable(it.toDrawable(resources))
|
window.setBackgroundDrawable(it.toDrawable(resources))
|
||||||
}
|
}
|
||||||
} catch (_: Exception) {}
|
} catch (_: Exception) {}
|
||||||
@@ -74,7 +73,6 @@ abstract class BaseComposeActivity(
|
|||||||
|
|
||||||
open fun observeLiveBus() {
|
open fun observeLiveBus() {
|
||||||
observeEvent<String>(EventBus.RECREATE) {
|
observeEvent<String>(EventBus.RECREATE) {
|
||||||
ThemeSyncer.syncAll()
|
|
||||||
recreate()
|
recreate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ object PreferKey {
|
|||||||
const val composeEngine = "composeEngine"
|
const val composeEngine = "composeEngine"
|
||||||
const val containerOpacity = "containerOpacity"
|
const val containerOpacity = "containerOpacity"
|
||||||
const val enableBlur = "enableBlur"
|
const val enableBlur = "enableBlur"
|
||||||
|
const val enableProgressiveBlur = "enableProgressiveBlur"
|
||||||
const val cBackground = "colorBackground"
|
const val cBackground = "colorBackground"
|
||||||
const val cBBackground = "colorBottomBackground"
|
const val cBBackground = "colorBottomBackground"
|
||||||
const val bgImage = "backgroundImage"
|
const val bgImage = "backgroundImage"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import io.legado.app.data.entities.KeyboardAssist
|
|||||||
import io.legado.app.data.entities.RssSource
|
import io.legado.app.data.entities.RssSource
|
||||||
import io.legado.app.data.entities.TxtTocRule
|
import io.legado.app.data.entities.TxtTocRule
|
||||||
import io.legado.app.help.config.LocalConfig
|
import io.legado.app.help.config.LocalConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
|
||||||
import io.legado.app.help.coroutine.Coroutine
|
import io.legado.app.help.coroutine.Coroutine
|
||||||
import io.legado.app.model.BookCover
|
import io.legado.app.model.BookCover
|
||||||
import io.legado.app.utils.GSON
|
import io.legado.app.utils.GSON
|
||||||
@@ -70,12 +70,12 @@ object DefaultData {
|
|||||||
GSON.fromJsonArray<TxtTocRule>(json).getOrNull() ?: emptyList()
|
GSON.fromJsonArray<TxtTocRule>(json).getOrNull() ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val themeConfigs: List<ThemeConfig.Config> by lazy {
|
val themeConfigs: List<OldThemeConfig.Config> by lazy {
|
||||||
val json = String(
|
val json = String(
|
||||||
appCtx.assets.open("defaultData${File.separator}${ThemeConfig.configFileName}")
|
appCtx.assets.open("defaultData${File.separator}${OldThemeConfig.configFileName}")
|
||||||
.readBytes()
|
.readBytes()
|
||||||
)
|
)
|
||||||
GSON.fromJsonArray<ThemeConfig.Config>(json).getOrNull() ?: emptyList()
|
GSON.fromJsonArray<OldThemeConfig.Config>(json).getOrNull() ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val rssSources: List<RssSource> by lazy {
|
val rssSources: List<RssSource> by lazy {
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import io.legado.app.constant.AppPattern
|
|||||||
import io.legado.app.data.entities.BaseSource
|
import io.legado.app.data.entities.BaseSource
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
|
||||||
import io.legado.app.help.http.BackstageWebView
|
import io.legado.app.help.http.BackstageWebView
|
||||||
import io.legado.app.help.http.CookieManager.cookieJarHeader
|
import io.legado.app.help.http.CookieManager.cookieJarHeader
|
||||||
import io.legado.app.help.http.CookieStore
|
import io.legado.app.help.http.CookieStore
|
||||||
@@ -1203,12 +1203,12 @@ interface JsExtensions : JsEncodeUtils {
|
|||||||
*/
|
*/
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun getThemeConfig(): String {
|
fun getThemeConfig(): String {
|
||||||
val themeConfig = ThemeConfig.getDurConfig(appCtx)
|
val themeConfig = OldThemeConfig.getDurConfig(appCtx)
|
||||||
return GSON.toJson(themeConfig)
|
return GSON.toJson(themeConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getThemeConfigMap(): Map<String, Any?> {
|
fun getThemeConfigMap(): Map<String, Any?> {
|
||||||
return ThemeConfig.getDurConfig(appCtx).toMap()
|
return OldThemeConfig.getDurConfig(appCtx).toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -32,7 +32,7 @@ import splitties.init.appCtx
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
object ThemeConfig {
|
object OldThemeConfig {
|
||||||
const val configFileName = "themeConfig.json"
|
const val configFileName = "themeConfig.json"
|
||||||
val configFilePath = FileUtils.getPath(appCtx.filesDir, configFileName)
|
val configFilePath = FileUtils.getPath(appCtx.filesDir, configFileName)
|
||||||
|
|
||||||
@@ -13,8 +13,8 @@ import io.legado.app.help.AppWebDav
|
|||||||
import io.legado.app.help.DirectLinkUpload
|
import io.legado.app.help.DirectLinkUpload
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.config.LocalConfig
|
import io.legado.app.help.config.LocalConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
|
||||||
import io.legado.app.help.coroutine.Coroutine
|
import io.legado.app.help.coroutine.Coroutine
|
||||||
import io.legado.app.model.BookCover
|
import io.legado.app.model.BookCover
|
||||||
import io.legado.app.utils.FileUtils
|
import io.legado.app.utils.FileUtils
|
||||||
@@ -82,7 +82,7 @@ object Backup {
|
|||||||
DirectLinkUpload.ruleFileName,
|
DirectLinkUpload.ruleFileName,
|
||||||
ReadBookConfig.configFileName,
|
ReadBookConfig.configFileName,
|
||||||
ReadBookConfig.shareConfigFileName,
|
ReadBookConfig.shareConfigFileName,
|
||||||
ThemeConfig.configFileName,
|
OldThemeConfig.configFileName,
|
||||||
BookCover.configFileName,
|
BookCover.configFileName,
|
||||||
"config.xml"
|
"config.xml"
|
||||||
)
|
)
|
||||||
@@ -169,8 +169,8 @@ object Backup {
|
|||||||
FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.shareConfigFileName)
|
FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.shareConfigFileName)
|
||||||
.writeText(it)
|
.writeText(it)
|
||||||
}
|
}
|
||||||
GSON.toJson(ThemeConfig.configList).let {
|
GSON.toJson(OldThemeConfig.configList).let {
|
||||||
FileUtils.createFileIfNotExist(backupPath + File.separator + ThemeConfig.configFileName)
|
FileUtils.createFileIfNotExist(backupPath + File.separator + OldThemeConfig.configFileName)
|
||||||
.writeText(it)
|
.writeText(it)
|
||||||
}
|
}
|
||||||
DirectLinkUpload.getConfig()?.let {
|
DirectLinkUpload.getConfig()?.let {
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ import io.legado.app.help.LauncherIconHelp
|
|||||||
import io.legado.app.help.book.isLocal
|
import io.legado.app.help.book.isLocal
|
||||||
import io.legado.app.help.book.upType
|
import io.legado.app.help.book.upType
|
||||||
import io.legado.app.help.config.LocalConfig
|
import io.legado.app.help.config.LocalConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
|
||||||
import io.legado.app.model.BookCover
|
import io.legado.app.model.BookCover
|
||||||
import io.legado.app.model.localBook.LocalBook
|
import io.legado.app.model.localBook.LocalBook
|
||||||
import io.legado.app.utils.ACache
|
import io.legado.app.utils.ACache
|
||||||
@@ -216,12 +216,12 @@ object Restore {
|
|||||||
AppLog.put("恢复直链上传出错\n${it.localizedMessage}", it)
|
AppLog.put("恢复直链上传出错\n${it.localizedMessage}", it)
|
||||||
}
|
}
|
||||||
//恢复主题配置
|
//恢复主题配置
|
||||||
File(path, ThemeConfig.configFileName).takeIf {
|
File(path, OldThemeConfig.configFileName).takeIf {
|
||||||
it.exists()
|
it.exists()
|
||||||
}?.runCatching {
|
}?.runCatching {
|
||||||
FileUtils.delete(ThemeConfig.configFilePath)
|
FileUtils.delete(OldThemeConfig.configFilePath)
|
||||||
copyTo(File(ThemeConfig.configFilePath))
|
copyTo(File(OldThemeConfig.configFilePath))
|
||||||
ThemeConfig.upConfig()
|
OldThemeConfig.upConfig()
|
||||||
}?.onFailure {
|
}?.onFailure {
|
||||||
AppLog.put("恢复主题出错\n${it.localizedMessage}", it)
|
AppLog.put("恢复主题出错\n${it.localizedMessage}", it)
|
||||||
}
|
}
|
||||||
@@ -301,7 +301,7 @@ object Restore {
|
|||||||
if (!BuildConfig.DEBUG) {
|
if (!BuildConfig.DEBUG) {
|
||||||
LauncherIconHelp.changeIcon(appCtx.getPrefString(PreferKey.launcherIcon))
|
LauncherIconHelp.changeIcon(appCtx.getPrefString(PreferKey.launcherIcon))
|
||||||
}
|
}
|
||||||
ThemeConfig.applyDayNight(appCtx)
|
OldThemeConfig.applyDayNight(appCtx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import io.legado.app.constant.EventBus
|
|||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.lib.dialogs.alert
|
import io.legado.app.lib.dialogs.alert
|
||||||
import io.legado.app.ui.theme.ThemeSyncer
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
import io.legado.app.utils.getPrefString
|
import io.legado.app.utils.getPrefString
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
import io.legado.app.utils.restart
|
import io.legado.app.utils.restart
|
||||||
@@ -91,13 +91,13 @@ class ThemeCardPreference(context: Context, attrs: AttributeSet) : Preference(co
|
|||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
} else {
|
} else {
|
||||||
AppConfig.containerOpacity = 0
|
AppConfig.containerOpacity = 0
|
||||||
ThemeSyncer.syncContainerOpacity()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val oldValue = currentValue
|
val oldValue = currentValue
|
||||||
currentValue = value
|
currentValue = value
|
||||||
persistString(value)
|
persistString(value)
|
||||||
callChangeListener(value)
|
callChangeListener(value)
|
||||||
|
ThemeConfig.appTheme = value
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
val isDynamicSwitch = (oldValue == "12" || value == "12")
|
val isDynamicSwitch = (oldValue == "12" || value == "12")
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import android.util.AttributeSet
|
|||||||
import androidx.preference.PreferenceViewHolder
|
import androidx.preference.PreferenceViewHolder
|
||||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.help.config.ThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
|
|
||||||
|
|
||||||
class ThemeModePreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
|
class ThemeModePreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
|
||||||
@@ -59,7 +59,7 @@ class ThemeModePreference(context: Context, attrs: AttributeSet) : Preference(co
|
|||||||
persistString(newValue)
|
persistString(newValue)
|
||||||
callChangeListener(newValue)
|
callChangeListener(newValue)
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
ThemeConfig.applyDayNight(context)
|
OldThemeConfig.applyDayNight(context)
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import io.legado.app.R
|
|||||||
import io.legado.app.constant.AppConst.appInfo
|
import io.legado.app.constant.AppConst.appInfo
|
||||||
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
||||||
import io.legado.app.ui.widget.components.SplicedColumnGroup
|
import io.legado.app.ui.widget.components.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import io.legado.app.ui.widget.components.card.TextCard
|
import io.legado.app.ui.widget.components.card.TextCard
|
||||||
import io.legado.app.ui.widget.components.settingItem.SettingItem
|
import io.legado.app.ui.widget.components.settingItem.SettingItem
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ fun AboutScreen(
|
|||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(stringResource(R.string.about)) },
|
title = { Text(stringResource(R.string.about)) },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior
|
scrollBehavior = scrollBehavior
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import io.legado.app.base.adapter.ItemViewHolder
|
|||||||
import io.legado.app.base.adapter.RecyclerAdapter
|
import io.legado.app.base.adapter.RecyclerAdapter
|
||||||
import io.legado.app.databinding.DialogRecyclerViewBinding
|
import io.legado.app.databinding.DialogRecyclerViewBinding
|
||||||
import io.legado.app.databinding.ItemSourceImportBinding
|
import io.legado.app.databinding.ItemSourceImportBinding
|
||||||
import io.legado.app.help.config.ThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
//import io.legado.app.lib.theme.primaryColor
|
//import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.ui.widget.dialog.CodeDialog
|
import io.legado.app.ui.widget.dialog.CodeDialog
|
||||||
import io.legado.app.ui.widget.dialog.WaitDialog
|
import io.legado.app.ui.widget.dialog.WaitDialog
|
||||||
@@ -126,7 +126,7 @@ class ImportThemeDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_recycl
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class SourcesAdapter(context: Context) :
|
inner class SourcesAdapter(context: Context) :
|
||||||
RecyclerAdapter<ThemeConfig.Config, ItemSourceImportBinding>(context) {
|
RecyclerAdapter<OldThemeConfig.Config, ItemSourceImportBinding>(context) {
|
||||||
|
|
||||||
override fun getViewBinding(parent: ViewGroup): ItemSourceImportBinding {
|
override fun getViewBinding(parent: ViewGroup): ItemSourceImportBinding {
|
||||||
return ItemSourceImportBinding.inflate(inflater, parent, false)
|
return ItemSourceImportBinding.inflate(inflater, parent, false)
|
||||||
@@ -135,7 +135,7 @@ class ImportThemeDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_recycl
|
|||||||
override fun convert(
|
override fun convert(
|
||||||
holder: ItemViewHolder,
|
holder: ItemViewHolder,
|
||||||
binding: ItemSourceImportBinding,
|
binding: ItemSourceImportBinding,
|
||||||
item: ThemeConfig.Config,
|
item: OldThemeConfig.Config,
|
||||||
payloads: MutableList<Any>
|
payloads: MutableList<Any>
|
||||||
) {
|
) {
|
||||||
binding.apply {
|
binding.apply {
|
||||||
|
|||||||
@@ -8,12 +8,19 @@ import io.legado.app.base.BaseViewModel
|
|||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.config.ThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.help.http.decompressed
|
import io.legado.app.help.http.decompressed
|
||||||
import io.legado.app.help.http.newCallResponseBody
|
import io.legado.app.help.http.newCallResponseBody
|
||||||
import io.legado.app.help.http.okHttpClient
|
import io.legado.app.help.http.okHttpClient
|
||||||
import io.legado.app.help.http.text
|
import io.legado.app.help.http.text
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.GSON
|
||||||
|
import io.legado.app.utils.fromJsonArray
|
||||||
|
import io.legado.app.utils.fromJsonObject
|
||||||
|
import io.legado.app.utils.isAbsUrl
|
||||||
|
import io.legado.app.utils.isJsonArray
|
||||||
|
import io.legado.app.utils.isJsonObject
|
||||||
|
import io.legado.app.utils.isUri
|
||||||
|
import io.legado.app.utils.readText
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
|
|
||||||
class ImportThemeViewModel(app: Application) : BaseViewModel(app) {
|
class ImportThemeViewModel(app: Application) : BaseViewModel(app) {
|
||||||
@@ -21,8 +28,8 @@ class ImportThemeViewModel(app: Application) : BaseViewModel(app) {
|
|||||||
val errorLiveData = MutableLiveData<String>()
|
val errorLiveData = MutableLiveData<String>()
|
||||||
val successLiveData = MutableLiveData<Int>()
|
val successLiveData = MutableLiveData<Int>()
|
||||||
|
|
||||||
val allSources = arrayListOf<ThemeConfig.Config>()
|
val allSources = arrayListOf<OldThemeConfig.Config>()
|
||||||
val checkSources = arrayListOf<ThemeConfig.Config?>()
|
val checkSources = arrayListOf<OldThemeConfig.Config?>()
|
||||||
val selectStatus = arrayListOf<Boolean>()
|
val selectStatus = arrayListOf<Boolean>()
|
||||||
|
|
||||||
val isSelectAll: Boolean
|
val isSelectAll: Boolean
|
||||||
@@ -50,7 +57,7 @@ class ImportThemeViewModel(app: Application) : BaseViewModel(app) {
|
|||||||
execute {
|
execute {
|
||||||
selectStatus.forEachIndexed { index, b ->
|
selectStatus.forEachIndexed { index, b ->
|
||||||
if (b) {
|
if (b) {
|
||||||
ThemeConfig.addConfig(allSources[index])
|
OldThemeConfig.addConfig(allSources[index])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
@@ -72,11 +79,12 @@ class ImportThemeViewModel(app: Application) : BaseViewModel(app) {
|
|||||||
private suspend fun importSourceAwait(text: String) {
|
private suspend fun importSourceAwait(text: String) {
|
||||||
when {
|
when {
|
||||||
text.isJsonObject() -> {
|
text.isJsonObject() -> {
|
||||||
GSON.fromJsonObject<ThemeConfig.Config>(text).getOrThrow().let {
|
GSON.fromJsonObject<OldThemeConfig.Config>(text).getOrThrow().let {
|
||||||
allSources.add(it)
|
allSources.add(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text.isJsonArray() -> GSON.fromJsonArray<ThemeConfig.Config>(text).getOrThrow()
|
|
||||||
|
text.isJsonArray() -> GSON.fromJsonArray<OldThemeConfig.Config>(text).getOrThrow()
|
||||||
.let { items ->
|
.let { items ->
|
||||||
allSources.addAll(items)
|
allSources.addAll(items)
|
||||||
}
|
}
|
||||||
@@ -106,7 +114,7 @@ class ImportThemeViewModel(app: Application) : BaseViewModel(app) {
|
|||||||
private fun comparisonSource() {
|
private fun comparisonSource() {
|
||||||
execute {
|
execute {
|
||||||
allSources.forEach { config ->
|
allSources.forEach { config ->
|
||||||
val source = ThemeConfig.configList.find {
|
val source = OldThemeConfig.configList.find {
|
||||||
it.themeName == config.themeName
|
it.themeName == config.themeName
|
||||||
}
|
}
|
||||||
checkSources.add(source)
|
checkSources.add(source)
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ import androidx.compose.material.icons.filled.MoreVert
|
|||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material.icons.filled.UnfoldLess
|
import androidx.compose.material.icons.filled.UnfoldLess
|
||||||
import androidx.compose.material.icons.filled.UnfoldMore
|
import androidx.compose.material.icons.filled.UnfoldMore
|
||||||
import androidx.compose.material3.DropdownMenu
|
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -48,9 +46,11 @@ import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
|||||||
import io.legado.app.ui.widget.components.SearchBarSection
|
import io.legado.app.ui.widget.components.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet
|
import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet
|
||||||
import io.legado.app.ui.widget.components.bookmark.BookmarkItem
|
import io.legado.app.ui.widget.components.bookmark.BookmarkItem
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
||||||
import io.legado.app.ui.widget.components.lazylist.Scroller
|
import io.legado.app.ui.widget.components.lazylist.Scroller
|
||||||
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||||
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
|
||||||
@@ -105,7 +105,7 @@ fun AllBookmarkScreen(
|
|||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
if (bookmarksGrouped.isNotEmpty()) {
|
if (bookmarksGrouped.isNotEmpty()) {
|
||||||
@@ -127,11 +127,11 @@ fun AllBookmarkScreen(
|
|||||||
IconButton(onClick = { showMenu = true }) {
|
IconButton(onClick = { showMenu = true }) {
|
||||||
Icon(Icons.Default.MoreVert, contentDescription = "Menu")
|
Icon(Icons.Default.MoreVert, contentDescription = "Menu")
|
||||||
}
|
}
|
||||||
DropdownMenu(
|
RoundDropdownMenu(
|
||||||
expanded = showMenu,
|
expanded = showMenu,
|
||||||
onDismissRequest = { showMenu = false }
|
onDismissRequest = { showMenu = false }
|
||||||
) {
|
) {
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出 JSON") },
|
text = { Text("导出 JSON") },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
@@ -139,7 +139,7 @@ fun AllBookmarkScreen(
|
|||||||
exportLauncher.launch(null)
|
exportLauncher.launch(null)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("导出 Markdown") },
|
text = { Text("导出 Markdown") },
|
||||||
onClick = {
|
onClick = {
|
||||||
showMenu = false
|
showMenu = false
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class ExploreShowViewModel(
|
|||||||
private val _rawBooks = MutableStateFlow<List<SearchBook>>(emptyList())
|
private val _rawBooks = MutableStateFlow<List<SearchBook>>(emptyList())
|
||||||
private val _filterState = MutableStateFlow(BookFilterState.fromId(AppConfig.exploreFilterState))
|
private val _filterState = MutableStateFlow(BookFilterState.fromId(AppConfig.exploreFilterState))
|
||||||
private val _isLoading = MutableStateFlow(false)
|
private val _isLoading = MutableStateFlow(false)
|
||||||
|
private val _isRefreshing = MutableStateFlow(false)
|
||||||
private val _errorMsg = MutableStateFlow<String?>(null)
|
private val _errorMsg = MutableStateFlow<String?>(null)
|
||||||
private var bookSource: BookSource? = null
|
private var bookSource: BookSource? = null
|
||||||
private var exploreUrl: String? = null
|
private var exploreUrl: String? = null
|
||||||
@@ -68,10 +69,14 @@ class ExploreShowViewModel(
|
|||||||
private val _gridCount = MutableStateFlow(appCtx.exploreLayoutGrid)
|
private val _gridCount = MutableStateFlow(appCtx.exploreLayoutGrid)
|
||||||
val gridCount = _gridCount.asStateFlow()
|
val gridCount = _gridCount.asStateFlow()
|
||||||
val isEnd: StateFlow<Boolean> = _isEndStateFlow.asStateFlow()
|
val isEnd: StateFlow<Boolean> = _isEndStateFlow.asStateFlow()
|
||||||
|
|
||||||
|
val isRefreshing = _isRefreshing.asStateFlow()
|
||||||
|
|
||||||
fun saveGridCount(value: Int) {
|
fun saveGridCount(value: Int) {
|
||||||
appCtx.exploreLayoutGrid = value
|
appCtx.exploreLayoutGrid = value
|
||||||
_gridCount.value = value
|
_gridCount.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
val uiBooks = combine(
|
val uiBooks = combine(
|
||||||
_rawBooks,
|
_rawBooks,
|
||||||
_filterState,
|
_filterState,
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ import io.legado.app.R
|
|||||||
import io.legado.app.ui.book.changecover.ChangeCoverDialog
|
import io.legado.app.ui.book.changecover.ChangeCoverDialog
|
||||||
import io.legado.app.ui.widget.components.Cover
|
import io.legado.app.ui.widget.components.Cover
|
||||||
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
|
||||||
import io.legado.app.ui.widget.components.button.TopBarButtonVariant
|
import io.legado.app.ui.widget.components.button.TopBarButtonVariant
|
||||||
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import io.legado.app.utils.SelectImageContract
|
import io.legado.app.utils.SelectImageContract
|
||||||
import io.legado.app.utils.launch
|
import io.legado.app.utils.launch
|
||||||
import io.legado.app.utils.showDialogFragment
|
import io.legado.app.utils.showDialogFragment
|
||||||
@@ -72,13 +72,13 @@ fun BookInfoEditScreen(
|
|||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(text = stringResource(id = R.string.book_info_edit)) },
|
title = { Text(text = stringResource(id = R.string.book_info_edit)) },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(
|
TopbarNavigationButton(
|
||||||
onClick = onBack,
|
onClick = onBack,
|
||||||
style = TopBarButtonVariant.Outlined
|
style = TopBarButtonVariant.Outlined
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
SmallTopBarButton(
|
TopbarNavigationButton(
|
||||||
onClick = { viewModel.save(onSave) },
|
onClick = { viewModel.save(onSave) },
|
||||||
imageVector = Icons.Default.Save
|
imageVector = Icons.Default.Save
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ import io.legado.app.constant.PreferKey
|
|||||||
import io.legado.app.databinding.ViewReadMenuBinding
|
import io.legado.app.databinding.ViewReadMenuBinding
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.config.LocalConfig
|
import io.legado.app.help.config.LocalConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
|
||||||
import io.legado.app.help.coroutine.Coroutine
|
import io.legado.app.help.coroutine.Coroutine
|
||||||
import io.legado.app.help.source.getSourceType
|
import io.legado.app.help.source.getSourceType
|
||||||
import io.legado.app.lib.dialogs.alert
|
import io.legado.app.lib.dialogs.alert
|
||||||
@@ -693,7 +693,7 @@ class ReadMenu @JvmOverloads constructor(
|
|||||||
description = context.getString(R.string.day_night_switch),
|
description = context.getString(R.string.day_night_switch),
|
||||||
onClick = {
|
onClick = {
|
||||||
AppConfig.isNightTheme = !AppConfig.isNightTheme
|
AppConfig.isNightTheme = !AppConfig.isNightTheme
|
||||||
ThemeConfig.applyDayNight(context)
|
OldThemeConfig.applyDayNight(context)
|
||||||
buttonMap["theme"]?.setIconResource(
|
buttonMap["theme"]?.setIconResource(
|
||||||
if (AppConfig.isNightTheme) R.drawable.ic_daytime else R.drawable.ic_brightness
|
if (AppConfig.isNightTheme) R.drawable.ic_daytime else R.drawable.ic_brightness
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import io.legado.app.constant.EventBus
|
|||||||
import io.legado.app.databinding.DialogReadBookStyleBinding
|
import io.legado.app.databinding.DialogReadBookStyleBinding
|
||||||
import io.legado.app.databinding.ItemReadStyleBinding
|
import io.legado.app.databinding.ItemReadStyleBinding
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
|
||||||
import io.legado.app.lib.dialogs.alert
|
import io.legado.app.lib.dialogs.alert
|
||||||
import io.legado.app.model.ReadBook
|
import io.legado.app.model.ReadBook
|
||||||
import io.legado.app.ui.book.read.ReadBookActivity
|
import io.legado.app.ui.book.read.ReadBookActivity
|
||||||
@@ -121,7 +121,7 @@ class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_
|
|||||||
}
|
}
|
||||||
tvDayNight.setOnClickListener {
|
tvDayNight.setOnClickListener {
|
||||||
AppConfig.isNightTheme = !AppConfig.isNightTheme
|
AppConfig.isNightTheme = !AppConfig.isNightTheme
|
||||||
ThemeConfig.applyDayNight(requireContext())
|
OldThemeConfig.applyDayNight(requireContext())
|
||||||
}
|
}
|
||||||
// rgPageAnim.setOnCheckedChangeListener { _, checkedId ->
|
// rgPageAnim.setOnCheckedChangeListener { _, checkedId ->
|
||||||
// ReadBook.book?.setPageAnim(-1)
|
// ReadBook.book?.setPageAnim(-1)
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import androidx.compose.material3.Surface
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@@ -87,7 +88,7 @@ import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
|||||||
import io.legado.app.ui.widget.components.SearchBarSection
|
import io.legado.app.ui.widget.components.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.SectionHeader
|
import io.legado.app.ui.widget.components.SectionHeader
|
||||||
import io.legado.app.ui.widget.components.button.AlertButton
|
import io.legado.app.ui.widget.components.button.AlertButton
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import io.legado.app.ui.widget.components.heatmap.HeatmapCalendarTopBar
|
import io.legado.app.ui.widget.components.heatmap.HeatmapCalendarTopBar
|
||||||
import io.legado.app.ui.widget.components.heatmap.HeatmapConfig
|
import io.legado.app.ui.widget.components.heatmap.HeatmapConfig
|
||||||
import io.legado.app.ui.widget.components.heatmap.HeatmapLegend
|
import io.legado.app.ui.widget.components.heatmap.HeatmapLegend
|
||||||
@@ -98,6 +99,7 @@ import io.legado.app.ui.widget.components.heatmap.WeekdayLabelsColumn
|
|||||||
import io.legado.app.ui.widget.components.heatmap.rememberDateRange
|
import io.legado.app.ui.widget.components.heatmap.rememberDateRange
|
||||||
import io.legado.app.ui.widget.components.heatmap.rememberDaysInRange
|
import io.legado.app.ui.widget.components.heatmap.rememberDaysInRange
|
||||||
import io.legado.app.ui.widget.components.heatmap.rememberWeeks
|
import io.legado.app.ui.widget.components.heatmap.rememberWeeks
|
||||||
|
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
||||||
import io.legado.app.ui.widget.components.swipe.SwipeAction
|
import io.legado.app.ui.widget.components.swipe.SwipeAction
|
||||||
import io.legado.app.ui.widget.components.swipe.SwipeActionContainer
|
import io.legado.app.ui.widget.components.swipe.SwipeActionContainer
|
||||||
import io.legado.app.utils.StringUtils.formatFriendlyDate
|
import io.legado.app.utils.StringUtils.formatFriendlyDate
|
||||||
@@ -163,7 +165,7 @@ fun ReadRecordScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
@@ -318,8 +320,8 @@ fun ReadRecordScreen(
|
|||||||
|
|
||||||
if (showCalendar) {
|
if (showCalendar) {
|
||||||
val sheetState =
|
val sheetState =
|
||||||
androidx.compose.material3.rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||||
androidx.compose.material3.ModalBottomSheet(
|
GlassModalBottomSheet(
|
||||||
onDismissRequest = { showCalendar = false },
|
onDismissRequest = { showCalendar = false },
|
||||||
sheetState = sheetState
|
sheetState = sheetState
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ import io.legado.app.ui.widget.components.EmptyMessageView
|
|||||||
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
||||||
import io.legado.app.ui.widget.components.SearchBarSection
|
import io.legado.app.ui.widget.components.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.button.AnimatedActionButton
|
import io.legado.app.ui.widget.components.button.AnimatedActionButton
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import io.legado.app.ui.widget.components.card.TextCard
|
import io.legado.app.ui.widget.components.card.TextCard
|
||||||
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -141,7 +141,7 @@ fun SearchContentScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@@ -294,33 +294,33 @@ fun TocScreen(
|
|||||||
when (pagerState.currentPage) {
|
when (pagerState.currentPage) {
|
||||||
0 -> {
|
0 -> {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "使用替换规则",
|
text = { Text("使用替换规则") },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(checked = useReplace, onCheckedChange = null)
|
Checkbox(checked = useReplace, onCheckedChange = null)
|
||||||
},
|
},
|
||||||
onClick = { viewModel.toggleUseReplace() }
|
onClick = { viewModel.toggleUseReplace() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "显示字数",
|
text = { Text("显示字数") },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(checked = showWordCount, onCheckedChange = null)
|
Checkbox(checked = showWordCount, onCheckedChange = null)
|
||||||
},
|
},
|
||||||
onClick = { viewModel.toggleShowWordCount() }
|
onClick = { viewModel.toggleShowWordCount() }
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "反转目录",
|
text = { Text("反转目录") },
|
||||||
onClick = { viewModel.reverseToc() }
|
onClick = { viewModel.reverseToc() }
|
||||||
)
|
)
|
||||||
PillDivider()
|
PillDivider()
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "替换规则",
|
text = { Text("替换规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
onOpenReplaceRule(null)
|
onOpenReplaceRule(null)
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "新建替换规则",
|
text = { Text("新建替换规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val scopes = mutableListOf<String>()
|
val scopes = mutableListOf<String>()
|
||||||
book?.name?.let { scopes.add(it) }
|
book?.name?.let { scopes.add(it) }
|
||||||
@@ -340,7 +340,7 @@ fun TocScreen(
|
|||||||
if (book?.isLocal == true) {
|
if (book?.isLocal == true) {
|
||||||
PillHeaderDivider(title = "本地书籍选项")
|
PillHeaderDivider(title = "本地书籍选项")
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "本地书籍目录规则",
|
text = { Text("本地书籍目录规则") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val intent =
|
val intent =
|
||||||
Intent(context, TxtTocRuleActivity::class.java).apply {
|
Intent(context, TxtTocRuleActivity::class.java).apply {
|
||||||
@@ -351,7 +351,7 @@ fun TocScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "拆分超长章节",
|
text = { Text("拆分超长章节") },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Checkbox(
|
Checkbox(
|
||||||
checked = viewModel.isSplitLongChapter,
|
checked = viewModel.isSplitLongChapter,
|
||||||
@@ -368,7 +368,7 @@ fun TocScreen(
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "导出书签为JSON",
|
text = { Text("导出书签为JSON") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val dateFormat = SimpleDateFormat(
|
val dateFormat = SimpleDateFormat(
|
||||||
"yyyyMMdd_HHmm",
|
"yyyyMMdd_HHmm",
|
||||||
@@ -380,7 +380,7 @@ fun TocScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "导出书签为MarkDown",
|
text = { Text("导出书签为MarkDown") },
|
||||||
onClick = {
|
onClick = {
|
||||||
val dateFormat = SimpleDateFormat(
|
val dateFormat = SimpleDateFormat(
|
||||||
"yyyyMMdd_HHmm",
|
"yyyyMMdd_HHmm",
|
||||||
@@ -445,13 +445,13 @@ fun TocScreen(
|
|||||||
onDismissRequest = { showVolumeMenu = false }
|
onDismissRequest = { showVolumeMenu = false }
|
||||||
) {
|
) {
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "展开所有卷",
|
text = { Text("展开所有卷") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.expandAllVolumes(); showVolumeMenu = false
|
viewModel.expandAllVolumes(); showVolumeMenu = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = "收起所有卷",
|
text = { Text("收起所有卷") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.collapseAllVolumes(); showVolumeMenu = false
|
viewModel.collapseAllVolumes(); showVolumeMenu = false
|
||||||
}
|
}
|
||||||
@@ -463,7 +463,7 @@ fun TocScreen(
|
|||||||
PillHeaderDivider(title = "快速跳转")
|
PillHeaderDivider(title = "快速跳转")
|
||||||
volumeItems.forEach { uiItem ->
|
volumeItems.forEach { uiItem ->
|
||||||
RoundDropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = uiItem.title,
|
text = { Text(uiItem.title) },
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val targetIndex =
|
val targetIndex =
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import io.legado.app.databinding.DialogEditTextBinding
|
|||||||
import io.legado.app.databinding.DialogImageBlurringBinding
|
import io.legado.app.databinding.DialogImageBlurringBinding
|
||||||
import io.legado.app.help.LauncherIconHelp
|
import io.legado.app.help.LauncherIconHelp
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.config.ThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.lib.dialogs.alert
|
import io.legado.app.lib.dialogs.alert
|
||||||
import io.legado.app.lib.dialogs.selector
|
import io.legado.app.lib.dialogs.selector
|
||||||
import io.legado.app.lib.prefs.ColorPreference
|
import io.legado.app.lib.prefs.ColorPreference
|
||||||
@@ -32,7 +32,7 @@ import io.legado.app.lib.prefs.ThemeCardPreference
|
|||||||
import io.legado.app.lib.prefs.ThemeModePreference
|
import io.legado.app.lib.prefs.ThemeModePreference
|
||||||
import io.legado.app.lib.theme.ThemeStore
|
import io.legado.app.lib.theme.ThemeStore
|
||||||
import io.legado.app.lib.theme.primaryColor
|
import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.ui.theme.ThemeSyncer
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
import io.legado.app.ui.widget.number.NumberPickerDialog
|
import io.legado.app.ui.widget.number.NumberPickerDialog
|
||||||
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
|
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
|
||||||
import io.legado.app.utils.ColorUtils
|
import io.legado.app.utils.ColorUtils
|
||||||
@@ -181,13 +181,20 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PreferKey.paletteStyle, PreferKey.pureBlack, PreferKey.enableBlur, PreferKey.swipeAnimation -> {
|
PreferKey.paletteStyle, PreferKey.pureBlack, PreferKey.swipeAnimation -> {
|
||||||
ThemeSyncer.syncAll()
|
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
recreateActivities()
|
recreateActivities()
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreferKey.enableBlur -> {
|
||||||
|
ThemeConfig.enableBlur = PreferKey.enableBlur.toBoolean()
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferKey.enableProgressiveBlur -> {
|
||||||
|
ThemeConfig.enableProgressiveBlur = PreferKey.enableProgressiveBlur.toBoolean()
|
||||||
|
}
|
||||||
|
|
||||||
PreferKey.customMode -> handleRestartRequired()
|
PreferKey.customMode -> handleRestartRequired()
|
||||||
|
|
||||||
PreferKey.isPredictiveBackEnabled -> {
|
PreferKey.isPredictiveBackEnabled -> {
|
||||||
@@ -263,17 +270,15 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
|
|||||||
.setTitle(getString(R.string.container_opacity))
|
.setTitle(getString(R.string.container_opacity))
|
||||||
.setMaxValue(100)
|
.setMaxValue(100)
|
||||||
.setMinValue(0)
|
.setMinValue(0)
|
||||||
.setValue(AppConfig.containerOpacity)
|
.setValue(ThemeConfig.containerOpacity)
|
||||||
.setCustomButton((R.string.btn_default_s)) {
|
.setCustomButton((R.string.btn_default_s)) {
|
||||||
AppConfig.containerOpacity = 100
|
ThemeConfig.containerOpacity = 100
|
||||||
ThemeSyncer.syncContainerOpacity()
|
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
upPreferenceSummary(PreferKey.containerOpacity)
|
upPreferenceSummary(PreferKey.containerOpacity)
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
.show {
|
.show {
|
||||||
AppConfig.containerOpacity = it
|
ThemeConfig.containerOpacity = it
|
||||||
ThemeSyncer.syncContainerOpacity()
|
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
upPreferenceSummary(PreferKey.containerOpacity)
|
upPreferenceSummary(PreferKey.containerOpacity)
|
||||||
}, 100)
|
}, 100)
|
||||||
@@ -305,11 +310,11 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
|
|||||||
alertBinding.editView.text?.toString()?.let { themeName ->
|
alertBinding.editView.text?.toString()?.let { themeName ->
|
||||||
when (key) {
|
when (key) {
|
||||||
"saveDayTheme" -> {
|
"saveDayTheme" -> {
|
||||||
ThemeConfig.saveDayTheme(requireContext(), themeName)
|
OldThemeConfig.saveDayTheme(requireContext(), themeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
"saveNightTheme" -> {
|
"saveNightTheme" -> {
|
||||||
ThemeConfig.saveNightTheme(requireContext(), themeName)
|
OldThemeConfig.saveNightTheme(requireContext(), themeName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package io.legado.app.ui.config
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -15,11 +14,10 @@ import io.legado.app.base.adapter.ItemViewHolder
|
|||||||
import io.legado.app.base.adapter.RecyclerAdapter
|
import io.legado.app.base.adapter.RecyclerAdapter
|
||||||
import io.legado.app.databinding.DialogRecyclerViewBinding
|
import io.legado.app.databinding.DialogRecyclerViewBinding
|
||||||
import io.legado.app.databinding.ItemThemeConfigBinding
|
import io.legado.app.databinding.ItemThemeConfigBinding
|
||||||
import io.legado.app.help.config.ThemeConfig
|
import io.legado.app.help.config.OldThemeConfig
|
||||||
import io.legado.app.lib.dialogs.alert
|
import io.legado.app.lib.dialogs.alert
|
||||||
import io.legado.app.lib.theme.primaryColor
|
import io.legado.app.lib.theme.primaryColor
|
||||||
//import io.legado.app.lib.theme.primaryColor
|
//import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.ui.widget.recycler.VerticalDivider
|
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
|
|
||||||
@@ -54,14 +52,14 @@ class ThemeListDialog : BaseBottomSheetDialogFragment(R.layout.dialog_recycler_v
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun initData() {
|
fun initData() {
|
||||||
adapter.setItems(ThemeConfig.configList)
|
adapter.setItems(OldThemeConfig.configList)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||||
when (item?.itemId) {
|
when (item?.itemId) {
|
||||||
R.id.menu_import -> {
|
R.id.menu_import -> {
|
||||||
requireContext().getClipText()?.let {
|
requireContext().getClipText()?.let {
|
||||||
if (ThemeConfig.addConfig(it)) {
|
if (OldThemeConfig.addConfig(it)) {
|
||||||
initData()
|
initData()
|
||||||
} else {
|
} else {
|
||||||
toastOnUi("格式不对,添加失败")
|
toastOnUi("格式不对,添加失败")
|
||||||
@@ -75,7 +73,7 @@ class ThemeListDialog : BaseBottomSheetDialogFragment(R.layout.dialog_recycler_v
|
|||||||
fun delete(index: Int) {
|
fun delete(index: Int) {
|
||||||
alert(R.string.delete, R.string.sure_del) {
|
alert(R.string.delete, R.string.sure_del) {
|
||||||
yesButton {
|
yesButton {
|
||||||
ThemeConfig.delConfig(index)
|
OldThemeConfig.delConfig(index)
|
||||||
initData()
|
initData()
|
||||||
}
|
}
|
||||||
noButton()
|
noButton()
|
||||||
@@ -83,12 +81,12 @@ class ThemeListDialog : BaseBottomSheetDialogFragment(R.layout.dialog_recycler_v
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun share(index: Int) {
|
fun share(index: Int) {
|
||||||
val json = GSON.toJson(ThemeConfig.configList[index])
|
val json = GSON.toJson(OldThemeConfig.configList[index])
|
||||||
requireContext().share(json, "主题分享")
|
requireContext().share(json, "主题分享")
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class Adapter(context: Context) :
|
inner class Adapter(context: Context) :
|
||||||
RecyclerAdapter<ThemeConfig.Config, ItemThemeConfigBinding>(context) {
|
RecyclerAdapter<OldThemeConfig.Config, ItemThemeConfigBinding>(context) {
|
||||||
|
|
||||||
override fun getViewBinding(parent: ViewGroup): ItemThemeConfigBinding {
|
override fun getViewBinding(parent: ViewGroup): ItemThemeConfigBinding {
|
||||||
return ItemThemeConfigBinding.inflate(inflater, parent, false)
|
return ItemThemeConfigBinding.inflate(inflater, parent, false)
|
||||||
@@ -97,7 +95,7 @@ class ThemeListDialog : BaseBottomSheetDialogFragment(R.layout.dialog_recycler_v
|
|||||||
override fun convert(
|
override fun convert(
|
||||||
holder: ItemViewHolder,
|
holder: ItemViewHolder,
|
||||||
binding: ItemThemeConfigBinding,
|
binding: ItemThemeConfigBinding,
|
||||||
item: ThemeConfig.Config,
|
item: OldThemeConfig.Config,
|
||||||
payloads: MutableList<Any>
|
payloads: MutableList<Any>
|
||||||
) {
|
) {
|
||||||
binding.apply {
|
binding.apply {
|
||||||
@@ -113,7 +111,10 @@ class ThemeListDialog : BaseBottomSheetDialogFragment(R.layout.dialog_recycler_v
|
|||||||
override fun registerListener(holder: ItemViewHolder, binding: ItemThemeConfigBinding) {
|
override fun registerListener(holder: ItemViewHolder, binding: ItemThemeConfigBinding) {
|
||||||
binding.apply {
|
binding.apply {
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
ThemeConfig.applyConfig(context, ThemeConfig.configList[holder.layoutPosition])
|
OldThemeConfig.applyConfig(
|
||||||
|
context,
|
||||||
|
OldThemeConfig.configList[holder.layoutPosition]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ivShare.setOnClickListener {
|
ivShare.setOnClickListener {
|
||||||
share(holder.layoutPosition)
|
share(holder.layoutPosition)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import io.legado.app.R
|
|||||||
import io.legado.app.service.WebService
|
import io.legado.app.service.WebService
|
||||||
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
||||||
import io.legado.app.ui.widget.components.SplicedColumnGroup
|
import io.legado.app.ui.widget.components.SplicedColumnGroup
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import io.legado.app.ui.widget.components.exportComponents.FilePickerSheet
|
import io.legado.app.ui.widget.components.exportComponents.FilePickerSheet
|
||||||
import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem
|
import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem
|
||||||
import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem
|
import io.legado.app.ui.widget.components.settingItem.DropdownListSettingItem
|
||||||
@@ -89,7 +89,7 @@ fun OtherConfigScreen(
|
|||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(onClick = onBackClick)
|
TopbarNavigationButton(onClick = onBackClick)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package io.legado.app.ui.config.themeConfig
|
||||||
|
|
||||||
|
import io.legado.app.constant.PreferKey
|
||||||
|
import io.legado.app.ui.config.prefDelegate
|
||||||
|
|
||||||
|
object ThemeConfig {
|
||||||
|
|
||||||
|
var containerOpacity by prefDelegate(PreferKey.containerOpacity, 100)
|
||||||
|
|
||||||
|
var enableBlur by prefDelegate(PreferKey.enableBlur, false)
|
||||||
|
|
||||||
|
var enableProgressiveBlur by prefDelegate(PreferKey.enableProgressiveBlur, true)
|
||||||
|
|
||||||
|
var paletteStyle by prefDelegate(PreferKey.paletteStyle, "tonalSpot")
|
||||||
|
|
||||||
|
var appTheme by prefDelegate(PreferKey.appTheme, "0")
|
||||||
|
|
||||||
|
var isPureBlack by prefDelegate(PreferKey.pureBlack, false)
|
||||||
|
|
||||||
|
var bgImageLight by prefDelegate<String?>(PreferKey.bgImage, null)
|
||||||
|
|
||||||
|
var bgImageDark by prefDelegate<String?>(PreferKey.bgImageN, null)
|
||||||
|
|
||||||
|
fun hasImageBg(isDark: Boolean): Boolean {
|
||||||
|
return if (isDark) {
|
||||||
|
!bgImageDark.isNullOrEmpty()
|
||||||
|
} else {
|
||||||
|
!bgImageLight.isNullOrEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,6 +73,7 @@ import io.legado.app.ui.widget.components.importComponents.BaseImportUiState
|
|||||||
import io.legado.app.ui.widget.components.importComponents.BatchImportDialog
|
import io.legado.app.ui.widget.components.importComponents.BatchImportDialog
|
||||||
import io.legado.app.ui.widget.components.importComponents.SourceInputDialog
|
import io.legado.app.ui.widget.components.importComponents.SourceInputDialog
|
||||||
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
||||||
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||||
import io.legado.app.ui.widget.components.rules.RuleListScaffold
|
import io.legado.app.ui.widget.components.rules.RuleListScaffold
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
@@ -387,35 +388,35 @@ fun ReplaceRuleScreen(
|
|||||||
},
|
},
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
dropDownMenuContent = { dismiss ->
|
dropDownMenuContent = { dismiss ->
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("在线导入") },
|
text = { Text("在线导入") },
|
||||||
onClick = {
|
onClick = {
|
||||||
dismiss()
|
dismiss()
|
||||||
showUrlInput = true // 触发输入框
|
showUrlInput = true // 触发输入框
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("本地导入") },
|
text = { Text("本地导入") },
|
||||||
onClick = { importDoc.launch(arrayOf("text/plain", "application/json")); dismiss() }
|
onClick = { importDoc.launch(arrayOf("text/plain", "application/json")); dismiss() }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("分组管理") },
|
text = { Text("分组管理") },
|
||||||
onClick = { showGroupManageSheet = true; dismiss() }
|
onClick = { showGroupManageSheet = true; dismiss() }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("帮助") },
|
text = { Text("帮助") },
|
||||||
onClick = { /*TODO*/ dismiss() }
|
onClick = { /*TODO*/ dismiss() }
|
||||||
)
|
)
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("旧的在前") },
|
text = { Text("旧的在前") },
|
||||||
onClick = { viewModel.setSortMode("asc"); dismiss() }
|
onClick = { viewModel.setSortMode("asc"); dismiss() }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("新的在前") },
|
text = { Text("新的在前") },
|
||||||
onClick = { viewModel.setSortMode("desc"); dismiss() }
|
onClick = { viewModel.setSortMode("desc"); dismiss() }
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("名称升序") },
|
text = { Text("名称升序") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setSortMode("name_asc")
|
viewModel.setSortMode("name_asc")
|
||||||
@@ -425,7 +426,7 @@ fun ReplaceRuleScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
RoundDropdownMenuItem(
|
||||||
text = { Text("名称降序") },
|
text = { Text("名称降序") },
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setSortMode("name_desc")
|
viewModel.setSortMode("name_desc")
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.zIndex
|
import androidx.compose.ui.zIndex
|
||||||
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
||||||
import io.legado.app.ui.widget.components.button.AlertButton
|
import io.legado.app.ui.widget.components.button.AlertButton
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -121,7 +121,7 @@ fun ReplaceEditScreen(
|
|||||||
GlassMediumFlexibleTopAppBar(
|
GlassMediumFlexibleTopAppBar(
|
||||||
title = { Text(if (state.id > 0) "编辑替换规则" else "新增替换规则") },
|
title = { Text(if (state.id > 0) "编辑替换规则" else "新增替换规则") },
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(onClick = onBack)
|
TopbarNavigationButton(onClick = onBack)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import androidx.compose.material3.MotionScheme
|
|||||||
import androidx.compose.material3.Shapes
|
import androidx.compose.material3.Shapes
|
||||||
import androidx.compose.material3.Typography
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -16,18 +17,23 @@ fun AppTheme(
|
|||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val appThemeMode by ThemeState.themeMode.collectAsState()
|
val context = LocalContext.current
|
||||||
val isPureBlack by ThemeState.isPureBlack.collectAsState()
|
val appThemeMode = ThemeResolver.resolveThemeMode(ThemeConfig.appTheme)
|
||||||
val hasImageBg by ThemeState.hasImageBg.collectAsState()
|
val isPureBlack = ThemeConfig.isPureBlack
|
||||||
val paletteStyle by ThemeState.paletteStyle.collectAsState()
|
val hasImageBg = ThemeConfig.hasImageBg(darkTheme)
|
||||||
|
val paletteStyle = ThemeConfig.paletteStyle
|
||||||
|
|
||||||
val colorScheme = ThemeManager.getColorScheme(
|
val colorScheme =
|
||||||
|
remember(context, appThemeMode, darkTheme, isPureBlack, hasImageBg, paletteStyle) {
|
||||||
|
ThemeManager.getColorScheme(
|
||||||
|
context = context,
|
||||||
mode = appThemeMode,
|
mode = appThemeMode,
|
||||||
darkTheme = darkTheme,
|
darkTheme = darkTheme,
|
||||||
isAmoled = isPureBlack,
|
isAmoled = isPureBlack,
|
||||||
isImageBg = hasImageBg,
|
isImageBg = hasImageBg,
|
||||||
paletteStyle = paletteStyle
|
paletteStyle = paletteStyle
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
MaterialExpressiveTheme(
|
MaterialExpressiveTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
@@ -36,5 +42,4 @@ fun AppTheme(
|
|||||||
shapes = Shapes(),
|
shapes = Shapes(),
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,11 @@
|
|||||||
package io.legado.app.ui.theme
|
package io.legado.app.ui.theme
|
||||||
|
|
||||||
import androidx.compose.material3.ColorScheme
|
import androidx.compose.material3.ColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
|
||||||
|
|
||||||
abstract class BaseColorScheme {
|
abstract class BaseColorScheme {
|
||||||
abstract val lightScheme: ColorScheme
|
abstract val lightScheme: ColorScheme
|
||||||
abstract val darkScheme: ColorScheme
|
abstract val darkScheme: ColorScheme
|
||||||
|
|
||||||
@Composable
|
|
||||||
@ReadOnlyComposable
|
|
||||||
fun getColorScheme(darkTheme: Boolean): ColorScheme {
|
fun getColorScheme(darkTheme: Boolean): ColorScheme {
|
||||||
return if (darkTheme) darkScheme else lightScheme
|
return if (darkTheme) darkScheme else lightScheme
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package io.legado.app.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.material3.ColorScheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
|
import io.legado.app.ui.theme.ThemeManager.getColorScheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun rememberOpaqueColorScheme(): ColorScheme {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val isDark = isSystemInDarkTheme()
|
||||||
|
val appThemeMode = ThemeResolver.resolveThemeMode(ThemeConfig.appTheme)
|
||||||
|
val isPureBlack = ThemeConfig.isPureBlack
|
||||||
|
val hasImageBg = ThemeConfig.hasImageBg(isDark)
|
||||||
|
val paletteStyle = ThemeConfig.paletteStyle
|
||||||
|
|
||||||
|
return remember(context, appThemeMode, isDark, isPureBlack, hasImageBg, paletteStyle) {
|
||||||
|
getColorScheme(
|
||||||
|
context = context,
|
||||||
|
mode = appThemeMode,
|
||||||
|
darkTheme = isDark,
|
||||||
|
isAmoled = isPureBlack,
|
||||||
|
isImageBg = hasImageBg,
|
||||||
|
paletteStyle = paletteStyle,
|
||||||
|
forceOpaque = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
package io.legado.app.ui.theme
|
package io.legado.app.ui.theme
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.material3.ColorScheme
|
import androidx.compose.material3.ColorScheme
|
||||||
import androidx.compose.material3.dynamicDarkColorScheme
|
import androidx.compose.material3.dynamicDarkColorScheme
|
||||||
import androidx.compose.material3.dynamicLightColorScheme
|
import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import io.legado.app.lib.theme.primaryColor
|
import io.legado.app.lib.theme.primaryColor
|
||||||
import io.legado.app.ui.theme.ThemeResolver.resolvePaletteStyle
|
import io.legado.app.ui.theme.ThemeResolver.resolvePaletteStyle
|
||||||
import io.legado.app.ui.theme.colorScheme.AugustColorScheme
|
import io.legado.app.ui.theme.colorScheme.AugustColorScheme
|
||||||
@@ -40,16 +38,17 @@ object ThemeManager {
|
|||||||
AppThemeMode.Transparent to TransparentColorScheme,
|
AppThemeMode.Transparent to TransparentColorScheme,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun getColorScheme(
|
fun getColorScheme(
|
||||||
|
context: Context,
|
||||||
mode: AppThemeMode,
|
mode: AppThemeMode,
|
||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
darkTheme: Boolean,
|
||||||
isAmoled: Boolean,
|
isAmoled: Boolean,
|
||||||
isImageBg: Boolean,
|
isImageBg: Boolean,
|
||||||
paletteStyle: String?,
|
paletteStyle: String?,
|
||||||
forceOpaque: Boolean = false
|
forceOpaque: Boolean = false
|
||||||
): ColorScheme {
|
): ColorScheme {
|
||||||
val context = LocalContext.current
|
|
||||||
val style = resolvePaletteStyle(paletteStyle)
|
val style = resolvePaletteStyle(paletteStyle)
|
||||||
val actualMode = if (forceOpaque && mode == AppThemeMode.Transparent) {
|
val actualMode = if (forceOpaque && mode == AppThemeMode.Transparent) {
|
||||||
AppThemeMode.WH
|
AppThemeMode.WH
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
package io.legado.app.ui.theme
|
|
||||||
|
|
||||||
import io.legado.app.constant.PreferKey
|
|
||||||
import io.legado.app.help.config.AppConfig
|
|
||||||
import io.legado.app.utils.getPrefBoolean
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import splitties.init.appCtx
|
|
||||||
|
|
||||||
object ThemeState {
|
|
||||||
|
|
||||||
private val _themeMode =
|
|
||||||
MutableStateFlow(ThemeResolver.resolveThemeMode(AppConfig.AppTheme.toString()))
|
|
||||||
val themeMode: StateFlow<AppThemeMode> = _themeMode.asStateFlow()
|
|
||||||
|
|
||||||
private val _isPureBlack =
|
|
||||||
MutableStateFlow(appCtx.getPrefBoolean(PreferKey.pureBlack, false))
|
|
||||||
val isPureBlack: StateFlow<Boolean> = _isPureBlack.asStateFlow()
|
|
||||||
|
|
||||||
private val _hasImageBg =
|
|
||||||
MutableStateFlow(AppConfig.hasImageBg)
|
|
||||||
val hasImageBg: StateFlow<Boolean> = _hasImageBg.asStateFlow()
|
|
||||||
|
|
||||||
private val _paletteStyle =
|
|
||||||
MutableStateFlow(AppConfig.paletteStyle)
|
|
||||||
val paletteStyle: StateFlow<String?> = _paletteStyle.asStateFlow()
|
|
||||||
|
|
||||||
private val _enableBlur =
|
|
||||||
MutableStateFlow(AppConfig.enableBlur)
|
|
||||||
val enableBlur: StateFlow<Boolean> = _enableBlur.asStateFlow()
|
|
||||||
|
|
||||||
private val _containerOpacity =
|
|
||||||
MutableStateFlow(AppConfig.containerOpacity)
|
|
||||||
val containerOpacity: StateFlow<Int> = _containerOpacity
|
|
||||||
|
|
||||||
fun updateThemeMode(newMode: AppThemeMode) {
|
|
||||||
if (_themeMode.value != newMode) {
|
|
||||||
_themeMode.value = newMode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updatePureBlack(enabled: Boolean) {
|
|
||||||
if (_isPureBlack.value != enabled) {
|
|
||||||
_isPureBlack.value = enabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateImageBg(enabled: Boolean) {
|
|
||||||
if (_hasImageBg.value != enabled) {
|
|
||||||
_hasImageBg.value = enabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updatePaletteStyle(style: String?) {
|
|
||||||
if (_paletteStyle.value != style) {
|
|
||||||
_paletteStyle.value = style
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateEnableBlur(enabled: Boolean) {
|
|
||||||
if (_enableBlur.value != enabled) {
|
|
||||||
_enableBlur.value = enabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateContainerOpacity(opacity: Int) {
|
|
||||||
if (_containerOpacity.value != opacity) {
|
|
||||||
_containerOpacity.value = opacity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package io.legado.app.ui.theme
|
|
||||||
|
|
||||||
import io.legado.app.constant.PreferKey
|
|
||||||
import io.legado.app.help.config.AppConfig
|
|
||||||
import io.legado.app.utils.getPrefBoolean
|
|
||||||
import splitties.init.appCtx
|
|
||||||
|
|
||||||
object ThemeSyncer {
|
|
||||||
|
|
||||||
fun syncAll() {
|
|
||||||
syncThemeMode()
|
|
||||||
syncPureBlack()
|
|
||||||
syncImageBg()
|
|
||||||
syncPaletteStyle()
|
|
||||||
syncEnableBlur()
|
|
||||||
syncContainerOpacity()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun syncThemeMode() {
|
|
||||||
ThemeState.updateThemeMode(
|
|
||||||
ThemeResolver.resolveThemeMode(AppConfig.AppTheme.toString())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun syncPureBlack() {
|
|
||||||
ThemeState.updatePureBlack(appCtx.getPrefBoolean(PreferKey.pureBlack, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun syncImageBg() {
|
|
||||||
ThemeState.updateImageBg(AppConfig.hasImageBg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun syncPaletteStyle() {
|
|
||||||
ThemeState.updatePaletteStyle(AppConfig.paletteStyle)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun syncEnableBlur() {
|
|
||||||
ThemeState.updateEnableBlur(AppConfig.enableBlur)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun syncContainerOpacity() {
|
|
||||||
ThemeState.updateContainerOpacity(AppConfig.containerOpacity)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+44
-27
@@ -5,14 +5,13 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.MediumFlexibleTopAppBar
|
import androidx.compose.material3.MediumFlexibleTopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarColors
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import io.legado.app.ui.theme.ThemeState
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -22,30 +21,9 @@ fun GlassMediumFlexibleTopAppBar(
|
|||||||
subtitle: (@Composable () -> Unit)? = null,
|
subtitle: (@Composable () -> Unit)? = null,
|
||||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||||
navigationIcon: @Composable () -> Unit = {},
|
navigationIcon: @Composable () -> Unit = {},
|
||||||
actions: @Composable RowScope.() -> Unit = {}
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
|
colors: TopAppBarColors = GlassTopAppBarDefaults.glassColors()
|
||||||
) {
|
) {
|
||||||
val opacityValue by ThemeState.containerOpacity.collectAsState()
|
|
||||||
val enableBlur by ThemeState.enableBlur.collectAsState()
|
|
||||||
|
|
||||||
val alpha = opacityValue / 100f
|
|
||||||
|
|
||||||
val containerColor = if (enableBlur) {
|
|
||||||
Color.Transparent
|
|
||||||
} else {
|
|
||||||
MaterialTheme.colorScheme.surface.copy(alpha = alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
val scrolledContainerColor = if (enableBlur) {
|
|
||||||
Color.Transparent
|
|
||||||
} else {
|
|
||||||
MaterialTheme.colorScheme.surfaceContainer.copy(alpha = alpha)
|
|
||||||
}
|
|
||||||
|
|
||||||
val appBarColors = TopAppBarDefaults.topAppBarColors(
|
|
||||||
containerColor = containerColor,
|
|
||||||
scrolledContainerColor = scrolledContainerColor
|
|
||||||
)
|
|
||||||
|
|
||||||
MediumFlexibleTopAppBar(
|
MediumFlexibleTopAppBar(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
title = title,
|
title = title,
|
||||||
@@ -53,7 +31,46 @@ fun GlassMediumFlexibleTopAppBar(
|
|||||||
navigationIcon = navigationIcon,
|
navigationIcon = navigationIcon,
|
||||||
actions = actions,
|
actions = actions,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
colors = appBarColors
|
colors = colors
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
object GlassTopAppBarDefaults {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun glassColors(): TopAppBarColors {
|
||||||
|
val alpha = ThemeConfig.containerOpacity / 100f
|
||||||
|
val enableBlur = ThemeConfig.enableBlur
|
||||||
|
|
||||||
|
val containerColor = if (enableBlur) {
|
||||||
|
MaterialTheme.colorScheme.surface
|
||||||
|
} else {
|
||||||
|
MaterialTheme.colorScheme.surface.copy(alpha = alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrolledContainerColor = if (enableBlur) {
|
||||||
|
MaterialTheme.colorScheme.surface.copy(alpha = 0f)
|
||||||
|
} else {
|
||||||
|
MaterialTheme.colorScheme.surfaceContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
return TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = containerColor,
|
||||||
|
scrolledContainerColor = scrolledContainerColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun controlContainerColor(): Color {
|
||||||
|
val enableBlur = ThemeConfig.enableBlur
|
||||||
|
val baseColor = MaterialTheme.colorScheme.surfaceContainerHigh
|
||||||
|
|
||||||
|
return if (enableBlur) {
|
||||||
|
val alpha = 0.6f
|
||||||
|
baseColor.copy(alpha = alpha)
|
||||||
|
} else {
|
||||||
|
baseColor.copy(alpha = ThemeConfig.containerOpacity / 100f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+48
-9
@@ -17,31 +17,26 @@ import androidx.compose.material3.IconButtonDefaults
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedIconButton
|
import androidx.compose.material3.OutlinedIconButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.ui.theme.ThemeState
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
|
import io.legado.app.ui.widget.components.GlassTopAppBarDefaults
|
||||||
|
|
||||||
enum class TopBarButtonVariant {
|
enum class TopBarButtonVariant {
|
||||||
Filled, Outlined, Icon
|
Filled, Outlined, Icon
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SmallTopBarButton(
|
fun TopBarButton(
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
imageVector: ImageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
imageVector: ImageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
contentDescription: String? = null,
|
contentDescription: String? = null,
|
||||||
style: TopBarButtonVariant = TopBarButtonVariant.Filled
|
style: TopBarButtonVariant = TopBarButtonVariant.Filled
|
||||||
) {
|
) {
|
||||||
val themeOpacity by ThemeState.containerOpacity.collectAsState()
|
|
||||||
val baseColor = MaterialTheme.colorScheme.surfaceContainerHigh
|
|
||||||
val glassColor = baseColor.copy(alpha = (themeOpacity / 100f).coerceAtLeast(0.6f))
|
|
||||||
|
|
||||||
val commonModifier = modifier
|
val commonModifier = modifier
|
||||||
.padding(horizontal = 12.dp)
|
|
||||||
.size(36.dp)
|
.size(36.dp)
|
||||||
|
|
||||||
when (style) {
|
when (style) {
|
||||||
@@ -50,7 +45,7 @@ fun SmallTopBarButton(
|
|||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = commonModifier,
|
modifier = commonModifier,
|
||||||
colors = IconButtonDefaults.filledTonalIconButtonColors(
|
colors = IconButtonDefaults.filledTonalIconButtonColors(
|
||||||
containerColor = glassColor,
|
containerColor = GlassTopAppBarDefaults.controlContainerColor(),
|
||||||
contentColor = MaterialTheme.colorScheme.onSurface
|
contentColor = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@@ -79,6 +74,50 @@ fun SmallTopBarButton(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TopbarNavigationButton(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
imageVector: ImageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
contentDescription: String? = "返回",
|
||||||
|
style: TopBarButtonVariant = TopBarButtonVariant.Filled
|
||||||
|
) {
|
||||||
|
TopBarButton(
|
||||||
|
onClick = onClick,
|
||||||
|
imageVector = imageVector,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
modifier = modifier.padding(start = 12.dp, end = 4.dp),
|
||||||
|
style = style
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TopBarActionButton(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
imageVector: ImageVector,
|
||||||
|
contentDescription: String?,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val enableProgressive = ThemeConfig.enableProgressiveBlur
|
||||||
|
|
||||||
|
if (enableProgressive) {
|
||||||
|
TopBarButton(
|
||||||
|
onClick = onClick,
|
||||||
|
imageVector = imageVector,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
modifier = modifier.padding(end = 12.dp),
|
||||||
|
style = TopBarButtonVariant.Filled
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
IconButton(onClick = onClick) {
|
||||||
|
Icon(
|
||||||
|
imageVector = imageVector,
|
||||||
|
contentDescription = contentDescription
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SmallIcon(imageVector: ImageVector, contentDescription: String?) {
|
private fun SmallIcon(imageVector: ImageVector, contentDescription: String?) {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
@@ -7,12 +7,10 @@ import androidx.compose.material3.CardDefaults
|
|||||||
import androidx.compose.material3.CardElevation
|
import androidx.compose.material3.CardElevation
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.Shape
|
import androidx.compose.ui.graphics.Shape
|
||||||
import io.legado.app.ui.theme.ThemeState
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GlassCard(
|
fun GlassCard(
|
||||||
@@ -24,7 +22,7 @@ fun GlassCard(
|
|||||||
border: BorderStroke? = null,
|
border: BorderStroke? = null,
|
||||||
content: @Composable ColumnScope.() -> Unit
|
content: @Composable ColumnScope.() -> Unit
|
||||||
) {
|
) {
|
||||||
val opacity by ThemeState.containerOpacity.collectAsState()
|
val opacity = ThemeConfig.containerOpacity
|
||||||
val cardColors = CardDefaults.cardColors(
|
val cardColors = CardDefaults.cardColors(
|
||||||
containerColor = color.copy(alpha = opacity / 100f)
|
containerColor = color.copy(alpha = opacity / 100f)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,13 +4,21 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
|
import androidx.compose.material3.MaterialExpressiveTheme
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.MotionScheme
|
||||||
|
import androidx.compose.material3.Shapes
|
||||||
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Shape
|
import androidx.compose.ui.graphics.Shape
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.legado.app.ui.theme.rememberOpaqueColorScheme
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun RoundDropdownMenu(
|
fun RoundDropdownMenu(
|
||||||
expanded: Boolean,
|
expanded: Boolean,
|
||||||
@@ -21,12 +29,21 @@ fun RoundDropdownMenu(
|
|||||||
verticalSpacing: Dp = 8.dp,
|
verticalSpacing: Dp = 8.dp,
|
||||||
content: @Composable ColumnScope.(dismiss: () -> Unit) -> Unit
|
content: @Composable ColumnScope.(dismiss: () -> Unit) -> Unit
|
||||||
) {
|
) {
|
||||||
|
val colorScheme = rememberOpaqueColorScheme()
|
||||||
|
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
expanded = expanded,
|
expanded = expanded,
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
shape = shape,
|
shape = shape,
|
||||||
shadowElevation = shadowElevation
|
shadowElevation = shadowElevation,
|
||||||
|
containerColor = colorScheme.surfaceContainerLow
|
||||||
|
) {
|
||||||
|
MaterialExpressiveTheme(
|
||||||
|
colorScheme = colorScheme,
|
||||||
|
typography = Typography(),
|
||||||
|
motionScheme = MotionScheme.expressive(),
|
||||||
|
shapes = Shapes()
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(verticalSpacing)
|
verticalArrangement = Arrangement.spacedBy(verticalSpacing)
|
||||||
@@ -35,3 +52,4 @@ fun RoundDropdownMenu(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
+7
-5
@@ -4,26 +4,28 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.legado.app.ui.theme.rememberOpaqueColorScheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RoundDropdownMenuItem(
|
fun RoundDropdownMenuItem(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
text: String,
|
text: @Composable () -> Unit,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
trailingIcon: @Composable (() -> Unit)? = null,
|
trailingIcon: @Composable (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
|
val colorScheme = rememberOpaqueColorScheme()
|
||||||
|
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.padding(horizontal = 8.dp)
|
.padding(horizontal = 8.dp)
|
||||||
.clip(MaterialTheme.shapes.small)
|
.clip(MaterialTheme.shapes.small)
|
||||||
.background(MaterialTheme.colorScheme.surface),
|
.background(colorScheme.surface),
|
||||||
text = { Text(text) },
|
text = text,
|
||||||
trailingIcon = trailingIcon,
|
trailingIcon = trailingIcon,
|
||||||
onClick = onClick,
|
onClick = onClick
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+2
-16
@@ -15,12 +15,9 @@ import androidx.compose.material3.SheetState
|
|||||||
import androidx.compose.material3.Typography
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import io.legado.app.ui.theme.ThemeManager
|
import io.legado.app.ui.theme.rememberOpaqueColorScheme
|
||||||
import io.legado.app.ui.theme.ThemeState
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -31,18 +28,7 @@ fun GlassModalBottomSheet(
|
|||||||
containerColor: (ColorScheme) -> Color = { it.surfaceContainerLow },
|
containerColor: (ColorScheme) -> Color = { it.surfaceContainerLow },
|
||||||
content: @Composable ColumnScope.() -> Unit
|
content: @Composable ColumnScope.() -> Unit
|
||||||
) {
|
) {
|
||||||
val themeMode by ThemeState.themeMode.collectAsState()
|
val colorScheme = rememberOpaqueColorScheme()
|
||||||
val isPureBlack by ThemeState.isPureBlack.collectAsState()
|
|
||||||
val hasImageBg by ThemeState.hasImageBg.collectAsState()
|
|
||||||
val paletteStyle by ThemeState.paletteStyle.collectAsState()
|
|
||||||
|
|
||||||
val colorScheme = ThemeManager.getColorScheme(
|
|
||||||
mode = themeMode,
|
|
||||||
isAmoled = isPureBlack,
|
|
||||||
isImageBg = hasImageBg,
|
|
||||||
forceOpaque = true,
|
|
||||||
paletteStyle = paletteStyle
|
|
||||||
)
|
|
||||||
|
|
||||||
ModalBottomSheet(
|
ModalBottomSheet(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.SwipeToDismissBox
|
import androidx.compose.material3.SwipeToDismissBox
|
||||||
|
import androidx.compose.material3.SwipeToDismissBoxState
|
||||||
import androidx.compose.material3.SwipeToDismissBoxValue
|
import androidx.compose.material3.SwipeToDismissBoxValue
|
||||||
import androidx.compose.material3.contentColorFor
|
import androidx.compose.material3.contentColorFor
|
||||||
import androidx.compose.material3.rememberSwipeToDismissBoxState
|
import androidx.compose.material3.rememberSwipeToDismissBoxState
|
||||||
@@ -79,8 +80,8 @@ fun SwipeActionContainer(
|
|||||||
SwipeToDismissBoxValue.StartToEnd -> {
|
SwipeToDismissBoxValue.StartToEnd -> {
|
||||||
startAction?.let { action ->
|
startAction?.let { action ->
|
||||||
SwipeBackground(
|
SwipeBackground(
|
||||||
|
dismissState = dismissState,
|
||||||
action = action,
|
action = action,
|
||||||
progress = progress,
|
|
||||||
alignStart = true
|
alignStart = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -89,8 +90,8 @@ fun SwipeActionContainer(
|
|||||||
SwipeToDismissBoxValue.EndToStart -> {
|
SwipeToDismissBoxValue.EndToStart -> {
|
||||||
endAction?.let { action ->
|
endAction?.let { action ->
|
||||||
SwipeBackground(
|
SwipeBackground(
|
||||||
|
dismissState = dismissState,
|
||||||
action = action,
|
action = action,
|
||||||
progress = progress,
|
|
||||||
alignStart = false
|
alignStart = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -114,10 +115,13 @@ fun SwipeActionContainer(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun SwipeBackground(
|
private fun SwipeBackground(
|
||||||
action: SwipeAction,
|
action: SwipeAction,
|
||||||
progress: Float,
|
dismissState: SwipeToDismissBoxState,
|
||||||
alignStart: Boolean
|
alignStart: Boolean
|
||||||
) {
|
) {
|
||||||
val isThresholdReached = progress > 0.6f
|
val isThresholdReached = dismissState.targetValue == if (alignStart)
|
||||||
|
SwipeToDismissBoxValue.StartToEnd
|
||||||
|
else
|
||||||
|
SwipeToDismissBoxValue.EndToStart
|
||||||
|
|
||||||
val backgroundColor by animateColorAsState(
|
val backgroundColor by animateColorAsState(
|
||||||
targetValue = if (isThresholdReached)
|
targetValue = if (isThresholdReached)
|
||||||
@@ -128,8 +132,8 @@ private fun SwipeBackground(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val iconScale by animateFloatAsState(
|
val iconScale by animateFloatAsState(
|
||||||
targetValue = if (isThresholdReached) 1.3f
|
targetValue = if (isThresholdReached) 1.2f
|
||||||
else progress.coerceIn(0.5f, 1f),
|
else 1f,
|
||||||
label = "iconScale"
|
label = "iconScale"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import io.legado.app.ui.widget.components.AdaptiveAnimatedText
|
|||||||
import io.legado.app.ui.widget.components.AnimatedTextLine
|
import io.legado.app.ui.widget.components.AnimatedTextLine
|
||||||
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
import io.legado.app.ui.widget.components.GlassMediumFlexibleTopAppBar
|
||||||
import io.legado.app.ui.widget.components.SearchBarSection
|
import io.legado.app.ui.widget.components.SearchBarSection
|
||||||
import io.legado.app.ui.widget.components.button.SmallTopBarButton
|
import io.legado.app.ui.widget.components.button.TopbarNavigationButton
|
||||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||||
import io.legado.app.ui.widget.components.rules.RuleActionState
|
import io.legado.app.ui.widget.components.rules.RuleActionState
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ fun <T> DynamicTopAppBar(
|
|||||||
{ AnimatedTextLine(text = it) }
|
{ AnimatedTextLine(text = it) }
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
SmallTopBarButton(
|
TopbarNavigationButton(
|
||||||
onClick = { if (isSelecting) onClearSelection() else onBackClick() },
|
onClick = { if (isSelecting) onClearSelection() else onBackClick() },
|
||||||
imageVector = if (isSelecting) Icons.Default.Close else Icons.AutoMirrored.Filled.ArrowBack,
|
imageVector = if (isSelecting) Icons.Default.Close else Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
contentDescription = if (isSelecting) "取消选择" else "返回"
|
contentDescription = if (isSelecting) "取消选择" else "返回"
|
||||||
|
|||||||
@@ -1386,4 +1386,5 @@
|
|||||||
<string name="show_swipe_animation">启用滑动时动画</string>
|
<string name="show_swipe_animation">启用滑动时动画</string>
|
||||||
<string name="click_image_way">点击图片行为</string>
|
<string name="click_image_way">点击图片行为</string>
|
||||||
<string name="show_web_log">输出日志</string>
|
<string name="show_web_log">输出日志</string>
|
||||||
|
<string name="is_blur_progressive_enable">启用渐变模糊</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1390,4 +1390,5 @@
|
|||||||
<string name="show_swipe_animation">启用滑动时动画</string>
|
<string name="show_swipe_animation">启用滑动时动画</string>
|
||||||
<string name="click_image_way">点击图片行为</string>
|
<string name="click_image_way">点击图片行为</string>
|
||||||
<string name="show_web_log">输出日志</string>
|
<string name="show_web_log">输出日志</string>
|
||||||
|
<string name="is_blur_progressive_enable">启用渐变模糊</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -116,6 +116,12 @@
|
|||||||
android:title="@string/is_blur_enable"
|
android:title="@string/is_blur_enable"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<io.legado.app.lib.prefs.SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="enableProgressiveBlur"
|
||||||
|
android:title="@string/is_blur_progressive_enable"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
</io.legado.app.lib.prefs.PreferenceCategory>
|
</io.legado.app.lib.prefs.PreferenceCategory>
|
||||||
|
|
||||||
<io.legado.app.lib.prefs.PreferenceCategory
|
<io.legado.app.lib.prefs.PreferenceCategory
|
||||||
|
|||||||
Reference in new issue
Block a user