electron.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. const Sentry = require('@sentry/electron')
  8. Sentry.init({ dsn: '***REMOVED***' })
  9. let mainWindow = null
  10. let launchEvents = {
  11. songs: {
  12. details: [],
  13. download: []
  14. },
  15. playlists: {
  16. details: [],
  17. download: []
  18. },
  19. mods: {
  20. details: [],
  21. install: [],
  22. uninstall: []
  23. }
  24. }
  25. ipcMain.on('launch-events', (_, event, message) => {
  26. switch(event) {
  27. case 'check-launch-events':
  28. mainWindow.webContents.send('launch-events', 'launch-events', launchEvents)
  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. if(argv.length < 2 || !argv[1].startsWith('beatdrop')) return
  139. let args = argv[1].split(/beatdrop:\/\/|beatdrop:%5C%5C|beatdrop:\/|beatdrop:%5C|beatdrop:/i)[1].split(/\/|%5C/)
  140. switch(args[0].toLowerCase()) {
  141. case 'songs':
  142. if(args.length < 3) return
  143. let songs = args[2].split(',')
  144. switch(args[1].toLowerCase()) {
  145. case 'download':
  146. for(let i = 0; i < songs.length; i++) {
  147. launchEvents.songs.download.push(songs[i])
  148. }
  149. break
  150. case 'details':
  151. launchEvents.songs.details.push(args[2])
  152. break
  153. default:
  154. break
  155. }
  156. break
  157. case 'playlists':
  158. // Planned for future...
  159. case 'mods':
  160. if(args.length < 3) return
  161. let mods = args[2].split(',')
  162. switch(args[1].toLowerCase()) {
  163. case 'details':
  164. launchEvents.mods.details.push(decodeURIComponent(args[2]))
  165. return
  166. case 'install':
  167. for(let i = 0; i < songs.length; i++) {
  168. launchEvents.mods.install.push(decodeURIComponent(mods[i]))
  169. }
  170. return
  171. default:
  172. return
  173. }
  174. return
  175. default:
  176. break
  177. }
  178. if(sendImmediately) {
  179. mainWindow.webContents.send('launch-events', 'launch-events', launchEvents)
  180. launchEvents = {
  181. songs: {
  182. details: [],
  183. download: [],
  184. delete: []
  185. },
  186. playlists: {
  187. details: [],
  188. download: [],
  189. delete: []
  190. },
  191. mods: {
  192. details: [],
  193. install: [],
  194. uninstall: []
  195. }
  196. }
  197. }
  198. }
  199. function createWindow() {
  200. mainWindow = new BrowserWindow({
  201. width: 1015,
  202. height: 615,
  203. minWidth: 1015,
  204. minHeight: 615,
  205. resizable: true,
  206. frame: false,
  207. webPreferences: {
  208. webSecurity: false
  209. },
  210. title: 'BeatDrop',
  211. icon: appIcon,
  212. show: false
  213. })
  214. mainWindow.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, '../build/index.html')}`)
  215. mainWindow.on('closed', () => mainWindow = null)
  216. return mainWindow
  217. }
  218. app.on('window-all-closed', () => {
  219. if (process.platform !== 'darwin') {
  220. app.quit()
  221. }
  222. })
  223. app.on('activate', () => {
  224. if (mainWindow === null) {
  225. createWindow()
  226. }
  227. })