diff --git a/package.json b/package.json index b938f52..cc8b9c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "VencordDesktop", - "version": "0.1.4", + "version": "0.1.3", "private": true, "description": "", "keywords": [], diff --git a/src/main/index.ts b/src/main/index.ts index 68c8972..c10ccb4 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -42,7 +42,6 @@ if (!app.requestSingleInstanceLock()) { app.whenReady().then(async () => { checkUpdates(); - if (process.platform === "win32") app.setAppUserModelId("dev.vencord.desktop"); else if (process.platform === "darwin") app.dock.setIcon(ICON_PATH); diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 81db39c..83c4d58 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -52,8 +52,12 @@ ipcMain.handle(IpcEvents.SHOW_ITEM_IN_FOLDER, (_, path) => { shell.showItemInFolder(path); }); -ipcMain.handle(IpcEvents.FOCUS, () => { - mainWin?.focus(); +ipcMain.handle(IpcEvents.FOCUS, e => { + e.sender.focus(); +}); + +ipcMain.handle(IpcEvents.CLOSE, e => { + e.sender.close(); }); ipcMain.handle(IpcEvents.SELECT_VENCORD_DIR, async () => { diff --git a/src/main/splash.ts b/src/main/splash.ts index 6c21c6c..b158a58 100644 --- a/src/main/splash.ts +++ b/src/main/splash.ts @@ -6,18 +6,11 @@ import { BrowserWindow } from "electron"; import { join } from "path"; +import { SplashProps } from "shared/browserWinProperties"; import { STATIC_DIR } from "shared/paths"; export function createSplashWindow() { - const splash = new BrowserWindow({ - transparent: true, - frame: false, - height: 350, - width: 300, - center: true, - resizable: false, - maximizable: false - }); + const splash = new BrowserWindow(SplashProps); splash.loadFile(join(STATIC_DIR, "splash.html")); diff --git a/src/preload/VencordDesktopNative.ts b/src/preload/VencordDesktopNative.ts index 2daaa23..a4a23f4 100644 --- a/src/preload/VencordDesktopNative.ts +++ b/src/preload/VencordDesktopNative.ts @@ -4,19 +4,11 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { ipcRenderer } from "electron"; import type { Settings } from "shared/settings"; import type { LiteralUnion } from "type-fest"; import { IpcEvents } from "../shared/IpcEvents"; - -function invoke<T = any>(event: IpcEvents, ...args: any[]) { - return ipcRenderer.invoke(event, ...args) as Promise<T>; -} - -function sendSync<T = any>(event: IpcEvents, ...args: any[]) { - return ipcRenderer.sendSync(event, ...args) as T; -} +import { invoke, sendSync } from "./typedIpcs"; export const VencordDesktopNative = { app: { diff --git a/src/preload/typedIpcs.ts b/src/preload/typedIpcs.ts new file mode 100644 index 0000000..6522de6 --- /dev/null +++ b/src/preload/typedIpcs.ts @@ -0,0 +1,16 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { ipcRenderer } from "electron"; +import { IpcEvents } from "shared/IpcEvents"; + +export function invoke<T = any>(event: IpcEvents, ...args: any[]) { + return ipcRenderer.invoke(event, ...args) as Promise<T>; +} + +export function sendSync<T = any>(event: IpcEvents, ...args: any[]) { + return ipcRenderer.sendSync(event, ...args) as T; +} diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index 58bb316..efe095d 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -21,5 +21,8 @@ export const enum IpcEvents { SELECT_VENCORD_DIR = "VCD_SELECT_VENCORD_DIR", - UPDATER_GET_LATEST_VERSION = "VCD_UPDATER_GET_LATEST_VERSION" + UPDATER_GET_DATA = "VCD_UPDATER_GET_DATA", + UPDATER_DOWNLOAD = "VCD_UPDATER_DOWNLOAD", + + CLOSE = "VCD_CLOSE" } diff --git a/src/shared/browserWinProperties.ts b/src/shared/browserWinProperties.ts new file mode 100644 index 0000000..a263db0 --- /dev/null +++ b/src/shared/browserWinProperties.ts @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import type { BrowserWindowConstructorOptions } from "electron"; + +export const SplashProps: BrowserWindowConstructorOptions = { + transparent: true, + frame: false, + height: 350, + width: 300, + center: true, + resizable: false, + maximizable: false, + alwaysOnTop: true +}; diff --git a/src/updater/main.ts b/src/updater/main.ts index 1a6da0e..1bed9dc 100644 --- a/src/updater/main.ts +++ b/src/updater/main.ts @@ -4,15 +4,39 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { app, BrowserWindow, ipcMain } from "electron"; +import { app, BrowserWindow, ipcMain, shell } from "electron"; import { githubGet, ReleaseData } from "main/utils/vencordLoader"; import { join } from "path"; +import { SplashProps } from "shared/browserWinProperties"; import { IpcEvents } from "shared/IpcEvents"; import { STATIC_DIR } from "shared/paths"; -let latestVersion: string; +export interface UpdateData { + currentVersion: string; + latestVersion: string; + release: ReleaseData; +} -ipcMain.handle(IpcEvents.UPDATER_GET_LATEST_VERSION, () => latestVersion); +let updateData: UpdateData; + +ipcMain.handle(IpcEvents.UPDATER_GET_DATA, () => updateData); +ipcMain.handle(IpcEvents.UPDATER_DOWNLOAD, () => { + const { assets } = updateData.release; + const url = (() => { + switch (process.platform) { + case "win32": + return assets.find(a => a.name.endsWith(".exe"))!.browser_download_url; + case "darwin": + return assets.find(a => a.name.endsWith(".dmg"))!.browser_download_url; + case "linux": + return updateData.release.html_url; + default: + throw new Error(`Unsupported platform: ${process.platform}`); + } + })(); + + shell.openExternal(url); +}); function isOutdated(oldVersion: string, newVersion: string) { const oldParts = oldVersion.split("."); @@ -36,15 +60,21 @@ function isOutdated(oldVersion: string, newVersion: string) { } export async function checkUpdates() { - if (IS_DEV) return; - + // if (IS_DEV) return; try { const raw = await githubGet("/repos/Vencord/Desktop/releases/latest"); - const { tag_name } = JSON.parse(raw.toString("utf-8")) as ReleaseData; + const data = JSON.parse(raw.toString("utf-8")) as ReleaseData; const oldVersion = app.getVersion(); - const newVersion = (latestVersion = tag_name.replace(/^v/, "")); - if (isOutdated(oldVersion, newVersion)) openNewUpdateWindow(); + const newVersion = data.tag_name.replace(/^v/, ""); + if (isOutdated(oldVersion, newVersion)) { + updateData = { + currentVersion: oldVersion, + latestVersion: newVersion, + release: data + }; + openNewUpdateWindow(); + } } catch (e) { console.error("AppUpdater: Failed to check for updates\n", e); } @@ -52,6 +82,7 @@ export async function checkUpdates() { function openNewUpdateWindow() { const win = new BrowserWindow({ + ...SplashProps, webPreferences: { preload: join(__dirname, "updaterPreload.js") } diff --git a/src/updater/preload.ts b/src/updater/preload.ts index 88722d8..0b7b978 100644 --- a/src/updater/preload.ts +++ b/src/updater/preload.ts @@ -4,9 +4,17 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { contextBridge, ipcRenderer } from "electron"; +import { contextBridge } from "electron"; +import { invoke } from "preload/typedIpcs"; import { IpcEvents } from "shared/IpcEvents"; +import type { UpdateData } from "./main"; + contextBridge.exposeInMainWorld("Updater", { - getLatestVersion: () => ipcRenderer.invoke(IpcEvents.UPDATER_GET_LATEST_VERSION) + getData: () => invoke<UpdateData>(IpcEvents.UPDATER_GET_DATA), + download: () => { + invoke<void>(IpcEvents.UPDATER_DOWNLOAD); + invoke<void>(IpcEvents.CLOSE); + }, + close: () => invoke<void>(IpcEvents.CLOSE) }); diff --git a/static/updater.html b/static/updater.html index 2b52a69..d574e8a 100644 --- a/static/updater.html +++ b/static/updater.html @@ -1,7 +1,80 @@ -<div>hi</div> -<p></p> +<head> + <style> + body { + font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, + "Open Sans", "Helvetica Neue", sans-serif; + margin: 0; + padding: 0; + color: rgb(219, 222, 225); + } + + .wrapper { + display: flex; + flex-direction: column; + justify-content: space-between; + box-sizing: border-box; + height: 100%; + background-color: hsl(223 6.7% 20.6%); + border-radius: 8px; + border: 1px solid hsl(220 6.5% 18%); + padding: 1em; + } + + h1 { + text-align: center; + } + + .buttons { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.5em; + } + + button { + cursor: pointer; + padding: 0.5em; + color: white; + border: none; + border-radius: 3px; + font-weight: bold; + } + + button:hover, + button:active { + filter: brightness(0.9); + } + + .green { + background-color: #248046; + } + + .red { + background-color: #ed4245; + } + </style> +</head> + +<body> + <div class="wrapper"> + <section> + <h1>Update Available</h1> + <p>There's a new update for Vencord Desktop! Update now to get new fixes and features</p> + <p> + Current: <span id="current"></span> + <br /> + Latest: <span id="latest"></span> + </p> + </section> + + <section class="buttons"> + <button class="green" onclick="Updater.download()">Download Update</button> + <button class="red" onclick="Updater.close()">Close</button> + </section> + </div> +</body> <script type="module"> - const version = await Updater.getLatestVersion(); - document.querySelector("p").textContent = version; + const data = await Updater.getData(); + document.getElementById("current").textContent = data.currentVersion; + document.getElementById("latest").textContent = data.latestVersion; </script>