feat(偏好设置): 添加浏览器扩展存储支持及时间显示偏好功能
添加 webextension-polyfill 依赖以支持浏览器扩展存储 API 创建 usePreferences store 管理用户偏好设置 将 Playroom 页面的时间显示切换功能迁移至偏好设置 store
This commit is contained in:
parent
4a8f68346a
commit
32ab4574dd
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -14,11 +14,13 @@
|
||||||
"pinia": "^3.0.2",
|
"pinia": "^3.0.2",
|
||||||
"tailwindcss": "^4.1.7",
|
"tailwindcss": "^4.1.7",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-router": "^4.5.1"
|
"vue-router": "^4.5.1",
|
||||||
|
"webextension-polyfill": "^0.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/node": "^22.15.21",
|
"@types/node": "^22.15.21",
|
||||||
|
"@types/webextension-polyfill": "^0.12.3",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"typescript": "~5.6.2",
|
"typescript": "~5.6.2",
|
||||||
"vite": "^6.0.1",
|
"vite": "^6.0.1",
|
||||||
|
@ -1246,6 +1248,13 @@
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/webextension-polyfill": {
|
||||||
|
"version": "0.12.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/webextension-polyfill/-/webextension-polyfill-0.12.3.tgz",
|
||||||
|
"integrity": "sha512-F58aDVSeN/MjUGazXo/cPsmR76EvqQhQ1v4x23hFjUX0cfAJYE+JBWwiOGW36/VJGGxoH74sVlRIF3z7SJCKyg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@vitejs/plugin-vue": {
|
"node_modules/@vitejs/plugin-vue": {
|
||||||
"version": "5.2.4",
|
"version": "5.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
|
||||||
|
@ -2647,6 +2656,12 @@
|
||||||
"typescript": ">=5.0.0"
|
"typescript": ">=5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/webextension-polyfill": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.12.0.tgz",
|
||||||
|
"integrity": "sha512-97TBmpoWJEE+3nFBQ4VocyCdLKfw54rFaJ6EVQYLBCXqCIpLSZkwGgASpv4oPt9gdKCJ80RJlcmNzNn008Ag6Q==",
|
||||||
|
"license": "MPL-2.0"
|
||||||
|
},
|
||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
"pinia": "^3.0.2",
|
"pinia": "^3.0.2",
|
||||||
"tailwindcss": "^4.1.7",
|
"tailwindcss": "^4.1.7",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-router": "^4.5.1"
|
"vue-router": "^4.5.1",
|
||||||
|
"webextension-polyfill": "^0.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@types/node": "^22.15.21",
|
"@types/node": "^22.15.21",
|
||||||
|
"@types/webextension-polyfill": "^0.12.3",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"typescript": "~5.6.2",
|
"typescript": "~5.6.2",
|
||||||
"vite": "^6.0.1",
|
"vite": "^6.0.1",
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Draggable } from "gsap/Draggable"
|
||||||
import { onMounted } from 'vue'
|
import { onMounted } from 'vue'
|
||||||
import { useTemplateRef } from 'vue'
|
import { useTemplateRef } from 'vue'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
import { usePreferences } from '../stores/usePreferences'
|
||||||
|
|
||||||
import RewindIcon from '../assets/icons/rewind.vue'
|
import RewindIcon from '../assets/icons/rewind.vue'
|
||||||
import ForwardIcon from '../assets/icons/forward.vue'
|
import ForwardIcon from '../assets/icons/forward.vue'
|
||||||
|
@ -23,6 +24,7 @@ import CycleTwoArrowsWithNumOneIcon from '../assets/icons/cycletwoarrowswithnumo
|
||||||
import SpeakerIcon from '../assets/icons/speaker.vue'
|
import SpeakerIcon from '../assets/icons/speaker.vue'
|
||||||
|
|
||||||
const playQueueStore = usePlayQueueStore()
|
const playQueueStore = usePlayQueueStore()
|
||||||
|
const preferences = usePreferences()
|
||||||
gsap.registerPlugin(Draggable)
|
gsap.registerPlugin(Draggable)
|
||||||
|
|
||||||
const progressBarThumb = useTemplateRef('progressBarThumb')
|
const progressBarThumb = useTemplateRef('progressBarThumb')
|
||||||
|
@ -30,10 +32,9 @@ const progressBarContainer = useTemplateRef('progressBarContainer')
|
||||||
const playQueueDialogContainer = useTemplateRef('playQueueDialogContainer')
|
const playQueueDialogContainer = useTemplateRef('playQueueDialogContainer')
|
||||||
const playQueueDialog = useTemplateRef('playQueueDialog')
|
const playQueueDialog = useTemplateRef('playQueueDialog')
|
||||||
|
|
||||||
const displayTimeLeft = ref(false)
|
|
||||||
const presentQueueListDialog = ref(false)
|
const presentQueueListDialog = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
Draggable.create(progressBarThumb.value, {
|
Draggable.create(progressBarThumb.value, {
|
||||||
type: 'x',
|
type: 'x',
|
||||||
bounds: progressBarContainer.value,
|
bounds: progressBarContainer.value,
|
||||||
|
@ -204,10 +205,10 @@ function getCurrentTrack() {
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1">
|
<div class="flex flex-1">
|
||||||
<div class="flex-1" />
|
<div class="flex-1" />
|
||||||
<button class="text-white/90 font-medium text-right relative" @click="displayTimeLeft = !displayTimeLeft">
|
<button class="text-white/90 font-medium text-right relative" @click="preferences.displayTimeLeft = !preferences.displayTimeLeft">
|
||||||
<span
|
<span
|
||||||
class="text-black blur-lg absolute top-0">{{ `${displayTimeLeft ? '-' : ''}${timeFormatter(displayTimeLeft ? Math.floor(playQueueStore.duration) - Math.floor(playQueueStore.currentTime) : playQueueStore.duration)}` }}</span>
|
class="text-black blur-lg absolute top-0">{{ `${preferences.displayTimeLeft ? '-' : ''}${timeFormatter(preferences.displayTimeLeft ? Math.floor(playQueueStore.duration) - Math.floor(playQueueStore.currentTime) : playQueueStore.duration)}` }}</span>
|
||||||
<span>{{ `${displayTimeLeft ? '-' : ''}${timeFormatter(displayTimeLeft ? Math.floor(playQueueStore.duration) - Math.floor(playQueueStore.currentTime) : playQueueStore.duration)}` }}</span>
|
<span>{{ `${preferences.displayTimeLeft ? '-' : ''}${timeFormatter(preferences.displayTimeLeft ? Math.floor(playQueueStore.duration) - Math.floor(playQueueStore.currentTime) : playQueueStore.duration)}` }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
47
src/stores/usePreferences.ts
Normal file
47
src/stores/usePreferences.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { defineStore } from "pinia"
|
||||||
|
import { ref, watch } from "vue"
|
||||||
|
import browser from 'webextension-polyfill'
|
||||||
|
|
||||||
|
export const usePreferences = defineStore('preferences', () => {
|
||||||
|
const displayTimeLeft = ref<boolean>(false) // 设置默认值
|
||||||
|
const isLoaded = ref(false) // 添加加载状态
|
||||||
|
|
||||||
|
// 异步初始化函数
|
||||||
|
const initializePreferences = async () => {
|
||||||
|
try {
|
||||||
|
// 指定默认值对象
|
||||||
|
const result = await browser.storage.local.get({
|
||||||
|
displayTimeLeft: false // 如果键不存在,使用这个默认值
|
||||||
|
})
|
||||||
|
|
||||||
|
displayTimeLeft.value = result.displayTimeLeft as boolean // 现在类型是安全的
|
||||||
|
isLoaded.value = true
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载偏好设置失败:', error)
|
||||||
|
displayTimeLeft.value = false
|
||||||
|
isLoaded.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听变化并保存
|
||||||
|
watch(displayTimeLeft, async (val) => {
|
||||||
|
if (isLoaded.value) { // 只有在初始化完成后才保存
|
||||||
|
try {
|
||||||
|
await browser.storage.local.set({
|
||||||
|
displayTimeLeft: val
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存偏好设置失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 立即初始化
|
||||||
|
initializePreferences()
|
||||||
|
|
||||||
|
return {
|
||||||
|
displayTimeLeft,
|
||||||
|
isLoaded,
|
||||||
|
initializePreferences
|
||||||
|
}
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user