5 Commits
Author SHA1 Message Date
Vincent 04b731cf37 Say when something is downloading, and where it goes
The webview saves the file perfectly well and mentions it to nobody,
which makes a download indistinguishable from a click that did nothing.
Each one is now announced in the corner as it saves, and offers to show
the finished file in the Finder. The folder is settable and defaults to
the system's Downloads.

Two gaps in the API shape this. There is no progress - DownloadEvent
reports a start and a finish and nothing between - so the destination
file is polled as it grows and the bytes written are shown; the indicator
spins rather than fills, because there is no total to divide by. And on
macOS the finish always reports no path at all, so the destination
assigned at request time is remembered against the URL and read back at
the end.

A name already taken gets "(2)" appended. Silently overwriting is the
last thing anyone wants from a download they were not told about.
2026-09-02 10:42:45 +02:00
Vincent 899f0b41c4 Remember window and tab; fill saved passwords; match the title bar
The window's position and size survive a restart, and so does the app
you were last in.

Saving a password was only half of it - a saved password you cannot get
back out is not saved in any useful sense. Right-click now offers "Fill
saved password" wherever a page has a password field. Only on an explicit
click, only for the host on screen, and only into that page's own fields,
never on load. The value is set through the native setter and followed by
input and change events, because assigning .value is invisible to React
and Angular and the site would submit an empty field.

The title bar is painted the nav's colour rather than its own grey, so
the two read as one surface in either theme. Doing that revealed that the
window's content had always run the full height underneath it - the
opaque bar was hiding it - so the shell is now inset by the measured
title bar height, or the nav lands on the traffic lights.

The rail's unread badge is a fixed circle inside the button's bounds.
Padding around a number made a pill at two digits, and hanging it off the
corner put it under the rail's clip; past nine it reads "9+", with the
figure itself in the expanded nav.
2026-09-01 19:17:38 +02:00
Vincent 17d13d2505 Show each site's own icon; restore the native title bar
Both previous attempts asked a question about a domain, and a domain does
not know which product it is serving. Google's favicon service returned a
marketing site's icon for anything behind a login and nothing for a
private host; Simple Icons returned one flat brand mark where the real
one is multicoloured and, for Gmail, carries the unread count.

The page already holds the answer - fetched, authenticated, current. The
injected script now reads link[rel~="icon"] and reports the best one:
largest declared sizes wins, an Apple touch icon counts as 180, and an
.ico is penalised as usually the 16px tab icon. It rechecks on the same
tick as the unread count, which is when a site like Gmail redraws its
icon with a badge. The URL is stored, so the nav is right at launch
rather than blank until every page has loaded.

The custom frame is gone with it: ordinary macOS title bar, traffic
lights where every other window puts them, and the bar following the
app's Light/Dark choice through set_theme. A window that behaves like a
window beats one that looks bespoke.
2026-09-01 15:03:09 +02:00
Vincent ada18d54ae Draw apps with Simple Icons instead of fetched favicons
The favicon service was wrong as often as it was right: a sign-in page's
icon for anything behind a login, nothing at all for a private host, and
both answers cached past any way of asking again. Refreshing could not
fix it, because the staleness was not local. Now every mark is.

Each app is its brand glyph in white on a round tile, coloured from
Tailwind's 500s by hashing the host - you find things by their colour, so
one that moved every launch would be worse than none. A host with no
glyph gets its initial in the same tile.

Matching tries the registrable name first, since a self-hosted tool is
nearly always on a subdomain of its vendor - aputure.odoo.com is Odoo,
not Aputure. A short table covers what a domain cannot answer, which is
most of Google.

The build reduces Simple Icons' 15MB of SVGs to one 4.5MB map in public/,
fetched once rather than parsed into the bundle at every start; the
bundle stays at 233KB. It is generated on every build, so never committed
and never stale.

Traffic lights are offset to sit inside the window margin rather than
crowding its edge.
2026-09-01 14:45:41 +02:00
Vincent a6c8e4336b Work App: a dedicated browser for work tools
A Tauri 2 shell with one child webview per configured tool. Nav on the left
with groups and a collapsible icon rail; links between configured apps switch
tabs, everything else leaves for the real browser.

Design spec in docs/superpowers/specs/2026-09-01-work-app-design.md.
2026-09-01 11:37:35 +02:00