Skip to content

Commit 5b4a7af

Browse files
authored
Merge pull request #685 from apoint123/refactor/split-playback-mode-button
🦄 refactor: 拆分单个播放模式按钮为两个
2 parents e021b25 + 32ce85a commit 5b4a7af

22 files changed

Lines changed: 633 additions & 401 deletions

auto-eslint.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,11 @@ export default {
9696
"refAutoReset": true,
9797
"refDebounced": true,
9898
"refDefault": true,
99+
"refManualReset": true,
99100
"refThrottled": true,
100101
"refWithControl": true,
101102
"resolveComponent": true,
102103
"resolveRef": true,
103-
"resolveUnref": true,
104104
"shallowReactive": true,
105105
"shallowReadonly": true,
106106
"shallowRef": true,

electron.vite.config.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { resolve } from "path";
2-
import { MainEnv } from "./env";
3-
import { defineConfig, loadEnv } from "electron-vite";
4-
import { NaiveUiResolver } from "unplugin-vue-components/resolvers";
51
import vue from "@vitejs/plugin-vue";
2+
import { defineConfig, loadEnv } from "electron-vite";
3+
import { resolve } from "path";
64
import AutoImport from "unplugin-auto-import/vite";
5+
import { NaiveUiResolver } from "unplugin-vue-components/resolvers";
76
import Components from "unplugin-vue-components/vite";
87
import viteCompression from "vite-plugin-compression";
8+
import { MainEnv } from "./env";
99
// import VueDevTools from "vite-plugin-vue-devtools";
1010
import wasm from "vite-plugin-wasm";
1111

@@ -70,6 +70,7 @@ export default defineConfig(({ mode }) => {
7070
alias: {
7171
"@": resolve(__dirname, "src/"),
7272
"@native": resolve(__dirname, "native/smtc-for-splayer"),
73+
"@shared": resolve(__dirname, "src/types/shared.ts"),
7374
},
7475
},
7576
css: {

electron/main/ipc/ipc-smtc.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { ipcMain, BrowserWindow, app } from "electron";
1+
import { BrowserWindow, app, ipcMain } from "electron";
22
import { join } from "path";
3-
import { loadNativeModule } from "../utils/native-loader";
4-
import { processLog } from "../logger";
53
import { IpcChannelMap } from "../../../src/types/global";
4+
import { processLog } from "../logger";
5+
import { loadNativeModule } from "../utils/native-loader";
66

77
type NativeSmtcModule = typeof import("@native");
88
type DiscordRpcModule = typeof import("@discord-rpc");

electron/main/ipc/ipc-tray.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import { PlayModePayload } from "@shared";
12
import { ipcMain } from "electron";
23
import { getMainTray } from "../tray";
3-
import lyricWindow from "../windows/lyric-window";
44
import { appName } from "../utils/config";
5+
import lyricWindow from "../windows/lyric-window";
56

67
/**
78
* 托盘 IPC
@@ -27,8 +28,8 @@ const initTrayIpc = (): void => {
2728
});
2829

2930
// 播放模式切换
30-
ipcMain.on("play-mode-change", (_, mode) => {
31-
tray?.setPlayMode(mode);
31+
ipcMain.on("play-mode-change", (_, data: PlayModePayload) => {
32+
tray?.setPlayMode(data.repeatMode, data.shuffleMode);
3233
});
3334

3435
// 喜欢状态切换

electron/main/tray/index.ts

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1+
import { RepeatModeType, ShuffleModeType } from "@shared";
12
import {
23
app,
3-
Tray,
4+
BrowserWindow,
45
Menu,
56
MenuItemConstructorOptions,
6-
BrowserWindow,
77
nativeImage,
88
nativeTheme,
9+
Tray,
910
} from "electron";
10-
import { isWin, appName } from "../utils/config";
1111
import { join } from "path";
1212
import { trayLog } from "../logger";
1313
import { useStore } from "../store";
14+
import { appName, isWin } from "../utils/config";
1415
import lyricWindow from "../windows/lyric-window";
1516

1617
// 播放模式
17-
type PlayMode = "repeat" | "repeat-once" | "shuffle";
1818
type PlayState = "play" | "pause" | "loading";
1919

20+
let repeatMode: RepeatModeType = "list";
21+
let shuffleMode: ShuffleModeType = "off";
22+
2023
// 全局数据
21-
let playMode: PlayMode = "repeat";
2224
let playState: PlayState = "pause";
2325
let playName: string = "未播放歌曲";
2426
let likeSong: boolean = false;
@@ -27,7 +29,7 @@ let desktopLyricLock: boolean = false;
2729

2830
export interface MainTray {
2931
setTitle(title: string): void;
30-
setPlayMode(mode: PlayMode): void;
32+
setPlayMode(repeat: RepeatModeType, shuffle: ShuffleModeType): void;
3133
setLikeState(like: boolean): void;
3234
setPlayState(state: PlayState): void;
3335
setPlayName(name: string): void;
@@ -58,6 +60,22 @@ const createTrayMenu = (win: BrowserWindow): MenuItemConstructorOptions[] => {
5860
height: 16,
5961
});
6062
};
63+
/**
64+
* 获取 {@linkcode RepeatModeType} 对应的显示字符串
65+
* @param mode 重复模式
66+
* @returns 对应的显示字符串
67+
*/
68+
const getRepeatLabel = (mode: RepeatModeType): string => {
69+
switch (mode) {
70+
case "one":
71+
return "单曲循环";
72+
case "off":
73+
return "不循环";
74+
case "list":
75+
default:
76+
return "列表循环";
77+
}
78+
};
6179
// 菜单
6280
const menu: MenuItemConstructorOptions[] = [
6381
{
@@ -79,34 +97,38 @@ const createTrayMenu = (win: BrowserWindow): MenuItemConstructorOptions[] => {
7997
click: () => win.webContents.send("toggle-like-song"),
8098
},
8199
{
82-
id: "changeMode",
83-
label:
84-
playMode === "repeat" ? "列表循环" : playMode === "repeat-once" ? "单曲循环" : "随机播放",
85-
icon: showIcon(playMode),
100+
id: "shuffle",
101+
label: shuffleMode === "heartbeat" ? "心动模式" : "随机播放",
102+
icon: showIcon("shuffle"),
103+
type: "checkbox",
104+
checked: shuffleMode !== "off",
105+
click: () => win.webContents.send("toggleShuffle"),
106+
},
107+
{
108+
id: "repeatMode",
109+
label: getRepeatLabel(repeatMode),
110+
icon: showIcon(repeatMode === "one" ? "repeat-once" : "repeat"),
86111
submenu: [
87112
{
88-
id: "repeat",
89113
label: "列表循环",
90114
icon: showIcon("repeat"),
91-
checked: playMode === "repeat",
92115
type: "radio",
93-
click: () => win.webContents.send("changeMode", "repeat"),
116+
checked: repeatMode === "list",
117+
click: () => win.webContents.send("changeRepeat", "list"),
94118
},
95119
{
96-
id: "repeat-once",
97120
label: "单曲循环",
98121
icon: showIcon("repeat-once"),
99-
checked: playMode === "repeat-once",
100122
type: "radio",
101-
click: () => win.webContents.send("changeMode", "repeat-once"),
123+
checked: repeatMode === "one",
124+
click: () => win.webContents.send("changeRepeat", "one"),
102125
},
103126
{
104-
id: "shuffle",
105-
label: "随机播放",
106-
icon: showIcon("shuffle"),
107-
checked: playMode === "shuffle",
127+
label: "关闭循环",
128+
icon: showIcon("repeat"),
108129
type: "radio",
109-
click: () => win.webContents.send("changeMode", "shuffle"),
130+
checked: repeatMode === "off",
131+
click: () => win.webContents.send("changeRepeat", "off"),
110132
},
111133
],
112134
},
@@ -259,10 +281,12 @@ class CreateTray implements MainTray {
259281
}
260282
/**
261283
* 设置播放模式
262-
* @param mode 播放模式
284+
* @param repeat 当前的重复播放模式
285+
* @param shuffle 当前的随机播放模式
263286
*/
264-
setPlayMode(mode: PlayMode) {
265-
playMode = mode;
287+
setPlayMode(repeat: RepeatModeType, shuffle: ShuffleModeType) {
288+
repeatMode = repeat;
289+
shuffleMode = shuffle;
266290
// 更新菜单
267291
this.initTrayMenu();
268292
}

src/api/playlist.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ export const playlistAllSongs = (id: number, limit: number = 50, offset: number
2626
* @param {number} id - 歌曲 id
2727
* @param {number} pid - 歌单 id
2828
* @param {number} sid - 要开始播放的歌曲的 id
29+
* @param {AbortSignal} [signal] - 用于取消请求的信号
2930
*/
30-
export const heartRateList = (id: number, pid: number, sid?: number) => {
31+
export const heartRateList = (id: number, pid: number, sid?: number, signal?: AbortSignal) => {
3132
return request({
3233
url: "/playmode/intelligence/list",
3334
params: { id, pid, sid, timestamp: Date.now() },
35+
signal,
3436
});
3537
};
3638

src/components/Layout/Menu.vue

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,25 @@
1717
</template>
1818

1919
<script setup lang="ts">
20+
import { usePlayerController } from "@/core/player/PlayerController";
21+
import { useDataStore, useMusicStore, useSettingStore, useStatusStore } from "@/stores";
22+
import type { CoverType } from "@/types/main";
23+
import { isLogin } from "@/utils/auth";
24+
import { isElectron } from "@/utils/env";
25+
import { renderIcon } from "@/utils/helper";
26+
import { openCreatePlaylist } from "@/utils/modal";
27+
import { debounce } from "lodash-es";
2028
import {
21-
type MenuOption,
2229
type MenuGroupOption,
2330
type MenuInst,
24-
NText,
25-
NButton,
26-
NEllipsis,
31+
type MenuOption,
2732
NAvatar,
2833
NBadge,
34+
NButton,
35+
NEllipsis,
36+
NText,
2937
} from "naive-ui";
30-
import type { CoverType } from "@/types/main";
31-
import { useStatusStore, useSettingStore, useDataStore, useMusicStore } from "@/stores";
32-
import { useRouter, RouterLink } from "vue-router";
33-
import { renderIcon } from "@/utils/helper";
34-
import { openCreatePlaylist } from "@/utils/modal";
35-
import { debounce } from "lodash-es";
36-
import { isLogin } from "@/utils/auth";
37-
import { isElectron } from "@/utils/env";
38-
import { usePlayerController } from "@/core/player/PlayerController";
38+
import { RouterLink, useRouter } from "vue-router";
3939
4040
const router = useRouter();
4141
const dataStore = useDataStore();
@@ -105,7 +105,7 @@ const menuOptions = computed<MenuOption[] | MenuGroupOption[]>(() => {
105105
h(NText, null, () => "我喜欢的音乐"),
106106
!settingStore.hideHeartbeatMode
107107
? h(NButton, {
108-
type: statusStore.playHeartbeatMode ? "primary" : "default",
108+
type: statusStore.shuffleMode === "heartbeat" ? "primary" : "default",
109109
round: true,
110110
strong: true,
111111
secondary: true,
@@ -271,7 +271,7 @@ const menuUpdate = (key: string, item: MenuOption) => {
271271
} else {
272272
// 更改播放模式
273273
statusStore.personalFmMode = true;
274-
statusStore.playHeartbeatMode = false;
274+
statusStore.shuffleMode = "off";
275275
player.playSong();
276276
}
277277
statusStore.showFullPlayer = true;
@@ -345,7 +345,7 @@ const checkMenuItem = () => {
345345
};
346346
347347
// 开启心动模式
348-
const openHeartMode = debounce(() => player.toggleHeartMode(), 1000, {
348+
const openHeartMode = debounce(() => player.toggleShuffle("heartbeat"), 1000, {
349349
leading: true,
350350
trailing: false,
351351
});

src/components/Player/MainPlayer.vue

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@
104104
</div>
105105
<!-- 控制 -->
106106
<div class="play-control">
107+
<!-- 随机按钮 -->
108+
<template v-if="musicStore.playSong.type !== 'radio' && !statusStore.personalFmMode">
109+
<div class="play-icon" @click.stop="player.toggleShuffle()">
110+
<SvgIcon
111+
:name="statusStore.shuffleIcon"
112+
:size="20"
113+
:depth="statusStore.shuffleMode === 'off' ? 3 : 1"
114+
/>
115+
</div>
116+
</template>
107117
<!-- 不喜欢 -->
108118
<div
109119
v-if="statusStore.personalFmMode"
@@ -142,6 +152,16 @@
142152
<div class="play-icon" v-debounce="() => player.nextOrPrev('next')">
143153
<SvgIcon :size="26" name="SkipNext" />
144154
</div>
155+
<!-- 循环按钮 -->
156+
<template v-if="musicStore.playSong.type !== 'radio' && !statusStore.personalFmMode">
157+
<div class="play-icon" @click.stop="player.toggleRepeat()">
158+
<SvgIcon
159+
:name="statusStore.repeatIcon"
160+
:size="20"
161+
:depth="statusStore.repeatMode === 'off' ? 3 : 1"
162+
/>
163+
</div>
164+
</template>
145165
</div>
146166
<!-- 功能 -->
147167
<Transition name="fade" mode="out-in">
@@ -187,21 +207,21 @@
187207
</template>
188208

189209
<script setup lang="ts">
190-
import type { DropdownOption } from "naive-ui";
191-
import { useMusicStore, useStatusStore, useDataStore, useSettingStore } from "@/stores";
192-
import { convertSecondsToTime } from "@/utils/time";
193-
import { renderIcon, coverLoaded, copyData } from "@/utils/helper";
210+
import { usePlayerController } from "@/core/player/PlayerController";
211+
import { useSongManager } from "@/core/player/SongManager";
212+
import { useDataStore, useMusicStore, useSettingStore, useStatusStore } from "@/stores";
194213
import { toLikeSong } from "@/utils/auth";
214+
import { getTimeDisplay, TIME_FORMATS } from "@/utils/format";
215+
import { copyData, coverLoaded, renderIcon } from "@/utils/helper";
195216
import {
196217
openAutoClose,
197218
openChangeRate,
198219
openDownloadSong,
199220
openJumpArtist,
200221
openPlaylistAdd,
201222
} from "@/utils/modal";
202-
import { useSongManager } from "@/core/player/SongManager";
203-
import { usePlayerController } from "@/core/player/PlayerController";
204-
import { getTimeDisplay, TIME_FORMATS } from "@/utils/format";
223+
import { convertSecondsToTime } from "@/utils/time";
224+
import type { DropdownOption } from "naive-ui";
205225
206226
const router = useRouter();
207227
const dataStore = useDataStore();
@@ -217,7 +237,7 @@ const timeDisplay0 = timeDisplay(0);
217237
const timeDisplay1 = timeDisplay(1);
218238
219239
const toggleTimeFormat = () => {
220-
const currentIndex = TIME_FORMATS.indexOf(settingStore.timeFormatMainPlayer)
240+
const currentIndex = TIME_FORMATS.indexOf(settingStore.timeFormatMainPlayer);
221241
settingStore.timeFormatMainPlayer = TIME_FORMATS[(currentIndex + 1) % TIME_FORMATS.length];
222242
};
223243
@@ -537,6 +557,7 @@ const instantLyrics = computed(() => {
537557
background-color 0.3s,
538558
transform 0.3s;
539559
cursor: pointer;
560+
margin: 0 2px;
540561
.n-icon {
541562
color: var(--primary-hex);
542563
}

src/components/Player/PersonalFM.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@
7676
</template>
7777

7878
<script setup lang="ts">
79+
import { usePlayerController } from "@/core/player/PlayerController";
80+
import { useSongManager } from "@/core/player/SongManager";
7981
import { useMusicStore, useStatusStore } from "@/stores";
8082
import { coverLoaded } from "@/utils/helper";
8183
import { debounce, isObject } from "lodash-es";
82-
import { useSongManager } from "@/core/player/SongManager";
83-
import { usePlayerController } from "@/core/player/PlayerController";
8484
8585
const musicStore = useMusicStore();
8686
const statusStore = useStatusStore();
@@ -100,15 +100,15 @@ const fmPlayOrPause = () => {
100100
} else {
101101
// 更改播放模式
102102
statusStore.personalFmMode = true;
103-
statusStore.playHeartbeatMode = false;
103+
statusStore.shuffleMode = "off";
104104
player.playSong();
105105
}
106106
};
107107
108108
// 下一曲
109109
const fmPlayNext = debounce(() => {
110110
statusStore.personalFmMode = true;
111-
statusStore.playHeartbeatMode = false;
111+
statusStore.shuffleMode = "off";
112112
player.nextOrPrev("next");
113113
}, 300);
114114

0 commit comments

Comments
 (0)