mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 23:56:42 +08:00
fix
This commit is contained in:
@@ -7,7 +7,6 @@ import { addBackgroundTimer, removeBackgroundTimer } from '@/utils/backgroundMan
|
|||||||
* 统一管理SSE连接和定时器,优化iOS后台性能
|
* 统一管理SSE连接和定时器,优化iOS后台性能
|
||||||
*/
|
*/
|
||||||
export function useBackgroundOptimization() {
|
export function useBackgroundOptimization() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用优化的SSE连接
|
* 使用优化的SSE连接
|
||||||
* @param url SSE连接地址
|
* @param url SSE连接地址
|
||||||
@@ -23,7 +22,7 @@ export function useBackgroundOptimization() {
|
|||||||
backgroundCloseDelay?: number
|
backgroundCloseDelay?: number
|
||||||
reconnectDelay?: number
|
reconnectDelay?: number
|
||||||
maxReconnectAttempts?: number
|
maxReconnectAttempts?: number
|
||||||
}
|
},
|
||||||
) => {
|
) => {
|
||||||
const manager = sseManagerSingleton.getManager(url, options)
|
const manager = sseManagerSingleton.getManager(url, options)
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ export function useBackgroundOptimization() {
|
|||||||
return {
|
return {
|
||||||
manager,
|
manager,
|
||||||
readyState: () => manager.readyState,
|
readyState: () => manager.readyState,
|
||||||
close: () => manager.removeMessageListener(listenerId)
|
close: () => manager.removeMessageListener(listenerId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +55,7 @@ export function useBackgroundOptimization() {
|
|||||||
options?: {
|
options?: {
|
||||||
runInBackground?: boolean
|
runInBackground?: boolean
|
||||||
skipInitialRun?: boolean
|
skipInitialRun?: boolean
|
||||||
}
|
},
|
||||||
) => {
|
) => {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
addBackgroundTimer(id, callback, interval, options)
|
addBackgroundTimer(id, callback, interval, options)
|
||||||
@@ -67,7 +66,7 @@ export function useBackgroundOptimization() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
remove: () => removeBackgroundTimer(id)
|
remove: () => removeBackgroundTimer(id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +83,7 @@ export function useBackgroundOptimization() {
|
|||||||
messageHandler: (event: MessageEvent) => void,
|
messageHandler: (event: MessageEvent) => void,
|
||||||
listenerId: string,
|
listenerId: string,
|
||||||
delay: number = 3000,
|
delay: number = 3000,
|
||||||
options?: Parameters<typeof useSSE>[3]
|
options?: Parameters<typeof useSSE>[3],
|
||||||
) => {
|
) => {
|
||||||
const manager = sseManagerSingleton.getManager(url, options)
|
const manager = sseManagerSingleton.getManager(url, options)
|
||||||
|
|
||||||
@@ -101,7 +100,7 @@ export function useBackgroundOptimization() {
|
|||||||
return {
|
return {
|
||||||
manager,
|
manager,
|
||||||
readyState: () => manager.readyState,
|
readyState: () => manager.readyState,
|
||||||
close: () => manager.removeMessageListener(listenerId)
|
close: () => manager.removeMessageListener(listenerId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,12 +115,12 @@ export function useBackgroundOptimization() {
|
|||||||
url: string,
|
url: string,
|
||||||
messageHandler: (event: MessageEvent) => void,
|
messageHandler: (event: MessageEvent) => void,
|
||||||
listenerId: string,
|
listenerId: string,
|
||||||
isActive: Ref<boolean>
|
isActive: Ref<boolean>,
|
||||||
) => {
|
) => {
|
||||||
const manager = sseManagerSingleton.getManager(url, {
|
const manager = sseManagerSingleton.getManager(url, {
|
||||||
backgroundCloseDelay: 1000, // 进度SSE更快关闭
|
backgroundCloseDelay: 1000, // 进度SSE更快关闭
|
||||||
reconnectDelay: 1000,
|
reconnectDelay: 1000,
|
||||||
maxReconnectAttempts: 5
|
maxReconnectAttempts: 5,
|
||||||
})
|
})
|
||||||
|
|
||||||
const startProgress = () => {
|
const startProgress = () => {
|
||||||
@@ -141,7 +140,7 @@ export function useBackgroundOptimization() {
|
|||||||
return {
|
return {
|
||||||
start: startProgress,
|
start: startProgress,
|
||||||
stop: stopProgress,
|
stop: stopProgress,
|
||||||
manager
|
manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +155,7 @@ export function useBackgroundOptimization() {
|
|||||||
id: string,
|
id: string,
|
||||||
loadDataFunc: () => Promise<void> | void,
|
loadDataFunc: () => Promise<void> | void,
|
||||||
interval: number = 3000,
|
interval: number = 3000,
|
||||||
immediate: boolean = true
|
immediate: boolean = true,
|
||||||
) => {
|
) => {
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
@@ -178,15 +177,10 @@ export function useBackgroundOptimization() {
|
|||||||
await wrappedLoadData()
|
await wrappedLoadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
addBackgroundTimer(
|
addBackgroundTimer(id, wrappedLoadData, interval, {
|
||||||
id,
|
runInBackground: false, // 后台不刷新数据
|
||||||
wrappedLoadData,
|
skipInitialRun: true, // 已经手动执行过了
|
||||||
interval,
|
})
|
||||||
{
|
|
||||||
runInBackground: false, // 后台不刷新数据
|
|
||||||
skipInitialRun: true // 已经手动执行过了
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
@@ -196,7 +190,7 @@ export function useBackgroundOptimization() {
|
|||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
refresh: wrappedLoadData,
|
refresh: wrappedLoadData,
|
||||||
stop: () => removeBackgroundTimer(id)
|
stop: () => removeBackgroundTimer(id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +207,7 @@ export function useBackgroundOptimization() {
|
|||||||
loadDataFunc: () => Promise<void> | void,
|
loadDataFunc: () => Promise<void> | void,
|
||||||
condition: Ref<boolean>,
|
condition: Ref<boolean>,
|
||||||
interval: number = 3000,
|
interval: number = 3000,
|
||||||
immediate: boolean = true
|
immediate: boolean = true,
|
||||||
) => {
|
) => {
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const isTimerActive = ref(false)
|
const isTimerActive = ref(false)
|
||||||
@@ -233,15 +227,10 @@ export function useBackgroundOptimization() {
|
|||||||
|
|
||||||
const startTimer = () => {
|
const startTimer = () => {
|
||||||
if (!isTimerActive.value && condition.value) {
|
if (!isTimerActive.value && condition.value) {
|
||||||
addBackgroundTimer(
|
addBackgroundTimer(id, wrappedLoadData, interval, {
|
||||||
id,
|
runInBackground: false,
|
||||||
wrappedLoadData,
|
skipInitialRun: !immediate,
|
||||||
interval,
|
})
|
||||||
{
|
|
||||||
runInBackground: false,
|
|
||||||
skipInitialRun: !immediate
|
|
||||||
}
|
|
||||||
)
|
|
||||||
isTimerActive.value = true
|
isTimerActive.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,7 +266,7 @@ export function useBackgroundOptimization() {
|
|||||||
refresh: wrappedLoadData,
|
refresh: wrappedLoadData,
|
||||||
stop: stopTimer,
|
stop: stopTimer,
|
||||||
start: startTimer,
|
start: startTimer,
|
||||||
isActive: isTimerActive
|
isActive: isTimerActive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,6 +276,6 @@ export function useBackgroundOptimization() {
|
|||||||
useDelayedSSE,
|
useDelayedSSE,
|
||||||
useProgressSSE,
|
useProgressSSE,
|
||||||
useDataRefresh,
|
useDataRefresh,
|
||||||
useConditionalDataRefresh
|
useConditionalDataRefresh,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-114
@@ -13,10 +13,6 @@ const options = {
|
|||||||
// 存储未读消息数量的键名
|
// 存储未读消息数量的键名
|
||||||
const UNREAD_COUNT_KEY = 'mp_unread_count'
|
const UNREAD_COUNT_KEY = 'mp_unread_count'
|
||||||
|
|
||||||
// 状态管理相关的缓存名称和端点
|
|
||||||
const STATE_CACHE_NAME = 'mp-pwa-state-cache'
|
|
||||||
const STATE_ENDPOINT = '/api/pwa-state'
|
|
||||||
|
|
||||||
// 从IndexedDB获取未读消息数量
|
// 从IndexedDB获取未读消息数量
|
||||||
async function getStoredUnreadCount(): Promise<number> {
|
async function getStoredUnreadCount(): Promise<number> {
|
||||||
try {
|
try {
|
||||||
@@ -37,60 +33,6 @@ async function setStoredUnreadCount(count: number): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存PWA状态到缓存
|
|
||||||
async function saveStateToCache(request: Request): Promise<Response> {
|
|
||||||
try {
|
|
||||||
const state = await request.json()
|
|
||||||
const cache = await caches.open(STATE_CACHE_NAME)
|
|
||||||
|
|
||||||
await cache.put(
|
|
||||||
STATE_ENDPOINT,
|
|
||||||
new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
...state,
|
|
||||||
timestamp: Date.now(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
return new Response(JSON.stringify({ success: true }))
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to save state to cache:', error)
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }),
|
|
||||||
{
|
|
||||||
status: 500,
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从缓存获取PWA状态
|
|
||||||
async function getStateFromCache(): Promise<Response> {
|
|
||||||
try {
|
|
||||||
const cache = await caches.open(STATE_CACHE_NAME)
|
|
||||||
const response = await cache.match(STATE_ENDPOINT)
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const state = await response.json()
|
|
||||||
return new Response(JSON.stringify(state), {
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(JSON.stringify({}), {
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to get state from cache:', error)
|
|
||||||
return new Response(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }), {
|
|
||||||
status: 500,
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 简单的IndexedDB包装器
|
// 简单的IndexedDB包装器
|
||||||
async function openDB(): Promise<IDBDatabase> {
|
async function openDB(): Promise<IDBDatabase> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -158,25 +100,9 @@ async function clearBadge() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 安装事件
|
// 安装事件
|
||||||
self.addEventListener('install', event => {
|
self.addEventListener('install', () => {
|
||||||
event.waitUntil(
|
// 强制等待中的Service Worker立即成为活动的Service Worker
|
||||||
(async () => {
|
self.skipWaiting()
|
||||||
// 预缓存关键状态数据
|
|
||||||
try {
|
|
||||||
const cache = await caches.open(STATE_CACHE_NAME)
|
|
||||||
const existingState = await cache.match(STATE_ENDPOINT)
|
|
||||||
|
|
||||||
if (existingState) {
|
|
||||||
// 预热状态数据(无需处理,仅确保缓存可用)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// 静默处理错误
|
|
||||||
}
|
|
||||||
|
|
||||||
// 强制等待中的Service Worker立即成为活动的Service Worker
|
|
||||||
self.skipWaiting()
|
|
||||||
})(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 激活事件
|
// 激活事件
|
||||||
@@ -207,16 +133,6 @@ self.addEventListener('activate', event => {
|
|||||||
self.addEventListener('fetch', event => {
|
self.addEventListener('fetch', event => {
|
||||||
const url = new URL(event.request.url)
|
const url = new URL(event.request.url)
|
||||||
|
|
||||||
// 处理PWA状态管理请求
|
|
||||||
if (url.pathname === STATE_ENDPOINT) {
|
|
||||||
if (event.request.method === 'POST') {
|
|
||||||
event.respondWith(saveStateToCache(event.request))
|
|
||||||
} else if (event.request.method === 'GET') {
|
|
||||||
event.respondWith(getStateFromCache())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.request.url.includes('/api/v1/') && event.request.method === 'GET') {
|
if (event.request.url.includes('/api/v1/') && event.request.method === 'GET') {
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -336,32 +252,5 @@ self.addEventListener('message', function (event) {
|
|||||||
.catch(error => {
|
.catch(error => {
|
||||||
event.ports[0]?.postMessage({ count: 0 })
|
event.ports[0]?.postMessage({ count: 0 })
|
||||||
})
|
})
|
||||||
} else if (event.data && event.data.type === 'SAVE_PWA_STATE') {
|
|
||||||
// 保存PWA状态
|
|
||||||
const state = event.data.state || {}
|
|
||||||
saveStateToCache(
|
|
||||||
new Request(STATE_ENDPOINT, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(state),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(result => {
|
|
||||||
event.ports[0]?.postMessage({ success: result.success })
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
event.ports[0]?.postMessage({ success: false, error: error instanceof Error ? error.message : String(error) })
|
|
||||||
})
|
|
||||||
} else if (event.data && event.data.type === 'GET_PWA_STATE') {
|
|
||||||
// 获取PWA状态
|
|
||||||
getStateFromCache()
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(state => {
|
|
||||||
event.ports[0]?.postMessage({ state })
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
event.ports[0]?.postMessage({ state: {} })
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user