diff --git a/src/main/firstLaunch.ts b/src/main/firstLaunch.ts index 0ce585d..d1bbceb 100644 --- a/src/main/firstLaunch.ts +++ b/src/main/firstLaunch.ts @@ -14,7 +14,7 @@ import { ICON_PATH, VIEW_DIR } from "shared/paths"; import { autoStart } from "./autoStart"; import { DATA_DIR } from "./constants"; import { createWindows } from "./mainWindow"; -import { Settings } from "./settings"; +import { Settings, State } from "./settings"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; interface Data { @@ -44,9 +44,9 @@ export function createFirstLaunchTour() { if (!msg.startsWith("form:")) return; const data = JSON.parse(msg.slice(5)) as Data; + State.store.firstLaunch = false; Settings.store.minimizeToTray = data.minimizeToTray; Settings.store.discordBranch = data.discordBranch; - Settings.store.firstLaunch = false; Settings.store.arRPC = data.richPresence; if (data.autoStart) autoStart.enable(); diff --git a/src/main/index.ts b/src/main/index.ts index f73a543..6c43dfe 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -14,7 +14,7 @@ import { createFirstLaunchTour } from "./firstLaunch"; import { createWindows, mainWin } from "./mainWindow"; import { registerMediaPermissionsHandler } from "./mediaPermissions"; import { registerScreenShareHandler } from "./screenShare"; -import { Settings } from "./settings"; +import { Settings, State } from "./settings"; import { isDeckGameMode } from "./utils/steamOS"; if (IS_DEV) { @@ -84,7 +84,7 @@ if (!app.requestSingleInstanceLock({ IS_DEV })) { } async function bootstrap() { - if (!Object.hasOwn(Settings.store, "firstLaunch")) { + if (!Object.hasOwn(State.store, "firstLaunch")) { createFirstLaunchTour(); } else { createWindows(); diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 9c929db..cff400b 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -34,7 +34,7 @@ import { UserAgent, VENCORD_FILES_DIR } from "./constants"; -import { Settings, VencordSettings } from "./settings"; +import { Settings, State, VencordSettings } from "./settings"; import { createSplashWindow } from "./splash"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./utils/steamOS"; @@ -268,7 +268,7 @@ function getWindowBoundsOptions(): BrowserWindowConstructorOptions { // We want the default window behaivour to apply in game mode since it expects everything to be fullscreen and maximized. if (isDeckGameMode) return {}; - const { x, y, width, height } = Settings.store.windowBounds ?? {}; + const { x, y, width, height } = State.store.windowBounds ?? {}; const options = { width: width ?? DEFAULT_WIDTH, @@ -313,8 +313,8 @@ function getDarwinOptions(): BrowserWindowConstructorOptions { function initWindowBoundsListeners(win: BrowserWindow) { const saveState = () => { - Settings.store.maximized = win.isMaximized(); - Settings.store.minimized = win.isMinimized(); + State.store.maximized = win.isMaximized(); + State.store.minimized = win.isMinimized(); }; win.on("maximize", saveState); @@ -322,7 +322,7 @@ function initWindowBoundsListeners(win: BrowserWindow) { win.on("unmaximize", saveState); const saveBounds = () => { - Settings.store.windowBounds = win.getBounds(); + State.store.windowBounds = win.getBounds(); }; win.on("resize", saveBounds); @@ -459,7 +459,7 @@ export async function createWindows() { splash.destroy(); mainWin!.show(); - if (Settings.store.maximized && !isDeckGameMode) { + if (State.store.maximized && !isDeckGameMode) { mainWin!.maximize(); } diff --git a/src/main/settings.ts b/src/main/settings.ts index 6fad97f..c4df364 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -4,14 +4,15 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ -import { mkdirSync, readFileSync, writeFileSync } from "fs"; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"; import { dirname, join } from "path"; -import type { Settings as TSettings } from "shared/settings"; +import type { Settings as TSettings, State as TState } from "shared/settings"; import { SettingsStore } from "shared/utils/SettingsStore"; import { DATA_DIR, VENCORD_SETTINGS_FILE } from "./constants"; const SETTINGS_FILE = join(DATA_DIR, "settings.json"); +const STATE_FILE = join(DATA_DIR, "state.json"); function loadSettings(file: string, name: string) { let settings = {} as T; @@ -20,7 +21,7 @@ function loadSettings(file: string, name: string) { try { settings = JSON.parse(content); } catch (err) { - console.error(`Failed to parse ${name} settings.json:`, err); + console.error(`Failed to parse ${name}.json:`, err); } } catch {} @@ -33,5 +34,25 @@ function loadSettings(file: string, name: string) { return store; } -export const Settings = loadSettings(SETTINGS_FILE, "Vesktop"); -export const VencordSettings = loadSettings(VENCORD_SETTINGS_FILE, "Vencord"); +export const Settings = loadSettings(SETTINGS_FILE, "Vesktop settings"); +export const VencordSettings = loadSettings(VENCORD_SETTINGS_FILE, "Vencord settings"); + +if (Object.hasOwn(Settings.store, "firstLaunch") && !existsSync(STATE_FILE)) { + console.warn("legacy state in settings.json detected. migrating to state.json"); + const state = {} as TState; + for (const prop of [ + "firstLaunch", + "maximized", + "minimized", + "skippedUpdate", + "steamOSLayoutVersion", + "windowBounds" + ]) { + state[prop] = Settings.plain[prop]; + delete Settings.plain[prop]; + } + Settings.markAsChanged(); + writeFileSync(STATE_FILE, JSON.stringify(state, null, 4)); +} + +export const State = loadSettings(STATE_FILE, "Vesktop state"); diff --git a/src/main/utils/steamOS.ts b/src/main/utils/steamOS.ts index 8145e5a..e61166c 100644 --- a/src/main/utils/steamOS.ts +++ b/src/main/utils/steamOS.ts @@ -9,7 +9,7 @@ import { writeFile } from "fs/promises"; import { join } from "path"; import { MessageBoxChoice } from "../constants"; -import { Settings } from "../settings"; +import { State } from "../settings"; // Bump this to re-show the prompt const layoutVersion = 2; @@ -70,8 +70,8 @@ async function showLayout(appId: string) { export async function askToApplySteamLayout(win: BrowserWindow) { const appId = getAppId(); if (!appId) return; - if (Settings.store.steamOSLayoutVersion === layoutVersion) return; - const update = Boolean(Settings.store.steamOSLayoutVersion); + if (State.store.steamOSLayoutVersion === layoutVersion) return; + const update = Boolean(State.store.steamOSLayoutVersion); // Touch screen breaks in some menus when native touch mode is enabled on latest SteamOS beta, remove most of the update specific text once that's fixed. const { response } = await dialog.showMessageBox(win, { @@ -87,8 +87,8 @@ ${update ? "Click" : "Tap"} no to keep your current layout.`, type: "question" }); - if (Settings.store.steamOSLayoutVersion !== layoutVersion) { - Settings.store.steamOSLayoutVersion = layoutVersion; + if (State.store.steamOSLayoutVersion !== layoutVersion) { + State.store.steamOSLayoutVersion = layoutVersion; } if (response === MessageBoxChoice.Cancel) return; diff --git a/src/shared/settings.d.ts b/src/shared/settings.d.ts index 6e5ccfc..8c63373 100644 --- a/src/shared/settings.d.ts +++ b/src/shared/settings.d.ts @@ -20,19 +20,22 @@ export interface Settings { arRPC?: boolean; appBadge?: boolean; discordWindowsTitleBar?: boolean; - - maximized?: boolean; - minimized?: boolean; - windowBounds?: Rectangle; disableMinSize?: boolean; checkUpdates?: boolean; - skippedUpdate?: string; - firstLaunch?: boolean; splashTheming?: boolean; splashColor?: string; splashBackground?: string; +} + +export interface State { + maximized?: boolean; + minimized?: boolean; + windowBounds?: Rectangle; + + skippedUpdate?: string; + firstLaunch?: boolean; steamOSLayoutVersion?: number; } diff --git a/src/shared/utils/SettingsStore.ts b/src/shared/utils/SettingsStore.ts index 89c57dd..22dd145 100644 --- a/src/shared/utils/SettingsStore.ts +++ b/src/shared/utils/SettingsStore.ts @@ -144,4 +144,11 @@ export class SettingsStore { listeners.delete(cb); if (!listeners.size) this.pathListeners.delete(path as string); } + + /** + * Call all global change listeners + */ + public markAsChanged() { + this.globalListeners.forEach(cb => cb(this.plain, "")); + } } diff --git a/src/updater/main.ts b/src/updater/main.ts index b84081c..059afb9 100644 --- a/src/updater/main.ts +++ b/src/updater/main.ts @@ -5,7 +5,7 @@ */ import { app, BrowserWindow, shell } from "electron"; -import { Settings } from "main/settings"; +import { Settings, State } from "main/settings"; import { handle } from "main/utils/ipcWrappers"; import { makeLinksOpenExternally } from "main/utils/makeLinksOpenExternally"; import { githubGet, ReleaseData } from "main/utils/vencordLoader"; @@ -52,7 +52,7 @@ handle(IpcEvents.UPDATER_DOWNLOAD, () => { }); handle(IpcEvents.UPDATE_IGNORE, () => { - Settings.store.skippedUpdate = updateData.latestVersion; + State.store.skippedUpdate = updateData.latestVersion; }); function isOutdated(oldVersion: string, newVersion: string) { @@ -91,7 +91,7 @@ export async function checkUpdates() { release: data }; - if (Settings.store.skippedUpdate !== newVersion && isOutdated(oldVersion, newVersion)) { + if (State.store.skippedUpdate !== newVersion && isOutdated(oldVersion, newVersion)) { openNewUpdateWindow(); } } catch (e) {