|
|
@@ -1,20 +1,16 @@
|
|
|
package io.legado.app.help.config
|
|
|
|
|
|
-import android.content.Context
|
|
|
-import android.net.Uri
|
|
|
import androidx.annotation.Keep
|
|
|
-import com.google.gson.GsonBuilder
|
|
|
import com.google.gson.JsonObject
|
|
|
import com.google.gson.JsonParser
|
|
|
import com.google.gson.reflect.TypeToken
|
|
|
-import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
|
|
|
-import io.legado.app.ui.config.coverConfig.CoverConfig
|
|
|
-import io.legado.app.ui.config.themeConfig.ThemeConfig
|
|
|
+import io.legado.app.domain.model.settings.ThemeExportData
|
|
|
import io.legado.app.utils.EncoderUtils
|
|
|
import io.legado.app.utils.GSON
|
|
|
import splitties.init.appCtx
|
|
|
import java.io.File
|
|
|
import java.io.FileOutputStream
|
|
|
+import java.util.UUID
|
|
|
|
|
|
/**
|
|
|
* 轻量级主题导入导出系统
|
|
|
@@ -23,148 +19,23 @@ import java.io.FileOutputStream
|
|
|
*/
|
|
|
object ThemeImportExport {
|
|
|
|
|
|
- private val EXPORT_GSON = GsonBuilder()
|
|
|
- .setPrettyPrinting()
|
|
|
- .disableHtmlEscaping()
|
|
|
- .create()
|
|
|
-
|
|
|
- /**
|
|
|
- * 从当前配置创建导出数据
|
|
|
- */
|
|
|
- fun exportFromCurrent(includeEmbeddedAssets: Boolean = true): ThemeExportData {
|
|
|
- return ThemeExportData(
|
|
|
- // 基础主题设置
|
|
|
- appTheme = ThemeConfig.appTheme,
|
|
|
- themeMode = ThemeConfig.themeMode,
|
|
|
- isPureBlack = ThemeConfig.isPureBlack,
|
|
|
- composeEngine = ThemeConfig.composeEngine,
|
|
|
- paletteStyle = ThemeConfig.paletteStyle,
|
|
|
- materialVersion = ThemeConfig.materialVersion,
|
|
|
- customMode = ThemeConfig.customMode,
|
|
|
- customContrast = ThemeConfig.customContrast,
|
|
|
- launcherIcon = ThemeConfig.launcherIcon,
|
|
|
- isPredictiveBackEnabled = ThemeConfig.isPredictiveBackEnabled,
|
|
|
- fontScale = ThemeConfig.fontScale,
|
|
|
-
|
|
|
- // 深度个性化颜色
|
|
|
- enableDeepPersonalization = ThemeConfig.enableDeepPersonalization,
|
|
|
- cPrimary = ThemeConfig.cPrimary,
|
|
|
- cNPrimary = ThemeConfig.cNPrimary,
|
|
|
- themeColor = ThemeConfig.themeColor,
|
|
|
- secondaryThemeColor = ThemeConfig.secondaryThemeColor,
|
|
|
- primaryTextColor = ThemeConfig.primaryTextColor,
|
|
|
- secondaryTextColor = ThemeConfig.secondaryTextColor,
|
|
|
- themeBackgroundColor = ThemeConfig.themeBackgroundColor,
|
|
|
- labelContainerColor = ThemeConfig.labelContainerColor,
|
|
|
- themeColorNight = ThemeConfig.themeColorNight,
|
|
|
- secondaryThemeColorNight = ThemeConfig.secondaryThemeColorNight,
|
|
|
- primaryTextColorNight = ThemeConfig.primaryTextColorNight,
|
|
|
- secondaryTextColorNight = ThemeConfig.secondaryTextColorNight,
|
|
|
- themeBackgroundColorNight = ThemeConfig.themeBackgroundColorNight,
|
|
|
- labelContainerColorNight = ThemeConfig.labelContainerColorNight,
|
|
|
- bookInfoInputColor = ThemeConfig.bookInfoInputColor,
|
|
|
- bookInfoFollowCoverColor = ThemeConfig.bookInfoFollowCoverColor,
|
|
|
- bookInfoBackgroundBlur = ThemeConfig.bookInfoBackgroundBlur,
|
|
|
- bookInfoNetworkCoverBackground = ThemeConfig.bookInfoNetworkCoverBackground,
|
|
|
- bookInfoDefaultCoverBackground = ThemeConfig.bookInfoDefaultCoverBackground,
|
|
|
-
|
|
|
- // 容器设置
|
|
|
- containerOpacity = ThemeConfig.containerOpacity,
|
|
|
-
|
|
|
- // 分割线设置
|
|
|
- enableItemDivider = ThemeConfig.enableItemDivider,
|
|
|
- itemDividerWidth = ThemeConfig.itemDividerWidth,
|
|
|
- itemDividerLength = ThemeConfig.itemDividerLength,
|
|
|
- itemDividerColor = ThemeConfig.itemDividerColor,
|
|
|
-
|
|
|
- // 模糊设置
|
|
|
- enableBlur = ThemeConfig.enableBlur,
|
|
|
- enableProgressiveBlur = ThemeConfig.enableProgressiveBlur,
|
|
|
- topBarBlurRadius = ThemeConfig.topBarBlurRadius,
|
|
|
- bottomBarBlurRadius = ThemeConfig.bottomBarBlurRadius,
|
|
|
- topBarBlurAlpha = ThemeConfig.topBarBlurAlpha,
|
|
|
- bottomBarBlurAlpha = ThemeConfig.bottomBarBlurAlpha,
|
|
|
- bottomBarLensRadius = ThemeConfig.bottomBarLensRadius,
|
|
|
-
|
|
|
- // 透明度设置
|
|
|
- topBarOpacity = ThemeConfig.topBarOpacity,
|
|
|
- bottomBarOpacity = ThemeConfig.bottomBarOpacity,
|
|
|
-
|
|
|
- // 标签颜色
|
|
|
- enableCustomTagColors = ThemeConfig.enableCustomTagColors,
|
|
|
- customTagColorsJson = ThemeConfig.customTagColorsJson,
|
|
|
-
|
|
|
- // 书架卡片颜色
|
|
|
- bookshelfCardColor = BookshelfConfig.bookshelfCardColor,
|
|
|
- bookshelfCardColorDark = BookshelfConfig.bookshelfCardColorDark,
|
|
|
-
|
|
|
- // 主界面设置
|
|
|
- showHome = ThemeConfig.showHome,
|
|
|
- showDiscovery = ThemeConfig.showDiscovery,
|
|
|
- showRss = ThemeConfig.showRss,
|
|
|
- showStatusBar = ThemeConfig.showStatusBar,
|
|
|
- swipeAnimation = ThemeConfig.swipeAnimation,
|
|
|
- showBottomView = ThemeConfig.showBottomView,
|
|
|
- useFloatingBottomBar = ThemeConfig.useFloatingBottomBar,
|
|
|
- useFloatingBottomBarLiquidGlass = ThemeConfig.useFloatingBottomBarLiquidGlass,
|
|
|
- tabletInterface = ThemeConfig.tabletInterface,
|
|
|
- labelVisibilityMode = ThemeConfig.labelVisibilityMode,
|
|
|
- defaultHomePage = ThemeConfig.defaultHomePage,
|
|
|
- mainNavigationOrder = ThemeConfig.mainNavigationOrder,
|
|
|
-
|
|
|
- // 导航栏图标
|
|
|
- navIconHome = ThemeConfig.navIconHome,
|
|
|
- navIconBookshelf = ThemeConfig.navIconBookshelf,
|
|
|
- navIconExplore = ThemeConfig.navIconExplore,
|
|
|
- navIconRss = ThemeConfig.navIconRss,
|
|
|
- navIconMy = ThemeConfig.navIconMy,
|
|
|
-
|
|
|
- // Miuix 设置
|
|
|
- useMiuixMonet = ThemeConfig.useMiuixMonet,
|
|
|
-
|
|
|
- // 其他
|
|
|
- useFlexibleTopAppBar = ThemeConfig.useFlexibleTopAppBar,
|
|
|
- bgImageLight = ThemeConfig.bgImageLight,
|
|
|
- bgImageDark = ThemeConfig.bgImageDark,
|
|
|
- bgImageBlurring = ThemeConfig.bgImageBlurring,
|
|
|
- bgImageNBlurring = ThemeConfig.bgImageNBlurring,
|
|
|
- appFontPath = ThemeConfig.appFontPath,
|
|
|
-
|
|
|
- // 封面配置 (CoverConfig)
|
|
|
- coverLoadOnlyWifi = CoverConfig.loadCoverOnlyWifi,
|
|
|
- coverUseDefault = CoverConfig.useDefaultCover,
|
|
|
- coverShowShadow = CoverConfig.coverShowShadow,
|
|
|
- coverShowStroke = CoverConfig.coverShowStroke,
|
|
|
- coverDefaultColor = CoverConfig.coverDefaultColor,
|
|
|
- coverDefaultImage = CoverConfig.defaultCover,
|
|
|
- coverTextColor = CoverConfig.coverTextColor,
|
|
|
- coverShadowColor = CoverConfig.coverShadowColor,
|
|
|
- coverShowName = CoverConfig.coverShowName,
|
|
|
- coverShowAuthor = CoverConfig.coverShowAuthor,
|
|
|
- coverDefaultImageDark = CoverConfig.defaultCoverDark,
|
|
|
- coverTextColorN = CoverConfig.coverTextColorN,
|
|
|
- coverShadowColorN = CoverConfig.coverShadowColorN,
|
|
|
- coverShowNameN = CoverConfig.coverShowNameN,
|
|
|
- coverShowAuthorN = CoverConfig.coverShowAuthorN,
|
|
|
- coverInfoOrientation = CoverConfig.coverInfoOrientation,
|
|
|
- assets = if (includeEmbeddedAssets) exportAssets() else null
|
|
|
- )
|
|
|
- }
|
|
|
+ internal fun withEmbeddedAssets(data: ThemeExportData): ThemeExportData =
|
|
|
+ data.copy(assets = exportAssets(data))
|
|
|
|
|
|
/**
|
|
|
* 将相关的图片、字体资源转换为Base64
|
|
|
*/
|
|
|
- private fun exportAssets(): Map<String, String> {
|
|
|
+ private fun exportAssets(data: ThemeExportData): Map<String, String> {
|
|
|
val assets = mutableMapOf<String, String>()
|
|
|
val assetPaths = mapOf(
|
|
|
- "bgImageLight" to ThemeConfig.bgImageLight,
|
|
|
- "bgImageDark" to ThemeConfig.bgImageDark,
|
|
|
- "navIconHome" to ThemeConfig.navIconHome,
|
|
|
- "navIconBookshelf" to ThemeConfig.navIconBookshelf,
|
|
|
- "navIconExplore" to ThemeConfig.navIconExplore,
|
|
|
- "navIconRss" to ThemeConfig.navIconRss,
|
|
|
- "navIconMy" to ThemeConfig.navIconMy,
|
|
|
- "appFontPath" to ThemeConfig.appFontPath
|
|
|
+ "bgImageLight" to data.bgImageLight,
|
|
|
+ "bgImageDark" to data.bgImageDark,
|
|
|
+ "navIconHome" to data.navIconHome,
|
|
|
+ "navIconBookshelf" to data.navIconBookshelf,
|
|
|
+ "navIconExplore" to data.navIconExplore,
|
|
|
+ "navIconRss" to data.navIconRss,
|
|
|
+ "navIconMy" to data.navIconMy,
|
|
|
+ "appFontPath" to data.appFontPath,
|
|
|
)
|
|
|
|
|
|
assetPaths.forEach { (key, path) ->
|
|
|
@@ -185,8 +56,8 @@ object ThemeImportExport {
|
|
|
}
|
|
|
|
|
|
// 处理封面图集(可能包含多个逗号分隔的路径)
|
|
|
- exportCoverAssets(assets, "coverDefaultImage", CoverConfig.defaultCover)
|
|
|
- exportCoverAssets(assets, "coverDefaultImageDark", CoverConfig.defaultCoverDark)
|
|
|
+ exportCoverAssets(assets, "coverDefaultImage", data.coverDefaultImage)
|
|
|
+ exportCoverAssets(assets, "coverDefaultImageDark", data.coverDefaultImageDark)
|
|
|
|
|
|
return assets
|
|
|
}
|
|
|
@@ -214,144 +85,42 @@ object ThemeImportExport {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 将导出数据应用到当前配置
|
|
|
- */
|
|
|
- internal fun applyToThemeConfig(
|
|
|
+ internal fun prepareForApply(
|
|
|
data: ThemeExportData,
|
|
|
applyEmbeddedCoverAssets: Boolean = true,
|
|
|
- ): AppliedThemeAssets {
|
|
|
- // 基础主题设置
|
|
|
- ThemeConfig.appTheme = data.appTheme
|
|
|
- ThemeConfig.themeMode = data.themeMode
|
|
|
- ThemeConfig.isPureBlack = data.isPureBlack
|
|
|
- ThemeConfig.composeEngine = data.composeEngine
|
|
|
- ThemeConfig.paletteStyle = data.paletteStyle
|
|
|
- ThemeConfig.materialVersion = data.materialVersion
|
|
|
- ThemeConfig.customMode = data.customMode
|
|
|
- ThemeConfig.customContrast = data.customContrast
|
|
|
- ThemeConfig.launcherIcon = data.launcherIcon
|
|
|
- ThemeConfig.isPredictiveBackEnabled = data.isPredictiveBackEnabled
|
|
|
- ThemeConfig.fontScale = data.fontScale
|
|
|
-
|
|
|
- // 深度个性化颜色
|
|
|
- ThemeConfig.enableDeepPersonalization = data.enableDeepPersonalization
|
|
|
- ThemeConfig.cPrimary = data.cPrimary
|
|
|
- ThemeConfig.cNPrimary = data.cNPrimary
|
|
|
- ThemeConfig.themeColor = data.themeColor
|
|
|
- ThemeConfig.secondaryThemeColor = data.secondaryThemeColor
|
|
|
- ThemeConfig.primaryTextColor = data.primaryTextColor
|
|
|
- ThemeConfig.secondaryTextColor = data.secondaryTextColor
|
|
|
- ThemeConfig.themeBackgroundColor = data.themeBackgroundColor
|
|
|
- ThemeConfig.labelContainerColor = data.labelContainerColor
|
|
|
- ThemeConfig.themeColorNight = data.themeColorNight
|
|
|
- ThemeConfig.secondaryThemeColorNight = data.secondaryThemeColorNight
|
|
|
- ThemeConfig.primaryTextColorNight = data.primaryTextColorNight
|
|
|
- ThemeConfig.secondaryTextColorNight = data.secondaryTextColorNight
|
|
|
- ThemeConfig.themeBackgroundColorNight = data.themeBackgroundColorNight
|
|
|
- ThemeConfig.labelContainerColorNight = data.labelContainerColorNight
|
|
|
- ThemeConfig.bookInfoInputColor = data.bookInfoInputColor
|
|
|
- ThemeConfig.bookInfoFollowCoverColor = data.bookInfoFollowCoverColor
|
|
|
- ThemeConfig.bookInfoBackgroundBlur = data.bookInfoBackgroundBlur
|
|
|
- ThemeConfig.bookInfoNetworkCoverBackground =
|
|
|
- data.bookInfoNetworkCoverBackground ?: data.bookInfoBackgroundBlur
|
|
|
- ThemeConfig.bookInfoDefaultCoverBackground =
|
|
|
- data.bookInfoDefaultCoverBackground ?: data.bookInfoBackgroundBlur
|
|
|
-
|
|
|
- // 容器设置
|
|
|
- ThemeConfig.containerOpacity = data.containerOpacity
|
|
|
-
|
|
|
- // 分割线设置
|
|
|
- ThemeConfig.enableItemDivider = data.enableItemDivider
|
|
|
- ThemeConfig.itemDividerWidth = data.itemDividerWidth
|
|
|
- ThemeConfig.itemDividerLength = data.itemDividerLength
|
|
|
- ThemeConfig.itemDividerColor = data.itemDividerColor
|
|
|
-
|
|
|
- // 模糊设置
|
|
|
- ThemeConfig.enableBlur = data.enableBlur
|
|
|
- ThemeConfig.enableProgressiveBlur = data.enableProgressiveBlur
|
|
|
- ThemeConfig.topBarBlurRadius = data.topBarBlurRadius
|
|
|
- ThemeConfig.bottomBarBlurRadius = data.bottomBarBlurRadius
|
|
|
- ThemeConfig.topBarBlurAlpha = data.topBarBlurAlpha
|
|
|
- ThemeConfig.bottomBarBlurAlpha = data.bottomBarBlurAlpha
|
|
|
- ThemeConfig.bottomBarLensRadius = data.bottomBarLensRadius
|
|
|
-
|
|
|
- // 透明度设置
|
|
|
- ThemeConfig.topBarOpacity = data.topBarOpacity
|
|
|
- ThemeConfig.bottomBarOpacity = data.bottomBarOpacity
|
|
|
-
|
|
|
- // 标签颜色
|
|
|
- ThemeConfig.enableCustomTagColors = data.enableCustomTagColors
|
|
|
- ThemeConfig.customTagColorsJson = data.customTagColorsJson
|
|
|
-
|
|
|
- // 书架卡片颜色
|
|
|
- BookshelfConfig.bookshelfCardColor = data.bookshelfCardColor
|
|
|
- BookshelfConfig.bookshelfCardColorDark = data.bookshelfCardColorDark
|
|
|
-
|
|
|
- // 主界面设置
|
|
|
- ThemeConfig.showHome = data.showHome
|
|
|
- ThemeConfig.showDiscovery = data.showDiscovery
|
|
|
- ThemeConfig.showRss = data.showRss
|
|
|
- ThemeConfig.showStatusBar = data.showStatusBar
|
|
|
- ThemeConfig.swipeAnimation = data.swipeAnimation
|
|
|
- ThemeConfig.showBottomView = data.showBottomView
|
|
|
- ThemeConfig.useFloatingBottomBar = data.useFloatingBottomBar
|
|
|
- ThemeConfig.useFloatingBottomBarLiquidGlass = data.useFloatingBottomBarLiquidGlass
|
|
|
- ThemeConfig.tabletInterface = data.tabletInterface
|
|
|
- ThemeConfig.labelVisibilityMode = data.labelVisibilityMode
|
|
|
- ThemeConfig.defaultHomePage = data.defaultHomePage
|
|
|
- ThemeConfig.mainNavigationOrder = data.mainNavigationOrder
|
|
|
-
|
|
|
- // 导航栏图标
|
|
|
- ThemeConfig.navIconHome = data.navIconHome
|
|
|
- ThemeConfig.navIconBookshelf = data.navIconBookshelf
|
|
|
- ThemeConfig.navIconExplore = data.navIconExplore
|
|
|
- ThemeConfig.navIconRss = data.navIconRss
|
|
|
- ThemeConfig.navIconMy = data.navIconMy
|
|
|
-
|
|
|
- // Miuix 设置
|
|
|
- ThemeConfig.useMiuixMonet = data.useMiuixMonet
|
|
|
-
|
|
|
- // 其他
|
|
|
- ThemeConfig.useFlexibleTopAppBar = data.useFlexibleTopAppBar
|
|
|
- ThemeConfig.bgImageLight = data.bgImageLight
|
|
|
- ThemeConfig.bgImageDark = data.bgImageDark
|
|
|
- ThemeConfig.bgImageBlurring = data.bgImageBlurring
|
|
|
- ThemeConfig.bgImageNBlurring = data.bgImageNBlurring
|
|
|
- ThemeConfig.appFontPath = data.appFontPath
|
|
|
-
|
|
|
- // 封面配置 (CoverConfig)
|
|
|
- CoverConfig.loadCoverOnlyWifi = data.coverLoadOnlyWifi
|
|
|
- CoverConfig.useDefaultCover = data.coverUseDefault
|
|
|
- CoverConfig.coverShowShadow = data.coverShowShadow
|
|
|
- CoverConfig.coverShowStroke = data.coverShowStroke
|
|
|
- CoverConfig.coverDefaultColor = data.coverDefaultColor
|
|
|
- CoverConfig.defaultCover = data.coverDefaultImage
|
|
|
- CoverConfig.coverTextColor = data.coverTextColor
|
|
|
- CoverConfig.coverShadowColor = data.coverShadowColor
|
|
|
- CoverConfig.coverShowName = data.coverShowName
|
|
|
- CoverConfig.coverShowAuthor = data.coverShowAuthor
|
|
|
- CoverConfig.defaultCoverDark = data.coverDefaultImageDark
|
|
|
- CoverConfig.coverTextColorN = data.coverTextColorN
|
|
|
- CoverConfig.coverShadowColorN = data.coverShadowColorN
|
|
|
- CoverConfig.coverShowNameN = data.coverShowNameN
|
|
|
- CoverConfig.coverShowAuthorN = data.coverShowAuthorN
|
|
|
- CoverConfig.coverInfoOrientation = data.coverInfoOrientation
|
|
|
-
|
|
|
- // 应用嵌入的资源
|
|
|
+ ): PreparedTheme {
|
|
|
val embeddedAssets = data.assets?.let { assets ->
|
|
|
applyAssets(
|
|
|
assets = assets,
|
|
|
applyCoverAssets = applyEmbeddedCoverAssets,
|
|
|
)
|
|
|
} ?: AppliedThemeAssets()
|
|
|
- return AppliedThemeAssets(
|
|
|
+ val appliedAssets = AppliedThemeAssets(
|
|
|
lightCoverPaths = embeddedAssets.lightCoverPaths.ifEmpty {
|
|
|
data.coverDefaultImage.toCoverPaths()
|
|
|
},
|
|
|
darkCoverPaths = embeddedAssets.darkCoverPaths.ifEmpty {
|
|
|
data.coverDefaultImageDark.toCoverPaths()
|
|
|
},
|
|
|
+ paths = embeddedAssets.paths,
|
|
|
+ createdFiles = embeddedAssets.createdFiles,
|
|
|
+ )
|
|
|
+ return PreparedTheme(
|
|
|
+ data = data.copy(
|
|
|
+ bgImageLight = embeddedAssets.paths["bgImageLight"] ?: data.bgImageLight,
|
|
|
+ bgImageDark = embeddedAssets.paths["bgImageDark"] ?: data.bgImageDark,
|
|
|
+ navIconHome = embeddedAssets.paths["navIconHome"] ?: data.navIconHome,
|
|
|
+ navIconBookshelf = embeddedAssets.paths["navIconBookshelf"]
|
|
|
+ ?: data.navIconBookshelf,
|
|
|
+ navIconExplore = embeddedAssets.paths["navIconExplore"] ?: data.navIconExplore,
|
|
|
+ navIconRss = embeddedAssets.paths["navIconRss"] ?: data.navIconRss,
|
|
|
+ navIconMy = embeddedAssets.paths["navIconMy"] ?: data.navIconMy,
|
|
|
+ appFontPath = embeddedAssets.paths["appFontPath"] ?: data.appFontPath,
|
|
|
+ coverDefaultImage = appliedAssets.lightCoverPaths.joinToString(","),
|
|
|
+ coverDefaultImageDark = appliedAssets.darkCoverPaths.joinToString(","),
|
|
|
+ assets = null,
|
|
|
+ ),
|
|
|
+ appliedAssets = appliedAssets,
|
|
|
)
|
|
|
}
|
|
|
|
|
|
@@ -360,6 +129,8 @@ object ThemeImportExport {
|
|
|
applyCoverAssets: Boolean,
|
|
|
): AppliedThemeAssets {
|
|
|
val coverPaths = mutableMapOf<String, MutableList<String>>()
|
|
|
+ val paths = mutableMapOf<String, String>()
|
|
|
+ val createdFiles = mutableListOf<File>()
|
|
|
|
|
|
assets.forEach { (key, base64) ->
|
|
|
if (base64.isBlank()) return@forEach
|
|
|
@@ -371,44 +142,39 @@ object ThemeImportExport {
|
|
|
val baseDir = appCtx.getExternalFilesDir(null) ?: appCtx.filesDir
|
|
|
val folder = File(baseDir, key)
|
|
|
folder.mkdirs()
|
|
|
- File(folder, "theme_asset_${System.currentTimeMillis()}.jpg")
|
|
|
+ File(folder, "theme_asset_${UUID.randomUUID()}.jpg")
|
|
|
}
|
|
|
|
|
|
key.startsWith("navIcon") -> {
|
|
|
val folder = File(appCtx.filesDir, "nav_icons")
|
|
|
folder.mkdirs()
|
|
|
- File(folder, "${key.removePrefix("navIcon").lowercase()}.png")
|
|
|
+ File(
|
|
|
+ folder,
|
|
|
+ "theme_${key.removePrefix("navIcon").lowercase()}_${UUID.randomUUID()}.png",
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
key == "appFontPath" -> {
|
|
|
val folder = File(appCtx.filesDir, "fonts")
|
|
|
folder.mkdirs()
|
|
|
- File(folder, "theme_font.ttf")
|
|
|
+ File(folder, "theme_font_${UUID.randomUUID()}.ttf")
|
|
|
}
|
|
|
|
|
|
key.startsWith("coverDefaultImage") -> {
|
|
|
val baseDir = appCtx.getExternalFilesDir(null) ?: appCtx.filesDir
|
|
|
val folder = File(baseDir, "covers")
|
|
|
folder.mkdirs()
|
|
|
- File(folder, "${key}_${System.currentTimeMillis()}.jpg")
|
|
|
+ File(folder, "${key}_${UUID.randomUUID()}.jpg")
|
|
|
}
|
|
|
|
|
|
else -> null
|
|
|
}
|
|
|
|
|
|
destFile?.let { file ->
|
|
|
+ createdFiles += file
|
|
|
FileOutputStream(file).use { it.write(bytes) }
|
|
|
val path = file.absolutePath
|
|
|
- when {
|
|
|
- key == "bgImageLight" -> ThemeConfig.bgImageLight = path
|
|
|
- key == "bgImageDark" -> ThemeConfig.bgImageDark = path
|
|
|
- key == "navIconHome" -> ThemeConfig.navIconHome = path
|
|
|
- key == "navIconBookshelf" -> ThemeConfig.navIconBookshelf = path
|
|
|
- key == "navIconExplore" -> ThemeConfig.navIconExplore = path
|
|
|
- key == "navIconRss" -> ThemeConfig.navIconRss = path
|
|
|
- key == "navIconMy" -> ThemeConfig.navIconMy = path
|
|
|
- key == "appFontPath" -> ThemeConfig.appFontPath = path
|
|
|
- key.startsWith("coverDefaultImage") -> {
|
|
|
+ if (key.startsWith("coverDefaultImage")) {
|
|
|
// 判断是日间还是夜间封面
|
|
|
val baseKey = if (key.removePrefix("coverDefaultImage").startsWith("Dark")) {
|
|
|
"coverDefaultImageDark"
|
|
|
@@ -416,7 +182,8 @@ object ThemeImportExport {
|
|
|
"coverDefaultImage"
|
|
|
}
|
|
|
coverPaths.getOrPut(baseKey) { mutableListOf() }.add(path)
|
|
|
- }
|
|
|
+ } else {
|
|
|
+ paths[key] = path
|
|
|
}
|
|
|
}
|
|
|
} catch (e: Exception) {
|
|
|
@@ -424,38 +191,18 @@ object ThemeImportExport {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 将收集到的封面路径合并为逗号分隔的字符串
|
|
|
- coverPaths["coverDefaultImage"]?.let { paths ->
|
|
|
- CoverConfig.defaultCover = paths.joinToString(",")
|
|
|
- }
|
|
|
- coverPaths["coverDefaultImageDark"]?.let { paths ->
|
|
|
- CoverConfig.defaultCoverDark = paths.joinToString(",")
|
|
|
- }
|
|
|
return AppliedThemeAssets(
|
|
|
lightCoverPaths = coverPaths["coverDefaultImage"].orEmpty(),
|
|
|
darkCoverPaths = coverPaths["coverDefaultImageDark"].orEmpty(),
|
|
|
+ paths = paths,
|
|
|
+ createdFiles = createdFiles,
|
|
|
)
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 导出主题到JSON字符串
|
|
|
- */
|
|
|
- fun exportToJson(): String {
|
|
|
- val data = exportFromCurrent()
|
|
|
- return EXPORT_GSON.toJson(data)
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 从JSON字符串导入主题
|
|
|
- */
|
|
|
- fun importFromJson(json: String): Boolean {
|
|
|
- return importFromJsonWithAssets(json) != null
|
|
|
- }
|
|
|
-
|
|
|
- internal fun importFromJsonWithAssets(json: String): AppliedThemeAssets? {
|
|
|
+ internal fun prepareLegacyJson(json: String): PreparedTheme? {
|
|
|
return try {
|
|
|
val data = parseThemeData(json) ?: return null
|
|
|
- applyToThemeConfig(data)
|
|
|
+ prepareForApply(data)
|
|
|
} catch (e: Exception) {
|
|
|
e.printStackTrace()
|
|
|
null
|
|
|
@@ -584,163 +331,8 @@ object ThemeImportExport {
|
|
|
private fun JsonObject.float(key: String, default: Float = 0f): Float =
|
|
|
get(key)?.takeUnless { it.isJsonNull }?.asFloat ?: default
|
|
|
|
|
|
- /**
|
|
|
- * 从文件URI导入主题
|
|
|
- */
|
|
|
- fun importFromUri(context: Context, uri: Uri): Boolean {
|
|
|
- return try {
|
|
|
- val json = context.contentResolver.openInputStream(uri)?.use {
|
|
|
- it.bufferedReader().readText()
|
|
|
- } ?: return false
|
|
|
- importFromJson(json)
|
|
|
- } catch (e: Exception) {
|
|
|
- e.printStackTrace()
|
|
|
- false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 导出主题到文件
|
|
|
- */
|
|
|
- fun exportToFile(context: Context, uri: Uri): Boolean {
|
|
|
- return try {
|
|
|
- val json = exportToJson()
|
|
|
- context.contentResolver.openOutputStream(uri)?.use {
|
|
|
- it.write(json.toByteArray())
|
|
|
- }
|
|
|
- true
|
|
|
- } catch (e: Exception) {
|
|
|
- e.printStackTrace()
|
|
|
- false
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 主题导出数据类
|
|
|
- */
|
|
|
-@Keep
|
|
|
-data class ThemeExportData(
|
|
|
- // 基础主题设置
|
|
|
- val appTheme: String = "0",
|
|
|
- val themeMode: String = "0",
|
|
|
- val isPureBlack: Boolean = false,
|
|
|
- val composeEngine: String = "material",
|
|
|
- val paletteStyle: String = "tonalSpot",
|
|
|
- val materialVersion: String = "material3",
|
|
|
- val customMode: String? = "tonalSpot",
|
|
|
- val customContrast: String = "Default",
|
|
|
- val launcherIcon: String = "ic_launcher",
|
|
|
- val isPredictiveBackEnabled: Boolean = true,
|
|
|
- val fontScale: Int = 10,
|
|
|
-
|
|
|
- // 深度个性化颜色
|
|
|
- val enableDeepPersonalization: Boolean = false,
|
|
|
- val cPrimary: Int = 0,
|
|
|
- val cNPrimary: Int = 0,
|
|
|
- val themeColor: Int = 0,
|
|
|
- val secondaryThemeColor: Int = 0,
|
|
|
- val primaryTextColor: Int = 0,
|
|
|
- val secondaryTextColor: Int = 0,
|
|
|
- val themeBackgroundColor: Int = 0,
|
|
|
- val labelContainerColor: Int = 0,
|
|
|
- val themeColorNight: Int = 0,
|
|
|
- val secondaryThemeColorNight: Int = 0,
|
|
|
- val primaryTextColorNight: Int = 0,
|
|
|
- val secondaryTextColorNight: Int = 0,
|
|
|
- val themeBackgroundColorNight: Int = 0,
|
|
|
- val labelContainerColorNight: Int = 0,
|
|
|
- val bookInfoInputColor: Int = 0,
|
|
|
- val bookInfoFollowCoverColor: Boolean = true,
|
|
|
- val bookInfoBackgroundBlur: String = ThemeConfig.BOOK_INFO_BACKGROUND_BLUR_ON,
|
|
|
- val bookInfoNetworkCoverBackground: String? = null,
|
|
|
- val bookInfoDefaultCoverBackground: String? = null,
|
|
|
-
|
|
|
- // 容器设置
|
|
|
- val containerOpacity: Int = 100,
|
|
|
-
|
|
|
- // 分割线设置
|
|
|
- val enableItemDivider: Boolean = false,
|
|
|
- val itemDividerWidth: Float = 1f,
|
|
|
- val itemDividerLength: Float = 80f,
|
|
|
- val itemDividerColor: Int = 0,
|
|
|
-
|
|
|
- // 模糊设置
|
|
|
- val enableBlur: Boolean = false,
|
|
|
- val enableProgressiveBlur: Boolean = false,
|
|
|
- val topBarBlurRadius: Int = 24,
|
|
|
- val bottomBarBlurRadius: Int = 8,
|
|
|
- val topBarBlurAlpha: Int = 73,
|
|
|
- val bottomBarBlurAlpha: Int = 40,
|
|
|
- val bottomBarLensRadius: Float = 24f,
|
|
|
-
|
|
|
- // 透明度设置
|
|
|
- val topBarOpacity: Int = 100,
|
|
|
- val bottomBarOpacity: Int = 100,
|
|
|
-
|
|
|
- // 标签颜色
|
|
|
- val enableCustomTagColors: Boolean = false,
|
|
|
- val customTagColorsJson: String? = null,
|
|
|
-
|
|
|
- // 书架卡片颜色
|
|
|
- val bookshelfCardColor: Int = 0,
|
|
|
- val bookshelfCardColorDark: Int = 0,
|
|
|
-
|
|
|
- // 主界面设置
|
|
|
- val showHome: Boolean = true,
|
|
|
- val showDiscovery: Boolean = true,
|
|
|
- val showRss: Boolean = true,
|
|
|
- val showStatusBar: Boolean = true,
|
|
|
- val swipeAnimation: Boolean = true,
|
|
|
- val showBottomView: Boolean = true,
|
|
|
- val useFloatingBottomBar: Boolean = false,
|
|
|
- val useFloatingBottomBarLiquidGlass: Boolean = false,
|
|
|
- val tabletInterface: String = "auto",
|
|
|
- val labelVisibilityMode: String = "auto",
|
|
|
- val defaultHomePage: String = "bookshelf",
|
|
|
- val mainNavigationOrder: String = "home,bookshelf,explore,rss,my",
|
|
|
-
|
|
|
- // 导航栏图标
|
|
|
- val navIconHome: String = "",
|
|
|
- val navIconBookshelf: String = "",
|
|
|
- val navIconExplore: String = "",
|
|
|
- val navIconRss: String = "",
|
|
|
- val navIconMy: String = "",
|
|
|
-
|
|
|
- // Miuix 设置
|
|
|
- val useMiuixMonet: Boolean = false,
|
|
|
-
|
|
|
- // 其他
|
|
|
- val useFlexibleTopAppBar: Boolean = true,
|
|
|
- val bgImageLight: String? = null,
|
|
|
- val bgImageDark: String? = null,
|
|
|
- val bgImageBlurring: Int = 0,
|
|
|
- val bgImageNBlurring: Int = 0,
|
|
|
- val appFontPath: String? = null,
|
|
|
- val selectedCoverAlbumId: String? = null,
|
|
|
-
|
|
|
- // 封面配置 (CoverConfig)
|
|
|
- val coverLoadOnlyWifi: Boolean = false,
|
|
|
- val coverUseDefault: Boolean = false,
|
|
|
- val coverShowShadow: Boolean = false,
|
|
|
- val coverShowStroke: Boolean = true,
|
|
|
- val coverDefaultColor: Boolean = true,
|
|
|
- val coverDefaultImage: String = "",
|
|
|
- val coverTextColor: Int = -16777216,
|
|
|
- val coverShadowColor: Int = -16777216,
|
|
|
- val coverShowName: Boolean = true,
|
|
|
- val coverShowAuthor: Boolean = true,
|
|
|
- val coverDefaultImageDark: String = "",
|
|
|
- val coverTextColorN: Int = -1,
|
|
|
- val coverShadowColorN: Int = -1,
|
|
|
- val coverShowNameN: Boolean = true,
|
|
|
- val coverShowAuthorN: Boolean = true,
|
|
|
- val coverInfoOrientation: String = "0",
|
|
|
-
|
|
|
- // 嵌入的二进制资源 (Base64)
|
|
|
- val assets: Map<String, String>? = null
|
|
|
-)
|
|
|
-
|
|
|
/**
|
|
|
* 已保存的主题
|
|
|
*/
|
|
|
@@ -755,4 +347,11 @@ data class SavedTheme(
|
|
|
internal data class AppliedThemeAssets(
|
|
|
val lightCoverPaths: List<String> = emptyList(),
|
|
|
val darkCoverPaths: List<String> = emptyList(),
|
|
|
+ val paths: Map<String, String> = emptyMap(),
|
|
|
+ val createdFiles: List<File> = emptyList(),
|
|
|
+)
|
|
|
+
|
|
|
+internal data class PreparedTheme(
|
|
|
+ val data: ThemeExportData,
|
|
|
+ val appliedAssets: AppliedThemeAssets,
|
|
|
)
|