experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: remove persistWindowState, fix settings checkbox alignment, fix drag click suppression

- Remove persistWindowState pref and window_state persistence from ipc.ts
(session restore already handles window bounds)
- Fix settings checkbox alignment: restructure boolean pref rows to
two-column layout (text + checkbox) for consistent spacing
- Fix click-hold-drag engaging without mouse movement: hold timer now
sets holdReady, actual drag requires 3px movement threshold

+42 -77
-7
app/config.js
··· 10 10 showInDockAndSwitcher: 'Show in dock', 11 11 backupDir: 'Backup directory', 12 12 hideTitleBar: 'Hide title bars', 13 - persistWindowState: 'Remember window positions', 14 13 restoreSession: 'Restore session on startup', 15 14 sessionAutosaveInterval: 'Autosave interval (minutes)', 16 15 } ··· 65 64 }, 66 65 "hideTitleBar": { 67 66 "description": "Hide window title bars by default (frameless windows)", 68 - "type": "boolean", 69 - "default": true 70 - }, 71 - "persistWindowState": { 72 - "description": "Remember window position and size across app restarts", 73 67 "type": "boolean", 74 68 "default": true 75 69 }, ··· 164 158 showInDockAndSwitcher: true, 165 159 backupDir: '', 166 160 hideTitleBar: true, 167 - persistWindowState: true, 168 161 restoreSession: true, 169 162 sessionAutosaveInterval: 5, 170 163 pageWidth: 800,
+9 -1
app/settings/settings.css
··· 186 186 187 187 .form-group-inline { 188 188 display: flex; 189 - align-items: center; 189 + align-items: flex-start; 190 190 justify-content: space-between; 191 + gap: 16px; 191 192 padding: 12px 0; 192 193 border-bottom: 1px solid var(--border-light); 194 + } 195 + 196 + .form-group-inline-text { 197 + flex: 1; 198 + min-width: 0; 193 199 } 194 200 195 201 .form-group-inline:last-child { ··· 205 211 206 212 /* Checkbox */ 207 213 .checkbox-wrapper { 214 + flex-shrink: 0; 208 215 display: inline-flex; 209 216 align-items: center; 217 + padding-top: 2px; 210 218 } 211 219 212 220 .checkbox-wrapper input[type="checkbox"] {
+8 -3
app/settings/settings.js
··· 67 67 }); 68 68 69 69 wrapper.appendChild(input); 70 - group.appendChild(labelEl); 71 - group.appendChild(wrapper); 70 + 71 + const textDiv = document.createElement('div'); 72 + textDiv.className = 'form-group-inline-text'; 73 + textDiv.appendChild(labelEl); 72 74 73 75 if (options.helpText) { 74 76 const help = document.createElement('div'); 75 77 help.className = 'help-text'; 76 78 help.textContent = options.helpText; 77 - group.appendChild(help); 79 + textDiv.appendChild(help); 78 80 } 81 + 82 + group.appendChild(textDiv); 83 + group.appendChild(wrapper); 79 84 80 85 return group; 81 86 };
+1 -54
backend/electron/ipc.ts
··· 2097 2097 } 2098 2098 }; 2099 2099 2100 - // Load saved window state if persistState is enabled and window has a key 2101 - let savedState: { x?: number; y?: number; width?: number; height?: number } | null = null; 2102 - if (options.key && (options.persistState === true || getPrefs().persistWindowState)) { 2103 - try { 2104 - const rowId = `window_state:${options.key}`; 2105 - const row = getRow('extension_settings', rowId); 2106 - if (row && row.value) { 2107 - savedState = JSON.parse(row.value as string); 2108 - DEBUG && console.log('Loaded saved window state for key:', options.key, savedState); 2109 - } 2110 - } catch (e) { 2111 - DEBUG && console.log('Failed to load window state:', e); 2112 - } 2113 - } 2114 - 2115 - // Apply saved state or explicit position parameters 2116 - if (savedState) { 2117 - if (savedState.x !== undefined) winOptions.x = savedState.x; 2118 - if (savedState.y !== undefined) winOptions.y = savedState.y; 2119 - if (savedState.width !== undefined) winOptions.width = savedState.width; 2120 - if (savedState.height !== undefined) winOptions.height = savedState.height; 2121 - } 2122 - // Explicit options override saved state 2100 + // Apply explicit position parameters (used by session restore and direct callers) 2123 2101 if (options.x !== undefined) { 2124 2102 winOptions.x = parseInt(options.x); 2125 2103 } ··· 2733 2711 trackContentWindowFocus(win); 2734 2712 if (!options.modal) { 2735 2713 trackVisibleWindowFocus(win); 2736 - } 2737 - 2738 - // Set up window state persistence if enabled 2739 - const shouldPersist = options.key && (options.persistState === true || getPrefs().persistWindowState); 2740 - if (shouldPersist) { 2741 - // Debounce timer for saving state 2742 - let saveTimer: NodeJS.Timeout | null = null; 2743 - const saveState = () => { 2744 - if (saveTimer) clearTimeout(saveTimer); 2745 - saveTimer = setTimeout(() => { 2746 - if (win.isDestroyed()) return; 2747 - const bounds = win.getBounds(); 2748 - const rowId = `window_state:${options.key}`; 2749 - const data = { 2750 - extensionId: 'window_state', 2751 - key: options.key, 2752 - value: JSON.stringify({ 2753 - x: bounds.x, 2754 - y: bounds.y, 2755 - width: bounds.width, 2756 - height: bounds.height 2757 - }), 2758 - updatedAt: Date.now() 2759 - }; 2760 - setRow('extension_settings', rowId, data); 2761 - DEBUG && console.log('Saved window state for key:', options.key, bounds); 2762 - }, 500); // Debounce 500ms 2763 - }; 2764 - 2765 - win.on('move', saveState); 2766 - win.on('resize', saveState); 2767 2714 } 2768 2715 2769 2716 // Set up DevTools if requested
+24 -12
preload.js
··· 2158 2158 // ============================================================================ 2159 2159 (function initWindowDrag() { 2160 2160 const HOLD_DELAY = 80; // ms before drag engages 2161 + const MOVE_THRESHOLD = 3; // px of movement required to engage drag 2161 2162 2162 2163 // State 2163 2164 let isDragging = false; 2165 + let holdReady = false; // hold timer fired, waiting for movement to engage drag 2164 2166 let holdTimer = null; 2165 2167 let mouseButtonDown = false; 2166 2168 let cachedWindowId = null; ··· 2220 2222 const endDrag = (reason) => { 2221 2223 const wasDragging = isDragging; 2222 2224 cancelHold(); 2225 + holdReady = false; 2223 2226 if (isDragging) { 2224 2227 isDragging = false; 2225 2228 suppressClick = true; ··· 2289 2292 return; 2290 2293 } 2291 2294 2292 - // Snapshot CURRENT mouse position as drag origin (not the original 2293 - // mousedown position). This way any movement during the hold period 2294 - // doesn't cause a sudden jump when drag starts. 2295 + // Mark ready — actual drag engages on first mousemove with enough movement. 2296 + // This prevents click-and-hold (no movement) from engaging drag and 2297 + // swallowing the subsequent click event. 2295 2298 dragOriginX = lastScreenX; 2296 2299 dragOriginY = lastScreenY; 2297 2300 windowOriginX = pos.x; 2298 2301 windowOriginY = pos.y; 2299 - isDragging = true; 2300 - document.body.style.cursor = 'grabbing'; 2301 - document.body.classList.add('is-dragging'); 2302 - // Clear any accidental text selection that formed during the hold period 2303 - // and suppress further selections while dragging 2304 - window.getSelection()?.removeAllRanges(); 2305 - document.body.style.userSelect = 'none'; 2306 - document.body.style.webkitUserSelect = 'none'; 2302 + holdReady = true; 2307 2303 2308 - console.log('[DRAG] ENGAGED origin=(' + dragOriginX + ',' + dragOriginY + 2304 + console.log('[DRAG] HOLD READY origin=(' + dragOriginX + ',' + dragOriginY + 2309 2305 ') window=(' + windowOriginX + ',' + windowOriginY + ')'); 2310 2306 }, HOLD_DELAY); 2311 2307 }; ··· 2316 2312 // Always track latest mouse position (hold timer reads this) 2317 2313 lastScreenX = e.screenX; 2318 2314 lastScreenY = e.screenY; 2315 + 2316 + // Hold timer fired — engage drag once movement exceeds threshold 2317 + if (holdReady && !isDragging) { 2318 + const dx = e.screenX - dragOriginX; 2319 + const dy = e.screenY - dragOriginY; 2320 + if (Math.abs(dx) < MOVE_THRESHOLD && Math.abs(dy) < MOVE_THRESHOLD) return; 2321 + 2322 + holdReady = false; 2323 + isDragging = true; 2324 + document.body.style.cursor = 'grabbing'; 2325 + document.body.classList.add('is-dragging'); 2326 + window.getSelection()?.removeAllRanges(); 2327 + document.body.style.userSelect = 'none'; 2328 + document.body.style.webkitUserSelect = 'none'; 2329 + console.log('[DRAG] ENGAGED after movement'); 2330 + } 2319 2331 2320 2332 if (!isDragging) return; 2321 2333