fix: 顺序渲染BangDream歌曲列表

This commit is contained in:
sunlei 2026-06-16 07:38:19 +08:00
parent 1deb2dc8b6
commit e19f573699
2 changed files with 71 additions and 14 deletions

View File

@ -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;
}

View File

@ -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]);
});
});