electron.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. const electron = require('electron')
  2. const { app, ipcMain, BrowserWindow } = electron
  3. const path = require('path')
  4. const isDev = require('electron-is-dev')
  5. const { autoUpdater } = require("electron-updater")
  6. const appIcon = path.join(__dirname, 'assets', 'appicons', 'ico', 'icon.ico')
  7. let mainWindow = null
  8. let launchEvents = {
  9. songs: {
  10. details: [],
  11. download: []
  12. },
  13. playlists: {
  14. details: [],
  15. download: []
  16. },
  17. mods: {
  18. details: [],
  19. install: [],
  20. uninstall: []
  21. },
  22. files: []
  23. }
  24. ipcMain.on('launch-events', (_, event, message) => {
  25. switch(event) {
  26. case 'check-launch-events':
  27. mainWindow.webContents.send('launch-events', 'launch-events', launchEvents)
  28. //mainWindow.webContents.openDevTools();
  29. launchEvents = {
  30. songs: {
  31. details: [],
  32. download: [],
  33. delete: []
  34. },
  35. playlists: {
  36. details: [],
  37. download: [],
  38. delete: []
  39. },
  40. mods: {
  41. details: [],
  42. install: [],
  43. uninstall: []
  44. }
  45. }
  46. return
  47. default:
  48. return
  49. }
  50. })
  51. const gotTheLock = app.requestSingleInstanceLock()
  52. if (process.defaultApp) {
  53. if (process.argv.length >= 2) {
  54. app.setAsDefaultProtocolClient('beatdrop', process.execPath, [path.resolve(process.argv[1])])
  55. }
  56. } else {
  57. app.setAsDefaultProtocolClient('beatdrop')
  58. }
  59. if (!gotTheLock) {
  60. app.quit()
  61. } else {
  62. app.on('second-instance', (event, argv, workingDirectory) => {
  63. if(!isDev) handleArgs(argv, true)
  64. if (mainWindow) {
  65. if (mainWindow.isMinimized()) mainWindow.restore()
  66. mainWindow.focus()
  67. }
  68. })
  69. app.on('ready', () => {
  70. autoUpdater.autoDownload = false
  71. autoUpdater.autoInstallOnAppQuit = false
  72. ipcMain.on('electron-updater', (_, event, message) => {
  73. switch(event) {
  74. case 'download-update':
  75. autoUpdater.downloadUpdate()
  76. return
  77. case 'check-for-updates':
  78. try {
  79. autoUpdater.checkForUpdates()
  80. } catch(err) {
  81. main.webContents.send('electron-updater', 'error')
  82. }
  83. return
  84. case 'set-update-channel':
  85. autoUpdater.channel = message
  86. autoUpdater.allowPrerelease = (message !== 'latest')
  87. autoUpdater.allowDowngrade = (message === 'latest')
  88. return
  89. default:
  90. return
  91. }
  92. })
  93. let loading = new BrowserWindow({ width: 400, height: 400, show: false, frame: false, resizable: false, webPreferences: { webSecurity: false } })
  94. if(!isDev) handleArgs(process.argv)
  95. loading.once('show', () => {
  96. let main = createWindow()
  97. autoUpdater.on('checking-for-update', () => {
  98. main.webContents.send('electron-updater', 'checking-for-update')
  99. })
  100. autoUpdater.on('update-available', info => {
  101. main.webContents.send('electron-updater', 'update-available', info)
  102. })
  103. autoUpdater.on('update-not-available', () => {
  104. main.webContents.send('electron-updater', 'update-not-available')
  105. })
  106. autoUpdater.on('error', () => {
  107. main.webContents.send('electron-updater', 'error')
  108. })
  109. autoUpdater.on('download-progress', (progress) => {
  110. main.webContents.send('electron-updater', 'download-progress', progress.percent)
  111. })
  112. autoUpdater.on('update-downloaded', () => {
  113. autoUpdater.quitAndInstall()
  114. })
  115. main.once('ready-to-show', () => {
  116. main.show()
  117. loading.hide()
  118. loading.close()
  119. })
  120. })
  121. loading.loadURL(`file://${path.join(__dirname, '../build/loading.html')}`)
  122. loading.once('ready-to-show', () => loading.show())
  123. if(isDev) {
  124. const { default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } = require('electron-devtools-installer')
  125. let extensions = [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS]
  126. for(let i = 0; i < extensions.length; i++) {
  127. installExtension(extensions[i]).then((name) => {
  128. console.log(`Added Extension: ${name}`)
  129. })
  130. .catch((err) => {
  131. console.log('An error occurred: ', err)
  132. })
  133. }
  134. }
  135. })
  136. }
  137. function handleArgs(argv, sendImmediately) {
  138. // check if args were passed
  139. if (!argv || argv.length < 2) return undefined
  140. // handle beatdrop://
  141. if (argv[1].startsWith('beatdrop://')) return handleBeatdrop(argv, sendImmediately)
  142. // handle files
  143. const args = argv.filter((_, i) => !(i < (isDev ? 2 : 1)))
  144. const { ext } = path.parse(args[0])
  145. launchEvents.files.push({ file: args[0], ext })
  146. }
  147. function handleBeatdrop(argv, sendImmediately){
  148. let args = argv[1].split(/beatdrop:\/\/|beatdrop:%5C%5C|beatdrop:\/|beatdrop:%5C|beatdrop:/i)[1].split(/\/|%5C/)
  149. switch(args[0].toLowerCase()) {
  150. case 'songs':
  151. if(args.length < 3) return
  152. let songs = args[2].split(',')
  153. switch(args[1].toLowerCase()) {
  154. case 'download':
  155. for(let i = 0; i < songs.length; i++) {
  156. launchEvents.songs.download.push(songs[i])
  157. }
  158. break
  159. case 'details':
  160. launchEvents.songs.details.push(args[2])
  161. break
  162. default:
  163. break
  164. }
  165. break
  166. case 'playlists':
  167. // Planned for future...
  168. case 'mods':
  169. if(args.length < 3) return
  170. let mods = args[2].split(',')
  171. switch(args[1].toLowerCase()) {
  172. case 'details':
  173. launchEvents.mods.details.push(decodeURIComponent(args[2]))
  174. return
  175. case 'install':
  176. for(let i = 0; i < songs.length; i++) {
  177. launchEvents.mods.install.push(decodeURIComponent(mods[i]))
  178. }
  179. return
  180. default:
  181. return
  182. }
  183. default:
  184. break
  185. }
  186. if(sendImmediately) {
  187. mainWindow.webContents.send('launch-events', 'launch-events', launchEvents)
  188. launchEvents = {
  189. songs: {
  190. details: [],
  191. download: [],
  192. delete: []
  193. },
  194. playlists: {
  195. details: [],
  196. download: [],
  197. delete: []
  198. },
  199. mods: {
  200. details: [],
  201. install: [],
  202. uninstall: []
  203. }
  204. }
  205. }
  206. }
  207. function createWindow() {
  208. mainWindow = new BrowserWindow({
  209. width: 1080,
  210. height: 615,
  211. minWidth: 1090,
  212. minHeight: 615,
  213. resizable: true,
  214. frame: false,
  215. webPreferences: {
  216. webSecurity: false
  217. },
  218. title: 'BeatDrop',
  219. icon: appIcon,
  220. show: false
  221. })
  222. mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`)
  223. mainWindow.on('closed', () => mainWindow = null)
  224. return mainWindow
  225. }
  226. app.on('window-all-closed', () => {
  227. if (process.platform !== 'darwin') {
  228. app.quit()
  229. }
  230. })
  231. app.on('activate', () => {
  232. if (mainWindow === null) {
  233. createWindow()
  234. }
  235. })