diff --git a/src/main/constants.ts b/src/main/constants.ts index 1bce3037..45a4749d 100644 --- a/src/main/constants.ts +++ b/src/main/constants.ts @@ -18,6 +18,7 @@ export const PORTABLE = const LEGACY_DATA_DIR = join(app.getPath("appData"), "VencordDesktop", "VencordDesktop"); export const DATA_DIR = process.env.VENCORD_USER_DATA_DIR || (PORTABLE ? join(vesktopDir, "Data") : join(app.getPath("userData"))); +export const TRAY_ICON_PATH = join(DATA_DIR, "settings", "tray_icon"); mkdirSync(DATA_DIR, { recursive: true }); diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 3404d34a..1d2b1cee 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -8,16 +8,17 @@ if (process.platform === "linux") import("./venmic"); import { execFile } from "child_process"; import { app, BrowserWindow, clipboard, dialog, nativeImage, RelaunchOptions, session, shell } from "electron"; -import { mkdirSync, readFileSync, watch } from "fs"; +import { copyFileSync, mkdirSync, readFileSync, watch } from "fs"; import { open, readFile } from "fs/promises"; import { release } from "os"; import { join } from "path"; +import { ICON_PATH } from "shared/paths"; import { debounce } from "shared/utils/debounce"; import { IpcEvents } from "../shared/IpcEvents"; import { setBadgeCount } from "./appBadge"; import { autoStart } from "./autoStart"; -import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants"; +import { TRAY_ICON_PATH, VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants"; import { mainWin } from "./mainWindow"; import { Settings } from "./settings"; import { handle, handleSync } from "./utils/ipcWrappers"; @@ -41,6 +42,13 @@ handleSync( () => process.platform === "win32" && Number(release().split(".").pop()) >= 22621 ); +handleSync(IpcEvents.GET_TRAY_ICON, () => { + if (!Settings.store.trayIconPath) return nativeImage.createFromPath(ICON_PATH).toDataURL(); + const img = nativeImage.createFromPath(TRAY_ICON_PATH).resize({ width: 64, height: 64 }); + if (img.isEmpty()) return nativeImage.createFromPath(ICON_PATH).toDataURL(); + return img.toDataURL(); +}); + handleSync(IpcEvents.AUTOSTART_ENABLED, () => autoStart.isEnabled()); handle(IpcEvents.ENABLE_AUTOSTART, autoStart.enable); handle(IpcEvents.DISABLE_AUTOSTART, autoStart.disable); @@ -117,6 +125,20 @@ handle(IpcEvents.SELECT_VENCORD_DIR, async () => { return dir; }); +handle(IpcEvents.SELECT_TRAY_ICON, async () => { + const res = await dialog.showOpenDialog(mainWin!, { + properties: ["openFile"], + filters: [{ name: "Image", extensions: ["png", "jpg"] }] + }); + if (!res.filePaths.length) return "cancelled"; + + const dir = res.filePaths[0]; + const image = nativeImage.createFromPath(dir); + if (image.isEmpty()) return "invalid"; + copyFileSync(dir, TRAY_ICON_PATH); + return dir; +}); + handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count)); handle(IpcEvents.CLIPBOARD_COPY_IMAGE, async (_, buf: ArrayBuffer, src: string) => { diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 5bbbb619..222f39f8 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -11,6 +11,7 @@ import { dialog, Menu, MenuItemConstructorOptions, + nativeImage, nativeTheme, screen, session, @@ -34,6 +35,7 @@ import { MessageBoxChoice, MIN_HEIGHT, MIN_WIDTH, + TRAY_ICON_PATH, VENCORD_FILES_DIR } from "./constants"; import { Settings, State, VencordSettings } from "./settings"; @@ -122,8 +124,16 @@ function initTray(win: BrowserWindow) { } } ]); + var trayImage = nativeImage.createFromPath(ICON_PATH); + if (Settings.store.trayIconPath) trayImage = nativeImage.createFromPath(TRAY_ICON_PATH); + if (trayImage.isEmpty()) trayImage = nativeImage.createFromPath(ICON_PATH); + + if (process.platform === "darwin") { + tray = new Tray(trayImage.resize({ width: 16, height: 16 })); + } else { + tray = new Tray(trayImage.resize({ width: 32, height: 32 })); + } - tray = new Tray(ICON_PATH); tray.setToolTip("Vesktop"); tray.setContextMenu(trayMenu); tray.on("click", onTrayClick); @@ -333,6 +343,10 @@ function initSettingsListeners(win: BrowserWindow) { if (enable) initTray(win); else tray?.destroy(); }); + addSettingsListener("trayIconPath", _ => { + tray?.destroy(); + initTray(win); + }); addSettingsListener("disableMinSize", disable => { if (disable) { // 0 no work @@ -447,7 +461,7 @@ function createMainWindow() { if (Settings.store.staticTitle) win.on("page-title-updated", e => e.preventDefault()); initWindowBoundsListeners(win); - if (!isDeckGameMode && (Settings.store.tray ?? true) && process.platform !== "darwin") initTray(win); + if (!isDeckGameMode && (Settings.store.tray ?? true)) initTray(win); initMenuBar(win); makeLinksOpenExternally(win); initSettingsListeners(win); diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index c8fc13f4..903577d8 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -34,7 +34,8 @@ export const VesktopNative = { }, fileManager: { showItemInFolder: (path: string) => invoke(IpcEvents.SHOW_ITEM_IN_FOLDER, path), - selectVencordDir: () => invoke>(IpcEvents.SELECT_VENCORD_DIR) + selectVencordDir: () => invoke>(IpcEvents.SELECT_VENCORD_DIR), + selectTrayIcon: () => invoke>(IpcEvents.SELECT_TRAY_ICON) }, settings: { get: () => sendSync(IpcEvents.GET_SETTINGS), @@ -57,6 +58,9 @@ export const VesktopNative = { minimize: () => invoke(IpcEvents.MINIMIZE), maximize: () => invoke(IpcEvents.MAXIMIZE) }, + tray: { + getTrayIcon: () => sendSync(IpcEvents.GET_TRAY_ICON) + }, capturer: { getLargeThumbnail: (id: string) => invoke(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id) }, diff --git a/src/renderer/components/settings/Settings.tsx b/src/renderer/components/settings/Settings.tsx index d6de13c4..5f7479ce 100644 --- a/src/renderer/components/settings/Settings.tsx +++ b/src/renderer/components/settings/Settings.tsx @@ -14,6 +14,7 @@ import { isMac, isWindows } from "renderer/utils"; import { AutoStartToggle } from "./AutoStartToggle"; import { DiscordBranchPicker } from "./DiscordBranchPicker"; import { NotificationBadgeToggle } from "./NotificationBadgeToggle"; +import { TrayIconImagePicker } from "./TrayIconImagePicker"; import { VencordLocationPicker } from "./VencordLocationPicker"; import { WindowsTransparencyControls } from "./WindowsTransparencyControls"; @@ -68,13 +69,6 @@ const SettingsOptions: Record> WindowsTransparencyControls ], Behaviour: [ - { - key: "tray", - title: "Tray Icon", - description: "Add a tray icon for Vesktop", - defaultValue: true, - invisible: () => isMac - }, { key: "minimizeToTray", title: "Minimize to tray", @@ -126,6 +120,7 @@ const SettingsOptions: Record> defaultValue: false } ], + "Tray Icon Image": [TrayIconImagePicker], "Vencord Location": [VencordLocationPicker] }; diff --git a/src/renderer/components/settings/TrayIconImagePicker.tsx b/src/renderer/components/settings/TrayIconImagePicker.tsx new file mode 100644 index 00000000..ad458248 --- /dev/null +++ b/src/renderer/components/settings/TrayIconImagePicker.tsx @@ -0,0 +1,74 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vesktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { findByPropsLazy } from "@vencord/types/webpack"; +import { Forms, Switch, Toasts } from "@vencord/types/webpack/common"; +import { Settings } from "renderer/settings"; + +import { SettingsComponent } from "./Settings"; + +const { PencilIcon } = findByPropsLazy("PencilIcon"); + +export const TrayIconImagePicker: SettingsComponent = ({ settings }) => { + return ( + <> +
+
+ (Settings.store.tray = v)} + note={"Add a tray icon for Vesktop"} + > + Tray Icon + +
+ +
+ hello + { + const choice = await VesktopNative.fileManager.selectTrayIcon(); + switch (choice) { + case "cancelled": + return; + case "invalid": + Toasts.show({ + message: "Please select a valid .png or .jpg image!", + id: Toasts.genId(), + type: Toasts.Type.FAILURE + }); + return; + } + settings.trayIconPath = choice; + }} + /> +
+
+ + ); +}; diff --git a/src/renderer/components/settings/settings.css b/src/renderer/components/settings/settings.css index d55ff507..8bf7a9aa 100644 --- a/src/renderer/components/settings/settings.css +++ b/src/renderer/components/settings/settings.css @@ -11,4 +11,57 @@ .vcd-settings-title { margin-bottom: 0.5rem; -} \ No newline at end of file +} + +#vcd-tray-setting { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: nowrap; + +} +.vcd-tray-setting-switch { + flex-grow: 1; + align-self: flex-start; + margin-right: 20rem; +} +.vcd-tray-setting-reset { + align-self: right; + position: relative; + margin-left: auto; + margin-right: 1em; + bottom: 24px; +} + +.vcd-tray-icon-wrap { + position: relative; + align-self: right; + bottom: 24px; +} + +.vcd-tray-icon-image { + border-radius: 50%; + position: relative; + top: 0; + right: 0; +} + +.vcd-edit-button { + visibility: visible; + display: block; + opacity: 0; + position: absolute; + top: 3px; + left: 4px; +} + +.vcd-tray-icon-wrap:hover .vcd-tray-icon-image { + transition: 0.3s ease; + background-color: rgb(0, 0, 0) no-repeat; + opacity: 0.25; +} +.vcd-tray-icon-wrap:hover .vcd-edit-button { + transition: 0.3s ease; + visibility: visible; + opacity: 1; +} diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index ea632fba..87435adc 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -25,6 +25,9 @@ export const enum IpcEvents { SELECT_VENCORD_DIR = "VCD_SELECT_VENCORD_DIR", + SELECT_TRAY_ICON = "VCD_SELECT_TRAY_ICON", + GET_TRAY_ICON = "VCD_GET_TRAY_ICON", + UPDATER_GET_DATA = "VCD_UPDATER_GET_DATA", UPDATER_DOWNLOAD = "VCD_UPDATER_DOWNLOAD", UPDATE_IGNORE = "VCD_UPDATE_IGNORE", diff --git a/src/shared/settings.d.ts b/src/shared/settings.d.ts index 3eb96a06..0c8ee026 100644 --- a/src/shared/settings.d.ts +++ b/src/shared/settings.d.ts @@ -22,6 +22,7 @@ export interface Settings { disableMinSize?: boolean; clickTrayToShowHide?: boolean; customTitleBar?: boolean; + trayIconPath?: string; checkUpdates?: boolean; diff --git a/static/pencil-edit-icon.svg b/static/pencil-edit-icon.svg new file mode 100644 index 00000000..6288a638 --- /dev/null +++ b/static/pencil-edit-icon.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file