From ab49a6155b677375b7d2bd4a97291177232181da Mon Sep 17 00:00:00 2001 From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:15:59 -0700 Subject: [PATCH] Add launch-on-startup toggle to settings - Use Electron's app.setLoginItemSettings() / app.getLoginItemSettings() to register/unregister the app as a login item - Add toggle switch in the Library settings popover - Sync toggle state when opening settings - Works on macOS (login items) and Windows (registry) - Default is off (opt-in) This contribution was developed with AI assistance (Claude Code). --- src/main/ipc/config.js | 10 +++++++-- src/renderer/history.html | 44 +++++++++++++++++++++++++++++++++++++++ src/renderer/history.js | 11 ++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/main/ipc/config.js b/src/main/ipc/config.js index 90e81b7..ef176bd 100644 --- a/src/main/ipc/config.js +++ b/src/main/ipc/config.js @@ -1,6 +1,6 @@ 'use strict'; -const { ipcMain, shell, BrowserWindow } = require('electron'); +const { app, ipcMain, shell, BrowserWindow } = require('electron'); const { randomUUID } = require('crypto'); const { getAppConfig, saveUserConfig, resetAppConfig } = require('../lib/config'); const { CONFIG_FILE } = require('../lib/paths'); @@ -15,11 +15,17 @@ const fs = require('fs'); function registerConfigHandlers(getVideodbService) { ipcMain.handle('get-settings', () => { const config = getAppConfig(); - return { ...config, isConnected: !!config.accessToken }; + const loginSettings = app.getLoginItemSettings(); + return { ...config, isConnected: !!config.accessToken, openAtLogin: loginSettings.openAtLogin }; }); ipcMain.handle('save-settings', (event, data) => { try { + // Apply login item setting via Electron API (not persisted in config file) + if (data.openAtLogin !== undefined) { + app.setLoginItemSettings({ openAtLogin: data.openAtLogin }); + delete data.openAtLogin; // Don't persist in config — Electron manages this + } saveUserConfig(data); // Broadcast theme change to all other windows if (data.theme) { diff --git a/src/renderer/history.html b/src/renderer/history.html index 398c57c..ea3b983 100644 --- a/src/renderer/history.html +++ b/src/renderer/history.html @@ -1269,6 +1269,43 @@ text-align: right; } + /* Toggle switch */ + .switch { + position: relative; + display: inline-block; + width: 36px; + height: 20px; + } + .switch input { opacity: 0; width: 0; height: 0; } + .switch-slider { + position: absolute; + cursor: pointer; + top: 0; left: 0; right: 0; bottom: 0; + background: var(--bg-primary); + border: 1px solid var(--border-subtle); + border-radius: 20px; + transition: background 0.2s; + } + .switch-slider::before { + content: ""; + position: absolute; + height: 14px; + width: 14px; + left: 2px; + bottom: 2px; + background: var(--text-secondary); + border-radius: 50%; + transition: transform 0.2s, background 0.2s; + } + .switch input:checked + .switch-slider { + background: #EC5B16; + border-color: #EC5B16; + } + .switch input:checked + .switch-slider::before { + transform: translateX(16px); + background: #fff; + } + /* Theme toggle */ .theme-toggle { display: flex; @@ -1353,6 +1390,13 @@ +
+ Launch on startup + +
Shortcut ⌘⇧R diff --git a/src/renderer/history.js b/src/renderer/history.js index 0dc6d8d..396d52e 100644 --- a/src/renderer/history.js +++ b/src/renderer/history.js @@ -1029,9 +1029,20 @@ async function initSettings() { document.querySelectorAll('.theme-toggle-btn').forEach(btn => { btn.classList.toggle('active', btn.dataset.theme === currentTheme); }); + // Sync launch-on-startup toggle + const openAtLoginCheckbox = document.getElementById('openAtLoginCheckbox'); + if (openAtLoginCheckbox) { + openAtLoginCheckbox.checked = !!config.openAtLogin; + } popover.classList.add('visible'); }); + // Launch on startup toggle + const openAtLoginCheckbox = document.getElementById('openAtLoginCheckbox'); + openAtLoginCheckbox?.addEventListener('change', () => { + window.configAPI.saveConfig({ openAtLogin: openAtLoginCheckbox.checked }); + }); + // Close on outside click (mousedown works in drag regions too) document.addEventListener('mousedown', (e) => { if (!e.target.closest('.settings-popover-wrap')) {