Skip to content

Commit 89a0569

Browse files
authored
Merge pull request #947 from imsyy/dev-lrc
Add taskbar lyrics display modes and enhance floating window features
2 parents 76be3cc + cebf8bb commit 89a0569

12 files changed

Lines changed: 712 additions & 202 deletions

File tree

electron/main/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { trySendCustomProtocol } from "./utils/protocol";
1515
import { initSingleLock } from "./utils/single-lock";
1616
import loadWindow from "./windows/load-window";
1717
import mainWindow from "./windows/main-window";
18-
import taskbarLyricWindow from "./windows/taskbar-lyric-window";
18+
import taskbarLyricManager from "./utils/taskbar-lyric-manager";
1919

2020
// 屏蔽报错
2121
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = "true";
@@ -144,7 +144,7 @@ class MainProcess {
144144
// 清理媒体集成资源
145145
shutdownMedia();
146146
// 销毁任务栏歌词窗口
147-
taskbarLyricWindow.destroy();
147+
taskbarLyricManager.destroyAll();
148148
// 停止 MPV 服务
149149
const mpvService = MpvService.getInstance();
150150
try {

electron/main/ipc/ipc-taskbar.ts

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,26 @@ import type EventEmitter from "node:events";
44
import { useStore } from "../store";
55
import { getMainTray } from "../tray";
66
import mainWindow from "../windows/main-window";
7-
import taskbarLyricWindow from "../windows/taskbar-lyric-window";
7+
import taskbarLyricManager from "../utils/taskbar-lyric-manager";
88

99
let cachedIsPlaying = false;
1010

1111
const getTaskbarConfig = (): TaskbarConfig => {
1212
const store = useStore();
1313
return {
14+
mode: store.get("taskbar.mode", "taskbar"),
1415
maxWidth: store.get("taskbar.maxWidth", 300),
1516
position: store.get("taskbar.position", "automatic"),
1617
autoShrink: store.get("taskbar.autoShrink", false),
1718
margin: store.get("taskbar.margin", 10),
1819
minWidth: store.get("taskbar.minWidth", 10),
1920
enabled: store.get("taskbar.enabled", false),
21+
floatingAlign: store.get("taskbar.floatingAlign", "right"),
22+
floatingAutoWidth: store.get("taskbar.floatingAutoWidth", true),
23+
floatingWidth: store.get("taskbar.floatingWidth", 300),
24+
floatingHeight: store.get("taskbar.floatingHeight", 48),
25+
floatingAlwaysOnTop: store.get("taskbar.floatingAlwaysOnTop", false),
26+
2027
showWhenPaused: store.get("taskbar.showWhenPaused", true),
2128
showCover: store.get("taskbar.showCover", true),
2229
themeMode: store.get("taskbar.themeMode", "auto"),
@@ -40,11 +47,11 @@ const updateWindowVisibility = (config: TaskbarConfig) => {
4047

4148
const shouldBeVisible = config.enabled && (cachedIsPlaying || config.showWhenPaused);
4249

43-
taskbarLyricWindow.setVisibility(shouldBeVisible);
50+
taskbarLyricManager.setVisibility(shouldBeVisible);
4451
};
4552

4653
const updateWindowLayout = (animate: boolean = true) => {
47-
taskbarLyricWindow.updateLayout(animate);
54+
taskbarLyricManager.updateLayout(animate);
4855
};
4956

5057
const initTaskbarIpc = () => {
@@ -53,10 +60,14 @@ const initTaskbarIpc = () => {
5360

5461
const initialConfig = getTaskbarConfig();
5562
if (initialConfig.enabled) {
56-
taskbarLyricWindow.create();
63+
taskbarLyricManager.create(initialConfig.mode);
5764
updateWindowVisibility(initialConfig);
5865
}
5966

67+
ipcMain.on("taskbar:set-width", (_event, width: number) => {
68+
taskbarLyricManager.setContentWidth(width);
69+
});
70+
6071
ipcMain.on(
6172
TASKBAR_IPC_CHANNELS.UPDATE_CONFIG,
6273
(_event, partialConfig: Partial<TaskbarConfig>) => {
@@ -68,30 +79,53 @@ const initTaskbarIpc = () => {
6879

6980
const newConfig = getTaskbarConfig();
7081

71-
if (newConfig.enabled && !oldConfig.enabled) {
72-
taskbarLyricWindow.create();
82+
const modeChanged = newConfig.mode !== oldConfig.mode;
83+
84+
if (modeChanged) {
85+
taskbarLyricManager.close(false);
86+
}
87+
88+
if (newConfig.enabled && (!oldConfig.enabled || modeChanged)) {
89+
taskbarLyricManager.create(newConfig.mode);
7390
}
7491

7592
if (
7693
newConfig.enabled !== oldConfig.enabled ||
77-
newConfig.showWhenPaused !== oldConfig.showWhenPaused
94+
newConfig.showWhenPaused !== oldConfig.showWhenPaused ||
95+
modeChanged
7896
) {
7997
updateWindowVisibility(newConfig);
8098
}
8199

82100
if (newConfig.enabled) {
83-
if (
84-
newConfig.maxWidth !== oldConfig.maxWidth ||
85-
newConfig.position !== oldConfig.position ||
86-
newConfig.autoShrink !== oldConfig.autoShrink ||
87-
newConfig.margin !== oldConfig.margin ||
88-
newConfig.minWidth !== oldConfig.minWidth
89-
) {
90-
updateWindowLayout(true);
101+
if (newConfig.mode === "taskbar") {
102+
if (
103+
newConfig.maxWidth !== oldConfig.maxWidth ||
104+
newConfig.position !== oldConfig.position ||
105+
newConfig.autoShrink !== oldConfig.autoShrink ||
106+
newConfig.margin !== oldConfig.margin ||
107+
newConfig.minWidth !== oldConfig.minWidth
108+
) {
109+
updateWindowLayout(true);
110+
}
111+
} else {
112+
const floatingWidthChanged =
113+
newConfig.floatingAutoWidth === false && newConfig.floatingWidth !== oldConfig.floatingWidth;
114+
if (
115+
newConfig.maxWidth !== oldConfig.maxWidth ||
116+
newConfig.floatingAlign !== oldConfig.floatingAlign ||
117+
newConfig.floatingAutoWidth !== oldConfig.floatingAutoWidth ||
118+
floatingWidthChanged ||
119+
newConfig.floatingHeight !== oldConfig.floatingHeight ||
120+
newConfig.floatingAlwaysOnTop !== oldConfig.floatingAlwaysOnTop ||
121+
modeChanged
122+
) {
123+
updateWindowLayout(false);
124+
}
91125
}
92126
}
93127

94-
taskbarLyricWindow.send(TASKBAR_IPC_CHANNELS.SYNC_STATE, {
128+
taskbarLyricManager.send(TASKBAR_IPC_CHANNELS.SYNC_STATE, {
95129
type: "config-update",
96130
data: partialConfig,
97131
} as SyncStatePayload);
@@ -111,11 +145,11 @@ const initTaskbarIpc = () => {
111145
updateWindowVisibility(getTaskbarConfig());
112146
}
113147

114-
taskbarLyricWindow.send(TASKBAR_IPC_CHANNELS.SYNC_STATE, payload);
148+
taskbarLyricManager.send(TASKBAR_IPC_CHANNELS.SYNC_STATE, payload);
115149
});
116150

117151
ipcMain.on(TASKBAR_IPC_CHANNELS.SYNC_TICK, (_event, payload) => {
118-
taskbarLyricWindow.send(TASKBAR_IPC_CHANNELS.SYNC_TICK, payload);
152+
taskbarLyricManager.send(TASKBAR_IPC_CHANNELS.SYNC_TICK, payload);
119153
});
120154

121155
ipcMain.on(TASKBAR_IPC_CHANNELS.REQUEST_DATA, () => {
@@ -124,27 +158,28 @@ const initTaskbarIpc = () => {
124158
mainWin.webContents.send(TASKBAR_IPC_CHANNELS.REQUEST_DATA);
125159
}
126160

127-
taskbarLyricWindow.updateLayout(false);
161+
taskbarLyricManager.updateLayout(false);
128162

129163
const isDark = nativeTheme.shouldUseDarkColors;
130-
taskbarLyricWindow.send(TASKBAR_IPC_CHANNELS.SYNC_STATE, {
164+
taskbarLyricManager.send(TASKBAR_IPC_CHANNELS.SYNC_STATE, {
131165
type: "system-theme",
132166
data: { isDark },
133167
} as SyncStatePayload);
134168
});
135169

136170
ipcMain.on("taskbar:fade-done", () => {
137-
taskbarLyricWindow.handleFadeDone();
171+
taskbarLyricManager.handleFadeDone();
138172
});
139173

140174
// 把事件发射到 app 里不太好,但是我觉得也没有必要为了这一个事件创建一个事件总线
141175
// TODO: 如果有了事件总线,通过那个事件总线发射这个事件
142176
(app as EventEmitter).on("explorer-restarted", () => {
143177
const currentEnabled = store.get("taskbar.enabled");
144-
if (currentEnabled) {
145-
taskbarLyricWindow.close(false);
178+
const currentMode = store.get("taskbar.mode", "taskbar");
179+
if (currentEnabled && currentMode === "taskbar") {
180+
taskbarLyricManager.close(false);
146181
setTimeout(() => {
147-
taskbarLyricWindow.create();
182+
taskbarLyricManager.create("taskbar");
148183
}, 500);
149184
}
150185
});

electron/main/store/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export interface StoreType {
4343
taskbar: {
4444
/** 是否启用 */
4545
enabled: boolean;
46+
/** 模式 */
47+
mode?: "taskbar" | "floating";
4648
/** 最大宽度 */
4749
maxWidth?: number;
4850
/** 显示封面 */
@@ -57,6 +59,13 @@ export interface StoreType {
5759
margin?: number;
5860
/** 最小宽度 (百分比) */
5961
minWidth?: number;
62+
floatingX?: number;
63+
floatingY?: number;
64+
floatingAlign?: "left" | "right";
65+
floatingAutoWidth?: boolean;
66+
floatingWidth?: number;
67+
floatingHeight?: number;
68+
floatingAlwaysOnTop?: boolean;
6069
};
6170
/** 代理 */
6271
proxy: string;
@@ -112,13 +121,21 @@ export const useStore = () => {
112121
},
113122
taskbar: {
114123
enabled: false,
124+
mode: "taskbar",
115125
maxWidth: 30,
116126
showCover: true,
117127
position: "automatic",
118128
showWhenPaused: true,
119129
autoShrink: false,
120130
margin: 10,
121131
minWidth: 10,
132+
floatingX: screenData.workArea.x + screenData.workArea.width / 2 - 150,
133+
floatingY: screenData.workArea.y + screenData.workArea.height - 120,
134+
floatingAlign: "right",
135+
floatingAutoWidth: true,
136+
floatingWidth: 300,
137+
floatingHeight: 48,
138+
floatingAlwaysOnTop: false,
122139
},
123140
macos: {
124141
statusBarLyric: {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import floatingTaskbarLyricWindow from "../windows/floating-taskbar-lyric-window";
2+
import taskbarLyricWindow from "../windows/taskbar-lyric-window";
3+
4+
export type TaskbarLyricMode = "taskbar" | "floating";
5+
6+
class TaskbarLyricManager {
7+
private mode: TaskbarLyricMode = "taskbar";
8+
9+
getMode() {
10+
return this.mode;
11+
}
12+
13+
private getActive() {
14+
return this.mode === "floating" ? floatingTaskbarLyricWindow : taskbarLyricWindow;
15+
}
16+
17+
create(mode: TaskbarLyricMode) {
18+
if (mode !== this.mode) {
19+
this.close(false);
20+
this.mode = mode;
21+
}
22+
return this.getActive().create();
23+
}
24+
25+
close(animate: boolean = true) {
26+
if (this.mode === "floating") {
27+
floatingTaskbarLyricWindow.close();
28+
return;
29+
}
30+
taskbarLyricWindow.close(animate);
31+
}
32+
33+
setVisibility(shouldShow: boolean) {
34+
this.getActive().setVisibility(shouldShow);
35+
}
36+
37+
updateLayout(animate: boolean = false) {
38+
if (this.mode === "floating") {
39+
floatingTaskbarLyricWindow.updateLayout(animate);
40+
return;
41+
}
42+
taskbarLyricWindow.updateLayout(animate);
43+
}
44+
45+
setContentWidth(width: number) {
46+
this.getActive().setContentWidth(width);
47+
}
48+
49+
handleFadeDone() {
50+
this.getActive().handleFadeDone();
51+
}
52+
53+
send(channel: string, ...args: unknown[]) {
54+
this.getActive().send(channel, ...args);
55+
}
56+
57+
destroyAll() {
58+
floatingTaskbarLyricWindow.close();
59+
floatingTaskbarLyricWindow.destroy();
60+
taskbarLyricWindow.destroy();
61+
}
62+
}
63+
64+
export default new TaskbarLyricManager();

0 commit comments

Comments
 (0)