experiments in a post-browser web
10
fork

Configure Feed

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

feat(windows): surface pin-hidden windows in the Windows switcher

Hidden windows were already in the tile:window:list payload but the
Windows feature rendered them indistinguishably and clicking them did
not unhide. Now hidden cards render dimmed with a "Hidden" badge and
clicking unhides before focusing. Adds desktop e2e regression guard
that a hidden window stays in the list with visible:false.

+94 -2
+25
features/windows/windows.css
··· 103 103 text-overflow: ellipsis; 104 104 } 105 105 106 + /* Hidden (pin-hidden) windows: dim the card and tag it. */ 107 + peek-card[data-hidden="true"] { 108 + --peek-card-bg: var(--base01); 109 + opacity: 0.65; 110 + } 111 + 112 + peek-card[data-hidden="true"] .card-title { 113 + font-style: italic; 114 + color: var(--base04); 115 + } 116 + 117 + .card-hidden-badge { 118 + font-size: 10px; 119 + font-weight: 600; 120 + color: var(--base05); 121 + background: var(--base02); 122 + border: 1px solid var(--base03); 123 + border-radius: 3px; 124 + padding: 1px 6px; 125 + margin-left: auto; 126 + flex-shrink: 0; 127 + text-transform: uppercase; 128 + letter-spacing: 0.5px; 129 + } 130 + 106 131 /* List view mode - remove max-width constraint */ 107 132 peek-grid.cards[view-mode="list"] peek-card { 108 133 max-width: none;
+15 -2
features/windows/windows.js
··· 256 256 card.interactive = true; 257 257 card.elevated = true; 258 258 card.dataset.windowId = win.id; 259 + if (win.visible === false) { 260 + card.dataset.hidden = 'true'; 261 + } 259 262 260 263 // Header with optional favicon and title 261 264 const header = document.createElement('div'); ··· 284 287 title.textContent = win.title || 'Untitled'; 285 288 header.appendChild(title); 286 289 290 + if (win.visible === false) { 291 + const badge = document.createElement('span'); 292 + badge.className = 'card-hidden-badge'; 293 + badge.textContent = 'Hidden'; 294 + header.appendChild(badge); 295 + } 296 + 287 297 card.appendChild(header); 288 298 289 299 // URL in body ··· 292 302 url.textContent = win.url || ''; 293 303 card.appendChild(url); 294 304 295 - // Click to focus window and close windows view 305 + // Click to focus window and close windows view; un-hide first if hidden 296 306 card.addEventListener('card-click', async () => { 297 - debug && console.log('[windows] Clicking window:', win.id, win.title); 307 + debug && console.log('[windows] Clicking window:', win.id, win.title, 'visible:', win.visible); 308 + if (win.visible === false && api?.window?.show) { 309 + await api.window.show(win.id); 310 + } 298 311 await api.window.setOverlayFocusTarget(win.id); 299 312 closeWindowsView(); 300 313 });
+54
tests/desktop/windows-hidden-surface.spec.ts
··· 1 + /** 2 + * Regression coverage: pin-hidden web page windows must remain in the 3 + * Windows feature listing (tile:window:list) so the user can find and 4 + * unhide them. The Windows UI renders them dimmed with a "Hidden" badge. 5 + */ 6 + import { test, expect, DesktopApp } from '../fixtures/desktop-app'; 7 + import { Page } from '@playwright/test'; 8 + import { createPerDescribeApp } from '../helpers/test-app'; 9 + 10 + test.describe('Windows feature surfaces hidden windows @desktop', () => { 11 + let app: DesktopApp; 12 + let bgWindow: Page; 13 + 14 + test.beforeAll(async () => { 15 + ({ app, bgWindow } = await createPerDescribeApp('windows-hidden')); 16 + }); 17 + 18 + test.afterAll(async () => { 19 + if (app) await app.close(); 20 + }); 21 + 22 + test('hidden window appears in tile:window:list with visible:false', async () => { 23 + // Open a transient page-host window 24 + const open = await bgWindow.evaluate(async () => { 25 + return await (window as any).app.window.open('https://example.com/', { 26 + width: 600, 27 + height: 400, 28 + }); 29 + }); 30 + expect(open.success).toBe(true); 31 + const winId = open.id; 32 + expect(winId).toBeTruthy(); 33 + 34 + // Hide it 35 + const hideRes = await bgWindow.evaluate(async (id: number) => { 36 + return await (window as any).app.window.hide(id); 37 + }, winId); 38 + expect(hideRes.success !== false).toBe(true); 39 + 40 + // List windows; the hidden one should still be present with visible: false 41 + const list = await bgWindow.evaluate(async () => { 42 + return await (window as any).app.window.list({ includeInternal: true }); 43 + }); 44 + expect(list.success).toBe(true); 45 + const found = (list.windows || []).find((w: { id: number }) => w.id === winId); 46 + expect(found).toBeTruthy(); 47 + expect(found.visible).toBe(false); 48 + 49 + // Cleanup 50 + await bgWindow.evaluate(async (id: number) => { 51 + return await (window as any).app.window.close(id); 52 + }, winId); 53 + }); 54 + });