fix: storage / network permission issue
This commit is contained in:
		
							parent
							
								
									c129b2dd1b
								
							
						
					
					
						commit
						145a2d2dbb
					
				
							
								
								
									
										36
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										36
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
			},
 | 
			
		||||
			"devDependencies": {
 | 
			
		||||
				"@biomejs/biome": "1.9.4",
 | 
			
		||||
				"@types/chrome": "^0.0.323",
 | 
			
		||||
				"@types/node": "^22.15.21",
 | 
			
		||||
				"@types/webextension-polyfill": "^0.12.3",
 | 
			
		||||
				"@vitejs/plugin-vue": "^5.2.1",
 | 
			
		||||
| 
						 | 
				
			
			@ -1232,12 +1233,47 @@
 | 
			
		|||
				"vite": "^5.2.0 || ^6"
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/chrome": {
 | 
			
		||||
			"version": "0.0.323",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.323.tgz",
 | 
			
		||||
			"integrity": "sha512-ipiDwx41lmGeLnbiT6ENOayvWXdkqKqNwqDQWEuz6dujaX7slSkk1nbSt5Q5c6xnQ708+kuCFrC00VLltSbWVA==",
 | 
			
		||||
			"dev": true,
 | 
			
		||||
			"license": "MIT",
 | 
			
		||||
			"dependencies": {
 | 
			
		||||
				"@types/filesystem": "*",
 | 
			
		||||
				"@types/har-format": "*"
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/estree": {
 | 
			
		||||
			"version": "1.0.7",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
 | 
			
		||||
			"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
 | 
			
		||||
			"license": "MIT"
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/filesystem": {
 | 
			
		||||
			"version": "0.0.36",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz",
 | 
			
		||||
			"integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==",
 | 
			
		||||
			"dev": true,
 | 
			
		||||
			"license": "MIT",
 | 
			
		||||
			"dependencies": {
 | 
			
		||||
				"@types/filewriter": "*"
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/filewriter": {
 | 
			
		||||
			"version": "0.0.33",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz",
 | 
			
		||||
			"integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==",
 | 
			
		||||
			"dev": true,
 | 
			
		||||
			"license": "MIT"
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/har-format": {
 | 
			
		||||
			"version": "1.2.16",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz",
 | 
			
		||||
			"integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==",
 | 
			
		||||
			"dev": true,
 | 
			
		||||
			"license": "MIT"
 | 
			
		||||
		},
 | 
			
		||||
		"node_modules/@types/node": {
 | 
			
		||||
			"version": "22.15.21",
 | 
			
		||||
			"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@
 | 
			
		|||
	},
 | 
			
		||||
	"devDependencies": {
 | 
			
		||||
		"@biomejs/biome": "1.9.4",
 | 
			
		||||
		"@types/chrome": "^0.0.323",
 | 
			
		||||
		"@types/node": "^22.15.21",
 | 
			
		||||
		"@types/webextension-polyfill": "^0.12.3",
 | 
			
		||||
		"@vitejs/plugin-vue": "^5.2.1",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,8 @@
 | 
			
		|||
	"host_permissions": [
 | 
			
		||||
		"https://monster-siren.hypergryph.com/*",
 | 
			
		||||
		"http://localhost:5173/*",
 | 
			
		||||
		"https://res01.hycdn.cn/*"
 | 
			
		||||
		"https://res01.hycdn.cn/*",
 | 
			
		||||
		"https://web.hycdn.cn/*"
 | 
			
		||||
	],
 | 
			
		||||
	"icons": {
 | 
			
		||||
		"16": "vite.svg",
 | 
			
		||||
| 
						 | 
				
			
			@ -29,10 +30,11 @@
 | 
			
		|||
	},
 | 
			
		||||
	"permissions": [
 | 
			
		||||
		"tabs",
 | 
			
		||||
		"webRequest"
 | 
			
		||||
		"webRequest",
 | 
			
		||||
		"storage"
 | 
			
		||||
	],
 | 
			
		||||
	"content_security_policy": {
 | 
			
		||||
		"extension_pages": "default-src 'self'; script-src 'self' http://localhost:5173; style-src 'self' 'unsafe-inline'; connect-src 'self' ws://localhost:5173 https://monster-siren.hypergryph.com; img-src 'self' https://web.hycdn.cn; media-src 'self' https://res01.hycdn.cn;",
 | 
			
		||||
		"extension_pages": "default-src 'self'; script-src 'self' http://localhost:5173; style-src 'self' 'unsafe-inline'; connect-src 'self' ws://localhost:5173 https://monster-siren.hypergryph.com https://web.hycdn.cn; img-src 'self' https://web.hycdn.cn; media-src 'self' https://res01.hycdn.cn;",
 | 
			
		||||
		"sandbox": "sandbox"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -511,6 +511,7 @@ watch(() => playQueueStore.currentTime, (time) => {
 | 
			
		|||
 | 
			
		||||
// 监听歌词源变化
 | 
			
		||||
watch(() => props.lrcSrc, async (newSrc) => {
 | 
			
		||||
  console.log('Loading new lyrics from:', newSrc)
 | 
			
		||||
  // 重置状态
 | 
			
		||||
  currentLineIndex.value = -1
 | 
			
		||||
  lineRefs.value = []
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,6 +41,7 @@ const songInfo = useTemplateRef('songInfo')
 | 
			
		|||
const playButton = useTemplateRef('playButton')
 | 
			
		||||
 | 
			
		||||
const presentQueueListDialog = ref(false)
 | 
			
		||||
// const presentLyrics = ref(false)
 | 
			
		||||
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
	Draggable.create(progressBarThumb.value, {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,23 +1,164 @@
 | 
			
		|||
import { defineStore } from "pinia"
 | 
			
		||||
import { ref, watch } from "vue"
 | 
			
		||||
import browser from 'webextension-polyfill'
 | 
			
		||||
 | 
			
		||||
// 声明全局类型
 | 
			
		||||
declare global {
 | 
			
		||||
	interface Window {
 | 
			
		||||
		browser?: any
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const usePreferences = defineStore('preferences', () => {
 | 
			
		||||
	const displayTimeLeft = ref<boolean>(false) // 设置默认值
 | 
			
		||||
	const isLoaded = ref(false) // 添加加载状态
 | 
			
		||||
	const displayTimeLeft = ref<boolean>(false)
 | 
			
		||||
	const isLoaded = ref(false)
 | 
			
		||||
	const storageType = ref<'chrome' | 'localStorage' | 'memory'>('chrome')
 | 
			
		||||
	const debugInfo = ref<string[]>([])
 | 
			
		||||
 | 
			
		||||
	// 添加调试日志
 | 
			
		||||
	const addDebugInfo = (info: string) => {
 | 
			
		||||
		debugInfo.value.push(`[${new Date().toISOString()}] ${info}`)
 | 
			
		||||
		console.log(info)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 检测可用的 API
 | 
			
		||||
	const detectAvailableAPIs = () => {
 | 
			
		||||
		addDebugInfo('开始检测可用的存储 API...')
 | 
			
		||||
 | 
			
		||||
		// 检查原生 chrome API
 | 
			
		||||
		try {
 | 
			
		||||
			if (typeof chrome !== 'undefined' && chrome.storage && chrome.storage.local) {
 | 
			
		||||
				addDebugInfo('✅ 检测到 chrome.storage.local')
 | 
			
		||||
				storageType.value = 'chrome'
 | 
			
		||||
				return 'chrome'
 | 
			
		||||
			} else {
 | 
			
		||||
				addDebugInfo('❌ 未检测到原生 chrome.storage.local')
 | 
			
		||||
			}
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			addDebugInfo(`❌ chrome API 检测失败: ${error}`)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 检查 window.chrome
 | 
			
		||||
		try {
 | 
			
		||||
			if (window.chrome && window.chrome.storage && window.chrome.storage.local) {
 | 
			
		||||
				addDebugInfo('✅ 检测到 window.chrome.storage.local')
 | 
			
		||||
				storageType.value = 'chrome'
 | 
			
		||||
				return 'chrome'
 | 
			
		||||
			}
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			addDebugInfo(`❌ window.chrome API 检测失败: ${error}`)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 检查 localStorage
 | 
			
		||||
		try {
 | 
			
		||||
			if (typeof localStorage !== 'undefined') {
 | 
			
		||||
				localStorage.setItem('msr_test', 'test')
 | 
			
		||||
				localStorage.removeItem('msr_test')
 | 
			
		||||
				addDebugInfo('✅ 检测到 localStorage')
 | 
			
		||||
				storageType.value = 'localStorage'
 | 
			
		||||
				return 'localStorage'
 | 
			
		||||
			}
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			addDebugInfo(`❌ localStorage 检测失败: ${error}`)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 都不可用,使用内存存储
 | 
			
		||||
		addDebugInfo('⚠️ 使用内存存储(不持久化)')
 | 
			
		||||
		storageType.value = 'memory'
 | 
			
		||||
		return 'memory'
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 通用的获取存储值函数
 | 
			
		||||
	const getStoredValue = async (key: string, defaultValue: any) => {
 | 
			
		||||
		const type = detectAvailableAPIs()
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			switch (type) {
 | 
			
		||||
				case 'chrome':
 | 
			
		||||
					return await new Promise((resolve) => {
 | 
			
		||||
						const api = chrome?.storage?.local || window.chrome?.storage?.local
 | 
			
		||||
						if (api) {
 | 
			
		||||
							api.get({ [key]: defaultValue }, (result) => {
 | 
			
		||||
								if (chrome.runtime.lastError) {
 | 
			
		||||
									addDebugInfo(`Chrome storage 错误: ${chrome.runtime.lastError.message}`)
 | 
			
		||||
									resolve(defaultValue)
 | 
			
		||||
								} else {
 | 
			
		||||
									addDebugInfo(`从 Chrome storage 读取: ${key} = ${result[key]}`)
 | 
			
		||||
									resolve(result[key])
 | 
			
		||||
								}
 | 
			
		||||
							})
 | 
			
		||||
						} else {
 | 
			
		||||
							resolve(defaultValue)
 | 
			
		||||
						}
 | 
			
		||||
					})
 | 
			
		||||
 | 
			
		||||
				case 'localStorage':
 | 
			
		||||
					const stored = localStorage.getItem(`msr_${key}`)
 | 
			
		||||
					const value = stored ? JSON.parse(stored) : defaultValue
 | 
			
		||||
					addDebugInfo(`从 localStorage 读取: ${key} = ${value}`)
 | 
			
		||||
					return value
 | 
			
		||||
 | 
			
		||||
				case 'memory':
 | 
			
		||||
				default:
 | 
			
		||||
					addDebugInfo(`从内存返回默认值: ${key} = ${defaultValue}`)
 | 
			
		||||
					return defaultValue
 | 
			
		||||
			}
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			addDebugInfo(`获取存储值失败 (${type}): ${error}`)
 | 
			
		||||
			return defaultValue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 通用的设置存储值函数
 | 
			
		||||
	const setStoredValue = async (key: string, value: any) => {
 | 
			
		||||
		const type = storageType.value
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			switch (type) {
 | 
			
		||||
				case 'chrome':
 | 
			
		||||
					return await new Promise<void>((resolve, reject) => {
 | 
			
		||||
						const api = chrome?.storage?.local || window.chrome?.storage?.local
 | 
			
		||||
						if (api) {
 | 
			
		||||
							api.set({ [key]: value }, () => {
 | 
			
		||||
								if (chrome.runtime.lastError) {
 | 
			
		||||
									const error = `Chrome storage 保存错误: ${chrome.runtime.lastError.message}`
 | 
			
		||||
									addDebugInfo(error)
 | 
			
		||||
									reject(new Error(error))
 | 
			
		||||
								} else {
 | 
			
		||||
									addDebugInfo(`保存到 Chrome storage: ${key} = ${value}`)
 | 
			
		||||
									resolve()
 | 
			
		||||
								}
 | 
			
		||||
							})
 | 
			
		||||
						} else {
 | 
			
		||||
							reject(new Error('Chrome storage API 不可用'))
 | 
			
		||||
						}
 | 
			
		||||
					})
 | 
			
		||||
 | 
			
		||||
				case 'localStorage':
 | 
			
		||||
					localStorage.setItem(`msr_${key}`, JSON.stringify(value))
 | 
			
		||||
					addDebugInfo(`保存到 localStorage: ${key} = ${value}`)
 | 
			
		||||
					break
 | 
			
		||||
 | 
			
		||||
				case 'memory':
 | 
			
		||||
					addDebugInfo(`内存存储(不持久化): ${key} = ${value}`)
 | 
			
		||||
					break
 | 
			
		||||
			}
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			addDebugInfo(`保存设置失败 (${type}): ${error}`)
 | 
			
		||||
			throw error
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 异步初始化函数
 | 
			
		||||
	const initializePreferences = async () => {
 | 
			
		||||
		addDebugInfo('开始初始化偏好设置...')
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			// 指定默认值对象
 | 
			
		||||
			const result = await browser.storage.local.get({
 | 
			
		||||
				displayTimeLeft: false // 如果键不存在,使用这个默认值
 | 
			
		||||
			})
 | 
			
		||||
			
 | 
			
		||||
			displayTimeLeft.value = result.displayTimeLeft as boolean // 现在类型是安全的
 | 
			
		||||
			const value = await getStoredValue('displayTimeLeft', false)
 | 
			
		||||
			displayTimeLeft.value = value as boolean
 | 
			
		||||
			isLoaded.value = true
 | 
			
		||||
			addDebugInfo(`✅ 偏好设置初始化完成: displayTimeLeft = ${value}`)
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			console.error('加载偏好设置失败:', error)
 | 
			
		||||
			addDebugInfo(`❌ 初始化失败: ${error}`)
 | 
			
		||||
			displayTimeLeft.value = false
 | 
			
		||||
			isLoaded.value = true
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,23 +166,51 @@ export const usePreferences = defineStore('preferences', () => {
 | 
			
		|||
 | 
			
		||||
	// 监听变化并保存
 | 
			
		||||
	watch(displayTimeLeft, async (val) => {
 | 
			
		||||
		if (isLoaded.value) { // 只有在初始化完成后才保存
 | 
			
		||||
		if (isLoaded.value) {
 | 
			
		||||
			try {
 | 
			
		||||
				await browser.storage.local.set({
 | 
			
		||||
					displayTimeLeft: val
 | 
			
		||||
				})
 | 
			
		||||
				await setStoredValue('displayTimeLeft', val)
 | 
			
		||||
			} catch (error) {
 | 
			
		||||
				console.error('保存偏好设置失败:', error)
 | 
			
		||||
				addDebugInfo(`❌ 监听器保存失败: ${error}`)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// 手动保存函数(用于调试)
 | 
			
		||||
	const manualSave = async () => {
 | 
			
		||||
		try {
 | 
			
		||||
			await setStoredValue('displayTimeLeft', displayTimeLeft.value)
 | 
			
		||||
			addDebugInfo(`✅ 手动保存成功`)
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			addDebugInfo(`❌ 手动保存失败: ${error}`)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 获取调试信息
 | 
			
		||||
	const getDebugInfo = () => {
 | 
			
		||||
		return {
 | 
			
		||||
			storageType: storageType.value,
 | 
			
		||||
			isLoaded: isLoaded.value,
 | 
			
		||||
			displayTimeLeft: displayTimeLeft.value,
 | 
			
		||||
			logs: debugInfo.value,
 | 
			
		||||
			chromeAvailable: typeof chrome !== 'undefined',
 | 
			
		||||
			chromeStorageAvailable: !!(chrome?.storage?.local),
 | 
			
		||||
			windowChromeAvailable: !!(window.chrome?.storage?.local),
 | 
			
		||||
			localStorageAvailable: typeof localStorage !== 'undefined'
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 立即初始化
 | 
			
		||||
	initializePreferences()
 | 
			
		||||
 | 
			
		||||
	return {
 | 
			
		||||
		displayTimeLeft,
 | 
			
		||||
		isLoaded,
 | 
			
		||||
		initializePreferences
 | 
			
		||||
		storageType,
 | 
			
		||||
		debugInfo,
 | 
			
		||||
		initializePreferences,
 | 
			
		||||
		getStoredValue,
 | 
			
		||||
		setStoredValue,
 | 
			
		||||
		manualSave,
 | 
			
		||||
		getDebugInfo
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user