|
| 1 | +import { useDataStore, useSettingStore, useShortcutStore, useStatusStore } from "@/stores"; |
| 2 | +import { useEventListener } from "@vueuse/core"; |
| 3 | +import { watch, onMounted } from "vue"; |
| 4 | +import { openUserAgreement } from "@/utils/modal"; |
| 5 | +import { debounce } from "lodash-es"; |
| 6 | +import { isElectron } from "@/utils/env"; |
| 7 | +import { usePlayerController } from "@/core/player/PlayerController"; |
| 8 | +import { mediaSessionManager } from "@/core/player/MediaSessionManager"; |
| 9 | +import { useDownloadManager } from "@/core/resource/DownloadManager"; |
| 10 | +import { printVersion } from "@/utils/log"; |
| 11 | + |
| 12 | +/** |
| 13 | + * 应用初始化时需要执行的操作 |
| 14 | + */ |
| 15 | +export const useInit = () => { |
| 16 | + // init pinia-data |
| 17 | + const dataStore = useDataStore(); |
| 18 | + const statusStore = useStatusStore(); |
| 19 | + const settingStore = useSettingStore(); |
| 20 | + const shortcutStore = useShortcutStore(); |
| 21 | + |
| 22 | + const player = usePlayerController(); |
| 23 | + const downloadManager = useDownloadManager(); |
| 24 | + |
| 25 | + // 事件监听 |
| 26 | + initEventListener(); |
| 27 | + |
| 28 | + onMounted(async () => { |
| 29 | + // 检查并执行设置迁移 |
| 30 | + settingStore.checkAndMigrate(); |
| 31 | + // 打印版本信息 |
| 32 | + printVersion(); |
| 33 | + // 用户协议 |
| 34 | + openUserAgreement(); |
| 35 | + // 加载数据 |
| 36 | + await dataStore.loadData(); |
| 37 | + // 初始化 MediaSession |
| 38 | + mediaSessionManager.init(); |
| 39 | + // 初始化播放器 |
| 40 | + player.playSong({ |
| 41 | + autoPlay: settingStore.autoPlay, |
| 42 | + seek: settingStore.memoryLastSeek ? statusStore.currentTime : 0, |
| 43 | + }); |
| 44 | + // 同步播放模式 |
| 45 | + player.playModeSyncIpc(); |
| 46 | + // 初始化自动关闭定时器 |
| 47 | + if (statusStore.autoClose.enable) { |
| 48 | + const { endTime, time } = statusStore.autoClose; |
| 49 | + const now = Date.now(); |
| 50 | + if (endTime > now) { |
| 51 | + // 计算真实剩余时间 |
| 52 | + const realRemainTime = Math.ceil((endTime - now) / 1000); |
| 53 | + player.startAutoCloseTimer(time, realRemainTime); |
| 54 | + } else { |
| 55 | + // 定时器已过期,重置状态 |
| 56 | + statusStore.autoClose.enable = false; |
| 57 | + statusStore.autoClose.remainTime = time * 60; |
| 58 | + statusStore.autoClose.endTime = 0; |
| 59 | + } |
| 60 | + } |
| 61 | + if (isElectron) { |
| 62 | + // 注册全局快捷键 |
| 63 | + shortcutStore.registerAllShortcuts(); |
| 64 | + // 初始化下载管理器 |
| 65 | + downloadManager.init(); |
| 66 | + // 显示窗口 |
| 67 | + window.electron.ipcRenderer.send("win-loaded"); |
| 68 | + // 同步任务栏歌词状态 |
| 69 | + window.electron.ipcRenderer.send("taskbar:toggle", statusStore.showTaskbarLyric); |
| 70 | + // 显示桌面歌词 |
| 71 | + window.electron.ipcRenderer.send("toggle-desktop-lyric", statusStore.showDesktopLyric); |
| 72 | + // 检查更新 |
| 73 | + if (settingStore.checkUpdateOnStart) window.electron.ipcRenderer.send("check-update"); |
| 74 | + |
| 75 | + // 监听任务栏歌词设置 |
| 76 | + watch( |
| 77 | + () => settingStore.taskbarLyricMaxWidth, |
| 78 | + (val) => { |
| 79 | + window.electron.ipcRenderer.send("taskbar:set-max-width", val); |
| 80 | + }, |
| 81 | + ); |
| 82 | + |
| 83 | + watch( |
| 84 | + () => settingStore.taskbarLyricShowCover, |
| 85 | + (val) => { |
| 86 | + window.electron.ipcRenderer.send("taskbar:set-show-cover", val); |
| 87 | + }, |
| 88 | + ); |
| 89 | + |
| 90 | + watch( |
| 91 | + () => settingStore.taskbarLyricPosition, |
| 92 | + (val) => { |
| 93 | + window.electron.ipcRenderer.send("taskbar:set-position", val); |
| 94 | + }, |
| 95 | + ); |
| 96 | + |
| 97 | + watch( |
| 98 | + () => settingStore.taskbarLyricShowWhenPaused, |
| 99 | + (val) => { |
| 100 | + window.electron.ipcRenderer.send("taskbar:set-show-when-paused", val); |
| 101 | + }, |
| 102 | + ); |
| 103 | + |
| 104 | + watch( |
| 105 | + () => settingStore.taskbarLyricAutoShrink, |
| 106 | + (val) => { |
| 107 | + window.electron.ipcRenderer.send("taskbar:set-auto-shrink", val); |
| 108 | + }, |
| 109 | + ); |
| 110 | + |
| 111 | + watch( |
| 112 | + () => [ |
| 113 | + settingStore.taskbarLyricAnimationMode, |
| 114 | + settingStore.taskbarLyricSingleLineMode, |
| 115 | + settingStore.LyricFont, |
| 116 | + settingStore.globalFont, |
| 117 | + settingStore.taskbarLyricFontWeight, |
| 118 | + ], |
| 119 | + () => { |
| 120 | + window.electron.ipcRenderer.send("taskbar:broadcast-settings", { |
| 121 | + animationMode: settingStore.taskbarLyricAnimationMode, |
| 122 | + singleLineMode: settingStore.taskbarLyricSingleLineMode, |
| 123 | + lyricFont: settingStore.LyricFont, |
| 124 | + globalFont: settingStore.globalFont, |
| 125 | + fontWeight: settingStore.taskbarLyricFontWeight, |
| 126 | + }); |
| 127 | + }, |
| 128 | + { deep: true }, |
| 129 | + ); |
| 130 | + } |
| 131 | + }); |
| 132 | +}; |
| 133 | + |
| 134 | +// 事件监听 |
| 135 | +const initEventListener = () => { |
| 136 | + // 键盘事件 |
| 137 | + useEventListener(window, "keydown", keyDownEvent); |
| 138 | +}; |
| 139 | + |
| 140 | +// 键盘事件 |
| 141 | +const keyDownEvent = debounce((event: KeyboardEvent) => { |
| 142 | + const player = usePlayerController(); |
| 143 | + const shortcutStore = useShortcutStore(); |
| 144 | + const statusStore = useStatusStore(); |
| 145 | + const target = event.target as HTMLElement; |
| 146 | + // 排除元素 |
| 147 | + const extendsDom = ["input", "textarea"]; |
| 148 | + if (extendsDom.includes(target.tagName.toLowerCase())) return; |
| 149 | + event.preventDefault(); |
| 150 | + event.stopPropagation(); |
| 151 | + // 获取按键信息 |
| 152 | + const key = event.code; |
| 153 | + const isCtrl = event.ctrlKey || event.metaKey; |
| 154 | + const isShift = event.shiftKey; |
| 155 | + const isAlt = event.altKey; |
| 156 | + // 循环注册快捷键 |
| 157 | + for (const shortcutKey in shortcutStore.shortcutList) { |
| 158 | + const shortcut = shortcutStore.shortcutList[shortcutKey]; |
| 159 | + const shortcutParts = shortcut.shortcut.split("+"); |
| 160 | + // 标志位 |
| 161 | + let match = true; |
| 162 | + // 检查是否包含修饰键 |
| 163 | + const hasCmdOrCtrl = shortcutParts.includes("CmdOrCtrl"); |
| 164 | + const hasShift = shortcutParts.includes("Shift"); |
| 165 | + const hasAlt = shortcutParts.includes("Alt"); |
| 166 | + // 检查修饰键匹配 |
| 167 | + if (hasCmdOrCtrl && !isCtrl) match = false; |
| 168 | + if (hasShift && !isShift) match = false; |
| 169 | + if (hasAlt && !isAlt) match = false; |
| 170 | + // 如果快捷键定义中没有修饰键,确保没有按下任何修饰键 |
| 171 | + if (!hasCmdOrCtrl && !hasShift && !hasAlt) { |
| 172 | + if (isCtrl || isShift || isAlt) match = false; |
| 173 | + } |
| 174 | + // 检查实际按键 |
| 175 | + const mainKey = shortcutParts.find( |
| 176 | + (part: string) => part !== "CmdOrCtrl" && part !== "Shift" && part !== "Alt", |
| 177 | + ); |
| 178 | + if (mainKey !== key) match = false; |
| 179 | + if (match && shortcutKey) { |
| 180 | + console.log(shortcutKey, `快捷键触发: ${shortcut.name}`); |
| 181 | + switch (shortcutKey) { |
| 182 | + case "playOrPause": |
| 183 | + player.playOrPause(); |
| 184 | + break; |
| 185 | + case "playPrev": |
| 186 | + player.nextOrPrev("prev"); |
| 187 | + break; |
| 188 | + case "playNext": |
| 189 | + player.nextOrPrev("next"); |
| 190 | + break; |
| 191 | + case "volumeUp": |
| 192 | + player.setVolume("up"); |
| 193 | + break; |
| 194 | + case "volumeDown": |
| 195 | + player.setVolume("down"); |
| 196 | + break; |
| 197 | + case "toggle-desktop-lyric": |
| 198 | + player.toggleDesktopLyric(); |
| 199 | + break; |
| 200 | + case "openPlayer": |
| 201 | + // 打开播放界面(任意界面) |
| 202 | + statusStore.showFullPlayer = true; |
| 203 | + break; |
| 204 | + case "closePlayer": |
| 205 | + // 关闭播放界面(仅在播放界面时) |
| 206 | + if (statusStore.showFullPlayer) { |
| 207 | + statusStore.showFullPlayer = false; |
| 208 | + } |
| 209 | + break; |
| 210 | + case "openPlayList": |
| 211 | + // 打开播放列表(任意界面) |
| 212 | + statusStore.playListShow = !statusStore.playListShow; |
| 213 | + break; |
| 214 | + default: |
| 215 | + break; |
| 216 | + } |
| 217 | + } |
| 218 | + } |
| 219 | +}, 100); |
0 commit comments