Rename
This commit is contained in:
1 parent
b86d90021c
commit
6c0757c91b
972 files changed
+6885
-7321
No files matched your search
@@ -0,0 +1,668 @@
|
||||
package io.legato.kazusa.help.config
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Build
|
||||
import io.legato.kazusa.BuildConfig
|
||||
import io.legato.kazusa.constant.PreferKey
|
||||
import io.legato.kazusa.data.appDb
|
||||
import io.legato.kazusa.utils.canvasrecorder.CanvasRecorderFactory
|
||||
import io.legato.kazusa.utils.getPrefBoolean
|
||||
import io.legato.kazusa.utils.getPrefInt
|
||||
import io.legato.kazusa.utils.getPrefLong
|
||||
import io.legato.kazusa.utils.getPrefString
|
||||
import io.legato.kazusa.utils.isNightMode
|
||||
import io.legato.kazusa.utils.putPrefBoolean
|
||||
import io.legato.kazusa.utils.putPrefInt
|
||||
import io.legato.kazusa.utils.putPrefLong
|
||||
import io.legato.kazusa.utils.putPrefString
|
||||
import io.legato.kazusa.utils.removePref
|
||||
import io.legato.kazusa.utils.sysConfiguration
|
||||
import io.legato.kazusa.utils.toastOnUi
|
||||
import splitties.init.appCtx
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate", "ConstPropertyName")
|
||||
object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
val isCronet = appCtx.getPrefBoolean(PreferKey.cronet)
|
||||
var useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)
|
||||
var userAgent: String = getPrefUserAgent()
|
||||
var isEInkMode = appCtx.getPrefString(PreferKey.themeMode) == "3"
|
||||
var clickActionTL = appCtx.getPrefInt(PreferKey.clickActionTL, 2)
|
||||
var clickActionTC = appCtx.getPrefInt(PreferKey.clickActionTC, 2)
|
||||
var clickActionTR = appCtx.getPrefInt(PreferKey.clickActionTR, 1)
|
||||
var clickActionML = appCtx.getPrefInt(PreferKey.clickActionML, 2)
|
||||
var clickActionMC = appCtx.getPrefInt(PreferKey.clickActionMC, 0)
|
||||
var clickActionMR = appCtx.getPrefInt(PreferKey.clickActionMR, 1)
|
||||
var clickActionBL = appCtx.getPrefInt(PreferKey.clickActionBL, 2)
|
||||
var clickActionBC = appCtx.getPrefInt(PreferKey.clickActionBC, 1)
|
||||
var clickActionBR = appCtx.getPrefInt(PreferKey.clickActionBR, 1)
|
||||
var themeMode = appCtx.getPrefString(PreferKey.themeMode, "0")
|
||||
var useDefaultCover = appCtx.getPrefBoolean(PreferKey.useDefaultCover, false)
|
||||
var optimizeRender = CanvasRecorderFactory.isSupport
|
||||
&& appCtx.getPrefBoolean(PreferKey.optimizeRender, false)
|
||||
var recordLog = appCtx.getPrefBoolean(PreferKey.recordLog)
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
when (key) {
|
||||
PreferKey.themeMode -> {
|
||||
themeMode = appCtx.getPrefString(PreferKey.themeMode, "0")
|
||||
isEInkMode = themeMode == "3"
|
||||
}
|
||||
|
||||
PreferKey.clickActionTL -> clickActionTL =
|
||||
appCtx.getPrefInt(PreferKey.clickActionTL, 2)
|
||||
|
||||
PreferKey.clickActionTC -> clickActionTC =
|
||||
appCtx.getPrefInt(PreferKey.clickActionTC, 2)
|
||||
|
||||
PreferKey.clickActionTR -> clickActionTR =
|
||||
appCtx.getPrefInt(PreferKey.clickActionTR, 1)
|
||||
|
||||
PreferKey.clickActionML -> clickActionML =
|
||||
appCtx.getPrefInt(PreferKey.clickActionML, 2)
|
||||
|
||||
PreferKey.clickActionMC -> clickActionMC =
|
||||
appCtx.getPrefInt(PreferKey.clickActionMC, 0)
|
||||
|
||||
PreferKey.clickActionMR -> clickActionMR =
|
||||
appCtx.getPrefInt(PreferKey.clickActionMR, 1)
|
||||
|
||||
PreferKey.clickActionBL -> clickActionBL =
|
||||
appCtx.getPrefInt(PreferKey.clickActionBL, 2)
|
||||
|
||||
PreferKey.clickActionBC -> clickActionBC =
|
||||
appCtx.getPrefInt(PreferKey.clickActionBC, 1)
|
||||
|
||||
PreferKey.clickActionBR -> clickActionBR =
|
||||
appCtx.getPrefInt(PreferKey.clickActionBR, 1)
|
||||
|
||||
PreferKey.readBodyToLh -> ReadBookConfig.readBodyToLh =
|
||||
appCtx.getPrefBoolean(PreferKey.readBodyToLh, true)
|
||||
|
||||
PreferKey.useZhLayout -> ReadBookConfig.useZhLayout =
|
||||
appCtx.getPrefBoolean(PreferKey.useZhLayout)
|
||||
|
||||
PreferKey.userAgent -> userAgent = getPrefUserAgent()
|
||||
|
||||
PreferKey.antiAlias -> useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)
|
||||
|
||||
PreferKey.useDefaultCover -> useDefaultCover =
|
||||
appCtx.getPrefBoolean(PreferKey.useDefaultCover, false)
|
||||
|
||||
PreferKey.optimizeRender -> optimizeRender = CanvasRecorderFactory.isSupport
|
||||
&& appCtx.getPrefBoolean(PreferKey.optimizeRender, false)
|
||||
|
||||
PreferKey.recordLog -> recordLog = appCtx.getPrefBoolean(PreferKey.recordLog)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var isNightTheme: Boolean
|
||||
get() = when (themeMode) {
|
||||
"1" -> false
|
||||
"2" -> true
|
||||
"3" -> false
|
||||
else -> sysConfiguration.isNightMode
|
||||
}
|
||||
set(value) {
|
||||
if (isNightTheme != value) {
|
||||
if (value) {
|
||||
appCtx.putPrefString(PreferKey.themeMode, "2")
|
||||
} else {
|
||||
appCtx.putPrefString(PreferKey.themeMode, "1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var showUnread: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showUnread, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.showUnread, value)
|
||||
}
|
||||
|
||||
var showLastUpdateTime: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showLastUpdateTime, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.showLastUpdateTime, value)
|
||||
}
|
||||
|
||||
var showWaitUpCount: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showWaitUpCount, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.showWaitUpCount, value)
|
||||
}
|
||||
|
||||
var readBrightness: Int
|
||||
get() = if (isNightTheme) {
|
||||
appCtx.getPrefInt(PreferKey.nightBrightness, 100)
|
||||
} else {
|
||||
appCtx.getPrefInt(PreferKey.brightness, 100)
|
||||
}
|
||||
set(value) {
|
||||
if (isNightTheme) {
|
||||
appCtx.putPrefInt(PreferKey.nightBrightness, value)
|
||||
} else {
|
||||
appCtx.putPrefInt(PreferKey.brightness, value)
|
||||
}
|
||||
}
|
||||
|
||||
val textSelectAble: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.textSelectAble, true)
|
||||
|
||||
// val isTransparentStatusBar: Boolean
|
||||
// get() = appCtx.getPrefBoolean(PreferKey.transparentStatusBar, true)
|
||||
//
|
||||
// val immNavigationBar: Boolean
|
||||
// get() = appCtx.getPrefBoolean(PreferKey.immNavigationBar, true)
|
||||
|
||||
val screenOrientation: String?
|
||||
get() = appCtx.getPrefString(PreferKey.screenOrientation)
|
||||
|
||||
var bookGroupStyle: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.bookGroupStyle, 0)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.bookGroupStyle, value)
|
||||
}
|
||||
|
||||
var bookshelfLayout: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.bookshelfLayout, 0)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.bookshelfLayout, value)
|
||||
}
|
||||
|
||||
var saveTabPosition: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.saveTabPosition, 0)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.saveTabPosition, value)
|
||||
}
|
||||
|
||||
var bookExportFileName: String?
|
||||
get() = appCtx.getPrefString(PreferKey.bookExportFileName)
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.bookExportFileName, value)
|
||||
}
|
||||
|
||||
// 保存 自定义导出章节模式 文件名js表达式
|
||||
var episodeExportFileName: String?
|
||||
get() = appCtx.getPrefString(PreferKey.episodeExportFileName, "")
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.episodeExportFileName, value)
|
||||
}
|
||||
|
||||
var bookImportFileName: String?
|
||||
get() = appCtx.getPrefString(PreferKey.bookImportFileName)
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.bookImportFileName, value)
|
||||
}
|
||||
|
||||
var backupPath: String?
|
||||
get() = appCtx.getPrefString(PreferKey.backupPath)
|
||||
set(value) {
|
||||
if (value.isNullOrEmpty()) {
|
||||
appCtx.removePref(PreferKey.backupPath)
|
||||
} else {
|
||||
appCtx.putPrefString(PreferKey.backupPath, value)
|
||||
}
|
||||
}
|
||||
|
||||
// 书籍保存位置
|
||||
var defaultBookTreeUri: String?
|
||||
get() = appCtx.getPrefString(PreferKey.defaultBookTreeUri)
|
||||
set(value) {
|
||||
if (value.isNullOrEmpty()) {
|
||||
appCtx.removePref(PreferKey.defaultBookTreeUri)
|
||||
} else {
|
||||
appCtx.putPrefString(PreferKey.defaultBookTreeUri, value)
|
||||
}
|
||||
}
|
||||
|
||||
val showDiscovery: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showDiscovery, true)
|
||||
|
||||
val showRSS: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showRss, true)
|
||||
|
||||
val autoRefreshBook: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.autoRefresh)
|
||||
|
||||
var enableReview: Boolean
|
||||
get() = BuildConfig.DEBUG && appCtx.getPrefBoolean(PreferKey.enableReview, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.enableReview, value)
|
||||
}
|
||||
|
||||
var threadCount: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.threadCount, 16)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.threadCount, value)
|
||||
}
|
||||
|
||||
var remoteServerId: Long
|
||||
get() = appCtx.getPrefLong(PreferKey.remoteServerId)
|
||||
set(value) {
|
||||
appCtx.putPrefLong(PreferKey.remoteServerId, value)
|
||||
}
|
||||
|
||||
// 添加本地选择的目录
|
||||
var importBookPath: String?
|
||||
get() = appCtx.getPrefString("importBookPath")
|
||||
set(value) {
|
||||
if (value == null) {
|
||||
appCtx.removePref("importBookPath")
|
||||
} else {
|
||||
appCtx.putPrefString("importBookPath", value)
|
||||
}
|
||||
}
|
||||
|
||||
var ttsFlowSys: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.ttsFollowSys, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.ttsFollowSys, value)
|
||||
}
|
||||
|
||||
val noAnimScrollPage: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.noAnimScrollPage, false)
|
||||
|
||||
const val defaultSpeechRate = 5
|
||||
|
||||
var ttsSpeechRate: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.ttsSpeechRate, defaultSpeechRate)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.ttsSpeechRate, value)
|
||||
}
|
||||
|
||||
var ttsTimer: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.ttsTimer, 0)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.ttsTimer, value)
|
||||
}
|
||||
|
||||
val speechRatePlay: Int get() = if (ttsFlowSys) defaultSpeechRate else ttsSpeechRate
|
||||
|
||||
var chineseConverterType: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.chineseConverterType)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.chineseConverterType, value)
|
||||
}
|
||||
|
||||
var systemTypefaces: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.systemTypefaces)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.systemTypefaces, value)
|
||||
}
|
||||
|
||||
// var elevation: Int
|
||||
// get() = if (isEInkMode) 0 else appCtx.getPrefInt(
|
||||
// PreferKey.barElevation,
|
||||
// AppConst.sysElevation
|
||||
// )
|
||||
// set(value) {
|
||||
// appCtx.putPrefInt(PreferKey.barElevation, value)
|
||||
// }
|
||||
|
||||
var readUrlInBrowser: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.readUrlOpenInBrowser)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.readUrlOpenInBrowser, value)
|
||||
}
|
||||
|
||||
var exportCharset: String
|
||||
get() {
|
||||
val c = appCtx.getPrefString(PreferKey.exportCharset)
|
||||
if (c.isNullOrBlank()) {
|
||||
return "UTF-8"
|
||||
}
|
||||
return c
|
||||
}
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.exportCharset, value)
|
||||
}
|
||||
|
||||
var exportUseReplace: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.exportUseReplace, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.exportUseReplace, value)
|
||||
}
|
||||
|
||||
var exportToWebDav: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.exportToWebDav)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.exportToWebDav, value)
|
||||
}
|
||||
var exportNoChapterName: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.exportNoChapterName)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.exportNoChapterName, value)
|
||||
}
|
||||
|
||||
// 是否启用自定义导出 default->false
|
||||
var enableCustomExport: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.enableCustomExport, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.enableCustomExport, value)
|
||||
}
|
||||
|
||||
var exportType: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.exportType)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.exportType, value)
|
||||
}
|
||||
var exportPictureFile: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.exportPictureFile, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.exportPictureFile, value)
|
||||
}
|
||||
|
||||
var parallelExportBook: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.parallelExportBook, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.parallelExportBook, value)
|
||||
}
|
||||
|
||||
var changeSourceCheckAuthor: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.changeSourceCheckAuthor)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.changeSourceCheckAuthor, value)
|
||||
}
|
||||
|
||||
var ttsEngine: String?
|
||||
get() = appCtx.getPrefString(PreferKey.ttsEngine)
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.ttsEngine, value)
|
||||
}
|
||||
|
||||
var webPort: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.webPort, 1122)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.webPort, value)
|
||||
}
|
||||
|
||||
var tocUiUseReplace: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.tocUiUseReplace)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.tocUiUseReplace, value)
|
||||
}
|
||||
|
||||
var tocCountWords: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.tocCountWords, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.tocCountWords, value)
|
||||
}
|
||||
|
||||
var enableReadRecord: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.enableReadRecord, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.enableReadRecord, value)
|
||||
}
|
||||
|
||||
val autoChangeSource: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.autoChangeSource, true)
|
||||
|
||||
var changeSourceLoadInfo: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadInfo)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.changeSourceLoadInfo, value)
|
||||
}
|
||||
|
||||
var changeSourceLoadToc: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadToc)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.changeSourceLoadToc, value)
|
||||
}
|
||||
|
||||
var changeSourceLoadWordCount: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.changeSourceLoadWordCount)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.changeSourceLoadWordCount, value)
|
||||
}
|
||||
|
||||
var openBookInfoByClickTitle: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.openBookInfoByClickTitle, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.openBookInfoByClickTitle, value)
|
||||
}
|
||||
|
||||
var showBookshelfFastScroller: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showBookshelfFastScroller, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.showBookshelfFastScroller, value)
|
||||
}
|
||||
|
||||
var contentSelectSpeakMod: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.contentSelectSpeakMod)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.contentSelectSpeakMod, value)
|
||||
}
|
||||
|
||||
var batchChangeSourceDelay: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.batchChangeSourceDelay)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.batchChangeSourceDelay, value)
|
||||
}
|
||||
|
||||
val importKeepName get() = appCtx.getPrefBoolean(PreferKey.importKeepName)
|
||||
val importKeepGroup get() = appCtx.getPrefBoolean(PreferKey.importKeepGroup)
|
||||
var importKeepEnable: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.importKeepEnable, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.importKeepEnable, value)
|
||||
}
|
||||
|
||||
var previewImageByClick: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.previewImageByClick, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.previewImageByClick, value)
|
||||
}
|
||||
|
||||
var preDownloadNum
|
||||
get() = appCtx.getPrefInt(PreferKey.preDownloadNum, 10)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.preDownloadNum, value)
|
||||
}
|
||||
|
||||
val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true)
|
||||
|
||||
val syncBookProgressPlus get() = appCtx.getPrefBoolean(PreferKey.syncBookProgressPlus, false)
|
||||
|
||||
val mediaButtonOnExit get() = appCtx.getPrefBoolean("mediaButtonOnExit", true)
|
||||
|
||||
val readAloudByMediaButton
|
||||
get() = appCtx.getPrefBoolean(PreferKey.readAloudByMediaButton, false)
|
||||
|
||||
val replaceEnableDefault get() = appCtx.getPrefBoolean(PreferKey.replaceEnableDefault, true)
|
||||
|
||||
val webDavDir get() = appCtx.getPrefString(PreferKey.webDavDir, "legado")
|
||||
|
||||
val webDavDeviceName get() = appCtx.getPrefString(PreferKey.webDavDeviceName, Build.MODEL)
|
||||
|
||||
val recordHeapDump get() = appCtx.getPrefBoolean(PreferKey.recordHeapDump, false)
|
||||
|
||||
val loadCoverOnlyWifi get() = appCtx.getPrefBoolean(PreferKey.loadCoverOnlyWifi, false)
|
||||
|
||||
val showAddToShelfAlert get() = appCtx.getPrefBoolean(PreferKey.showAddToShelfAlert, true)
|
||||
|
||||
val ignoreAudioFocus get() = appCtx.getPrefBoolean(PreferKey.ignoreAudioFocus, false)
|
||||
|
||||
var pauseReadAloudWhilePhoneCalls
|
||||
get() = appCtx.getPrefBoolean(PreferKey.pauseReadAloudWhilePhoneCalls, false)
|
||||
set(value) = appCtx.putPrefBoolean(PreferKey.pauseReadAloudWhilePhoneCalls, value)
|
||||
|
||||
val onlyLatestBackup get() = appCtx.getPrefBoolean(PreferKey.onlyLatestBackup, true)
|
||||
|
||||
val defaultHomePage get() = appCtx.getPrefString(PreferKey.defaultHomePage, "bookshelf")
|
||||
|
||||
val updateToVariant get() = appCtx.getPrefString(PreferKey.updateToVariant, "default_version")
|
||||
|
||||
val streamReadAloudAudio get() = appCtx.getPrefBoolean(PreferKey.streamReadAloudAudio, false)
|
||||
|
||||
val doublePageHorizontal: String?
|
||||
get() = appCtx.getPrefString(PreferKey.doublePageHorizontal)
|
||||
|
||||
val progressBarBehavior: String?
|
||||
get() = appCtx.getPrefString(PreferKey.progressBarBehavior, "page")
|
||||
|
||||
val keyPageOnLongPress
|
||||
get() = appCtx.getPrefBoolean(PreferKey.keyPageOnLongPress, false)
|
||||
|
||||
val volumeKeyPage
|
||||
get() = appCtx.getPrefBoolean(PreferKey.volumeKeyPage, true)
|
||||
|
||||
val volumeKeyPageOnPlay
|
||||
get() = appCtx.getPrefBoolean(PreferKey.volumeKeyPageOnPlay, true)
|
||||
|
||||
val mouseWheelPage
|
||||
get() = appCtx.getPrefBoolean(PreferKey.mouseWheelPage, true)
|
||||
|
||||
var searchScope: String
|
||||
get() = appCtx.getPrefString("searchScope") ?: ""
|
||||
set(value) {
|
||||
appCtx.putPrefString("searchScope", value)
|
||||
}
|
||||
|
||||
var searchGroup: String
|
||||
get() = appCtx.getPrefString("searchGroup") ?: ""
|
||||
set(value) {
|
||||
appCtx.putPrefString("searchGroup", value)
|
||||
}
|
||||
|
||||
var pageTouchSlop: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.pageTouchSlop, 0)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.pageTouchSlop, value)
|
||||
}
|
||||
|
||||
var bookshelfSort: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.bookshelfSort, 0)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.bookshelfSort, value)
|
||||
}
|
||||
|
||||
fun getBookSortByGroupId(groupId: Long): Int {
|
||||
return appDb.bookGroupDao.getByID(groupId)?.getRealBookSort()
|
||||
?: bookshelfSort
|
||||
}
|
||||
|
||||
private fun getPrefUserAgent(): String {
|
||||
val ua = appCtx.getPrefString(PreferKey.userAgent)
|
||||
if (ua.isNullOrBlank()) {
|
||||
return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + BuildConfig.Cronet_Main_Version + " Safari/537.36"
|
||||
}
|
||||
return ua
|
||||
}
|
||||
|
||||
var bitmapCacheSize: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.bitmapCacheSize, 50)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.bitmapCacheSize, value)
|
||||
}
|
||||
|
||||
var imageRetainNum: Int
|
||||
get() = appCtx.getPrefInt(PreferKey.imageRetainNum, 0)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.imageRetainNum, value)
|
||||
}
|
||||
|
||||
var showReadTitleBarAddition: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showReadTitleAddition, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.showReadTitleAddition, value)
|
||||
}
|
||||
var readBarStyleFollowPage: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.readBarStyleFollowPage, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.readBarStyleFollowPage, value)
|
||||
}
|
||||
|
||||
var sourceEditMaxLine: Int
|
||||
get() {
|
||||
val maxLine = appCtx.getPrefInt(PreferKey.sourceEditMaxLine, Int.MAX_VALUE)
|
||||
if (maxLine < 10) {
|
||||
return Int.MAX_VALUE
|
||||
}
|
||||
return maxLine
|
||||
}
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.sourceEditMaxLine, value)
|
||||
}
|
||||
|
||||
var audioPlayUseWakeLock: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.audioPlayWakeLock)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.audioPlayWakeLock, value)
|
||||
}
|
||||
|
||||
var brightnessVwPos: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.brightnessVwPos)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.brightnessVwPos, value)
|
||||
}
|
||||
|
||||
fun detectClickArea() {
|
||||
if (clickActionTL * clickActionTC * clickActionTR
|
||||
* clickActionML * clickActionMC * clickActionMR
|
||||
* clickActionBL * clickActionBC * clickActionBR != 0
|
||||
) {
|
||||
appCtx.putPrefInt(PreferKey.clickActionMC, 0)
|
||||
appCtx.toastOnUi("当前没有配置菜单区域,自动恢复中间区域为菜单.")
|
||||
}
|
||||
}
|
||||
|
||||
//跳转到漫画界面不使用富文本模式
|
||||
val showMangaUi: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.showMangaUi, true)
|
||||
|
||||
//禁用漫画缩放
|
||||
var disableMangaScale: Boolean
|
||||
get() = appCtx.getPrefBoolean(PreferKey.disableMangaScale, true)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.disableMangaScale, value)
|
||||
}
|
||||
|
||||
//漫画预加载数量
|
||||
var mangaPreDownloadNum
|
||||
get() = appCtx.getPrefInt(PreferKey.mangaPreDownloadNum, 10)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.mangaPreDownloadNum, value)
|
||||
}
|
||||
|
||||
//点击翻页
|
||||
var disableClickScroll
|
||||
get() = appCtx.getPrefBoolean(PreferKey.disableClickScroll, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.disableClickScroll, value)
|
||||
}
|
||||
|
||||
//漫画滚动速度
|
||||
var mangaAutoPageSpeed
|
||||
get() = appCtx.getPrefInt(PreferKey.mangaAutoPageSpeed, 3)
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.mangaAutoPageSpeed, value)
|
||||
}
|
||||
|
||||
//漫画页脚配置
|
||||
var mangaFooterConfig
|
||||
get() = appCtx.getPrefString(PreferKey.mangaFooterConfig, "")
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.mangaFooterConfig, value)
|
||||
}
|
||||
|
||||
//漫画水平滚动
|
||||
var enableMangaHorizontalScroll
|
||||
get() = appCtx.getPrefBoolean(PreferKey.enableMangaHorizontalScroll, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.enableMangaHorizontalScroll, value)
|
||||
}
|
||||
|
||||
var mangaColorFilter
|
||||
get() = appCtx.getPrefString(PreferKey.mangaColorFilter, "")
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.mangaColorFilter, value)
|
||||
}
|
||||
|
||||
//禁用漫画内标题
|
||||
var hideMangaTitle
|
||||
get() = appCtx.getPrefBoolean(PreferKey.hideMangaTitle, false)
|
||||
set(value) {
|
||||
appCtx.putPrefBoolean(PreferKey.hideMangaTitle, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package io.legato.kazusa.help.config
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import io.legato.kazusa.utils.getBoolean
|
||||
import io.legato.kazusa.utils.putBoolean
|
||||
import io.legato.kazusa.utils.putLong
|
||||
import io.legato.kazusa.utils.putString
|
||||
import io.legato.kazusa.utils.remove
|
||||
import splitties.init.appCtx
|
||||
|
||||
@Suppress("ConstPropertyName")
|
||||
object LocalConfig : SharedPreferences
|
||||
by appCtx.getSharedPreferences("local", Context.MODE_PRIVATE) {
|
||||
|
||||
private const val versionCodeKey = "appVersionCode"
|
||||
|
||||
/**
|
||||
* 本地密码,用来对需要备份的敏感信息加密,如 webdav 配置等
|
||||
*/
|
||||
var password: String?
|
||||
get() = getString("password", null)
|
||||
set(value) {
|
||||
if (value != null) {
|
||||
putString("password", value)
|
||||
} else {
|
||||
remove("password")
|
||||
}
|
||||
}
|
||||
|
||||
var lastBackup: Long
|
||||
get() = getLong("lastBackup", 0)
|
||||
set(value) {
|
||||
putLong("lastBackup", value)
|
||||
}
|
||||
|
||||
var privacyPolicyOk: Boolean
|
||||
get() = getBoolean("privacyPolicyOk")
|
||||
set(value) {
|
||||
putBoolean("privacyPolicyOk", value)
|
||||
}
|
||||
|
||||
val readHelpVersionIsLast: Boolean
|
||||
get() = isLastVersion(1, "readHelpVersion", "firstRead")
|
||||
|
||||
val backupHelpVersionIsLast: Boolean
|
||||
get() = isLastVersion(1, "backupHelpVersion", "firstBackup")
|
||||
|
||||
val readMenuHelpVersionIsLast: Boolean
|
||||
get() = isLastVersion(1, "readMenuHelpVersion", "firstReadMenu")
|
||||
|
||||
val bookSourcesHelpVersionIsLast: Boolean
|
||||
get() = isLastVersion(1, "bookSourceHelpVersion", "firstOpenBookSources")
|
||||
|
||||
val webDavBookHelpVersionIsLast: Boolean
|
||||
get() = isLastVersion(1, "webDavBookHelpVersion", "firstOpenWebDavBook")
|
||||
|
||||
val ruleHelpVersionIsLast: Boolean
|
||||
get() = isLastVersion(1, "ruleHelpVersion")
|
||||
|
||||
val needUpHttpTTS: Boolean
|
||||
get() = !isLastVersion(6, "httpTtsVersion")
|
||||
|
||||
val needUpTxtTocRule: Boolean
|
||||
get() = !isLastVersion(3, "txtTocRuleVersion")
|
||||
|
||||
val needUpRssSources: Boolean
|
||||
get() = !isLastVersion(6, "rssSourceVersion")
|
||||
|
||||
val needUpDictRule: Boolean
|
||||
get() = !isLastVersion(2, "needUpDictRule")
|
||||
|
||||
var versionCode
|
||||
get() = getLong(versionCodeKey, 0)
|
||||
set(value) {
|
||||
edit { putLong(versionCodeKey, value) }
|
||||
}
|
||||
|
||||
val isFirstOpenApp: Boolean
|
||||
get() {
|
||||
val value = getBoolean("firstOpen", true)
|
||||
if (value) {
|
||||
edit { putBoolean("firstOpen", false) }
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
@Suppress("SameParameterValue")
|
||||
private fun isLastVersion(
|
||||
lastVersion: Int,
|
||||
versionKey: String,
|
||||
firstOpenKey: String? = null
|
||||
): Boolean {
|
||||
var version = getInt(versionKey, 0)
|
||||
if (version == 0 && firstOpenKey != null) {
|
||||
if (!getBoolean(firstOpenKey, true)) {
|
||||
version = 1
|
||||
}
|
||||
}
|
||||
if (version < lastVersion) {
|
||||
edit { putInt(versionKey, lastVersion) }
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var bookInfoDeleteAlert: Boolean
|
||||
get() = getBoolean("bookInfoDeleteAlert", true)
|
||||
set(value) {
|
||||
putBoolean("bookInfoDeleteAlert", value)
|
||||
}
|
||||
|
||||
var deleteBookOriginal: Boolean
|
||||
get() = getBoolean("deleteBookOriginal")
|
||||
set(value) {
|
||||
putBoolean("deleteBookOriginal", value)
|
||||
}
|
||||
|
||||
var appCrash: Boolean
|
||||
get() = getBoolean("appCrash")
|
||||
set(value) {
|
||||
putBoolean("appCrash", value)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,710 @@
|
||||
package io.legato.kazusa.help.config
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.Keep
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.constant.AppLog
|
||||
import io.legato.kazusa.constant.PageAnim
|
||||
import io.legato.kazusa.constant.PreferKey
|
||||
import io.legato.kazusa.help.DefaultData
|
||||
import io.legato.kazusa.help.coroutine.Coroutine
|
||||
import io.legato.kazusa.utils.BitmapUtils
|
||||
import io.legato.kazusa.utils.FileUtils
|
||||
import io.legato.kazusa.utils.GSON
|
||||
import io.legato.kazusa.utils.compress.ZipUtils
|
||||
import io.legato.kazusa.utils.createFolderReplace
|
||||
import io.legato.kazusa.utils.externalCache
|
||||
import io.legato.kazusa.utils.externalFiles
|
||||
import io.legato.kazusa.utils.fromJsonArray
|
||||
import io.legato.kazusa.utils.fromJsonObject
|
||||
import io.legato.kazusa.utils.getFile
|
||||
import io.legato.kazusa.utils.getMeanColor
|
||||
import io.legato.kazusa.utils.getPrefBoolean
|
||||
import io.legato.kazusa.utils.getPrefInt
|
||||
import io.legato.kazusa.utils.hexString
|
||||
import io.legato.kazusa.utils.printOnDebug
|
||||
import io.legato.kazusa.utils.putPrefBoolean
|
||||
import io.legato.kazusa.utils.putPrefInt
|
||||
import io.legato.kazusa.utils.resizeAndRecycle
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.withContext
|
||||
import splitties.init.appCtx
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* 阅读界面配置
|
||||
*/
|
||||
@Suppress("ConstPropertyName")
|
||||
@Keep
|
||||
object ReadBookConfig {
|
||||
const val configFileName = "readConfig.json"
|
||||
const val shareConfigFileName = "shareReadConfig.json"
|
||||
val configFilePath = FileUtils.getPath(appCtx.filesDir, configFileName)
|
||||
val shareConfigFilePath = FileUtils.getPath(appCtx.filesDir, shareConfigFileName)
|
||||
val configList: ArrayList<Config> = arrayListOf()
|
||||
lateinit var shareConfig: Config
|
||||
var durConfig
|
||||
get() = getConfig(styleSelect)
|
||||
set(value) {
|
||||
configList[styleSelect] = value
|
||||
if (shareLayout) {
|
||||
shareConfig = value
|
||||
}
|
||||
}
|
||||
|
||||
var isComic: Boolean = false
|
||||
var bg: Drawable? = null
|
||||
var bgMeanColor: Int = 0
|
||||
val textColor: Int get() = durConfig.curTextColor()
|
||||
|
||||
init {
|
||||
initConfigs()
|
||||
initShareConfig()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun getConfig(index: Int): Config {
|
||||
if (configList.size < 5) {
|
||||
resetAll()
|
||||
}
|
||||
return configList.getOrNull(index) ?: configList[0]
|
||||
}
|
||||
|
||||
fun initConfigs() {
|
||||
val configFile = File(configFilePath)
|
||||
var configs: List<Config>? = null
|
||||
if (configFile.exists()) {
|
||||
try {
|
||||
val json = configFile.readText()
|
||||
configs = GSON.fromJsonArray<Config>(json).getOrThrow()
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("读取排版配置文件出错", e)
|
||||
}
|
||||
}
|
||||
(configs ?: DefaultData.readConfigs).let {
|
||||
configList.clear()
|
||||
configList.addAll(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun initShareConfig() {
|
||||
val configFile = File(shareConfigFilePath)
|
||||
var c: Config? = null
|
||||
if (configFile.exists()) {
|
||||
try {
|
||||
val json = configFile.readText()
|
||||
c = GSON.fromJsonObject<Config>(json).getOrThrow()
|
||||
} catch (e: Exception) {
|
||||
e.printOnDebug()
|
||||
}
|
||||
}
|
||||
shareConfig = c ?: configList.getOrNull(5) ?: Config()
|
||||
}
|
||||
|
||||
fun upBg(width: Int, height: Int) {
|
||||
val drawable = durConfig.curBgDrawable(width, height)
|
||||
if (drawable is BitmapDrawable && drawable.bitmap != null) {
|
||||
bgMeanColor = drawable.bitmap.getMeanColor()
|
||||
} else if (drawable is ColorDrawable) {
|
||||
bgMeanColor = drawable.color
|
||||
}
|
||||
val tmp = bg
|
||||
bg = drawable
|
||||
(tmp as? BitmapDrawable)?.bitmap?.recycle()
|
||||
}
|
||||
|
||||
fun save() {
|
||||
Coroutine.async {
|
||||
synchronized(this) {
|
||||
GSON.toJson(configList).let {
|
||||
FileUtils.delete(configFilePath)
|
||||
FileUtils.createFileIfNotExist(configFilePath).writeText(it)
|
||||
}
|
||||
GSON.toJson(shareConfig).let {
|
||||
FileUtils.delete(shareConfigFilePath)
|
||||
FileUtils.createFileIfNotExist(shareConfigFilePath).writeText(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getAllPicBgStr(): ArrayList<String> {
|
||||
val list = arrayListOf<String>()
|
||||
configList.forEach {
|
||||
if (it.bgType == 2) {
|
||||
list.add(it.bgStr)
|
||||
}
|
||||
if (it.bgTypeNight == 2) {
|
||||
list.add(it.bgStrNight)
|
||||
}
|
||||
if (it.bgTypeEInk == 2) {
|
||||
list.add(it.bgStrEInk)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
fun deleteDur(): Boolean {
|
||||
if (configList.size > 5) {
|
||||
val removeIndex = styleSelect
|
||||
configList.removeAt(removeIndex)
|
||||
if (removeIndex <= readStyleSelect) {
|
||||
readStyleSelect -= 1
|
||||
}
|
||||
if (removeIndex <= comicStyleSelect) {
|
||||
comicStyleSelect -= 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun resetAll() {
|
||||
DefaultData.readConfigs.let {
|
||||
configList.clear()
|
||||
configList.addAll(it)
|
||||
save()
|
||||
}
|
||||
}
|
||||
|
||||
//配置写入读取
|
||||
var readBodyToLh = appCtx.getPrefBoolean(PreferKey.readBodyToLh, true)
|
||||
var autoReadSpeed = appCtx.getPrefInt(PreferKey.autoReadSpeed, 10)
|
||||
set(value) {
|
||||
field = value
|
||||
appCtx.putPrefInt(PreferKey.autoReadSpeed, value)
|
||||
}
|
||||
var styleSelect: Int
|
||||
get() = if (isComic) comicStyleSelect else readStyleSelect
|
||||
set(value) {
|
||||
if (isComic) {
|
||||
comicStyleSelect = value
|
||||
} else {
|
||||
readStyleSelect = value
|
||||
}
|
||||
}
|
||||
var readStyleSelect = appCtx.getPrefInt(PreferKey.readStyleSelect)
|
||||
set(value) {
|
||||
field = value
|
||||
if (appCtx.getPrefInt(PreferKey.readStyleSelect) != value) {
|
||||
appCtx.putPrefInt(PreferKey.readStyleSelect, value)
|
||||
}
|
||||
}
|
||||
var comicStyleSelect = appCtx.getPrefInt(PreferKey.comicStyleSelect, readStyleSelect)
|
||||
set(value) {
|
||||
field = value
|
||||
if (appCtx.getPrefInt(PreferKey.comicStyleSelect) != value) {
|
||||
appCtx.putPrefInt(PreferKey.comicStyleSelect, value)
|
||||
}
|
||||
}
|
||||
var shareLayout = appCtx.getPrefBoolean(PreferKey.shareLayout)
|
||||
set(value) {
|
||||
field = value
|
||||
if (appCtx.getPrefBoolean(PreferKey.shareLayout) != value) {
|
||||
appCtx.putPrefBoolean(PreferKey.shareLayout, value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 两端对齐
|
||||
*/
|
||||
val textFullJustify get() = appCtx.getPrefBoolean(PreferKey.textFullJustify, true)
|
||||
|
||||
/**
|
||||
* 底部对齐
|
||||
*/
|
||||
val textBottomJustify get() = appCtx.getPrefBoolean(PreferKey.textBottomJustify, true)
|
||||
var hideStatusBar = appCtx.getPrefBoolean(PreferKey.hideStatusBar)
|
||||
var hideNavigationBar = appCtx.getPrefBoolean(PreferKey.hideNavigationBar)
|
||||
var useZhLayout = appCtx.getPrefBoolean(PreferKey.useZhLayout)
|
||||
|
||||
val config get() = if (shareLayout) shareConfig else durConfig
|
||||
|
||||
var bgAlpha: Int
|
||||
get() = config.bgAlpha
|
||||
set(value) {
|
||||
config.bgAlpha = value
|
||||
}
|
||||
|
||||
var pageAnim: Int
|
||||
get() = config.curPageAnim()
|
||||
set(@PageAnim.Anim value) {
|
||||
config.setCurPageAnim(value)
|
||||
}
|
||||
|
||||
var textFont: String
|
||||
get() = config.textFont
|
||||
set(value) {
|
||||
config.textFont = value
|
||||
}
|
||||
|
||||
var textBold: Int
|
||||
get() = config.textBold
|
||||
set(value) {
|
||||
config.textBold = value
|
||||
}
|
||||
|
||||
var textSize: Int
|
||||
get() = config.textSize
|
||||
set(value) {
|
||||
config.textSize = value
|
||||
}
|
||||
|
||||
var letterSpacing: Float
|
||||
get() = config.letterSpacing
|
||||
set(value) {
|
||||
config.letterSpacing = value
|
||||
}
|
||||
|
||||
var lineSpacingExtra: Int
|
||||
get() = config.lineSpacingExtra
|
||||
set(value) {
|
||||
config.lineSpacingExtra = value
|
||||
}
|
||||
|
||||
var paragraphSpacing: Int
|
||||
get() = config.paragraphSpacing
|
||||
set(value) {
|
||||
config.paragraphSpacing = value
|
||||
}
|
||||
|
||||
/**
|
||||
* 标题位置 0:居左 1:居中 2:隐藏
|
||||
*/
|
||||
var titleMode: Int
|
||||
get() = config.titleMode
|
||||
set(value) {
|
||||
config.titleMode = value
|
||||
}
|
||||
var titleSize: Int
|
||||
get() = config.titleSize
|
||||
set(value) {
|
||||
config.titleSize = value
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否标题居中
|
||||
*/
|
||||
val isMiddleTitle get() = titleMode == 1
|
||||
|
||||
var titleTopSpacing: Int
|
||||
get() = config.titleTopSpacing
|
||||
set(value) {
|
||||
config.titleTopSpacing = value
|
||||
}
|
||||
|
||||
var titleBottomSpacing: Int
|
||||
get() = config.titleBottomSpacing
|
||||
set(value) {
|
||||
config.titleBottomSpacing = value
|
||||
}
|
||||
|
||||
var paragraphIndent: String
|
||||
get() = config.paragraphIndent
|
||||
set(value) {
|
||||
config.paragraphIndent = value
|
||||
}
|
||||
|
||||
var underline: Boolean
|
||||
get() = config.underline
|
||||
set(value) {
|
||||
config.underline = value
|
||||
}
|
||||
|
||||
var paddingBottom: Int
|
||||
get() = config.paddingBottom
|
||||
set(value) {
|
||||
config.paddingBottom = value
|
||||
}
|
||||
|
||||
var paddingLeft: Int
|
||||
get() = config.paddingLeft
|
||||
set(value) {
|
||||
config.paddingLeft = value
|
||||
}
|
||||
|
||||
var paddingRight: Int
|
||||
get() = config.paddingRight
|
||||
set(value) {
|
||||
config.paddingRight = value
|
||||
}
|
||||
|
||||
var paddingTop: Int
|
||||
get() = config.paddingTop
|
||||
set(value) {
|
||||
config.paddingTop = value
|
||||
}
|
||||
|
||||
var headerPaddingBottom: Int
|
||||
get() = config.headerPaddingBottom
|
||||
set(value) {
|
||||
config.headerPaddingBottom = value
|
||||
}
|
||||
|
||||
var headerPaddingLeft: Int
|
||||
get() = config.headerPaddingLeft
|
||||
set(value) {
|
||||
config.headerPaddingLeft = value
|
||||
}
|
||||
|
||||
var headerPaddingRight: Int
|
||||
get() = config.headerPaddingRight
|
||||
set(value) {
|
||||
config.headerPaddingRight = value
|
||||
}
|
||||
|
||||
var headerPaddingTop: Int
|
||||
get() = config.headerPaddingTop
|
||||
set(value) {
|
||||
config.headerPaddingTop = value
|
||||
}
|
||||
|
||||
var footerPaddingBottom: Int
|
||||
get() = config.footerPaddingBottom
|
||||
set(value) {
|
||||
config.footerPaddingBottom = value
|
||||
}
|
||||
|
||||
var footerPaddingLeft: Int
|
||||
get() = config.footerPaddingLeft
|
||||
set(value) {
|
||||
config.footerPaddingLeft = value
|
||||
}
|
||||
|
||||
var footerPaddingRight: Int
|
||||
get() = config.footerPaddingRight
|
||||
set(value) {
|
||||
config.footerPaddingRight = value
|
||||
}
|
||||
|
||||
var footerPaddingTop: Int
|
||||
get() = config.footerPaddingTop
|
||||
set(value) {
|
||||
config.footerPaddingTop = value
|
||||
}
|
||||
|
||||
var showHeaderLine: Boolean
|
||||
get() = config.showHeaderLine
|
||||
set(value) {
|
||||
config.showHeaderLine = value
|
||||
}
|
||||
|
||||
var showFooterLine: Boolean
|
||||
get() = config.showFooterLine
|
||||
set(value) {
|
||||
config.showFooterLine = value
|
||||
}
|
||||
|
||||
fun getExportConfig(): Config {
|
||||
val exportConfig = durConfig.copy()
|
||||
if (shareLayout) {
|
||||
exportConfig.textFont = shareConfig.textFont
|
||||
exportConfig.textBold = shareConfig.textBold
|
||||
exportConfig.textSize = shareConfig.textSize
|
||||
exportConfig.letterSpacing = shareConfig.letterSpacing
|
||||
exportConfig.lineSpacingExtra = shareConfig.lineSpacingExtra
|
||||
exportConfig.paragraphSpacing = shareConfig.paragraphSpacing
|
||||
exportConfig.titleMode = shareConfig.titleMode
|
||||
exportConfig.titleSize = shareConfig.titleSize
|
||||
exportConfig.titleTopSpacing = shareConfig.titleTopSpacing
|
||||
exportConfig.titleBottomSpacing = shareConfig.titleBottomSpacing
|
||||
exportConfig.paddingBottom = shareConfig.paddingBottom
|
||||
exportConfig.paddingLeft = shareConfig.paddingLeft
|
||||
exportConfig.paddingRight = shareConfig.paddingRight
|
||||
exportConfig.paddingTop = shareConfig.paddingTop
|
||||
exportConfig.headerPaddingBottom = shareConfig.headerPaddingBottom
|
||||
exportConfig.headerPaddingLeft = shareConfig.headerPaddingLeft
|
||||
exportConfig.headerPaddingRight = shareConfig.headerPaddingRight
|
||||
exportConfig.headerPaddingTop = shareConfig.headerPaddingTop
|
||||
exportConfig.footerPaddingBottom = shareConfig.footerPaddingBottom
|
||||
exportConfig.footerPaddingLeft = shareConfig.footerPaddingLeft
|
||||
exportConfig.footerPaddingRight = shareConfig.footerPaddingRight
|
||||
exportConfig.footerPaddingTop = shareConfig.footerPaddingTop
|
||||
exportConfig.showHeaderLine = shareConfig.showHeaderLine
|
||||
exportConfig.showFooterLine = shareConfig.showFooterLine
|
||||
exportConfig.tipHeaderLeft = shareConfig.tipHeaderLeft
|
||||
exportConfig.tipHeaderMiddle = shareConfig.tipHeaderMiddle
|
||||
exportConfig.tipHeaderRight = shareConfig.tipHeaderRight
|
||||
exportConfig.tipFooterLeft = shareConfig.tipFooterLeft
|
||||
exportConfig.tipFooterMiddle = shareConfig.tipFooterMiddle
|
||||
exportConfig.tipFooterRight = shareConfig.tipFooterRight
|
||||
exportConfig.tipColor = shareConfig.tipColor
|
||||
exportConfig.headerMode = shareConfig.headerMode
|
||||
exportConfig.footerMode = shareConfig.footerMode
|
||||
}
|
||||
return exportConfig
|
||||
}
|
||||
|
||||
suspend fun import(byteArray: ByteArray): Result<Config> {
|
||||
return kotlin.runCatching {
|
||||
withContext(IO) {
|
||||
val configZipPath = FileUtils.getPath(appCtx.externalCache, "readConfig.zip")
|
||||
FileUtils.delete(configZipPath)
|
||||
val zipFile = FileUtils.createFileIfNotExist(configZipPath)
|
||||
zipFile.writeBytes(byteArray)
|
||||
val configDir = appCtx.externalCache.getFile("readConfig")
|
||||
configDir.createFolderReplace()
|
||||
ZipUtils.unZipToPath(zipFile, configDir)
|
||||
val configFile = configDir.getFile(configFileName)
|
||||
val config: Config = GSON.fromJsonObject<Config>(configFile.readText()).getOrThrow()
|
||||
if (config.textFont.isNotEmpty()) {
|
||||
val fontName = FileUtils.getName(config.textFont)
|
||||
val fontPath =
|
||||
FileUtils.getPath(appCtx.externalFiles, "font", fontName)
|
||||
if (!FileUtils.exist(fontPath)) {
|
||||
configDir.getFile(fontName).copyTo(File(fontPath))
|
||||
}
|
||||
config.textFont = fontPath
|
||||
}
|
||||
if (config.bgType == 2) {
|
||||
val bgName = FileUtils.getName(config.bgStr)
|
||||
config.bgStr = bgName
|
||||
val bgPath = FileUtils.getPath(appCtx.externalFiles, "bg", bgName)
|
||||
if (!FileUtils.exist(bgPath)) {
|
||||
val bgFile = configDir.getFile(bgName)
|
||||
if (bgFile.exists()) {
|
||||
bgFile.copyTo(File(bgPath))
|
||||
}
|
||||
}
|
||||
config.bgStr = bgPath
|
||||
}
|
||||
if (config.bgTypeNight == 2) {
|
||||
val bgName = FileUtils.getName(config.bgStrNight)
|
||||
config.bgStrNight = bgName
|
||||
val bgPath = FileUtils.getPath(appCtx.externalFiles, "bg", bgName)
|
||||
if (!FileUtils.exist(bgPath)) {
|
||||
val bgFile = configDir.getFile(bgName)
|
||||
if (bgFile.exists()) {
|
||||
bgFile.copyTo(File(bgPath))
|
||||
}
|
||||
}
|
||||
config.bgStrNight = bgPath
|
||||
}
|
||||
if (config.bgTypeEInk == 2) {
|
||||
val bgName = FileUtils.getName(config.bgStrEInk)
|
||||
config.bgStrEInk = bgName
|
||||
val bgPath = FileUtils.getPath(appCtx.externalFiles, "bg", bgName)
|
||||
if (!FileUtils.exist(bgPath)) {
|
||||
val bgFile = configDir.getFile(bgName)
|
||||
if (bgFile.exists()) {
|
||||
bgFile.copyTo(File(bgPath))
|
||||
}
|
||||
}
|
||||
config.bgStrEInk = bgPath
|
||||
}
|
||||
return@withContext config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
data class Config(
|
||||
var name: String = "",
|
||||
var bgStr: String = "#EEEEEE",//白天背景
|
||||
var bgStrNight: String = "#000000",//夜间背景
|
||||
var bgStrEInk: String = "#FFFFFF",//EInk背景
|
||||
var bgAlpha: Int = 100,//背景透明度
|
||||
var bgType: Int = 0,//白天背景类型 0:颜色, 1:assets图片, 2其它图片
|
||||
var bgTypeNight: Int = 0,//夜间背景类型
|
||||
var bgTypeEInk: Int = 0,//EInk背景类型
|
||||
private var darkStatusIcon: Boolean = true,//白天是否暗色状态栏
|
||||
private var darkStatusIconNight: Boolean = false,//晚上是否暗色状态栏
|
||||
private var darkStatusIconEInk: Boolean = true,
|
||||
private var textColor: String = "#3E3D3B",//白天文字颜色
|
||||
private var textColorNight: String = "#ADADAD",//夜间文字颜色
|
||||
private var textColorEInk: String = "#000000",
|
||||
private var pageAnim: Int = 0,//翻页动画
|
||||
private var pageAnimEInk: Int = 4,
|
||||
var textFont: String = "",//字体
|
||||
var textBold: Int = 0,//是否粗体字 0:正常, 1:粗体, 2:细体
|
||||
var textSize: Int = 20,//文字大小
|
||||
var letterSpacing: Float = 0.1f,//字间距
|
||||
var lineSpacingExtra: Int = 12,//行间距
|
||||
var paragraphSpacing: Int = 2,//段距
|
||||
var titleMode: Int = 0,//标题位置 0:居左 1:居中 2:隐藏
|
||||
var titleSize: Int = 0,
|
||||
var titleTopSpacing: Int = 0,
|
||||
var titleBottomSpacing: Int = 0,
|
||||
var paragraphIndent: String = " ",//段落缩进
|
||||
var underline: Boolean = false, //下划线
|
||||
var paddingBottom: Int = 6,
|
||||
var paddingLeft: Int = 16,
|
||||
var paddingRight: Int = 16,
|
||||
var paddingTop: Int = 6,
|
||||
var headerPaddingBottom: Int = 0,
|
||||
var headerPaddingLeft: Int = 16,
|
||||
var headerPaddingRight: Int = 16,
|
||||
var headerPaddingTop: Int = 0,
|
||||
var footerPaddingBottom: Int = 6,
|
||||
var footerPaddingLeft: Int = 16,
|
||||
var footerPaddingRight: Int = 16,
|
||||
var footerPaddingTop: Int = 6,
|
||||
var showHeaderLine: Boolean = false,
|
||||
var showFooterLine: Boolean = true,
|
||||
var tipHeaderLeft: Int = ReadTipConfig.time,
|
||||
var tipHeaderMiddle: Int = ReadTipConfig.none,
|
||||
var tipHeaderRight: Int = ReadTipConfig.battery,
|
||||
var tipFooterLeft: Int = ReadTipConfig.chapterTitle,
|
||||
var tipFooterMiddle: Int = ReadTipConfig.none,
|
||||
var tipFooterRight: Int = ReadTipConfig.pageAndTotal,
|
||||
var tipColor: Int = 0,
|
||||
var tipDividerColor: Int = -1,
|
||||
var headerMode: Int = 0,
|
||||
var footerMode: Int = 0
|
||||
) {
|
||||
|
||||
@Transient
|
||||
private var textColorIntEInk = -1
|
||||
|
||||
@Transient
|
||||
private var textColorIntNight = -1
|
||||
|
||||
@Transient
|
||||
private var textColorInt = -1
|
||||
|
||||
@Transient
|
||||
private var initColorInt = false
|
||||
|
||||
private fun initColorInt() {
|
||||
textColorIntEInk = Color.parseColor(textColorEInk)
|
||||
textColorIntNight = Color.parseColor(textColorNight)
|
||||
textColorInt = Color.parseColor(textColor)
|
||||
initColorInt = true
|
||||
}
|
||||
|
||||
fun setCurTextColor(color: Int) {
|
||||
when {
|
||||
AppConfig.isEInkMode -> {
|
||||
textColorEInk = "#${color.hexString}"
|
||||
textColorIntEInk = color
|
||||
}
|
||||
|
||||
AppConfig.isNightTheme -> {
|
||||
textColorNight = "#${color.hexString}"
|
||||
textColorIntNight = color
|
||||
}
|
||||
|
||||
else -> {
|
||||
textColor = "#${color.hexString}"
|
||||
textColorInt = color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun curTextColor(): Int {
|
||||
if (!initColorInt) {
|
||||
initColorInt()
|
||||
}
|
||||
return when {
|
||||
AppConfig.isEInkMode -> textColorIntEInk
|
||||
AppConfig.isNightTheme -> textColorIntNight
|
||||
else -> textColorInt
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurStatusIconDark(isDark: Boolean) {
|
||||
when {
|
||||
AppConfig.isEInkMode -> darkStatusIconEInk = isDark
|
||||
AppConfig.isNightTheme -> darkStatusIconNight = isDark
|
||||
else -> darkStatusIcon = isDark
|
||||
}
|
||||
}
|
||||
|
||||
fun curStatusIconDark(): Boolean {
|
||||
return when {
|
||||
AppConfig.isEInkMode -> darkStatusIconEInk
|
||||
AppConfig.isNightTheme -> darkStatusIconNight
|
||||
else -> darkStatusIcon
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurPageAnim(@PageAnim.Anim anim: Int) {
|
||||
when {
|
||||
AppConfig.isEInkMode -> pageAnimEInk = anim
|
||||
else -> pageAnim = anim
|
||||
}
|
||||
}
|
||||
|
||||
fun curPageAnim(): Int {
|
||||
return when {
|
||||
AppConfig.isEInkMode -> pageAnimEInk
|
||||
else -> pageAnim
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurBg(bgType: Int, bg: String) {
|
||||
when {
|
||||
AppConfig.isEInkMode -> {
|
||||
bgTypeEInk = bgType
|
||||
bgStrEInk = bg
|
||||
}
|
||||
|
||||
AppConfig.isNightTheme -> {
|
||||
bgTypeNight = bgType
|
||||
bgStrNight = bg
|
||||
}
|
||||
|
||||
else -> {
|
||||
this.bgType = bgType
|
||||
bgStr = bg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun curBgStr(): String {
|
||||
return when {
|
||||
AppConfig.isEInkMode -> bgStrEInk
|
||||
AppConfig.isNightTheme -> bgStrNight
|
||||
else -> bgStr
|
||||
}
|
||||
}
|
||||
|
||||
fun curBgType(): Int {
|
||||
return when {
|
||||
AppConfig.isEInkMode -> bgTypeEInk
|
||||
AppConfig.isNightTheme -> bgTypeNight
|
||||
else -> bgType
|
||||
}
|
||||
}
|
||||
|
||||
fun curBgDrawable(width: Int, height: Int): Drawable {
|
||||
if (width == 0 || height == 0) {
|
||||
val backgroundColor = MaterialColors.getColor(appCtx, com.google.android.material.R.attr.colorSurface, Color.WHITE)
|
||||
return ColorDrawable(backgroundColor)
|
||||
}
|
||||
|
||||
var bgDrawable: Drawable? = null
|
||||
val resources = appCtx.resources
|
||||
try {
|
||||
bgDrawable = when (curBgType()) {
|
||||
0 -> ColorDrawable(Color.parseColor(curBgStr()))
|
||||
1 -> {
|
||||
val path = "bg" + File.separator + curBgStr()
|
||||
val bitmap = BitmapUtils.decodeAssetsBitmap(appCtx, path, width, height)
|
||||
BitmapDrawable(resources, bitmap?.resizeAndRecycle(width, height))
|
||||
}
|
||||
else -> {
|
||||
val path = curBgStr().let {
|
||||
if (it.contains(File.separator)) it
|
||||
else FileUtils.getPath(appCtx.externalFiles, "bg", curBgStr())
|
||||
}
|
||||
val bitmap = BitmapUtils.decodeBitmap(path, width, height)
|
||||
BitmapDrawable(resources, bitmap?.resizeAndRecycle(width, height))
|
||||
}
|
||||
}
|
||||
} catch (e: OutOfMemoryError) {
|
||||
e.printOnDebug()
|
||||
} catch (e: Exception) {
|
||||
e.printOnDebug()
|
||||
}
|
||||
|
||||
// fallback 使用 MD3 的 colorSurface 作为背景色
|
||||
val fallbackColor = MaterialColors.getColor(appCtx, com.google.android.material.R.attr.colorSurface, Color.WHITE)
|
||||
return bgDrawable ?: ColorDrawable(fallbackColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package io.legato.kazusa.help.config
|
||||
|
||||
import android.content.Context
|
||||
import io.legato.kazusa.R
|
||||
import splitties.init.appCtx
|
||||
|
||||
@Suppress("ConstPropertyName")
|
||||
object ReadTipConfig {
|
||||
|
||||
const val none = 0
|
||||
const val chapterTitle = 1
|
||||
const val time = 2
|
||||
const val battery = 3
|
||||
const val batteryPercentage = 10
|
||||
const val page = 4
|
||||
const val totalProgress = 5
|
||||
const val pageAndTotal = 6
|
||||
const val bookName = 7
|
||||
const val timeBattery = 8
|
||||
const val timeBatteryPercentage = 9
|
||||
const val totalProgress1 = 11
|
||||
|
||||
val tipValues = arrayOf(
|
||||
none, bookName, chapterTitle, time, battery, batteryPercentage, page,
|
||||
totalProgress, totalProgress1, pageAndTotal, timeBattery, timeBatteryPercentage
|
||||
)
|
||||
val tipNames get() = appCtx.resources.getStringArray(R.array.read_tip).toList()
|
||||
|
||||
val tipColorNames get() = appCtx.resources.getStringArray(R.array.tip_color).toList()
|
||||
val tipDividerColorNames
|
||||
get() = appCtx.resources.getStringArray(R.array.tip_divider_color).toList()
|
||||
|
||||
var tipHeaderLeft: Int
|
||||
get() = ReadBookConfig.config.tipHeaderLeft
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipHeaderLeft = value
|
||||
}
|
||||
|
||||
var tipHeaderMiddle: Int
|
||||
get() = ReadBookConfig.config.tipHeaderMiddle
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipHeaderMiddle = value
|
||||
}
|
||||
|
||||
var tipHeaderRight: Int
|
||||
get() = ReadBookConfig.config.tipHeaderRight
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipHeaderRight = value
|
||||
}
|
||||
|
||||
var tipFooterLeft: Int
|
||||
get() = ReadBookConfig.config.tipFooterLeft
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipFooterLeft = value
|
||||
}
|
||||
|
||||
var tipFooterMiddle: Int
|
||||
get() = ReadBookConfig.config.tipFooterMiddle
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipFooterMiddle = value
|
||||
}
|
||||
|
||||
var tipFooterRight: Int
|
||||
get() = ReadBookConfig.config.tipFooterRight
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipFooterRight = value
|
||||
}
|
||||
|
||||
var headerMode: Int
|
||||
get() = ReadBookConfig.config.headerMode
|
||||
set(value) {
|
||||
ReadBookConfig.config.headerMode = value
|
||||
}
|
||||
|
||||
var footerMode: Int
|
||||
get() = ReadBookConfig.config.footerMode
|
||||
set(value) {
|
||||
ReadBookConfig.config.footerMode = value
|
||||
}
|
||||
|
||||
var tipColor: Int
|
||||
get() = ReadBookConfig.config.tipColor
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipColor = value
|
||||
}
|
||||
|
||||
var tipDividerColor: Int
|
||||
get() = ReadBookConfig.config.tipDividerColor
|
||||
set(value) {
|
||||
ReadBookConfig.config.tipDividerColor = value
|
||||
}
|
||||
|
||||
fun getHeaderModes(context: Context): LinkedHashMap<Int, String> {
|
||||
return linkedMapOf(
|
||||
Pair(0, context.getString(R.string.hide_when_status_bar_show)),
|
||||
Pair(1, context.getString(R.string.show)),
|
||||
Pair(2, context.getString(R.string.hide))
|
||||
)
|
||||
}
|
||||
|
||||
fun getFooterModes(context: Context): LinkedHashMap<Int, String> {
|
||||
return linkedMapOf(
|
||||
Pair(0, context.getString(R.string.show)),
|
||||
Pair(1, context.getString(R.string.hide))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package io.legato.kazusa.help.config
|
||||
|
||||
import android.content.Context.MODE_PRIVATE
|
||||
import androidx.core.content.edit
|
||||
import splitties.init.appCtx
|
||||
|
||||
object SourceConfig {
|
||||
private val sp = appCtx.getSharedPreferences("SourceConfig", MODE_PRIVATE)
|
||||
fun setBookScore(origin: String, name: String, author: String, score: Int) {
|
||||
sp.edit {
|
||||
val preScore = getBookScore(origin, name, author)
|
||||
var newScore = score
|
||||
if (preScore != 0) {
|
||||
newScore = score - preScore
|
||||
}
|
||||
|
||||
putInt(origin, getSourceScore(origin) + newScore)
|
||||
|
||||
putInt("${origin}_${name}_${author}", score)
|
||||
}
|
||||
}
|
||||
|
||||
fun getBookScore(origin: String, name: String, author: String): Int {
|
||||
return sp.getInt("${origin}_${name}_${author}", 0)
|
||||
}
|
||||
|
||||
fun getSourceScore(origin: String): Int {
|
||||
return sp.getInt(origin, 0)
|
||||
}
|
||||
|
||||
|
||||
fun removeSource(origin: String) {
|
||||
sp.all.keys.filter {
|
||||
it.startsWith(origin)
|
||||
}.let {
|
||||
sp.edit {
|
||||
it.forEach {
|
||||
remove(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
package io.legato.kazusa.help.config
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.util.DisplayMetrics
|
||||
import androidx.annotation.Keep
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.constant.EventBus
|
||||
import io.legato.kazusa.constant.PreferKey
|
||||
import io.legato.kazusa.constant.Theme
|
||||
import io.legato.kazusa.help.DefaultData
|
||||
import io.legato.kazusa.lib.theme.ThemeStore
|
||||
import io.legato.kazusa.model.BookCover
|
||||
import io.legato.kazusa.utils.BitmapUtils
|
||||
import io.legato.kazusa.utils.ColorUtils
|
||||
import io.legato.kazusa.utils.FileUtils
|
||||
import io.legato.kazusa.utils.GSON
|
||||
import io.legato.kazusa.utils.fromJsonArray
|
||||
import io.legato.kazusa.utils.fromJsonObject
|
||||
import io.legato.kazusa.utils.getCompatColor
|
||||
import io.legato.kazusa.utils.getPrefInt
|
||||
import io.legato.kazusa.utils.getPrefString
|
||||
import io.legato.kazusa.utils.hexString
|
||||
import io.legato.kazusa.utils.postEvent
|
||||
import io.legato.kazusa.utils.printOnDebug
|
||||
import io.legato.kazusa.utils.putPrefInt
|
||||
import io.legato.kazusa.utils.stackBlur
|
||||
import splitties.init.appCtx
|
||||
import java.io.File
|
||||
import androidx.core.graphics.toColorInt
|
||||
|
||||
@Keep
|
||||
object ThemeConfig {
|
||||
const val configFileName = "themeConfig.json"
|
||||
val configFilePath = FileUtils.getPath(appCtx.filesDir, configFileName)
|
||||
|
||||
val configList: ArrayList<Config> by lazy {
|
||||
val cList = getConfigs() ?: DefaultData.themeConfigs
|
||||
ArrayList(cList)
|
||||
}
|
||||
|
||||
fun getTheme() = when {
|
||||
AppConfig.isEInkMode -> Theme.EInk
|
||||
AppConfig.isNightTheme -> Theme.Dark
|
||||
else -> Theme.Light
|
||||
}
|
||||
|
||||
fun isDarkTheme(): Boolean {
|
||||
return getTheme() == Theme.Dark
|
||||
}
|
||||
|
||||
fun applyDayNight(context: Context) {
|
||||
applyTheme(context)
|
||||
initNightMode()
|
||||
BookCover.upDefaultCover()
|
||||
postEvent(EventBus.RECREATE, "")
|
||||
}
|
||||
|
||||
fun applyDayNightInit(context: Context) {
|
||||
applyTheme(context)
|
||||
initNightMode()
|
||||
}
|
||||
|
||||
private fun initNightMode() {
|
||||
val targetMode =
|
||||
if (AppConfig.isNightTheme) {
|
||||
AppCompatDelegate.MODE_NIGHT_YES
|
||||
} else {
|
||||
AppCompatDelegate.MODE_NIGHT_NO
|
||||
}
|
||||
AppCompatDelegate.setDefaultNightMode(targetMode)
|
||||
}
|
||||
|
||||
fun getBgImage(context: Context, metrics: DisplayMetrics): Bitmap? {
|
||||
val bgCfg = when (getTheme()) {
|
||||
Theme.Light -> Pair(
|
||||
context.getPrefString(PreferKey.bgImage),
|
||||
context.getPrefInt(PreferKey.bgImageBlurring, 0)
|
||||
)
|
||||
|
||||
Theme.Dark -> Pair(
|
||||
context.getPrefString(PreferKey.bgImageN),
|
||||
context.getPrefInt(PreferKey.bgImageNBlurring, 0)
|
||||
)
|
||||
|
||||
else -> null
|
||||
} ?: return null
|
||||
if (bgCfg.first.isNullOrBlank()) return null
|
||||
val bgImage = BitmapUtils
|
||||
.decodeBitmap(bgCfg.first!!, metrics.widthPixels, metrics.heightPixels)
|
||||
if (bgCfg.second == 0) {
|
||||
return bgImage
|
||||
}
|
||||
return bgImage?.stackBlur(bgCfg.second)
|
||||
}
|
||||
|
||||
fun upConfig() {
|
||||
getConfigs()?.forEach { config ->
|
||||
addConfig(config)
|
||||
}
|
||||
}
|
||||
|
||||
fun save() {
|
||||
val json = GSON.toJson(configList)
|
||||
FileUtils.delete(configFilePath)
|
||||
FileUtils.createFileIfNotExist(configFilePath).writeText(json)
|
||||
}
|
||||
|
||||
fun delConfig(index: Int) {
|
||||
configList.removeAt(index)
|
||||
save()
|
||||
}
|
||||
|
||||
fun addConfig(json: String): Boolean {
|
||||
GSON.fromJsonObject<Config>(json.trim { it < ' ' }).getOrNull()
|
||||
?.let {
|
||||
addConfig(it)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun addConfig(newConfig: Config) {
|
||||
configList.forEachIndexed { index, config ->
|
||||
if (newConfig.themeName == config.themeName) {
|
||||
configList[index] = newConfig
|
||||
return
|
||||
}
|
||||
}
|
||||
configList.add(newConfig)
|
||||
save()
|
||||
}
|
||||
|
||||
private fun getConfigs(): List<Config>? {
|
||||
val configFile = File(configFilePath)
|
||||
if (configFile.exists()) {
|
||||
kotlin.runCatching {
|
||||
val json = configFile.readText()
|
||||
return GSON.fromJsonArray<Config>(json).getOrThrow()
|
||||
}.onFailure {
|
||||
it.printOnDebug()
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun applyConfig(context: Context, config: Config) {
|
||||
val primary = config.primaryColor.toColorInt()
|
||||
val accent = config.accentColor.toColorInt()
|
||||
val background = config.backgroundColor.toColorInt()
|
||||
val bBackground = config.bottomBackground.toColorInt()
|
||||
if (config.isNightTheme) {
|
||||
context.putPrefInt(PreferKey.cNPrimary, primary)
|
||||
context.putPrefInt(PreferKey.cNAccent, accent)
|
||||
context.putPrefInt(PreferKey.cNBackground, background)
|
||||
context.putPrefInt(PreferKey.cNBBackground, bBackground)
|
||||
} else {
|
||||
context.putPrefInt(PreferKey.cPrimary, primary)
|
||||
context.putPrefInt(PreferKey.cAccent, accent)
|
||||
context.putPrefInt(PreferKey.cBackground, background)
|
||||
context.putPrefInt(PreferKey.cBBackground, bBackground)
|
||||
}
|
||||
AppConfig.isNightTheme = config.isNightTheme
|
||||
applyDayNight(context)
|
||||
}
|
||||
|
||||
fun saveDayTheme(context: Context, name: String) {
|
||||
val primary =
|
||||
context.getPrefInt(PreferKey.cPrimary, context.getCompatColor(R.color.md_brown_500))
|
||||
val accent =
|
||||
context.getPrefInt(PreferKey.cAccent, context.getCompatColor(R.color.md_red_600))
|
||||
val background =
|
||||
context.getPrefInt(PreferKey.cBackground, context.getCompatColor(R.color.md_grey_100))
|
||||
val bBackground =
|
||||
context.getPrefInt(PreferKey.cBBackground, context.getCompatColor(R.color.md_grey_200))
|
||||
val config = Config(
|
||||
themeName = name,
|
||||
isNightTheme = false,
|
||||
primaryColor = "#${primary.hexString}",
|
||||
accentColor = "#${accent.hexString}",
|
||||
backgroundColor = "#${background.hexString}",
|
||||
bottomBackground = "#${bBackground.hexString}"
|
||||
)
|
||||
addConfig(config)
|
||||
}
|
||||
|
||||
fun saveNightTheme(context: Context, name: String) {
|
||||
val primary =
|
||||
context.getPrefInt(
|
||||
PreferKey.cNPrimary,
|
||||
context.getCompatColor(R.color.md_blue_grey_600)
|
||||
)
|
||||
val accent =
|
||||
context.getPrefInt(
|
||||
PreferKey.cNAccent,
|
||||
context.getCompatColor(R.color.md_deep_orange_800)
|
||||
)
|
||||
val background =
|
||||
context.getPrefInt(PreferKey.cNBackground, context.getCompatColor(R.color.md_grey_900))
|
||||
val bBackground =
|
||||
context.getPrefInt(PreferKey.cNBBackground, context.getCompatColor(R.color.md_grey_850))
|
||||
val config = Config(
|
||||
themeName = name,
|
||||
isNightTheme = true,
|
||||
primaryColor = "#${primary.hexString}",
|
||||
accentColor = "#${accent.hexString}",
|
||||
backgroundColor = "#${background.hexString}",
|
||||
bottomBackground = "#${bBackground.hexString}"
|
||||
)
|
||||
addConfig(config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新主题
|
||||
*/
|
||||
fun applyTheme(context: Context) = with(context) {
|
||||
when {
|
||||
AppConfig.isEInkMode -> {
|
||||
ThemeStore.editTheme(this)
|
||||
.primaryColor(Color.WHITE)
|
||||
.accentColor(Color.BLACK)
|
||||
.backgroundColor(Color.WHITE)
|
||||
.bottomBackground(Color.WHITE)
|
||||
.apply()
|
||||
}
|
||||
|
||||
AppConfig.isNightTheme -> {
|
||||
val primary =
|
||||
getPrefInt(PreferKey.cNPrimary, getCompatColor(R.color.md_blue_grey_600))
|
||||
val accent =
|
||||
getPrefInt(PreferKey.cNAccent, getCompatColor(R.color.md_deep_orange_800))
|
||||
var background =
|
||||
getPrefInt(PreferKey.cNBackground, getCompatColor(R.color.md_grey_900))
|
||||
if (ColorUtils.isColorLight(background)) {
|
||||
background = getCompatColor(R.color.md_grey_900)
|
||||
putPrefInt(PreferKey.cNBackground, background)
|
||||
}
|
||||
val bBackground =
|
||||
getPrefInt(PreferKey.cNBBackground, getCompatColor(R.color.md_grey_850))
|
||||
ThemeStore.editTheme(this)
|
||||
.primaryColor(ColorUtils.withAlpha(primary, 1f))
|
||||
.accentColor(ColorUtils.withAlpha(accent, 1f))
|
||||
.backgroundColor(ColorUtils.withAlpha(background, 1f))
|
||||
.bottomBackground(ColorUtils.withAlpha(bBackground, 1f))
|
||||
.apply()
|
||||
}
|
||||
|
||||
else -> {
|
||||
val primary =
|
||||
getPrefInt(PreferKey.cPrimary, getCompatColor(R.color.md_brown_500))
|
||||
val accent =
|
||||
getPrefInt(PreferKey.cAccent, getCompatColor(R.color.md_red_600))
|
||||
var background =
|
||||
getPrefInt(PreferKey.cBackground, getCompatColor(R.color.md_grey_100))
|
||||
if (!ColorUtils.isColorLight(background)) {
|
||||
background = getCompatColor(R.color.md_grey_100)
|
||||
putPrefInt(PreferKey.cBackground, background)
|
||||
}
|
||||
val bBackground =
|
||||
getPrefInt(PreferKey.cBBackground, getCompatColor(R.color.md_grey_200))
|
||||
ThemeStore.editTheme(this)
|
||||
.primaryColor(ColorUtils.withAlpha(primary, 1f))
|
||||
.accentColor(ColorUtils.withAlpha(accent, 1f))
|
||||
.backgroundColor(ColorUtils.withAlpha(background, 1f))
|
||||
.bottomBackground(ColorUtils.withAlpha(bBackground, 1f))
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
data class Config(
|
||||
var themeName: String,
|
||||
var isNightTheme: Boolean,
|
||||
var primaryColor: String,
|
||||
var accentColor: String,
|
||||
var backgroundColor: String,
|
||||
var bottomBackground: String
|
||||
) {
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return GSON.toJson(this).hashCode()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
other ?: return false
|
||||
if (other is Config) {
|
||||
return other.themeName == themeName
|
||||
&& other.isNightTheme == isNightTheme
|
||||
&& other.primaryColor == primaryColor
|
||||
&& other.accentColor == accentColor
|
||||
&& other.backgroundColor == backgroundColor
|
||||
&& other.bottomBackground == bottomBackground
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user