它的原理其实就是从配置项里面读取到表单的选项,构造出表单,然后当修改的时候,通过统一的 IPC 信道,将修改的 key 和 value 发送回去。

新建定义文件

  1. const all: any
  2. const init: any
  3. const store: any
  4. export { init, store }
  5. export default all
  6. }

store 的方法全部来自于 electron-store

新建 tray.ts 文件,将配置项传递给 init,而 create 则是创建窗口的函数,第一个是参数配置项,第二个参数是是否开启 DEBUG 模式,这里我们开启它。

  1. import create, { init, store } from 'electron-auto-setting'
  2. import { app, Tray, Menu } from 'electron'
  3. import { resolve } from 'path'
  4. import { fromEvent } from 'rxjs'
  5. let win = null
  6. let tray = null
  7. let setting = [
  8. {
  9. icon: 'icon-setting',
  10. label: '普通设置',
  11. configs: {
  12. SAVA_PATH: {
  13. type: 'path',
  14. label: ' 输出路径',
  15. defaultValue: resolve(app.getPath('home'), 'xiaoshuo')
  16. },
  17. CONCURRENCE: {
  18. type: 'string',
  19. label: '下载并发量',
  20. defaultValue: 5
  21. }
  22. }
  23. },
  24. {
  25. icon: 'icon-download',
  26. label: 'API 设置',
  27. configs: {
  28. APP_ID: {
  29. type: 'string',
  30. label: '应用 ID',
  31. defaultValue: ''
  32. },
  33. API_KEY: {
  34. type: 'string',
  35. label: '应用秘钥',
  36. defaultValue: ''
  37. },
  38. SECRET_KEY: {
  39. type: 'string',
  40. label: '加密秘钥',
  41. defaultValue: ''
  42. }
  43. }
  44. }
  45. ]
  46. init(setting)
  47. win = create({}, true)
  48. }
  49. fromEvent(<any>app, 'ready').subscribe(() => {
  50. const contextMenu = Menu.buildFromTemplate([
  51. { label: '设置', click: opensetting }
  52. ])
  53. tray.setContextMenu(contextMenu)
  54. })
  55. export { store, tray, win }

app ready 的时候,我们创建一个通知栏的小图标,这个小图标是 24x24 大小的 png 图片,我是从 下载的,大家可以自行下载。

读取配置

在 index.ts 中 ,记得使用了 await ,一定要给函数加上 async 哦。此时可以把 on 函数提取到 helper 里面去,具体请看仓库源码。

  1. import { store } from './tray'
  2. const { folderName, url } = args
  3. const savePath = resolve(
  4. store.get('SAVA_PATH', app.getPath('music')),
  5. folderName
  6. )
  7. await download(url, plugin, { path: savePath })
  8. await transform(savePath)

修改 download.ts ,让默认的配置项可以读取到并发量。

修改 TTS.ts ,我们不希望每次设置完要重启,这里我们订阅一下更新。

  1. let APP_ID = store.get('APP_ID')
  2. let API_KEY = store.get('API_KEY')
  3. let SECRET_KEY = store.get('SECRET_KEY')
  4. // 每次修改更新值
  5. store.onDidChange('APP_ID', (newValue: any) => (APP_ID = newValue))
  6. store.onDidChange('API_KEY', (newValue: any) => (API_KEY = newValue))
  7. store.onDidChange('SECRET_KEY', (newValue: any) => (SECRET_KEY = newValue))
  8. let client: any = null
  9. try {
  10. client = new speech(APP_ID, API_KEY, SECRET_KEY)
  11. } catch (e) {
  12. log({ type: 'audio', step: 'new_speech_error', message: e.message })
  13. }

新建 Download.svelte , 然后像之前一样,在 App.svlete 里面引入并设置值。

  1. <input bind:value=folderName />
  2. <input bind:value=url />
  3. <button on:click="download()">下载</button>
  4. <button on:click="stop()">中断</button>
  5. <script>
  6. import {
  7. ipcRenderer
  8. } from 'electron'
  9. export default {
  10. data() {
  11. return {
  12. url: '',
  13. folderName: ''
  14. }
  15. },
  16. methods: {
  17. download() {
  18. const {
  19. url,
  20. folderName
  21. } = this.get()
  22. if (url.length && folderName.length) {
  23. console.log(url);
  24. url,
  25. folderName
  26. })
  27. }
  28. },
  29. stop() {
  30. ipcRenderer.send('stop') // 发送停止事件信号
  31. }
  32. }
  33. }
  34. </script>

中断处理函数

修改 helper.ts,此时你的 helper 应该会像下面这样,中断了的时候,我们应该把下载的给删除,这样可以保证目录的干净。

  1. import { Subject } from 'rxjs'
  2. import { ipcMain as ipc } from 'electron'
  3. import { store } from './tray'
  4. import { remove } from 'fs-extra'
  5. import log from './statusLog'
  6. function ready() {
  7. let resolveFN, rejectFN
  8. let promise = new Promise(
  9. (resolve, reject) => ([resolveFN, rejectFN] = [resolve, reject])
  10. )
  11. return [resolveFN, rejectFN, promise]
  12. }
  13. interface CombineEvent {
  14. event: any
  15. args: any
  16. }
  17. function on(channel: string): Subject<CombineEvent> {
  18. const eventListner = new Subject<CombineEvent>()
  19. ipc.on(channel, (event: any, args: any) => eventListner.next({ event, args }))
  20. return eventListner
  21. }
  22. async function handleStop(path: string, logInfo: any) {
  23. if (store.get('stop')) {
  24. path && (await remove(path)) // 删除目录
  25. log(logInfo)
  26. return true
  27. }
  28. return false
  29. }
  30. export { ready, on, handleStop }

修改 download.ts 在循环里面添加跳出代码,并发送消息显示给前端

同样修改 TTS.ts ,添加跳出代码

  1. if (
  2. await handleStop(chapterSavePath, {
  3. type: 'stop',
  4. message: '已停止该队列'
  5. })
  6. ) {
  7. break
  8. }

那么在开始与结束的时候应该添加重置信号量的代码

  1. store.set('stop', false)
  2. await download(url, plugin, { path: savePath })
  3. await transform(savePath)
  4. store.set('stop', false)
  1. on('stop').subscribe(() => {
  2. store.set('stop', true)
  3. })