Perf(custom): reduce init time of gallery page and upload page form 100ms to 6ms

This commit is contained in:
Kuingsmile
2026-01-15 12:46:26 +08:00
parent ffcb779347
commit 3775e1ff1a
11 changed files with 131 additions and 33 deletions

View File

@@ -169,7 +169,10 @@ class LifeCycle {
initI18n() initI18n()
rpcServer.start() rpcServer.start()
busEventList.listen() busEventList.listen()
const isDisableGPU = picgo.getConfig<boolean>(configPaths.settings.isDisableGPU) || false
if (isDisableGPU) {
app.disableHardwareAcceleration()
}
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
MemoryMonitor.start(30000) MemoryMonitor.start(30000)
} }

View File

@@ -782,11 +782,15 @@
"downloadThemes": "Download Themes", "downloadThemes": "Download Themes",
"downloadThemesFailed": "Failed to download themes", "downloadThemesFailed": "Failed to download themes",
"downloadThemesSuccess": "Themes downloaded successfully", "downloadThemesSuccess": "Themes downloaded successfully",
"enableAdvancedAnimation": "Enable Advanced Animation",
"enableAdvancedAnimationDesc": "Do not enable this option on low-performance devices or when GPU acceleration is disabled",
"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",
"importThemesFailed": "Failed to import themes", "importThemesFailed": "Failed to import themes",
"importThemesSuccess": "Themes imported successfully", "importThemesSuccess": "Themes imported successfully",
"isCustomMiniIcon": "Custom Mini Icon", "isCustomMiniIcon": "Custom Mini Icon",
"isDisableGPU": "Disable GPU Acceleration",
"isDisableGPUDesc": "Improve compatibility but may reduce performance",
"isHideDock": "Hide Dock Icon", "isHideDock": "Hide Dock Icon",
"languageAndAppearance": "Language and Appearance", "languageAndAppearance": "Language and Appearance",
"mainMode": "Main Mode", "mainMode": "Main Mode",

View File

@@ -777,11 +777,15 @@
"downloadThemes": "下载主题", "downloadThemes": "下载主题",
"downloadThemesFailed": "下载主题失败", "downloadThemesFailed": "下载主题失败",
"downloadThemesSuccess": "主题下载成功", "downloadThemesSuccess": "主题下载成功",
"enableAdvancedAnimation": "启用高级动画效果",
"enableAdvancedAnimationDesc": "不要在低性能设备上或关闭GPU加速时启用此选项",
"hideDockHint": "不支持同时隐藏 dock 和托盘", "hideDockHint": "不支持同时隐藏 dock 和托盘",
"importThemes": "导入主题", "importThemes": "导入主题",
"importThemesFailed": "导入主题失败", "importThemesFailed": "导入主题失败",
"importThemesSuccess": "主题导入成功", "importThemesSuccess": "主题导入成功",
"isCustomMiniIcon": "是否自定义迷你窗口图标", "isCustomMiniIcon": "是否自定义迷你窗口图标",
"isDisableGPU": "禁用 GPU 加速",
"isDisableGPUDesc": "提升兼容性,但可能降低性能",
"isHideDock": "是否隐藏 Dock 图标", "isHideDock": "是否隐藏 Dock 图标",
"languageAndAppearance": "语言和外观", "languageAndAppearance": "语言和外观",
"mainMode": "主窗口", "mainMode": "主窗口",

View File

@@ -777,11 +777,15 @@
"downloadThemes": "下載主題", "downloadThemes": "下載主題",
"downloadThemesFailed": "下載主題失敗", "downloadThemesFailed": "下載主題失敗",
"downloadThemesSuccess": "主題下載成功", "downloadThemesSuccess": "主題下載成功",
"enableAdvancedAnimation": "啟用高級動畫效果",
"enableAdvancedAnimationDesc": "不要在低性能設備上或關閉GPU加速時啟用此選項",
"hideDockHint": "不支持同時隱藏 dock 和托盤", "hideDockHint": "不支持同時隱藏 dock 和托盤",
"importThemes": "導入主題", "importThemes": "導入主題",
"importThemesFailed": "導入主題失敗", "importThemesFailed": "導入主題失敗",
"importThemesSuccess": "主題導入成功", "importThemesSuccess": "主題導入成功",
"isCustomMiniIcon": "是否自定義迷你窗口圖標", "isCustomMiniIcon": "是否自定義迷你窗口圖標",
"isDisableGPU": "禁用 GPU 加速",
"isDisableGPUDesc": "提升兼容性,但可能降低性能",
"isHideDock": "是否隱藏 Dock 圖標", "isHideDock": "是否隱藏 Dock 圖標",
"languageAndAppearance": "語言和外觀", "languageAndAppearance": "語言和外觀",
"mainMode": "主窗口", "mainMode": "主窗口",

View File

@@ -281,7 +281,7 @@
@wheel="handleImageWheel" @wheel="handleImageWheel"
@keydown="handleKeydown" @keydown="handleKeydown"
> >
<div class="modal-backdrop" /> <div class="modal-backdrop" :class="advancedAnimation" />
<div class="modal-content"> <div class="modal-content">
<button class="modal-close" @click="handleClose"> <button class="modal-close" @click="handleClose">
<XIcon :size="24" /> <XIcon :size="24" />
@@ -352,7 +352,7 @@
<!-- Edit URL Modal --> <!-- Edit URL Modal -->
<transition name="modal"> <transition name="modal">
<div v-if="dialogVisible" class="modal-overlay" @click="dialogVisible = false"> <div v-if="dialogVisible" class="modal-overlay" :class="advancedAnimation" @click="dialogVisible = false">
<div class="modal-container" @click.stop> <div class="modal-container" @click.stop>
<div class="modal-header"> <div class="modal-header">
<h3>{{ t('pages.gallery.changeImageUrl') }}</h3> <h3>{{ t('pages.gallery.changeImageUrl') }}</h3>
@@ -377,7 +377,12 @@
<!-- Batch Rename Modal --> <!-- Batch Rename Modal -->
<transition name="modal"> <transition name="modal">
<div v-if="isShowBatchRenameDialog" class="modal-overlay" @click="isShowBatchRenameDialog = false"> <div
v-if="isShowBatchRenameDialog"
class="modal-overlay"
:class="advancedAnimation"
@click="isShowBatchRenameDialog = false"
>
<div class="modal-container large" @click.stop> <div class="modal-container large" @click.stop>
<div class="modal-header"> <div class="modal-header">
<h3>{{ t('pages.gallery.batchEditUrl') }}</h3> <h3>{{ t('pages.gallery.batchEditUrl') }}</h3>
@@ -587,6 +592,7 @@ const dateRangeEnd = ref('')
const picBedDropdownOpen = ref(false) const picBedDropdownOpen = ref(false)
const sortDropdownOpen = ref(false) const sortDropdownOpen = ref(false)
const showFormatInfo = ref(false) const showFormatInfo = ref(false)
const enableAdvancedAnimation = ref(false)
const viewMode = useStorage<'list' | 'grid'>('galleryViewMode', 'grid') const viewMode = useStorage<'list' | 'grid'>('galleryViewMode', 'grid')
const componentKey = ref(0) const componentKey = ref(0)
const currentSortField = ref<'name' | 'time' | 'ext' | 'check'>('name') const currentSortField = ref<'name' | 'time' | 'ext' | 'check'>('name')
@@ -668,6 +674,10 @@ function copyPlaceholder(placeholder: string) {
message.success(t('pages.settings.upload.copySuccess', { content: placeholder })) message.success(t('pages.settings.upload.copySuccess', { content: placeholder }))
} }
const advancedAnimation = computed(() => ({
advancedAnimation: enableAdvancedAnimation.value,
}))
const filterList = computed(() => { const filterList = computed(() => {
return getGallery() return getGallery()
}) })
@@ -1000,13 +1010,13 @@ onBeforeRouteUpdate((to, from) => {
}) })
async function initConf() { async function initConf() {
pasteStyle.value = (await getConfig(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN const settingConfig = await getConfig<any>('settings')
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl)) pasteStyle.value = settingConfig.pasteStyle || IPasteStyle.MARKDOWN
? t('pages.gallery.shortUrl') useShortUrl.value = settingConfig.useShortUrl ? t('pages.gallery.shortUrl') : t('pages.gallery.longUrl')
: t('pages.gallery.longUrl') enableAdvancedAnimation.value = settingConfig.enableAdvancedAnimation || false
isAlwaysForceReload.value = (await getConfig<boolean>(configPaths.settings.isAlwaysForceReload)) || false isAlwaysForceReload.value = settingConfig.isAlwaysForceReload || false
deleteCloud.value = (await getConfig<boolean>(configPaths.settings.deleteCloudFile)) || false deleteCloud.value = settingConfig.deleteCloudFile || false
galleryPicBedFilterSetting.value = (await getConfig<string[]>(configPaths.settings.galleryPicBedFilter)) || [] galleryPicBedFilterSetting.value = settingConfig.galleryPicBedFilter || []
} }
const updateGalleryHandler = () => { const updateGalleryHandler = () => {

View File

@@ -73,6 +73,28 @@
<option value="main">{{ t('pages.settings.system.mainMode') }}</option> <option value="main">{{ t('pages.settings.system.mainMode') }}</option>
</select> </select>
</div> </div>
<!-- Performance & Animation Toggles -->
<div class="system-toggle-card">
<label class="switch-label">
<input v-model="isDisableGPU" type="checkbox" class="switch-input" />
<span class="switch-slider" />
<div class="switch-content">
<div class="switch-title">{{ t('pages.settings.system.isDisableGPU') }}</div>
<div class="switch-description">{{ t('pages.settings.system.isDisableGPUDesc') }}</div>
</div>
</label>
</div>
<div class="system-toggle-card">
<label class="switch-label">
<input v-model="formOfSetting.enableAdvancedAnimation" type="checkbox" class="switch-input" />
<span class="switch-slider" />
<div class="switch-content">
<div class="switch-title">{{ t('pages.settings.system.enableAdvancedAnimation') }}</div>
<div class="switch-description">{{ t('pages.settings.system.enableAdvancedAnimationDesc') }}</div>
</div>
</label>
</div>
<div class="system-option-card"> <div class="system-option-card">
<div class="system-option-header"> <div class="system-option-header">
@@ -960,7 +982,7 @@
<!-- Dialogs --> <!-- Dialogs -->
<!-- Custom Link Format Dialog --> <!-- Custom Link Format Dialog -->
<div v-if="customLinkVisible" class="dialog-overlay" @click="customLinkVisible = false"> <div v-if="customLinkVisible" class="dialog-overlay" :class="advancedAnimation" @click="customLinkVisible = false">
<div class="dialog enhanced-dialog" @click.stop> <div class="dialog enhanced-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1011,7 +1033,7 @@
</div> </div>
<!-- Proxy Settings Dialog --> <!-- Proxy Settings Dialog -->
<div v-if="proxyVisible" class="dialog-overlay" @click="proxyVisible = false"> <div v-if="proxyVisible" class="dialog-overlay" :class="advancedAnimation" @click="proxyVisible = false">
<div class="dialog enhanced-dialog" @click.stop> <div class="dialog enhanced-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1078,7 +1100,7 @@
</div> </div>
<!-- Main Window Size Dialog --> <!-- Main Window Size Dialog -->
<div v-if="mainWindowSizeVisible" class="dialog-overlay"> <div v-if="mainWindowSizeVisible" class="dialog-overlay" :class="advancedAnimation">
<div class="dialog enhanced-dialog" @click.stop> <div class="dialog enhanced-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1133,7 +1155,7 @@
</div> </div>
<!-- Check Update Dialog --> <!-- Check Update Dialog -->
<div v-if="checkUpdateVisible" class="dialog-overlay" @click="cancelCheckVersion"> <div v-if="checkUpdateVisible" class="dialog-overlay" :class="advancedAnimation" @click="cancelCheckVersion">
<div class="dialog enhanced-dialog update-dialog" @click.stop> <div class="dialog enhanced-dialog update-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1182,7 +1204,12 @@
</div> </div>
<!-- Advanced Rename Dialog --> <!-- Advanced Rename Dialog -->
<div v-if="advancedRenameVisible" class="dialog-overlay" @click="handleCancelAdvancedRename"> <div
v-if="advancedRenameVisible"
class="dialog-overlay"
:class="advancedAnimation"
@click="handleCancelAdvancedRename"
>
<div class="dialog enhanced-dialog rename-dialog" @click.stop> <div class="dialog enhanced-dialog rename-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1282,7 +1309,7 @@
</div> </div>
<!-- Log Settings Dialog --> <!-- Log Settings Dialog -->
<div v-if="logFileVisible" class="dialog-overlay" @click="cancelLogLevelSetting"> <div v-if="logFileVisible" class="dialog-overlay" :class="advancedAnimation" @click="cancelLogLevelSetting">
<div class="dialog enhanced-dialog log-dialog" @click.stop> <div class="dialog enhanced-dialog log-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1371,7 +1398,7 @@
</div> </div>
<!-- Server Settings Dialog --> <!-- Server Settings Dialog -->
<div v-if="serverVisible" class="dialog-overlay" @click="cancelServerSetting"> <div v-if="serverVisible" class="dialog-overlay" :class="advancedAnimation" @click="cancelServerSetting">
<div class="dialog enhanced-dialog server-dialog" @click.stop> <div class="dialog enhanced-dialog server-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1447,7 +1474,7 @@
</div> </div>
<!-- Web Server Settings Dialog --> <!-- Web Server Settings Dialog -->
<div v-if="webServerVisible" class="dialog-overlay" @click="confirmWebServerSetting"> <div v-if="webServerVisible" class="dialog-overlay" :class="advancedAnimation" @click="confirmWebServerSetting">
<div class="dialog enhanced-dialog webserver-dialog" @click.stop> <div class="dialog enhanced-dialog webserver-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1530,7 +1557,7 @@
</div> </div>
<!-- Sync Configuration Dialog --> <!-- Sync Configuration Dialog -->
<div v-if="syncVisible" class="dialog-overlay"> <div v-if="syncVisible" class="dialog-overlay" :class="advancedAnimation">
<div class="dialog sync-config-dialog" @click.stop> <div class="dialog sync-config-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1687,7 +1714,12 @@
</div> </div>
<!-- Upload/Download Config Dialog --> <!-- Upload/Download Config Dialog -->
<div v-if="upDownConfigVisible" class="dialog-overlay" @click="upDownConfigVisible = false"> <div
v-if="upDownConfigVisible"
class="dialog-overlay"
:class="advancedAnimation"
@click="upDownConfigVisible = false"
>
<div class="dialog config-dialog" @click.stop> <div class="dialog config-dialog" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<div class="dialog-header-content"> <div class="dialog-header-content">
@@ -1765,7 +1797,12 @@
</div> </div>
<!-- Image Process Dialog --> <!-- Image Process Dialog -->
<div v-if="imageProcessDialogVisible" class="dialog-overlay" @click="imageProcessDialogVisible = false"> <div
v-if="imageProcessDialogVisible"
class="dialog-overlay"
:class="advancedAnimation"
@click="imageProcessDialogVisible = false"
>
<div class="dialog large" @click.stop> <div class="dialog large" @click.stop>
<div class="dialog-header"> <div class="dialog-header">
<h3 class="dialog-title"> <h3 class="dialog-title">
@@ -1838,6 +1875,7 @@ const galleryPicBedFilterList = ref<string[]>([])
const themeList = ref<{ key: string; label: string }[]>([{ key: 'default.css', label: '默认' }]) const themeList = ref<{ key: string; label: string }[]>([{ key: 'default.css', label: '默认' }])
const currentTheme = ref('default.css') const currentTheme = ref('default.css')
const downloadingThemes = ref(false) const downloadingThemes = ref(false)
const isDisableGPU = ref(false)
const currentTab = useStorage<'system' | 'sync' | 'upload' | 'advanced' | 'update'>('settings-current-tab', 'system') const currentTab = useStorage<'system' | 'sync' | 'upload' | 'advanced' | 'update'>('settings-current-tab', 'system')
// Tab configuration // Tab configuration
@@ -1909,6 +1947,7 @@ const formOfSetting = ref<ISettingForm>({
mainWindowWidth: 1200, mainWindowWidth: 1200,
mainWindowHeight: 800, mainWindowHeight: 800,
enableSecondUploader: false, enableSecondUploader: false,
enableAdvancedAnimation: false,
theme: 'default.css', theme: 'default.css',
}) })
@@ -1946,8 +1985,13 @@ const autoWatchKeys = [
'encodeOutputURL', 'encodeOutputURL',
'useShortUrl', 'useShortUrl',
'enableSecondUploader', 'enableSecondUploader',
'enableAdvancedAnimation',
] ]
const advancedAnimation = computed(() => ({
advancedAnimation: formOfSetting.value.enableAdvancedAnimation,
}))
const addWatch = () => { const addWatch = () => {
autoWatchKeys.forEach(key => { autoWatchKeys.forEach(key => {
watch( watch(
@@ -1989,6 +2033,11 @@ const addWatch = () => {
handleThemeChange(newVal) handleThemeChange(newVal)
} }
}) })
watch(isDisableGPU, newVal => {
message.info(t('pages.settings.system.needRestart'))
saveConfig({ [configPaths.settings.isDisableGPU]: newVal })
})
} }
const addProxyWatch = () => { const addProxyWatch = () => {
@@ -2186,6 +2235,7 @@ async function handleThemeChange(theme: string) {
async function initData() { async function initData() {
const config = (await getConfig<IConfig>()) || ({} as IConfig) const config = (await getConfig<IConfig>()) || ({} as IConfig)
isDisableGPU.value = (await getConfig<boolean>(configPaths.settings.isDisableGPU)) || false
const settings = config.settings || {} const settings = config.settings || {}
const picBed = config.picBed const picBed = config.picBed
showPicBedList.value = picBedG.value.filter(item => item.visible).map(item => item.name) showPicBedList.value = picBedG.value.filter(item => item.visible).map(item => item.name)

View File

@@ -197,7 +197,7 @@
<!-- Image Process Dialog --> <!-- Image Process Dialog -->
<transition name="modal"> <transition name="modal">
<div v-if="imageProcessDialogVisible" class="modal-overlay" @click.stop> <div v-if="imageProcessDialogVisible" class="modal-overlay" :class="advancedAnimation" @click.stop>
<div class="modal-container" @click.stop> <div class="modal-container" @click.stop>
<div class="modal-header"> <div class="modal-header">
<h3 class="modal-title"> <h3 class="modal-title">
@@ -221,7 +221,7 @@
<!-- Task Queue Manager Modal --> <!-- Task Queue Manager Modal -->
<transition name="modal"> <transition name="modal">
<div v-if="taskDialogVisible" class="modal-overlay"> <div v-if="taskDialogVisible" class="modal-overlay" :class="advancedAnimation">
<div class="modal-container task-queue-modal" @click.stop> <div class="modal-container task-queue-modal" @click.stop>
<div class="modal-header"> <div class="modal-header">
<div class="modal-header-text"> <div class="modal-header-text">
@@ -663,6 +663,7 @@ const progress = ref(0)
const showProgress = ref(false) const showProgress = ref(false)
const showError = ref(false) const showError = ref(false)
const pasteStyle = ref(IPasteStyle.MARKDOWN) const pasteStyle = ref(IPasteStyle.MARKDOWN)
const enableAdvancedAnimation = ref(false)
const PicBedId = ref('') const PicBedId = ref('')
const fileInput = useTemplateRef('fileInput') const fileInput = useTemplateRef('fileInput')
const uploadInterval = ref(1000) const uploadInterval = ref(1000)
@@ -860,14 +861,17 @@ function ipcSendFiles(files: FileList) {
window.electron.sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, sendFiles) window.electron.sendRPC(IRPCActionType.UPLOAD_CHOOSED_FILES, sendFiles)
} }
async function getPasteStyle() { async function initConf() {
pasteStyle.value = (await getConfig(configPaths.settings.pasteStyle)) || IPasteStyle.MARKDOWN const settingConfig = await getConfig<any>('settings')
pasteFormatList.value.Custom = (await getConfig(configPaths.settings.customLink)) || '![$fileName]($url)' enableAdvancedAnimation.value = settingConfig?.enableAdvancedAnimation || false
pasteStyle.value = settingConfig?.pasteStyle || IPasteStyle.MARKDOWN
pasteFormatList.value.Custom = settingConfig?.customLink || '![$fileName]($url)'
useShortUrl.value = settingConfig?.useShortUrl || false
} }
async function getUseShortUrl() { const advancedAnimation = computed(() => ({
useShortUrl.value = (await getConfig(configPaths.settings.useShortUrl)) || false advancedAnimation: enableAdvancedAnimation.value,
} }))
function updatePasteStyle(style: string) { function updatePasteStyle(style: string) {
pasteStyle.value = style pasteStyle.value = style
@@ -1238,7 +1242,7 @@ onBeforeMount(async () => {
removeSyncPicBedListenerCallback = window.electron.ipcRendererOn('syncPicBed', syncPicBedHandler) removeSyncPicBedListenerCallback = window.electron.ipcRendererOn('syncPicBed', syncPicBedHandler)
removeTaskQueueUpdateListenerCallback = window.electron.ipcRendererOn('uploadTaskQueueUpdate', taskQueueUpdateHandler) removeTaskQueueUpdateListenerCallback = window.electron.ipcRendererOn('uploadTaskQueueUpdate', taskQueueUpdateHandler)
$bus.on(SHOW_INPUT_BOX_RESPONSE, handleInputBoxValue) $bus.on(SHOW_INPUT_BOX_RESPONSE, handleInputBoxValue)
await Promise.all([getUseShortUrl(), getPasteStyle(), refreshTaskStatus()]) await Promise.all([initConf(), refreshTaskStatus()])
}) })
</script> </script>

View File

@@ -1507,8 +1507,12 @@ input:checked + .switch-slider::before {
letter-spacing: 0.02em; letter-spacing: 0.02em;
} }
.advancedAnimation {
backdrop-filter: blur(5px) saturate(180%);
background: rgb(255 255 255 / 20%);
border: 1px solid rgb(255 255 255 / 30%);
box-shadow: 0 8px 32px rgb(0 0 0 / 10%);
}
.placeholder-item:hover { .placeholder-item:hover {
background: rgb(var(--color-accent-rgb), 0.08); background: rgb(var(--color-accent-rgb), 0.08);

View File

@@ -2667,3 +2667,10 @@ small {
padding: 0; padding: 0;
background: transparent; background: transparent;
} }
.advancedAnimation {
backdrop-filter: blur(5px) saturate(180%);
background: rgb(255 255 255 / 20%);
border: 1px solid rgb(255 255 255 / 30%);
box-shadow: 0 8px 32px rgb(0 0 0 / 10%);
}

View File

@@ -2363,3 +2363,10 @@ html, body {
.icon-btn:hover { .icon-btn:hover {
color: var(--color-text-primary); color: var(--color-text-primary);
} }
.advancedAnimation {
backdrop-filter: blur(5px) saturate(180%);
background: rgb(255 255 255 / 20%);
border: 1px solid rgb(255 255 255 / 30%);
box-shadow: 0 8px 32px rgb(0 0 0 / 10%);
}

View File

@@ -40,6 +40,7 @@ interface ISettingForm {
mainWindowWidth: number mainWindowWidth: number
mainWindowHeight: number mainWindowHeight: number
enableSecondUploader: boolean enableSecondUploader: boolean
enableAdvancedAnimation: boolean
theme: string theme: string
} }