mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-05-12 02:20:46 +08:00
✨ Feature(custom): support custom background image
This commit is contained in:
@@ -37,6 +37,7 @@
|
|||||||
- 接入主题仓库 [PicList ThemeHub](https://github.com/Kuingsmile/PicList-ThemeHub),支持自定义下载
|
- 接入主题仓库 [PicList ThemeHub](https://github.com/Kuingsmile/PicList-ThemeHub),支持自定义下载
|
||||||
- 提供 12 个内置主题(如 bilibili、二次元、极夜紫等风格)
|
- 提供 12 个内置主题(如 bilibili、二次元、极夜紫等风格)
|
||||||
- 支持自定义主题编辑和保存
|
- 支持自定义主题编辑和保存
|
||||||
|
- 支持自定义背景图片
|
||||||
- 重新设计了管理功能的全部页面
|
- 重新设计了管理功能的全部页面
|
||||||
- 优化相册页面卡片样式,边界更清晰,提升选择框视觉效果
|
- 优化相册页面卡片样式,边界更清晰,提升选择框视觉效果
|
||||||
- 优化多个页面在窄屏下的显示,避免内容溢出
|
- 优化多个页面在窄屏下的显示,避免内容溢出
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ Use custom `javascript` scripts to extend PicList's functionality without the ne
|
|||||||
- Integrated theme repository [PicList ThemeHub](https://github.com/Kuingsmile/PicList-ThemeHub), supporting custom downloads.
|
- Integrated theme repository [PicList ThemeHub](https://github.com/Kuingsmile/PicList-ThemeHub), supporting custom downloads.
|
||||||
- Provided 12 built-in themes (such as bilibili, Anime, purple styles).
|
- Provided 12 built-in themes (such as bilibili, Anime, purple styles).
|
||||||
- Supports custom theme editing and saving.
|
- Supports custom theme editing and saving.
|
||||||
|
- Supports custom background images.
|
||||||
- Redesigned all pages of the management function
|
- Redesigned all pages of the management function
|
||||||
- Optimized album page card styles, clearer boundaries, improved selection box visual effects.
|
- Optimized album page card styles, clearer boundaries, improved selection box visual effects.
|
||||||
- Optimized the display of multiple pages under narrow screens to avoid content overflow.
|
- Optimized the display of multiple pages under narrow screens to avoid content overflow.
|
||||||
|
|||||||
@@ -68,6 +68,17 @@ export default [
|
|||||||
},
|
},
|
||||||
type: IRPCType.INVOKE,
|
type: IRPCType.INVOKE,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
action: IRPCActionType.COPY_CUSTOM_IMG_TO_THEMES_DIR,
|
||||||
|
handler: async (_: IIPCEvent, args: [filePath: string]) => {
|
||||||
|
const fileName = `custom-bgimg-${Date.now()}${path.extname(args[0])}`
|
||||||
|
const abFilePath = path.join(themesDir(), 'image', fileName)
|
||||||
|
fs.ensureDirSync(path.dirname(abFilePath))
|
||||||
|
fs.copyFileSync(args[0], abFilePath)
|
||||||
|
return fileName
|
||||||
|
},
|
||||||
|
type: IRPCType.INVOKE,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
action: IRPCActionType.THEME_WRITE_THEME,
|
action: IRPCActionType.THEME_WRITE_THEME,
|
||||||
handler: async (_: IIPCEvent, args: [fileName: string, content: string]) => {
|
handler: async (_: IIPCEvent, args: [fileName: string, content: string]) => {
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ export const IRPCActionType = {
|
|||||||
THEME_IMPORT_THEMES: 'THEME_IMPORT_THEMES',
|
THEME_IMPORT_THEMES: 'THEME_IMPORT_THEMES',
|
||||||
THEME_APPLY_THEME: 'THEME_APPLY_THEME',
|
THEME_APPLY_THEME: 'THEME_APPLY_THEME',
|
||||||
THEME_GET_BOOTSTRAP: 'THEME_GET_BOOTSTRAP',
|
THEME_GET_BOOTSTRAP: 'THEME_GET_BOOTSTRAP',
|
||||||
|
COPY_CUSTOM_IMG_TO_THEMES_DIR: 'COPY_CUSTOM_IMG_TO_THEMES_DIR',
|
||||||
|
|
||||||
RELOAD_APP: 'RELOAD_APP',
|
RELOAD_APP: 'RELOAD_APP',
|
||||||
OPEN_URL: 'OPEN_URL',
|
OPEN_URL: 'OPEN_URL',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ function setTheme(mode: string) {
|
|||||||
document.documentElement.classList.toggle('light', m === 'light')
|
document.documentElement.classList.toggle('light', m === 'light')
|
||||||
}
|
}
|
||||||
|
|
||||||
function injectCSS(css: string) {
|
function injectCSS(css: string, config: { imageUrl?: string; opacity?: string; blur?: string }) {
|
||||||
const id = '__piclist_theme__'
|
const id = '__piclist_theme__'
|
||||||
let el = document.getElementById(id) as HTMLStyleElement | null
|
let el = document.getElementById(id) as HTMLStyleElement | null
|
||||||
if (!el) {
|
if (!el) {
|
||||||
@@ -22,14 +22,33 @@ function injectCSS(css: string) {
|
|||||||
el.id = id
|
el.id = id
|
||||||
;(document.head || document.documentElement).appendChild(el)
|
;(document.head || document.documentElement).appendChild(el)
|
||||||
}
|
}
|
||||||
el.textContent = css
|
const overrides = `
|
||||||
|
:root, .dark, .light, [data-theme='dark'], [data-theme='light'] {
|
||||||
|
${config.imageUrl ? `--background-image: url("${config.imageUrl}") !important;` : ''}
|
||||||
|
${config.opacity ? `--background-image-opacity: ${config.opacity} !important;` : ''}
|
||||||
|
${config.blur ? `--background-blur: ${config.blur} !important;` : ''}
|
||||||
|
--color-background-primary: transparent !important;
|
||||||
|
--color-background-secondary: transparent !important;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
el.textContent = css + '\n' + overrides
|
||||||
}
|
}
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
try {
|
try {
|
||||||
const { mode, css } = await ipcRenderer.invoke('RPC_ACTIONS_INVOKE', 'THEME_GET_BOOTSTRAP')
|
const { mode, css } = await ipcRenderer.invoke('RPC_ACTIONS_INVOKE', 'THEME_GET_BOOTSTRAP')
|
||||||
|
const allConfig = await ipcRenderer.invoke('RPC_ACTIONS_INVOKE', 'PICLIST_GET_CONFIG', [])
|
||||||
|
const enableCustomBgImg = allConfig?.settings?.enableCustomBgImg || false
|
||||||
|
const customBgImgPath = allConfig?.settings?.customBgImgPath || ''
|
||||||
|
const config = enableCustomBgImg
|
||||||
|
? {
|
||||||
|
imageUrl: customBgImgPath,
|
||||||
|
opacity: '0.7',
|
||||||
|
blur: '5px',
|
||||||
|
}
|
||||||
|
: {}
|
||||||
if (document.documentElement) setTheme(mode)
|
if (document.documentElement) setTheme(mode)
|
||||||
if (css) injectCSS(css)
|
if (css) injectCSS(css, config)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[theme] bootstrap failed', e)
|
console.error('[theme] bootstrap failed', e)
|
||||||
}
|
}
|
||||||
@@ -117,8 +136,18 @@ try {
|
|||||||
return webUtils.getPathForFile(file)
|
return webUtils.getPathForFile(file)
|
||||||
},
|
},
|
||||||
onThemeUpdate: (callback: (css: string) => void) => {
|
onThemeUpdate: (callback: (css: string) => void) => {
|
||||||
const subscription = (_: any, css: string) => {
|
const subscription = async (_: any, css: string) => {
|
||||||
injectCSS(css)
|
const allConfig = await ipcRenderer.invoke('RPC_ACTIONS_INVOKE', 'PICLIST_GET_CONFIG', [])
|
||||||
|
const enableCustomBgImg = allConfig?.settings?.enableCustomBgImg || false
|
||||||
|
const customBgImgPath = allConfig?.settings?.customBgImgPath || ''
|
||||||
|
const config = enableCustomBgImg
|
||||||
|
? {
|
||||||
|
imageUrl: customBgImgPath,
|
||||||
|
opacity: '0.7',
|
||||||
|
blur: '5px',
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
injectCSS(css, config)
|
||||||
callback(css)
|
callback(css)
|
||||||
}
|
}
|
||||||
ipcRenderer.on('THEME_UPDATE', subscription)
|
ipcRenderer.on('THEME_UPDATE', subscription)
|
||||||
|
|||||||
@@ -901,6 +901,7 @@
|
|||||||
"autoLaunchDesc": "Automatically start PicList when system boots",
|
"autoLaunchDesc": "Automatically start PicList when system boots",
|
||||||
"chooseLanguage": "Choose Language",
|
"chooseLanguage": "Choose Language",
|
||||||
"chooseTheme": "Choose Theme",
|
"chooseTheme": "Choose Theme",
|
||||||
|
"customBgImgPath": "Select custom background img",
|
||||||
"customMiniIconPath": "Custom Mini Icon Path",
|
"customMiniIconPath": "Custom Mini Icon Path",
|
||||||
"downloadingThemes": "Downloading...",
|
"downloadingThemes": "Downloading...",
|
||||||
"downloadThemes": "Download Themes",
|
"downloadThemes": "Download Themes",
|
||||||
@@ -909,6 +910,7 @@
|
|||||||
"editTheme": "Edit Theme",
|
"editTheme": "Edit Theme",
|
||||||
"enableAdvancedAnimation": "Enable Advanced Animation",
|
"enableAdvancedAnimation": "Enable Advanced Animation",
|
||||||
"enableAdvancedAnimationDesc": "Do not enable this option on low-performance devices or when GPU acceleration is disabled",
|
"enableAdvancedAnimationDesc": "Do not enable this option on low-performance devices or when GPU acceleration is disabled",
|
||||||
|
"enableCustomBgImg": "Enable Custom Background img",
|
||||||
"getThemeContentFailed": "Failed to get theme content",
|
"getThemeContentFailed": "Failed to get theme content",
|
||||||
"hideDockHint": "Cannot hide both dock and tray at the same time",
|
"hideDockHint": "Cannot hide both dock and tray at the same time",
|
||||||
"importThemes": "Import Themes",
|
"importThemes": "Import Themes",
|
||||||
|
|||||||
@@ -901,6 +901,7 @@
|
|||||||
"autoLaunchDesc": "登录时自动启动 PicList",
|
"autoLaunchDesc": "登录时自动启动 PicList",
|
||||||
"chooseLanguage": "选择语言",
|
"chooseLanguage": "选择语言",
|
||||||
"chooseTheme": "选择主题",
|
"chooseTheme": "选择主题",
|
||||||
|
"customBgImgPath": "自定义背景图片选择",
|
||||||
"customMiniIconPath": "自定义迷你窗口图标路径",
|
"customMiniIconPath": "自定义迷你窗口图标路径",
|
||||||
"downloadingThemes": "下载中...",
|
"downloadingThemes": "下载中...",
|
||||||
"downloadThemes": "下载主题",
|
"downloadThemes": "下载主题",
|
||||||
@@ -909,6 +910,7 @@
|
|||||||
"editTheme": "编辑主题",
|
"editTheme": "编辑主题",
|
||||||
"enableAdvancedAnimation": "启用高级动画效果",
|
"enableAdvancedAnimation": "启用高级动画效果",
|
||||||
"enableAdvancedAnimationDesc": "不要在低性能设备上或关闭GPU加速时启用此选项",
|
"enableAdvancedAnimationDesc": "不要在低性能设备上或关闭GPU加速时启用此选项",
|
||||||
|
"enableCustomBgImg": "启用自定义背景图片",
|
||||||
"getThemeContentFailed": "获取主题内容失败",
|
"getThemeContentFailed": "获取主题内容失败",
|
||||||
"hideDockHint": "不支持同时隐藏 dock 和托盘",
|
"hideDockHint": "不支持同时隐藏 dock 和托盘",
|
||||||
"importThemes": "导入主题",
|
"importThemes": "导入主题",
|
||||||
|
|||||||
@@ -901,6 +901,7 @@
|
|||||||
"autoLaunchDesc": "系統啟動時自動啟動 PicList",
|
"autoLaunchDesc": "系統啟動時自動啟動 PicList",
|
||||||
"chooseLanguage": "選擇語言",
|
"chooseLanguage": "選擇語言",
|
||||||
"chooseTheme": "選擇主題",
|
"chooseTheme": "選擇主題",
|
||||||
|
"customBgImgPath": "選擇自定義背景圖片",
|
||||||
"customMiniIconPath": "自定義迷你窗口圖標路徑",
|
"customMiniIconPath": "自定義迷你窗口圖標路徑",
|
||||||
"downloadingThemes": "下載中...",
|
"downloadingThemes": "下載中...",
|
||||||
"downloadThemes": "下載主題",
|
"downloadThemes": "下載主題",
|
||||||
@@ -909,6 +910,7 @@
|
|||||||
"editTheme": "編輯主題",
|
"editTheme": "編輯主題",
|
||||||
"enableAdvancedAnimation": "啟用高級動畫效果",
|
"enableAdvancedAnimation": "啟用高級動畫效果",
|
||||||
"enableAdvancedAnimationDesc": "不要在低性能設備上或關閉GPU加速時啟用此選項",
|
"enableAdvancedAnimationDesc": "不要在低性能設備上或關閉GPU加速時啟用此選項",
|
||||||
|
"enableCustomBgImg": "啟用自定義背景圖片",
|
||||||
"getThemeContentFailed": "獲取主題內容失敗",
|
"getThemeContentFailed": "獲取主題內容失敗",
|
||||||
"hideDockHint": "不支持同時隱藏 dock 和托盤",
|
"hideDockHint": "不支持同時隱藏 dock 和托盤",
|
||||||
"importThemes": "導入主題",
|
"importThemes": "導入主題",
|
||||||
|
|||||||
@@ -128,6 +128,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</SettingCard>
|
</SettingCard>
|
||||||
|
|
||||||
|
<SettingCard p1 class="flex flex-col justify-center">
|
||||||
|
<CustomSwitch
|
||||||
|
v-model="formOfSetting.enableCustomBgImg"
|
||||||
|
no-border
|
||||||
|
small
|
||||||
|
:title="t('pages.settings.system.enableCustomBgImg')"
|
||||||
|
/>
|
||||||
|
</SettingCard>
|
||||||
|
|
||||||
|
<CustomNavCard
|
||||||
|
v-if="formOfSetting.enableCustomBgImg"
|
||||||
|
:icon="ImageIcon"
|
||||||
|
noarrow
|
||||||
|
:title="t('pages.settings.system.customBgImgPath')"
|
||||||
|
>
|
||||||
|
<template #extra>
|
||||||
|
<CustomButton type="primary" :text="t('pages.settings.clickToSet')" @click="handleCustomBgImg" />
|
||||||
|
</template>
|
||||||
|
</CustomNavCard>
|
||||||
</SettingSection>
|
</SettingSection>
|
||||||
|
|
||||||
<!-- Window Behavior Section -->
|
<!-- Window Behavior Section -->
|
||||||
@@ -195,7 +215,7 @@
|
|||||||
:title="t('pages.settings.system.customMiniIconPath')"
|
:title="t('pages.settings.system.customMiniIconPath')"
|
||||||
>
|
>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<CustomButton type="secondary" :text="t('pages.settings.clickToSet')" @click="handleMiniIconPath" />
|
<CustomButton type="primary" :text="t('pages.settings.clickToSet')" @click="handleMiniIconPath" />
|
||||||
</template>
|
</template>
|
||||||
</CustomNavCard>
|
</CustomNavCard>
|
||||||
</SettingSection>
|
</SettingSection>
|
||||||
@@ -1402,6 +1422,8 @@ const formOfSetting = ref<ISettingForm>({
|
|||||||
enableSecondUploader: false,
|
enableSecondUploader: false,
|
||||||
enableAdvancedAnimation: false,
|
enableAdvancedAnimation: false,
|
||||||
theme: 'default.css',
|
theme: 'default.css',
|
||||||
|
enableCustomBgImg: false,
|
||||||
|
customBgImgPath: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
/* computed properties */
|
/* computed properties */
|
||||||
@@ -1690,6 +1712,14 @@ const addWatch = () => {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => formOfSetting.value.enableCustomBgImg,
|
||||||
|
newVal => {
|
||||||
|
saveConfig({ [configPaths.settings.enableCustomBgImg]: newVal })
|
||||||
|
window.electron.sendRPC(IRPCActionType.RELOAD_WINDOW)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* methods */
|
/* methods */
|
||||||
@@ -2129,12 +2159,22 @@ function handleMiniWindowOntop(val: ICheckBoxValueType) {
|
|||||||
window.electron.sendRPC(IRPCActionType.MINI_WINDOW_ON_TOP, val)
|
window.electron.sendRPC(IRPCActionType.MINI_WINDOW_ON_TOP, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleCustomBgImg() {
|
||||||
|
const result = await window.electron.triggerRPC<string[]>(IRPCActionType.MANAGE_OPEN_FILE_SELECT_DIALOG)
|
||||||
|
if (result && result[0]) {
|
||||||
|
const fileName = await window.electron.triggerRPC<string>(IRPCActionType.COPY_CUSTOM_IMG_TO_THEMES_DIR, result[0])
|
||||||
|
formOfSetting.value.customBgImgPath = `theme://./image/${fileName}`
|
||||||
|
saveConfig(configPaths.settings.customBgImgPath, formOfSetting.value.customBgImgPath)
|
||||||
|
await window.electron.triggerRPC(IRPCActionType.THEME_APPLY_THEME, currentTheme.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleMiniIconPath() {
|
async function handleMiniIconPath() {
|
||||||
const result = await window.electron.triggerRPC<string[]>(IRPCActionType.MANAGE_OPEN_FILE_SELECT_DIALOG)
|
const result = await window.electron.triggerRPC<string[]>(IRPCActionType.MANAGE_OPEN_FILE_SELECT_DIALOG)
|
||||||
if (result && result[0]) {
|
if (result && result[0]) {
|
||||||
formOfSetting.value.customMiniIcon = result[0]
|
formOfSetting.value.customMiniIcon = result[0]
|
||||||
saveConfig(configPaths.settings.customMiniIcon, formOfSetting.value.customMiniIcon)
|
saveConfig(configPaths.settings.customMiniIcon, formOfSetting.value.customMiniIcon)
|
||||||
window.electron.sendRPC(IRPCActionType.UPDATE_MINI_WINDOW_ICON, formOfSetting.value.customMiniIcon)
|
window.electron.sendRPC(IRPCActionType.RELOAD_WINDOW)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,8 @@ export const configPaths = {
|
|||||||
systemTheme: 'settings.systemTheme',
|
systemTheme: 'settings.systemTheme',
|
||||||
enableAdvancedAnimation: 'settings.enableAdvancedAnimation',
|
enableAdvancedAnimation: 'settings.enableAdvancedAnimation',
|
||||||
isDisableGPU: 'settings.isDisableGPU',
|
isDisableGPU: 'settings.isDisableGPU',
|
||||||
|
enableCustomBgImg: 'settings.enableCustomBgImg',
|
||||||
|
customBgImgPath: 'settings.customBgImgPath',
|
||||||
},
|
},
|
||||||
needReload: 'needReload',
|
needReload: 'needReload',
|
||||||
picgoPlugins: 'picgoPlugins',
|
picgoPlugins: 'picgoPlugins',
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const IRPCActionType = {
|
|||||||
THEME_FETCH_THEMES: 'THEME_FETCH_THEMES',
|
THEME_FETCH_THEMES: 'THEME_FETCH_THEMES',
|
||||||
THEME_IMPORT_THEMES: 'THEME_IMPORT_THEMES',
|
THEME_IMPORT_THEMES: 'THEME_IMPORT_THEMES',
|
||||||
THEME_APPLY_THEME: 'THEME_APPLY_THEME',
|
THEME_APPLY_THEME: 'THEME_APPLY_THEME',
|
||||||
|
COPY_CUSTOM_IMG_TO_THEMES_DIR: 'COPY_CUSTOM_IMG_TO_THEMES_DIR',
|
||||||
OPEN_WINDOW: 'OPEN_WINDOW',
|
OPEN_WINDOW: 'OPEN_WINDOW',
|
||||||
OPEN_MINI_WINDOW: 'OPEN_MINI_WINDOW',
|
OPEN_MINI_WINDOW: 'OPEN_MINI_WINDOW',
|
||||||
CLOSE_WINDOW: 'CLOSE_WINDOW',
|
CLOSE_WINDOW: 'CLOSE_WINDOW',
|
||||||
|
|||||||
2
src/universal/types/view.d.ts
vendored
2
src/universal/types/view.d.ts
vendored
@@ -42,6 +42,8 @@ interface ISettingForm {
|
|||||||
enableSecondUploader: boolean
|
enableSecondUploader: boolean
|
||||||
enableAdvancedAnimation: boolean
|
enableAdvancedAnimation: boolean
|
||||||
theme: string
|
theme: string
|
||||||
|
enableCustomBgImg: boolean
|
||||||
|
customBgImgPath: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IToolboxItem {
|
interface IToolboxItem {
|
||||||
|
|||||||
Reference in New Issue
Block a user