diff options
Diffstat (limited to 'desktop/main.js')
-rw-r--r-- | desktop/main.js | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/desktop/main.js b/desktop/main.js new file mode 100644 index 0000000..5efb923 --- /dev/null +++ b/desktop/main.js @@ -0,0 +1,348 @@ +const { app, BrowserWindow, shell, ipcMain, session, Notification, nativeImage, Menu } = require('electron'); +const path = require('node:path'); +const http = require('http'); + +function updateMenu(mainWindow) { + let template = [ + { + label: "File", + submenu: process.platform === "darwin" ? [ + { + role: "close", + label: "Close" + } + ] : [ + { + role: "quit" + } + ] + }, + { + role: "editMenu" + }, + { + label: "View", + submenu: [ + { + role: "reload" + }, + { + role: "forceReload" + }, + { + role: "toggleDevTools" + }, + { + type: "separator" + }, + { + role: "togglefullscreen" + } + ] + }, + { + label: "Controls", + submenu: [ + { + label: "Play/Pause", + accelerator: "Space", + click: () => { + mainWindow.webContents.executeJavaScript("window.playPause();"); + } + }, + { + label: "Stop", + accelerator: "CmdOrCtrl+.", + click: () => { + mainWindow.webContents.executeJavaScript("window.stop();"); + } + }, + { + label: "Next Track", + accelerator: "CmdOrCtrl+Right", + click: () => { + mainWindow.webContents.executeJavaScript("window.next();"); + } + }, + { + label: "Previous Track", + accelerator: "CmdOrCtrl+Left", + click: () => { + mainWindow.webContents.executeJavaScript("window.previous();"); + } + } + ] + }, + { + label: "Account", + submenu: [ + { + label: global.userInfo ? global.userInfo.name : "-", + enabled: false + }, + { + label: global.userInfo ? global.userInfo.profile.email.email : "-", + enabled: false + }, + { + label: "Account Settings...", + click: () => { + mainWindow.webContents.executeJavaScript('window.document.getElementById("navigation").contentDocument.getElementById("account").click();'); + } + }, + { + label: "Sign Out", + click: () => { + session.defaultSession.cookies.set({ + url: "https://mist.equestria.horse", + name: "WAVY_SESSION_TOKEN", + value: "", + httpOnly: true, + secure: true, + expirationDate: 0 + }).then(() => { + mainWindow.close(); + }); + } + } + ] + }, + { + role: "windowMenu" + }, + { + label: "Help", + role: "help", + submenu: process.platform === "darwin" ? [ + { + label: "Source Code", + onclick: () => { + shell.openExternal("https://source.equestria.dev/equestria.dev/mist"); + } + } + ] : [ + { + label: "Source Code", + onclick: () => { + shell.openExternal("https://source.equestria.dev/equestria.dev/mist"); + } + }, + { + type: "separator" + }, + { + role: "about" + } + ] + } + ]; + + if (process.platform === "darwin") template.unshift({ + label: "Mist", + submenu: [ + { + role: "about", + }, + { + type: "separator" + }, + { + label: "Settings...", + accelerator: "CmdOrCtrl+,", + click: () => { + mainWindow.webContents.executeJavaScript("window.openUI('settings');"); + } + }, + { + type: "separator" + }, + { + role: "services" + }, + { + type: "separator" + }, + { + role: "hide" + }, + { + role: "hideOthers" + }, + { + role: "unhide" + }, + { + type: "separator" + }, + { + role: "quit" + } + ], + }); + let menu = Menu.buildFromTemplate(template); + + mainWindow.setMenu(menu); + Menu.setApplicationMenu(menu); +} + +function getCopyrightYear() { + if (new Date().getFullYear() === 2023) { + return "2023"; + } else { + return "2023-" + new Date().getFullYear(); + } +} + +app.setName("Mist"); +app.setAsDefaultProtocolClient("mist"); +app.setAboutPanelOptions({ + applicationName: "Mist", + applicationVersion: "", + version: "", + copyright: "Copyright © " + getCopyrightYear() + " Equestria.dev Developers", + website: "https://mist.equestria.horse/app/" +}); + +const gotTheLock = app.requestSingleInstanceLock(); + +if (!gotTheLock) { + app.quit(); +} + +let loggedIn = false; +let token = null; + +const createWindow = () => { + global.mainWindow = new BrowserWindow({ + width: 1280, + height: 720, + minWidth: 864, + minHeight: 550, + frame: process.platform === "darwin" || process.platform === "win32", + titleBarStyle: "hidden", + titleBarOverlay: true, + autoHideMenuBar: true, + trafficLightPosition: { + x: 20, + y: 20 + }, + //vibrancy: "hud", + vibrancy: "under-window", + transparent: process.platform === "darwin" || process.platform === "win32", + backgroundMaterial: "mica", + title: "Mist", + type: "textured", + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + scrollBounce: true, + enableWebSQL: false + } + }); + + app.on('second-instance', () => { + if (mainWindow) { + if (mainWindow.isMinimized()) mainWindow.restore() + mainWindow.focus() + } + }); + + updateMenu(mainWindow); + + const server = http.createServer((req, res) => { + let url = new URL("http://localhost" + req.url); + if (url.searchParams.get("token")) { + token = url.searchParams.get("token"); + loggedIn = true; + + res.statusCode = 301; + res.setHeader('Location', '/'); + res.end(); + + session.defaultSession.cookies.set({ + url: "https://mist.equestria.horse", + name: "WAVY_SESSION_TOKEN", + value: token, + httpOnly: true, + secure: true, + expirationDate: Math.round((new Date().getTime() + 86400000 * 365) / 1000) + }).then(() => { + mainWindow.loadURL("https://mist.equestria.horse/app/"); + mainWindow.focus(); + }); + } else { + if (loggedIn) { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('Log in complete. Please go back to the Mist desktop application to continue.'); + server.close(); + } else { + res.statusCode = 500; + res.setHeader('Content-Type', 'text/plain'); + res.end('500. A token was expected but no such token was sent.'); + } + } + }); + + mainWindow.webContents.on('did-navigate', (event, url) => { + if (url.includes("/oauth/")) { + server.listen(12981, "127.0.0.1", () => { + console.log(`Server running at http://127.0.0.1:12981`); + }); + } + }); + + mainWindow.webContents.setUserAgent(mainWindow.webContents.getUserAgent() + " MistNative/" + process.platform); + mainWindow.loadURL("https://mist.equestria.horse/app/"); + mainWindow.webContents.setWindowOpenHandler((details) => { + shell.openExternal(details.url); + return { action: "deny" }; + }); +} + +ipcMain.handle('auth', () => { + shell.openExternal("https://mist.equestria.horse/oauth/native/"); +}); + +ipcMain.handle('about', () => { + app.showAboutPanel(); +}); + +ipcMain.handle('userInfo', (e, userInfo) => { + global.userInfo = JSON.parse(userInfo); + updateMenu(mainWindow); +}); + +ipcMain.handle('notification', (e, song, img) => { + let notification = new Notification({ + title: song.title, + body: song.artist + " — " + song.album, + silent: true, + icon: nativeImage.createFromDataURL(img) + }); + + notification.show(); +}); + +ipcMain.handle('version', (e, v, b) => { + app.setAboutPanelOptions({ + applicationName: "Mist", + applicationVersion: v ?? "", + version: b ?? "", + copyright: "Copyright © " + getCopyrightYear() + " Equestria.dev Developers, Released under the MIT license", + website: "https://mist.equestria.horse/app/" + }); +}); + +app.whenReady().then(() => { + createWindow(); + + app.userAgentFallback = app.userAgentFallback + " MistNative/" + process.platform; + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit(); +});
\ No newline at end of file |