diff --git a/src/common/utils/common.ts b/src/common/utils/common.ts index 945fb3a4..7aaa8b3a 100644 --- a/src/common/utils/common.ts +++ b/src/common/utils/common.ts @@ -60,6 +60,8 @@ export const decodeName = (str: string | null = '') => { return str?.replace(/(?:&|<|>|"|'|'| )/gm, (s: string) => encodeNames[s as keyof typeof encodeNames]) ?? '' } +export const isUrl = (path: string) => /https?:\/\//.test(path) + // 解析URL参数为对象 export const parseUrlParams = (str: string): Record => { const params: Record = {} diff --git a/src/main/utils/index.ts b/src/main/utils/index.ts index 21a768e3..2d3796c5 100644 --- a/src/main/utils/index.ts +++ b/src/main/utils/index.ts @@ -1,4 +1,4 @@ -import { throttle } from '@common/utils' +import { isUrl, throttle } from '@common/utils' import migrateSetting from '@common/utils/migrateSetting' import getStore from '@main/utils/store' import { STORE_NAMES, URL_SCHEME_RXP } from '@common/constants' @@ -247,7 +247,10 @@ export const getTheme = () => { if (theme) { if (theme.config.extInfo['--background-image'] != 'none') { theme = copyTheme(theme) - theme.config.extInfo['--background-image'] = `url(file:///${joinPath(global.lxDataPath, 'theme_images', theme.config.extInfo['--background-image']).replaceAll('\\', '/')})` + theme.config.extInfo['--background-image'] = + isUrl(theme.config.extInfo['--background-image']) + ? `url(${theme.config.extInfo['--background-image']})` + : `url(file:///${joinPath(global.lxDataPath, 'theme_images', theme.config.extInfo['--background-image']).replaceAll('\\', '/')})` } } else { themeId = global.lx.appSetting['theme.id'] == 'auto' && shouldUseDarkColors ? 'black' : 'green' diff --git a/src/renderer/store/utils.ts b/src/renderer/store/utils.ts index 5e570f15..808b7eff 100644 --- a/src/renderer/store/utils.ts +++ b/src/renderer/store/utils.ts @@ -6,6 +6,7 @@ // return listId == 'download' ? downloadList : getListFromState(listId) // } import { commonColorNames, commonDarkColorValues, commonLightColorValues } from '@common/config' +import { isUrl } from '@common/utils/common' import { joinPath } from '@common/utils/nodejs' import { markRaw, shallowReactive } from '@common/utils/vueTools' import { getThemes as getTheme } from '@renderer/utils/ipc' @@ -15,6 +16,12 @@ export const assertApiSupport = (source: LX.Source): boolean => { return source == 'local' || qualityList.value[source] != null } +export const buildBgUrl = (originUrl: string, dataPath: string): string => { + return isUrl(originUrl) + ? `url(${originUrl})` + : `url(file:///${joinPath(dataPath, originUrl).replaceAll('\\', '/')})` +} + export const getThemes = (callback: (themeInfo: LX.ThemeInfo) => void) => { if (themeInfo.themes.length) return callback(themeInfo) void getTheme().then(info => { @@ -27,7 +34,7 @@ export const getThemes = (callback: (themeInfo: LX.ThemeInfo) => void) => { export const buildThemeColors = (theme: LX.Theme, dataPath: string) => { if (theme.isCustom && theme.config.extInfo['--background-image'] != 'none') { theme = copyTheme(theme) - theme.config.extInfo['--background-image'] = `url(file:///${joinPath(dataPath, theme.config.extInfo['--background-image']).replaceAll('\\', '/')})` + theme.config.extInfo['--background-image'] = buildBgUrl(theme.config.extInfo['--background-image'], dataPath) } const colors: Record = { ...theme.config.themeColors, diff --git a/src/renderer/views/Setting/components/SettingBasic.vue b/src/renderer/views/Setting/components/SettingBasic.vue index 4a6bdf34..b293571f 100644 --- a/src/renderer/views/Setting/components/SettingBasic.vue +++ b/src/renderer/views/Setting/components/SettingBasic.vue @@ -100,8 +100,7 @@ import ThemeEditModal from './ThemeEditModal' import PlayTimeoutModal from './PlayTimeoutModal' import UserApiModal from './UserApiModal' import { appSetting, updateSetting } from '@renderer/store/setting' -import { getThemes, applyTheme, findTheme } from '@renderer/store/utils' -import { joinPath } from '@common/utils/nodejs' +import { getThemes, applyTheme, findTheme, buildBgUrl } from '@renderer/store/utils' export default { name: 'SettingBasic', @@ -126,13 +125,13 @@ export default { autoTheme['--background-image-theme-light'] = light.isCustom ? light.config.extInfo['--background-image'] == 'none' ? 'none' - : `url(file:///${joinPath(info.dataPath, light.config.extInfo['--background-image']).replaceAll('\\', '/')})` + : buildBgUrl(light.config.extInfo['--background-image'], info.dataPath) : light.config.extInfo['--background-image'] autoTheme['--color-primary-theme-dark'] = dark.config.themeColors['--color-theme'] autoTheme['--background-image-theme-dark'] = dark.isCustom ? dark.config.extInfo['--background-image'] == 'none' ? 'none' - : `url(file:///${joinPath(info.dataPath, dark.config.extInfo['--background-image']).replaceAll('\\', '/')})` + : buildBgUrl(dark.config.extInfo['--background-image'], info.dataPath) : dark.config.extInfo['--background-image'] } @@ -158,7 +157,7 @@ export default { '--color-primary-theme': t.config.themeColors['--color-theme'], '--background-image-theme': t.config.extInfo['--background-image'] == 'none' ? 'none' - : `url(file:///${joinPath(info.dataPath, t.config.extInfo['--background-image']).replaceAll('\\', '/')})`, + : buildBgUrl(t.config.extInfo['--background-image'], info.dataPath), }, } })) diff --git a/src/renderer/views/Setting/components/ThemeEditModal/index.vue b/src/renderer/views/Setting/components/ThemeEditModal/index.vue index 3f966bb6..07753b67 100644 --- a/src/renderer/views/Setting/components/ThemeEditModal/index.vue +++ b/src/renderer/views/Setting/components/ThemeEditModal/index.vue @@ -120,6 +120,7 @@ import { joinPath, extname, copyFile, checkPath, createDir, removeFile, moveFile, basename } from '@common/utils/nodejs' import { nextTick, ref, watch } from '@common/utils/vueTools' import { applyTheme, buildThemeColors, getThemes, copyTheme } from '@renderer/store/utils' +import { isUrl } from '@common/utils/common' // import { appSetting, updateSetting } from '@renderer/store/setting' // import { applyTheme, getThemes } from '@renderer/store/utils' import { createThemeColors } from '@common/theme/utils' @@ -244,7 +245,9 @@ export default { bgImg.value = '' originBgName = '' } else { - bgImg.value = joinPath(themeInfo.dataPath, theme.config.extInfo['--background-image']) + bgImg.value = isUrl(theme.config.extInfo['--background-image']) + ? theme.config.extInfo['--background-image'] + : joinPath(themeInfo.dataPath, theme.config.extInfo['--background-image']) originBgName = theme.config.extInfo['--background-image'] } appBgColorOrigin = theme.config.extInfo['--color-app-background'] @@ -387,6 +390,10 @@ export default { theme.isDark = val applyPrimaryColor(theme.config.themeColors['--color-primary'], theme.isDark) } + /** + * 预览主题 + * @param {*} val 是否预览当前编辑的主题 + */ const handlePreview = (val) => { if (val) { createPreview() @@ -398,17 +405,20 @@ export default { handlePreview(false) emit('update:modelValue', false) } + // 保存 const handleSubmit = async() => { if (!themeName.value) return theme.name = themeName.value.substring(0, 20) // 保存新背景 - if (currentBgPath) { + if (currentBgPath && !isUrl(currentBgPath)) { const name = basename(currentBgPath) await moveFile(currentBgPath, joinPath(themeInfo.dataPath, name)) theme.config.extInfo['--background-image'] = name } // 移除旧背景 - if (originBgName && theme.config.extInfo['--background-image'] != originBgName) removeFile(joinPath(themeInfo.dataPath, originBgName)) + if (originBgName && + theme.config.extInfo['--background-image'] != originBgName && + !isUrl(theme.config.extInfo['--background-image'])) removeFile(joinPath(themeInfo.dataPath, originBgName)) if (props.themeId) { const index = themeInfo.userThemes.findIndex(t => t.id == theme.id) if (index > -1) themeInfo.userThemes.splice(index, 1, theme) @@ -418,6 +428,7 @@ export default { emit('submit') emit('update:modelValue', false) } + // 删除 const handleRemove = async() => { const confirm = await dialog.confirm({ message: window.i18n.t('theme_edit_modal__remove_tip'), @@ -452,19 +463,22 @@ export default { emit('submit') emit('update:modelValue', false) } + // 另存为 const handleSaveNew = async() => { if (!themeName.value) return theme.name = themeName.value.substring(0, 20) theme.id = 'user_theme_' + Date.now() // 保存新背景 - if (currentBgPath) { - const name = basename(currentBgPath) - await moveFile(currentBgPath, joinPath(themeInfo.dataPath, name)) - theme.config.extInfo['--background-image'] = name - } else if (bgImg.value) { - const fileName = `${theme.id}_${Date.now()}${extname(bgImg.value)}` - await copyFile(bgImg.value, joinPath(themeInfo.dataPath, fileName)) - theme.config.extInfo['--background-image'] = fileName + if (!isUrl(currentBgPath)) { + if (currentBgPath) { + const name = basename(currentBgPath) + await moveFile(currentBgPath, joinPath(themeInfo.dataPath, name)) + theme.config.extInfo['--background-image'] = name + } else if (bgImg.value) { + const fileName = `${theme.id}_${Date.now()}${extname(bgImg.value)}` + await copyFile(bgImg.value, joinPath(themeInfo.dataPath, fileName)) + theme.config.extInfo['--background-image'] = fileName + } } themeInfo.userThemes.push(theme) handlePreview(false) diff --git a/src/renderer/views/Setting/components/ThemeSelectorModal.vue b/src/renderer/views/Setting/components/ThemeSelectorModal.vue index d97ae87a..7cdfec0e 100644 --- a/src/renderer/views/Setting/components/ThemeSelectorModal.vue +++ b/src/renderer/views/Setting/components/ThemeSelectorModal.vue @@ -38,10 +38,9 @@