mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 15:36:49 +08:00
fix(glass): 收敛壁纸预加载与失效恢复 (#592)
* fix(glass): streamline wallpaper loading * docs(glass): remove stale compatibility comment * docs(glass): remove obsolete texture fallback note
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import {
|
||||
BACKGROUND_ROTATION_GRACE_MS,
|
||||
commitPreloadedBackgroundRotation,
|
||||
findFirstAvailableBackground,
|
||||
preloadBackgroundRotationImages,
|
||||
preloadBackgroundSequence,
|
||||
shouldAllowBackgroundRotation,
|
||||
} from '@/utils/backgroundRotation'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
@@ -28,56 +27,6 @@ describe('background rotation lifecycle', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('commitPreloadedBackgroundRotation', () => {
|
||||
it('drops a successful preload when the rotation becomes inactive before completion', async () => {
|
||||
const preload = deferred<boolean>()
|
||||
const commit = vi.fn()
|
||||
let active = true
|
||||
const result = commitPreloadedBackgroundRotation({
|
||||
canCommit: () => active,
|
||||
commit,
|
||||
preload: () => preload.promise,
|
||||
})
|
||||
|
||||
active = false
|
||||
preload.resolve(true)
|
||||
|
||||
await expect(result).resolves.toBe(false)
|
||||
expect(commit).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('commits a successful preload while the request remains current', async () => {
|
||||
const commit = vi.fn()
|
||||
|
||||
await expect(
|
||||
commitPreloadedBackgroundRotation({
|
||||
canCommit: () => true,
|
||||
commit,
|
||||
preload: async () => true,
|
||||
}),
|
||||
).resolves.toBe(true)
|
||||
expect(commit).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('drops an obsolete preload even when decorative motion becomes active again', async () => {
|
||||
const preload = deferred<boolean>()
|
||||
const commit = vi.fn()
|
||||
const requestVersion = 1
|
||||
let currentVersion = requestVersion
|
||||
const result = commitPreloadedBackgroundRotation({
|
||||
canCommit: () => requestVersion === currentVersion,
|
||||
commit,
|
||||
preload: () => preload.promise,
|
||||
})
|
||||
|
||||
currentVersion += 1
|
||||
preload.resolve(true)
|
||||
|
||||
await expect(result).resolves.toBe(false)
|
||||
expect(commit).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('preloadBackgroundRotationImages', () => {
|
||||
it('does not let an unused optical texture block the visible wallpaper', async () => {
|
||||
const preload = vi.fn(async (url: string) => url === 'display.jpg')
|
||||
@@ -106,37 +55,34 @@ describe('preloadBackgroundRotationImages', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('preloadBackgroundSequence', () => {
|
||||
it('preloads remaining wallpapers sequentially in rotation order', async () => {
|
||||
const calls: string[] = []
|
||||
describe('findFirstAvailableBackground', () => {
|
||||
it('skips invalid entries without changing the original sequence', async () => {
|
||||
const preload = vi.fn(async (url: string) => url === 'two.jpg')
|
||||
|
||||
await expect(
|
||||
preloadBackgroundSequence({
|
||||
canContinue: () => true,
|
||||
preload: async url => {
|
||||
calls.push(url)
|
||||
return url !== 'two.jpg'
|
||||
},
|
||||
findFirstAvailableBackground({
|
||||
urls: ['one.jpg', 'two.jpg', 'three.jpg'],
|
||||
canContinue: () => true,
|
||||
preload,
|
||||
}),
|
||||
).resolves.toEqual([true, false, true])
|
||||
expect(calls).toEqual(['one.jpg', 'two.jpg', 'three.jpg'])
|
||||
).resolves.toBe(1)
|
||||
expect(preload.mock.calls.map(([url]) => url)).toEqual(['one.jpg', 'two.jpg'])
|
||||
})
|
||||
|
||||
it('stops an obsolete queue before starting the next image', async () => {
|
||||
let active = true
|
||||
const calls: string[] = []
|
||||
|
||||
await preloadBackgroundSequence({
|
||||
canContinue: () => active,
|
||||
preload: async url => {
|
||||
calls.push(url)
|
||||
active = false
|
||||
return true
|
||||
},
|
||||
it('drops an obsolete batch before trying another image', async () => {
|
||||
const pending = deferred<boolean>()
|
||||
let current = true
|
||||
const preload = vi.fn(() => pending.promise)
|
||||
const result = findFirstAvailableBackground({
|
||||
urls: ['one.jpg', 'two.jpg'],
|
||||
canContinue: () => current,
|
||||
preload,
|
||||
})
|
||||
|
||||
expect(calls).toEqual(['one.jpg'])
|
||||
current = false
|
||||
pending.resolve(true)
|
||||
|
||||
await expect(result).resolves.toBeNull()
|
||||
expect(preload).toHaveBeenCalledOnce()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -8,15 +8,6 @@ export function shouldAllowBackgroundRotation(state: AppActivityState, graceActi
|
||||
return !reducedMotion && (state === 'active' || graceActive)
|
||||
}
|
||||
|
||||
interface PreloadedBackgroundRotationOptions {
|
||||
/** 提交前重新判断当前生命周期和请求版本是否仍允许切换。 */
|
||||
canCommit: () => boolean
|
||||
/** 将已经完成预加载的壁纸切换为活动背景。 */
|
||||
commit: () => void
|
||||
/** 预加载目标壁纸,并以布尔值表示是否可安全显示。 */
|
||||
preload: () => Promise<boolean>
|
||||
}
|
||||
|
||||
interface BackgroundRotationImagePreloadOptions {
|
||||
/** 外层背景实际显示的壁纸地址。 */
|
||||
displayUrl: string
|
||||
@@ -26,25 +17,25 @@ interface BackgroundRotationImagePreloadOptions {
|
||||
preload: (url: string) => Promise<boolean>
|
||||
}
|
||||
|
||||
interface BackgroundSequencePreloadOptions {
|
||||
/** 每张图片完成后重新判断队列是否仍属于当前页面与请求代次。 */
|
||||
canContinue: () => boolean
|
||||
/** 按实际轮播顺序排列的待预加载地址。 */
|
||||
interface FirstAvailableBackgroundOptions {
|
||||
/** 保持后端返回顺序的候选壁纸。 */
|
||||
urls: string[]
|
||||
/** 当前加载批次仍可提交时返回 true。 */
|
||||
canContinue: () => boolean
|
||||
/** 执行单张图片预加载并返回可用状态。 */
|
||||
preload: (url: string) => Promise<boolean>
|
||||
}
|
||||
|
||||
/**
|
||||
* 将壁纸预加载与最终提交分离,确保异步加载期间失效的轮换请求不会改变可见背景。
|
||||
*/
|
||||
export async function commitPreloadedBackgroundRotation(options: PreloadedBackgroundRotationOptions) {
|
||||
const succeeded = await options.preload()
|
||||
/** 按来源顺序寻找首张可用壁纸,单项失败或过期批次不会提交可见状态。 */
|
||||
export async function findFirstAvailableBackground(options: FirstAvailableBackgroundOptions) {
|
||||
for (let index = 0; index < options.urls.length; index += 1) {
|
||||
if (!options.canContinue()) return null
|
||||
const available = await options.preload(options.urls[index])
|
||||
if (!options.canContinue()) return null
|
||||
if (available) return index
|
||||
}
|
||||
|
||||
if (!succeeded || !options.canCommit()) return false
|
||||
|
||||
options.commit()
|
||||
return true
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,15 +50,3 @@ export async function preloadBackgroundRotationImages(options: BackgroundRotatio
|
||||
|
||||
return results.every(Boolean)
|
||||
}
|
||||
|
||||
/** 当前壁纸稳定后串行预加载剩余轮播项,避免并发争抢首屏带宽。 */
|
||||
export async function preloadBackgroundSequence(options: BackgroundSequencePreloadOptions) {
|
||||
const results: boolean[] = []
|
||||
|
||||
for (const url of options.urls) {
|
||||
if (!options.canContinue()) break
|
||||
results.push(await options.preload(url))
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
@@ -111,7 +111,6 @@ export interface GlassOpticalRenderProfile {
|
||||
springFrequency: number
|
||||
/** 活动壁纸进入 GPU 前的最长边限制。 */
|
||||
textureLimit: number
|
||||
/** 登录页优先使用可读纹理,跨域外链自动退回程序化高光。 */
|
||||
textureSource: 'auto' | 'procedural' | 'wallpaper'
|
||||
/** 参与液态方向计算的最近输入采样数量。 */
|
||||
trailCount: number
|
||||
|
||||
Reference in New Issue
Block a user