Skip to content

Commit 7d1c212

Browse files
authored
🐛 Fix the playback queue disorder caused by the playlist (#13)
1 parent 1b3c9e4 commit 7d1c212

File tree

7 files changed

+67
-41
lines changed

7 files changed

+67
-41
lines changed

src/components/MusicList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { memo, useEffect, useRef, CSSProperties } from "react";
22
import useStore, { FileInfo } from "@/store";
33
import { Image, Skeleton } from "@heroui/react";
4-
import { secondsToMinutes, updatePlaylist } from "@/utils/player";
4+
import { secondsToMinutes, updatePlayQuque } from "@/utils/player";
55
import { parseMusicMeta } from "@/utils/meta";
66
import { FixedSizeList, areEqual } from "react-window";
77
import AutoSizer from "react-virtualized-auto-sizer";
@@ -148,7 +148,7 @@ const MusicList = ({ musicList }: { musicList: FileInfo[] }) => {
148148
style={style}
149149
onClick={() => {
150150
setCurrentMusic(sign, index, name);
151-
updatePlaylist("select");
151+
updatePlayQuque("select");
152152
}}
153153
onContextMenu={(e) => {
154154
curActMusicId.current = sign;

src/layout/Menu.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import useStore from "@/store";
1616
import { jumpLogin } from "@/utils/request";
1717
import { useEffect, useState, useRef } from "react";
1818
import ContextMenu, { ContextMenuRef } from "@/components/ContextMenu";
19+
import { updatePlayQuque } from "@/utils/player";
1920

2021
const CreatePlaylist = ({
2122
isOpen,
@@ -115,7 +116,10 @@ const Menu = () => {
115116
key={key}
116117
className={`flex items-center justify-start w-full px-4 bg-opacity-70 hover:bg-white cursor-pointer ${key === currentGroup ? "bg-white" : "bg-transparent"}`}
117118
style={{ height: 90 }}
118-
onClick={() => setCurrentGroup(key)}
119+
onClick={() => {
120+
setCurrentGroup(key);
121+
updatePlayQuque();
122+
}}
119123
onContextMenu={(e) => {
120124
e.preventDefault();
121125
if (key === "All Music") return;

src/layout/Player.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import useStore from "@/store";
33
import usePlayAudio from "@/hooks/usePlayAudio";
44
import MiniPlayer from "@/components/MiniPlayer";
55
import { parseMusicMeta } from "@/utils/meta";
6-
import { updatePlaylist } from "@/utils/player";
6+
import { updatePlayQuque } from "@/utils/player";
77

88
const Player = () => {
99
const currentMusicId = useStore((state) => state.currentMusicId);
@@ -12,7 +12,7 @@ const Player = () => {
1212
const musicMetaMap = useStore.getState().musicMetaMap;
1313
const musicList = useStore((state) => state.getMusicList());
1414
const history = useStore((state) => state.history);
15-
const playlist = useStore((state) => state.playlist);
15+
const playQueue = useStore((state) => state.playQueue);
1616
const isShuffle = useStore((state) => state.isShuffle);
1717
const isRepeat = useStore((state) => state.isRepeat);
1818
const isLoop = useStore((state) => state.isLoop);
@@ -48,23 +48,23 @@ const Player = () => {
4848
}, [currentMusicId, currentFileName]);
4949

5050
useEffect(() => {
51-
updatePlaylist();
51+
updatePlayQuque();
5252
}, [isShuffle, isLoop]);
5353

5454
const next = (isEnded?: boolean) => {
5555
if (useStore.getState().isRepeat && isEnded) {
5656
return controls.reload();
5757
}
5858

59-
const playlist = useStore.getState().playlist;
59+
const playQueue = useStore.getState().playQueue;
6060

61-
if (playlist.length === 0) return;
61+
if (playQueue.length === 0) return;
6262

63-
const musicIndex = playlist[0];
63+
const musicIndex = playQueue[0];
6464
const music = useStore.getState().getMusicList()[musicIndex];
6565

6666
setCurrentMusic(music.sign, musicIndex, music.name);
67-
updatePlaylist("next");
67+
updatePlayQuque("next");
6868
};
6969

7070
const prev = () => {
@@ -106,7 +106,7 @@ const Player = () => {
106106
artist,
107107
cover: coverUrl,
108108
prevDisabled: history.length === 0,
109-
nextDisabled: playlist.length === 0,
109+
nextDisabled: playQueue.length === 0,
110110
next,
111111
prev,
112112
isLoop,

src/store/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ type BeagleState = {
3131

3232
musicMetaMap: Map<string, Metadata | null>;
3333
getMusicList: () => FileInfo[];
34-
playlist: number[];
34+
playQueue: number[];
3535
history: number[];
36-
setPlaylist: (playlist: number[]) => void;
36+
setPlayQueue: (playQueue: number[]) => void;
3737
setHistory: (history: number[]) => void;
3838
addMusicMeta: (id: string, meta: Metadata | null) => void;
3939

@@ -80,13 +80,13 @@ const useStore = create<BeagleState>()(
8080
});
8181
},
8282

83-
// 音乐&元数据&播放列表
83+
// 音乐&元数据&播放队列
8484
musicMetaMap: new Map(),
85-
playlist: [],
85+
playQueue: [],
8686
history: [],
8787
setHistory: (history) => set({ history }),
88-
setPlaylist: (playlist) => {
89-
set({ playlist });
88+
setPlayQueue: (playQueue) => {
89+
set({ playQueue });
9090
},
9191
addMusicMeta: (id, meta) =>
9292
set((state) => ({

src/utils/array.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,28 @@ export const generateRandomArray = (
1717
max: number,
1818
exclude: number[] = [],
1919
) => {
20-
if (length > max + 1 - exclude.length) return [];
21-
const arr = Array.from({ length: max + 1 }, (_, i) => i).filter(
22-
(i) => !exclude.includes(i),
23-
);
24-
for (let i = 0; i < length; i++) {
25-
const j = i + Math.floor(Math.random() * (max + 1 - exclude.length - i));
26-
[arr[i], arr[j]] = [arr[j], arr[i]];
20+
const actualLen = max + 1 - exclude.length;
21+
const splitNum = Math.ceil(length / actualLen);
22+
let ans: number[] = [];
23+
24+
for (let count = 1; count <= splitNum; count++) {
25+
const len =
26+
length > actualLen
27+
? count * actualLen <= length
28+
? actualLen
29+
: length - actualLen
30+
: length;
31+
32+
const arr = Array.from({ length: max + 1 }, (_, i) => i).filter(
33+
(i) => !exclude.includes(i),
34+
);
35+
for (let i = 0; i < len; i++) {
36+
const j = i + Math.floor(Math.random() * (actualLen - i));
37+
[arr[i], arr[j]] = [arr[j], arr[i]];
38+
}
39+
40+
ans = [...ans, ...arr.slice(0, len)];
2741
}
28-
return arr.slice(0, length);
42+
43+
return ans;
2944
};

src/utils/player.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,28 @@ export const secondsToMinutes = (seconds: number) => {
1313
return `${formatTime(seconds / 60)}:${formatTime(seconds % 60)}`;
1414
};
1515

16-
export const updatePlaylist = (trigger?: "next" | "prev" | "select") => {
16+
export const updatePlayQuque = (trigger?: "next" | "prev" | "select") => {
1717
const {
1818
getMusicList,
1919
isShuffle,
2020
isLoop,
2121
currentMusicIndex,
22-
setPlaylist,
23-
playlist,
22+
setPlayQueue,
23+
playQueue,
2424
} = useStore.getState();
2525
const musicList = getMusicList();
2626

2727
if (musicList.length > 0) {
28-
let newPlaylist: number[] = [];
28+
let newPlayQueue: number[] = [];
2929
if (isShuffle) {
30-
newPlaylist =
30+
newPlayQueue =
3131
trigger === "next"
3232
? [
33-
...playlist.filter((item) => item !== currentMusicIndex),
33+
...playQueue.filter((item) => item !== currentMusicIndex),
3434
...generateRandomArray(
35-
Math.min(10, musicList.length) - playlist.length,
35+
Math.min(10, musicList.length) - playQueue.length,
3636
musicList.length - 1,
37-
playlist.slice(1),
37+
playQueue.slice(1),
3838
),
3939
]
4040
: generateRandomArray(
@@ -43,17 +43,17 @@ export const updatePlaylist = (trigger?: "next" | "prev" | "select") => {
4343
[currentMusicIndex],
4444
);
4545
} else {
46-
newPlaylist = generateOrderedArray(
46+
newPlayQueue = generateOrderedArray(
4747
isLoop ? 10 : Math.min(10, musicList.length),
4848
currentMusicIndex + 1,
49-
musicList.length - 1,
49+
musicList.length,
5050
isLoop,
5151
);
5252
}
5353

54-
setPlaylist(newPlaylist);
54+
setPlayQueue(newPlayQueue);
5555

56-
const nextMusic = musicList[newPlaylist[0]];
56+
const nextMusic = musicList[newPlayQueue[0]] || {};
5757
parseMusicMeta(nextMusic.sign, nextMusic.name);
5858
}
5959
};

test/array.test.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,34 @@ import {
55
} from "../src/utils/array.ts";
66

77
describe("generateRandomArray", () => {
8-
test("生成指定长度的数组", () => {
8+
test("should generate an array of specified length.", () => {
99
const array = generateRandomArray(5, 10);
1010
expect(array).toHaveLength(5);
1111
});
1212

13-
test("数组不重复", () => {
13+
test("the array does not repeat(when the length is sufficient)", () => {
1414
const array = generateRandomArray(5, 4);
1515
expect(array).toStrictEqual(Array.from(new Set(array)));
1616
});
1717

18-
test("数组元素在指定范围内", () => {
18+
test("array elements within the specified range", () => {
1919
const array = generateRandomArray(5, 4);
2020
expect(array.every((num) => num >= 0 && num <= 5)).toBe(true);
2121
});
2222

23-
test("数组元素不包含指定元素", () => {
23+
test("the array elements do not contain the specified element", () => {
2424
const array = generateRandomArray(5, 6, [2, 4]);
2525
expect(
2626
array.every((num) => num >= 0 && num <= 6 && ![2, 4].includes(num)),
2727
).toBe(true);
2828
});
29+
30+
test("Complete when the array length is insufficient", () => {
31+
const array = generateRandomArray(10, 4);
32+
expect(array).toHaveLength(10);
33+
expect(new Set(array.slice(0, 5))).toEqual(new Set([0, 1, 2, 3, 4]));
34+
expect(new Set(array.slice(5, 10))).toEqual(new Set([0, 1, 2, 3, 4]));
35+
});
2936
});
3037

3138
describe("generateOrderedArray", () => {

0 commit comments

Comments
 (0)