|
18 | 18 | * 职责: 安全地暴露主进程 API 到渲染进程 |
19 | 19 | */ |
20 | 20 |
|
21 | | -const { contextBridge, ipcRenderer } = require('electron') |
| 21 | +const { contextBridge, ipcRenderer } = require("electron"); |
22 | 22 |
|
23 | 23 | // IPC 频道白名单 |
24 | 24 | const validChannels = [ |
25 | | - // 窗口 |
26 | | - 'window:minimize', |
27 | | - 'window:maximize', |
28 | | - 'window:close', |
29 | | - 'window:toggleFullscreen', |
30 | | - 'window:getState', |
| 25 | + "window:minimize", |
| 26 | + "window:maximize", |
| 27 | + "window:close", |
| 28 | + "window:toggleFullscreen", |
| 29 | + "window:getState", |
31 | 30 |
|
32 | 31 | // 番剧 |
33 | | - 'anime:list', |
34 | | - 'anime:listWithProgress', |
35 | | - 'anime:detail', |
36 | | - 'anime:episodes', |
37 | | - 'anime:search', |
38 | | - 'anime:searchWithProgress', |
39 | | - 'anime:bangumi', |
40 | | - 'anime:video', |
41 | | - 'anime:video:proxy', |
42 | | - 'anime:cache:status', |
43 | | - 'anime:cache:refresh', |
44 | | - 'anime:pwEpisodes', |
| 32 | + "anime:list", |
| 33 | + "anime:listWithProgress", |
| 34 | + "anime:detail", |
| 35 | + "anime:episodes", |
| 36 | + "anime:search", |
| 37 | + "anime:searchWithProgress", |
| 38 | + "anime:bangumi", |
| 39 | + "anime:video", |
| 40 | + "anime:video:proxy", |
| 41 | + "anime:getHlsProxyUrl", |
| 42 | + "anime:cache:status", |
| 43 | + "anime:cache:refresh", |
| 44 | + "anime:pwEpisodes", |
45 | 45 |
|
46 | 46 | // 收藏 |
47 | | - 'favorite:list', |
48 | | - 'favorite:batchStatus', |
49 | | - 'favorite:add', |
50 | | - 'favorite:remove', |
51 | | - 'favorite:check', |
| 47 | + "favorite:list", |
| 48 | + "favorite:batchStatus", |
| 49 | + "favorite:add", |
| 50 | + "favorite:remove", |
| 51 | + "favorite:check", |
52 | 52 |
|
53 | 53 | // 播放历史 |
54 | | - 'history:list', |
55 | | - 'history:save', |
56 | | - 'history:progress', |
57 | | - 'history:clear', |
58 | | - 'history:delete', |
59 | | - 'history:byAnime', |
60 | | - 'history:batchProgress', |
| 54 | + "history:list", |
| 55 | + "history:save", |
| 56 | + "history:progress", |
| 57 | + "history:clear", |
| 58 | + "history:delete", |
| 59 | + "history:byAnime", |
61 | 60 |
|
62 | 61 | // 设置 |
63 | | - 'settings:get', |
64 | | - 'settings:set', |
65 | | - 'settings:getAll', |
| 62 | + "settings:get", |
| 63 | + "settings:set", |
| 64 | + "settings:getAll", |
66 | 65 |
|
67 | 66 | // 下载 |
68 | | - 'download:list', |
69 | | - 'download:add', |
70 | | - 'download:pause', |
71 | | - 'download:resume', |
72 | | - 'download:cancel', |
73 | | - 'download:onProgress', |
74 | | - 'download:getHistory', |
| 67 | + "download:list", |
| 68 | + "download:add", |
| 69 | + "download:pause", |
| 70 | + "download:resume", |
| 71 | + "download:cancel", |
| 72 | + "download:onProgress", |
| 73 | + "download:getHistory", |
75 | 74 |
|
76 | 75 | // 自动下载 |
77 | | - 'autoDownload:getConfig', |
78 | | - 'autoDownload:updateConfig', |
79 | | - 'autoDownload:getStatus', |
80 | | - 'autoDownload:getHistory', |
81 | | - 'autoDownload:previewFilter', |
82 | | - 'autoDownload:runCheck', |
| 76 | + "autoDownload:getConfig", |
| 77 | + "autoDownload:updateConfig", |
| 78 | + "autoDownload:getStatus", |
| 79 | + "autoDownload:getHistory", |
| 80 | + "autoDownload:previewFilter", |
| 81 | + "autoDownload:runCheck", |
83 | 82 |
|
84 | 83 | // 系统 |
85 | | - 'system:showItemInFolder', |
86 | | - 'system:openExternal', |
| 84 | + "system:showItemInFolder", |
| 85 | + "system:openExternal", |
87 | 86 |
|
88 | 87 | // 更新 |
89 | | - 'update:check', |
90 | | - 'update:download', |
91 | | - 'update:install', |
92 | | - 'update:onAvailable', |
93 | | - 'update:onProgress', |
94 | | - 'update:onDownloaded', |
95 | | -] |
| 88 | + "update:check", |
| 89 | + "update:download", |
| 90 | + "update:install", |
| 91 | + "update:onAvailable", |
| 92 | + "update:onProgress", |
| 93 | + "update:onDownloaded", |
| 94 | +]; |
96 | 95 |
|
97 | 96 | // 安全的 IPC 调用 |
98 | 97 | const invoke = async (channel, ...args) => { |
99 | 98 | if (validChannels.includes(channel)) { |
100 | | - return ipcRenderer.invoke(channel, ...args) |
| 99 | + return ipcRenderer.invoke(channel, ...args); |
101 | 100 | } |
102 | | - throw new Error(`Invalid channel: ${channel}`) |
103 | | -} |
| 101 | + throw new Error(`Invalid channel: ${channel}`); |
| 102 | +}; |
104 | 103 |
|
105 | 104 | // 事件监听 |
106 | 105 | const on = (channel, callback) => { |
107 | 106 | if (validChannels.includes(channel)) { |
108 | | - ipcRenderer.on(channel, (_, ...args) => callback(...args)) |
| 107 | + ipcRenderer.on(channel, (_, ...args) => callback(...args)); |
109 | 108 | } |
110 | | -} |
| 109 | +}; |
111 | 110 |
|
112 | | -// 完整的 API 对象 |
| 111 | +// 暴露 API |
113 | 112 | const api = { |
114 | 113 | window: { |
115 | | - minimize: () => invoke('window:minimize'), |
116 | | - maximize: () => invoke('window:maximize'), |
117 | | - close: () => invoke('window:close'), |
118 | | - toggleFullscreen: () => invoke('window:toggleFullscreen'), |
119 | | - getState: () => invoke('window:getState') |
120 | | - }, |
121 | | - |
122 | | - app: { |
123 | | - getInfo: () => { |
124 | | - return { |
125 | | - name: 'Anime1 Desktop', |
126 | | - version: '0.3.0', |
127 | | - electronVersion: process.versions.electron, |
128 | | - platform: process.platform |
129 | | - } |
130 | | - } |
| 114 | + minimize: () => invoke("window:minimize"), |
| 115 | + maximize: () => invoke("window:maximize"), |
| 116 | + close: () => invoke("window:close"), |
| 117 | + toggleFullscreen: () => invoke("window:toggleFullscreen"), |
| 118 | + getState: () => invoke("window:getState"), |
131 | 119 | }, |
132 | 120 |
|
133 | 121 | anime: { |
134 | | - getList: (params) => invoke('anime:list', params), |
135 | | - getListWithProgress: (params) => invoke('anime:listWithProgress', params), |
136 | | - getDetail: (params) => invoke('anime:detail', params), |
137 | | - getEpisodes: (params) => invoke('anime:episodes', params), |
138 | | - search: (params) => invoke('anime:search', params), |
139 | | - searchWithProgress: (params) => invoke('anime:searchWithProgress', params), |
140 | | - getBangumiInfo: (params) => invoke('anime:bangumi', params), |
141 | | - extractVideo: (params) => invoke('anime:video', params), |
142 | | - getVideoProxyUrl: (params) => invoke('anime:video:proxy', params), |
143 | | - getCacheStatus: () => invoke('anime:cache:status'), |
144 | | - refreshCache: () => invoke('anime:cache:refresh'), |
145 | | - parsePwEpisodes: (params) => invoke('anime:pwEpisodes', params) |
| 122 | + getList: (params) => invoke("anime:list", params), |
| 123 | + getListWithProgress: (params) => invoke("anime:listWithProgress", params), |
| 124 | + getDetail: (params) => invoke("anime:detail", params), |
| 125 | + getEpisodes: (params) => invoke("anime:episodes", params), |
| 126 | + search: (params) => invoke("anime:search", params), |
| 127 | + searchWithProgress: (params) => invoke("anime:searchWithProgress", params), |
| 128 | + getBangumiInfo: (params) => invoke("anime:bangumi", params), |
| 129 | + extractVideo: (params) => invoke("anime:video", params), |
| 130 | + getVideoProxyUrl: (params) => invoke("anime:video:proxy", params), |
| 131 | + getHlsProxyUrl: (params) => invoke("anime:getHlsProxyUrl", params), |
| 132 | + getCacheStatus: () => invoke("anime:cache:status"), |
| 133 | + refreshCache: () => invoke("anime:cache:refresh"), |
| 134 | + parsePwEpisodes: (params) => invoke("anime:pwEpisodes", params), |
146 | 135 | }, |
147 | 136 |
|
148 | 137 | favorite: { |
149 | | - getList: () => invoke('favorite:list'), |
150 | | - batchStatus: (params) => invoke('favorite:batchStatus', params), |
151 | | - add: (params) => invoke('favorite:add', params), |
152 | | - remove: (params) => invoke('favorite:remove', params), |
153 | | - check: (params) => invoke('favorite:check', params) |
| 138 | + getList: () => invoke("favorite:list"), |
| 139 | + batchStatus: (params) => invoke("favorite:batchStatus", params), |
| 140 | + add: (params) => invoke("favorite:add", params), |
| 141 | + remove: (params) => invoke("favorite:remove", params), |
| 142 | + check: (params) => invoke("favorite:check", params), |
154 | 143 | }, |
155 | 144 |
|
156 | 145 | history: { |
157 | | - getList: (params) => invoke('history:list', params), |
158 | | - save: (params) => invoke('history:save', params), |
159 | | - getProgress: (params) => invoke('history:progress', params), |
160 | | - clear: () => invoke('history:clear'), |
161 | | - delete: (params) => invoke('history:delete', params), |
162 | | - getByAnime: (params) => invoke('history:byAnime', params), |
163 | | - batchProgress: (params) => invoke('history:batchProgress', params) |
| 146 | + getList: (params) => invoke("history:list", params), |
| 147 | + save: (params) => invoke("history:save", params), |
| 148 | + getProgress: (params) => invoke("history:progress", params), |
| 149 | + clear: () => invoke("history:clear"), |
| 150 | + delete: (params) => invoke("history:delete", params), |
| 151 | + getByAnime: (params) => invoke("history:byAnime", params), |
| 152 | + batchProgress: (params) => invoke("history:batchProgress", params), |
164 | 153 | }, |
165 | 154 |
|
166 | 155 | settings: { |
167 | | - get: (params) => invoke('settings:get', params), |
168 | | - set: (params) => invoke('settings:set', params), |
169 | | - getAll: () => invoke('settings:getAll') |
| 156 | + get: (params) => invoke("settings:get", params), |
| 157 | + set: (params) => invoke("settings:set", params), |
| 158 | + getAll: () => invoke("settings:getAll"), |
170 | 159 | }, |
171 | 160 |
|
172 | 161 | download: { |
173 | | - getList: () => invoke('download:list'), |
174 | | - add: (params) => invoke('download:add', params), |
175 | | - pause: (params) => invoke('download:pause', params), |
176 | | - resume: (params) => invoke('download:resume', params), |
177 | | - cancel: (params) => invoke('download:cancel', params), |
178 | | - onProgress: (callback) => on('download:progress', callback) |
| 162 | + getList: () => invoke("download:list"), |
| 163 | + add: (params) => invoke("download:add", params), |
| 164 | + pause: (params) => invoke("download:pause", params), |
| 165 | + resume: (params) => invoke("download:resume", params), |
| 166 | + cancel: (params) => invoke("download:cancel", params), |
| 167 | + onProgress: (callback) => on("download:progress", callback), |
179 | 168 | }, |
180 | 169 |
|
181 | 170 | autoDownload: { |
182 | | - getConfig: () => invoke('autoDownload:getConfig'), |
183 | | - updateConfig: (params) => invoke('autoDownload:updateConfig', params), |
184 | | - getStatus: () => invoke('autoDownload:getStatus'), |
185 | | - getHistory: (params) => invoke('autoDownload:getHistory', params), |
186 | | - previewFilter: (params) => invoke('autoDownload:previewFilter', params), |
187 | | - runCheck: () => invoke('autoDownload:runCheck') |
| 171 | + getConfig: () => invoke("autoDownload:getConfig"), |
| 172 | + updateConfig: (params) => invoke("autoDownload:updateConfig", params), |
| 173 | + getStatus: () => invoke("autoDownload:getStatus"), |
| 174 | + getHistory: (params) => invoke("autoDownload:getHistory", params), |
| 175 | + previewFilter: (params) => invoke("autoDownload:previewFilter", params), |
| 176 | + runCheck: () => invoke("autoDownload:runCheck"), |
188 | 177 | }, |
189 | 178 |
|
190 | 179 | system: { |
191 | | - showItemInFolder: (params) => invoke('system:showItemInFolder', params), |
192 | | - openExternal: (params) => invoke('system:openExternal', params) |
| 180 | + showItemInFolder: (params) => invoke("system:showItemInFolder", params), |
| 181 | + openExternal: (params) => invoke("system:openExternal", params), |
193 | 182 | }, |
194 | 183 |
|
195 | 184 | update: { |
196 | | - check: () => invoke('update:check'), |
197 | | - download: () => invoke('update:download'), |
198 | | - install: () => invoke('update:install'), |
199 | | - |
200 | | - // 事件监听 |
201 | | - onAvailable: (callback) => on('update:onAvailable', callback), |
202 | | - onProgress: (callback) => on('update:onProgress', callback), |
203 | | - onDownloaded: (callback) => on('update:onDownloaded', callback), |
204 | | - |
205 | | - // 测试 API |
206 | | - getTestUpdate: () => ({ |
207 | | - hasUpdate: true, |
208 | | - currentVersion: '0.3.0', |
209 | | - latestVersion: '0.3.1', |
210 | | - isPrerelease: false, |
211 | | - releaseNotes: '测试更新 - 模拟的版本', |
212 | | - downloadUrl: 'http://test-mock-update.dmg', |
213 | | - publishedAt: new Date().toISOString() |
214 | | - }), |
215 | | - |
216 | | - setTestVersion: (version) => { |
217 | | - console.log('[测试] 版本设置为:', version) |
218 | | - return { success: true } |
219 | | - }, |
220 | | - |
221 | | - clearTestMode: () => { |
222 | | - console.log('[测试] 清除测试模式') |
223 | | - return { success: true } |
224 | | - }, |
225 | | - |
226 | | - triggerUpdateAvailable: () => { |
227 | | - console.log('[测试] 触发 update-available 事件') |
228 | | - return { success: true } |
229 | | - }, |
230 | | - |
231 | | - getStatus: () => invoke('update:getStatus') |
| 185 | + check: () => invoke("update:check"), |
| 186 | + download: () => invoke("update:download"), |
| 187 | + install: () => invoke("update:install"), |
| 188 | + onAvailable: (callback) => on("update:onAvailable", callback), |
| 189 | + onProgress: (callback) => on("update:onProgress", callback), |
| 190 | + onDownloaded: (callback) => on("update:onDownloaded", callback), |
232 | 191 | }, |
233 | | -} |
| 192 | +}; |
234 | 193 |
|
235 | 194 | // 暴露到 window.api |
236 | | -contextBridge.exposeInMainWorld('api', api) |
| 195 | +console.log("[Preload] Starting to expose API..."); |
| 196 | +try { |
| 197 | + contextBridge.exposeInMainWorld("api", api); |
| 198 | + console.log("[Preload] API exposed successfully"); |
| 199 | +} catch (error) { |
| 200 | + console.error("[Preload] Failed to expose API:", error); |
| 201 | +} |
0 commit comments