summaryrefslogtreecommitdiff
path: root/desktop/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/main.js')
-rw-r--r--desktop/main.js348
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