Skip to content

Commit 587f06e

Browse files
committed
perf: safely optimize list loading
1 parent 7114c63 commit 587f06e

7 files changed

Lines changed: 59 additions & 4 deletions

File tree

src/@core/utils/image.ts

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import ColorThief from 'colorthief'
22

3+
const DEFAULT_DOMINANT_COLOR = '#28A9E1'
4+
const DOMINANT_COLOR_CACHE_LIMIT = 100
5+
const colorThief = new ColorThief()
6+
const dominantColorCache = new Map<string, Promise<string>>()
7+
8+
interface DominantColorOptions {
9+
fallback?: string
10+
quality?: number
11+
}
12+
313
// 将 RGB 转换为十六进制
414
function rgbStringToHex(rgbArray: number[]): string {
515
if (rgbArray.length !== 3 || rgbArray.some(isNaN)) throw new Error('Invalid RGB string format')
@@ -14,11 +24,46 @@ function rgbStringToHex(rgbArray: number[]): string {
1424
return `#${toHex(r)}${toHex(g)}${toHex(b)}`
1525
}
1626

27+
function getImageCacheKey(image: HTMLImageElement) {
28+
return image.currentSrc || image.src || ''
29+
}
30+
31+
function rememberDominantColor(key: string, colorPromise: Promise<string>) {
32+
if (!key) return colorPromise
33+
34+
if (dominantColorCache.size >= DOMINANT_COLOR_CACHE_LIMIT) {
35+
const firstKey = dominantColorCache.keys().next().value
36+
if (firstKey) dominantColorCache.delete(firstKey)
37+
}
38+
39+
dominantColorCache.set(key, colorPromise)
40+
return colorPromise
41+
}
42+
1743
// 提取主要颜色
18-
export async function getDominantColor(image: HTMLImageElement): Promise<string> {
19-
const colorThief = new ColorThief()
20-
const dominantColor = colorThief.getColor(image)
21-
return rgbStringToHex(dominantColor)
44+
export async function getDominantColor(
45+
image: HTMLImageElement | undefined | null,
46+
options: DominantColorOptions = {},
47+
): Promise<string> {
48+
const fallback = options.fallback ?? DEFAULT_DOMINANT_COLOR
49+
50+
if (!image) return fallback
51+
52+
const cacheKey = getImageCacheKey(image)
53+
const cachedColor = cacheKey ? dominantColorCache.get(cacheKey) : undefined
54+
if (cachedColor) return cachedColor
55+
56+
const colorPromise = Promise.resolve()
57+
.then(() => {
58+
const dominantColor = colorThief.getColor(image, options.quality ?? 20)
59+
return rgbStringToHex(dominantColor)
60+
})
61+
.catch(error => {
62+
console.warn('Failed to extract dominant color:', error)
63+
return fallback
64+
})
65+
66+
return rememberDominantColor(cacheKey, colorPromise)
2267
}
2368

2469
// 预加载图片

src/views/discover/MediaCardListView.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ async function fetchData({ done }: { done: any }) {
118118
page.value++
119119
// 返回加载成功
120120
done('ok')
121+
await nextTick()
121122
}
122123
} else {
123124
// 加载一次

src/views/discover/PersonCardListView.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ async function fetchData({ done }: { done: any }) {
8686
page.value++
8787
// 返回加载成功
8888
done('ok')
89+
await nextTick()
8990
}
9091
}
9192
} else {

src/views/plugin/PluginCardListView.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,11 @@ watch([dataList, installedFilter, hasUpdateFilter, enabledFilter], () => {
923923
function loadMarketMore({ done }: { done: any }) {
924924
// 从 dataList 中获取最前面的 20 个元素
925925
const itemsToMove = sortedUninstalledList.value.splice(0, 20)
926+
if (itemsToMove.length === 0) {
927+
done('empty')
928+
return
929+
}
930+
926931
displayUninstalledList.value.push(...itemsToMove)
927932
done('ok')
928933
}

src/views/subscribe/SubscribePopularView.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ async function fetchData({ done }: { done: any }) {
170170
page.value++
171171
// 返回加载成功
172172
done('ok')
173+
await nextTick()
173174
}
174175
} else {
175176
// 设置加载中

src/views/subscribe/SubscribeShareView.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ async function fetchData({ done }: { done: any }) {
184184
page.value++
185185
// 返回加载成功
186186
done('ok')
187+
await nextTick()
187188
}
188189
} else {
189190
// 设置加载中

src/views/workflow/WorkflowShareView.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ async function fetchData({ done }: { done: any }) {
110110
page.value++
111111
// 返回加载成功
112112
done('ok')
113+
await nextTick()
113114
}
114115
} else {
115116
// 设置加载中

0 commit comments

Comments
 (0)