fix: 顺序渲染BangDream歌曲列表
This commit is contained in:
parent
1deb2dc8b6
commit
e19f573699
@ -54,20 +54,10 @@ export async function drawSongList(
|
|||||||
let tempSongImageList: Canvas[] = [];
|
let tempSongImageList: Canvas[] = [];
|
||||||
const songImageListHorizontal: Canvas[] = [];
|
const songImageListHorizontal: Canvas[] = [];
|
||||||
let tempH = 0;
|
let tempH = 0;
|
||||||
const songPromises: Promise<Canvas>[] = [];
|
const songImages = await renderSongListItemsSequentially(
|
||||||
|
tempSongList,
|
||||||
for (let i = 0; i < tempSongList.length; i++) {
|
displayedServerList,
|
||||||
songPromises.push(
|
);
|
||||||
drawSongInList(
|
|
||||||
tempSongList[i],
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
displayedServerList,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const songImages = await Promise.all(songPromises);
|
|
||||||
|
|
||||||
for (let i = 0; i < songImages.length; i++) {
|
for (let i = 0; i < songImages.length; i++) {
|
||||||
const tempImage = songImages[i];
|
const tempImage = songImages[i];
|
||||||
@ -131,3 +121,31 @@ export const matchSongList = createBangDreamEntityMatcher<Song>({
|
|||||||
*/
|
*/
|
||||||
relationValue: (song) => song.songId,
|
relationValue: (song) => song.songId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type SongListItemRenderer = (
|
||||||
|
song: Song,
|
||||||
|
difficulty: number | undefined,
|
||||||
|
text: string | undefined,
|
||||||
|
displayedServerList: Server[],
|
||||||
|
) => Promise<Canvas>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在歌曲列表中顺序渲染单项,避免并发 Skia 图片解码导致 native 内存峰值过高。
|
||||||
|
*
|
||||||
|
* @param songs - 待绘制歌曲列表。
|
||||||
|
* @param displayedServerList - 允许展示或下载资源的服务器优先级列表。
|
||||||
|
* @param renderItem - 单项渲染函数,未传入时使用默认歌曲列表渲染器。
|
||||||
|
*/
|
||||||
|
export async function renderSongListItemsSequentially(
|
||||||
|
songs: Song[],
|
||||||
|
displayedServerList: Server[],
|
||||||
|
renderItem: SongListItemRenderer = drawSongInList,
|
||||||
|
): Promise<Canvas[]> {
|
||||||
|
const songImages: Canvas[] = [];
|
||||||
|
for (const song of songs) {
|
||||||
|
songImages.push(
|
||||||
|
await renderItem(song, undefined, undefined, displayedServerList),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return songImages;
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,39 @@
|
|||||||
|
import { Server } from '@/modules/qqbot/plugins/bangdream/src/domain/catalog/server.model';
|
||||||
|
import type { Song } from '@/modules/qqbot/plugins/bangdream/src/domain/song/song.model';
|
||||||
|
|
||||||
|
describe('BangDream song search rendering', () => {
|
||||||
|
it('renders song list items sequentially to keep canvas memory bounded', async () => {
|
||||||
|
const { renderSongListItemsSequentially } = await import(
|
||||||
|
'@/modules/qqbot/plugins/bangdream/src/domain/song/song-search.renderer'
|
||||||
|
);
|
||||||
|
let active = 0;
|
||||||
|
let maxActive = 0;
|
||||||
|
const order: number[] = [];
|
||||||
|
const songs = [1, 2, 3].map(
|
||||||
|
(songId) =>
|
||||||
|
({
|
||||||
|
songId,
|
||||||
|
}) as Song,
|
||||||
|
);
|
||||||
|
|
||||||
|
const images = await renderSongListItemsSequentially(
|
||||||
|
songs,
|
||||||
|
[Server.cn, Server.jp],
|
||||||
|
async (song) => {
|
||||||
|
active++;
|
||||||
|
maxActive = Math.max(maxActive, active);
|
||||||
|
await Promise.resolve();
|
||||||
|
order.push(song.songId);
|
||||||
|
active--;
|
||||||
|
return {
|
||||||
|
height: song.songId,
|
||||||
|
width: song.songId,
|
||||||
|
} as any;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(maxActive).toBe(1);
|
||||||
|
expect(order).toEqual([1, 2, 3]);
|
||||||
|
expect(images.map((image) => image.width)).toEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user