Thing init

This commit is contained in:
zhongluofeng
2026-07-14 18:27:23 +08:00
parent 59c7d6d7ee
commit c514a7aced
150 changed files with 11861 additions and 22 deletions
+160
View File
@@ -0,0 +1,160 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { getCurrentWindow, Effect } from '@tauri-apps/api/window'
export type Theme = 'light' | 'dark' | 'system'
export type EffectType = 'normal' | 'mica' | 'acrylic'
const STORAGE_KEY = 'thing_app_settings'
export const useAppStore = defineStore('app', () => {
const theme = ref<Theme>('system')
const effect = ref<EffectType>('mica')
const isAutoStart = ref(false)
const isInitialized = ref(false)
const loadSettings = () => {
try {
const saved = localStorage.getItem(STORAGE_KEY)
if (saved) {
const settings = JSON.parse(saved)
if (settings.theme) theme.value = settings.theme
if (settings.effect) effect.value = settings.effect
if (settings.isAutoStart !== undefined) isAutoStart.value = settings.isAutoStart
}
} catch {
console.error('Failed to load settings from localStorage')
}
}
const saveSettings = () => {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify({
theme: theme.value,
effect: effect.value,
isAutoStart: isAutoStart.value
}))
} catch {
console.error('Failed to save settings to localStorage')
}
}
const setTheme = async (newTheme: Theme) => {
theme.value = newTheme
await applyTheme()
saveSettings()
}
const setEffect = async (newEffect: EffectType) => {
effect.value = newEffect
await applyEffect()
saveSettings()
}
const toggleAutoStart = () => {
isAutoStart.value = !isAutoStart.value
saveSettings()
}
const applyTheme = async () => {
const root = document.documentElement
root.classList.remove('dark')
let isDark = false
if (theme.value === 'dark') {
isDark = true
root.classList.add('dark')
} else if (theme.value === 'system') {
isDark = window.matchMedia('(prefers-color-scheme: dark)').matches
if (isDark) {
root.classList.add('dark')
}
}
try {
const tauriWindow = getCurrentWindow()
await tauriWindow.setTheme(isDark ? 'dark' : 'light')
} catch (e) {
console.error('Failed to set window theme:', e)
}
await applyEffect()
}
const applyEffect = async () => {
const root = document.documentElement
root.classList.remove('effect-mica', 'effect-acrylic', 'effect-normal')
root.classList.add(`effect-${effect.value}`)
try {
const tauriWindow = getCurrentWindow()
const isDark = root.classList.contains('dark')
await tauriWindow.clearEffects()
if (effect.value === 'normal') {
await tauriWindow.setBackgroundColor(isDark ? '#0f172a' : '#ffffff')
} else if (effect.value === 'mica') {
await tauriWindow.setEffects({
effects: [Effect.Mica],
color: isDark ? '#1e293b' : '#f1f5f9'
})
await tauriWindow.setBackgroundColor('#00000000')
} else if (effect.value === 'acrylic') {
await tauriWindow.setEffects({
effects: [Effect.Acrylic],
color: isDark ? '#1e293b' : '#f1f5f9'
})
await tauriWindow.setBackgroundColor('#00000000')
}
} catch (e) {
console.error('Failed to set window effects:', e)
}
}
const handleSystemThemeChange = async (e: MediaQueryListEvent) => {
if (theme.value === 'system') {
const root = document.documentElement
if (e.matches) {
root.classList.add('dark')
} else {
root.classList.remove('dark')
}
try {
const tauriWindow = getCurrentWindow()
await tauriWindow.setTheme(e.matches ? 'dark' : 'light')
} catch (err) {
console.error('Failed to update window theme on system change:', err)
}
await applyEffect()
}
}
const init = async () => {
loadSettings()
await applyTheme()
await applyEffect()
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
mediaQuery.addEventListener('change', handleSystemThemeChange)
isInitialized.value = true
}
return {
theme,
effect,
isAutoStart,
isInitialized,
setTheme,
setEffect,
toggleAutoStart,
applyTheme,
applyEffect,
init,
loadSettings
}
})
+113
View File
@@ -0,0 +1,113 @@
export interface SearchIndexItem {
title: string
description?: string
keywords: string[]
}
export interface SearchIndexConfig {
moduleId: string
items: SearchIndexItem[]
}
export const searchIndex: SearchIndexConfig[] = [
{
moduleId: 'settings',
items: [
{
title: '浅色模式',
description: '切换到浅色主题',
keywords: ['浅色', '主题', 'theme', 'light']
},
{
title: '深色模式',
description: '切换到深色主题',
keywords: ['深色', '主题', 'theme', 'dark']
},
{
title: '跟随系统',
description: '跟随系统主题设置',
keywords: ['系统', '主题', 'theme', 'system']
},
{
title: '普通模式',
description: '标准背景效果',
keywords: ['效果', '普通', 'normal', 'effect']
},
{
title: 'Win 云母',
description: 'Windows 11 云母效果',
keywords: ['效果', '云母', 'mica', 'effect']
},
{
title: 'Win 亚克力',
description: 'Windows 11 亚克力效果',
keywords: ['效果', '亚克力', 'acrylic', 'effect']
},
{
title: '开机自启',
description: '启动 Windows 时自动运行应用',
keywords: ['开机', '自启', '自动', 'auto', 'start']
}
]
},
{
moduleId: 'proxy',
items: [
{
title: '代理设置',
description: '配置网络代理',
keywords: ['代理', 'proxy', '网络', 'network']
}
]
},
{
moduleId: 'clipboard',
items: [
{
title: '剪贴板历史',
description: '查看和管理剪贴板记录',
keywords: ['剪贴板', '复制', '粘贴', 'clipboard', 'copy', 'paste']
}
]
},
{
moduleId: 'screenshot',
items: [
{
title: '截图工具',
description: '捕获屏幕截图',
keywords: ['截图', '屏幕', 'screenshot', 'capture']
}
]
},
{
moduleId: 'monitor',
items: [
{
title: '硬件监控',
description: '查看系统硬件状态',
keywords: ['监控', '硬件', 'cpu', '内存', 'monitor', 'hardware']
}
]
},
{
moduleId: 'downloader',
items: [
{
title: '下载管理',
description: '管理下载任务',
keywords: ['下载', 'download', '文件', 'file']
}
]
},
{
moduleId: 'finder',
items: [
{
title: '文件搜索',
description: '搜索本地文件',
keywords: ['文件', '搜索', 'finder', 'search', 'file']
}
]
}
]
+92
View File
@@ -0,0 +1,92 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { searchIndex } from './searchIndex'
export interface SearchItem {
id: string
moduleId: string
title: string
description?: string
keywords: string[]
action?: () => void
}
export const useSearchStore = defineStore('search', () => {
const items = ref<SearchItem[]>([])
const initGlobalIndex = () => {
searchIndex.forEach(config => {
config.items.forEach((item, index) => {
const searchItem: SearchItem = {
id: `${config.moduleId}-search-${index}`,
moduleId: config.moduleId,
title: item.title,
description: item.description,
keywords: item.keywords
}
if (!items.value.find(i => i.id === searchItem.id)) {
items.value.push(searchItem)
}
})
})
}
const registerAction = (moduleId: string, itemIndex: number, action: () => void) => {
const id = `${moduleId}-search-${itemIndex}`
const item = items.value.find(i => i.id === id)
if (item) {
item.action = action
}
}
const registerActions = (moduleId: string, actions: Map<number, () => void>) => {
actions.forEach((action, index) => {
registerAction(moduleId, index, action)
})
}
const registerItem = (item: SearchItem) => {
if (!items.value.find(i => i.id === item.id)) {
items.value.push(item)
}
}
const registerItems = (newItems: SearchItem[]) => {
newItems.forEach(item => registerItem(item))
}
const unregisterItem = (id: string) => {
const index = items.value.findIndex(i => i.id === id)
if (index !== -1) {
items.value.splice(index, 1)
}
}
const search = (query: string) => {
if (!query.trim()) return []
const lowerQuery = query.toLowerCase()
return items.value.filter(item => {
const titleMatch = item.title.toLowerCase().includes(lowerQuery)
const descMatch = item.description ? item.description.toLowerCase().includes(lowerQuery) : false
const keywordMatch = item.keywords.some(k => k.toLowerCase().includes(lowerQuery))
const moduleIdMatch = item.moduleId.toLowerCase().includes(lowerQuery)
return titleMatch || descMatch || keywordMatch || moduleIdMatch
})
}
const getItemsByModule = (moduleId: string) => {
return items.value.filter(i => i.moduleId === moduleId)
}
return {
items,
initGlobalIndex,
registerAction,
registerActions,
registerItem,
registerItems,
unregisterItem,
search,
getItemsByModule
}
})