STATE.md was five days stale. It now carries what is on the phone (viewtop r76, souveraine r333) and the four defects fixed on the glass: per-window capture was unreachable because quickshell holds wlr handles and the ext capture source is named by an ext handle with nothing correlating them; titles were never republished on commit; the border was a filled slab that relied on the client covering its middle; capture came back flipped. Also the packaging hole, which was the important one — viewtop's PKGBUILD existed and appeared in none of packages.yml's build lists, so nothing ever built it. Half closed: it builds now, but a viewtop commit still does not trigger a rebuild. TASK-15 question 1 is answered and closed: dropping the accelerometer claim took iio-sensor-proxy from 15.3% to 1.1%, sensors overall 17.2% to 2.6% of a core. Consequence noted against 08(g) — confidence loses accel's +0.3. New: 54, 55, 56, and 57/58 (Pi dock head, SMB2 OTG boost) with the USB notes they point at.
7.1 KiB
TASK 56 — the island, and the bar's honest face
Status: open — Part A is design questions only; Part B is small and buildable.
Created 2026-08-04, from Casey: the top bar is "static only due to a lack of
creativity and ingenuity" — the bar should clear a region ("an island") where a
notification can sprawl banner text; laptop/phone merge is the ultimate goal,
and "the agent is supposed to have full control on all the things soon".
Repos: souveraine (shell surfaces, ii-phone bar), sessiond for the
island's decision side.
What exists, measured
| Piece | Where | State |
|---|---|---|
| The phone bar | surfaces/quickshell/ii-phone/modules/ii/bar/BarContent.qml |
Three anchored regions: left (sidebar button + carrier + active window), middle (clock), right (pill: wifi/mute/mic/notify-unread reveals, battery, resources, systray, weather). Floating rounded rect with border |
| The island's seed | BarContent.qml:268-306 — Revealer + Layout.rightMargin Behaviors |
The right pill already animates contents apart to make room; the island is this same primitive with a real budget |
bar.bottom |
BarContent.qml:338 |
Exists — an island always grows away from the screen edge, so a top bar and a bottom bar are one layout mirrored |
| Banners today | ii-base/modules/ii/notificationPopup/NotificationPopup.qml (phone shares the desktop one) |
Corner-stacked, entirely separate from the bar — pure client noise; the bar's only hook is NotificationUnreadCount |
| Carrier | surfaces/quickshell/services/Cellular.qml — mmcli + gdbus PropertiesChanged, signal-driven; operatorName, accessTech (5G/LTE/H+/H/3G/E/G), hasService, materialSymbol |
Bar shows "<operator> <tech>" e.g. "Fido LTE" + signal bars (BarContent.qml:95-114) |
| Network face | services/Network.qml — materialSymbol is already honest about wifi (connected → strength bars, disconnected → wifi_find, disabled → off) |
The pill's always-visible face (BarContent.qml:312-318) — but it never shows cellular: wifi disconnected shows a scan glyph even while LTE is the live connection |
| Tap conflict | BarContent.qml:50-68 |
The whole left region is one FocusedScrollMouseArea (press = left sidebar toggle) — a carrier tap needs its own MouseArea ahead of the parent |
Part A — the island
A1. What is the island, exactly?
iPhone: the bar recedes around a pill that expands. Android: heads-up banners drop below the status bar. Our phone is 540×1080 portrait — an island cannot sprawl sideways; it grows downward into the screen. On the laptop it grows sideways from the center. Same surface, two geometries — that is the laptop/phone merge in miniature. Decide what class of content it carries: notifications only, or the agent's general attention surface (turn activity, timer runs, device-state changes)?
A2. What happens to the displaced sections?
Compress or hide? Hide is where the desktop bar went wrong — modules vanish and the user loses their place. The right pill's Revealers already compress; the island is that mechanism given a budget. On the phone the left section (sidebar button + carrier) and the clock must survive at reduced width or move out of the island's sprawl path.
A3. Who decides what lands in the island?
Today banners are client-driven noise (freedesktop notifications → corner
popup). For the island to be the agent's surface, the display decisions are
sessiond's — the surface reads a binding table, never decides (doctrine §12,
§13): island-worthy vs quiet (a policy), steal-vs-queue when a second banner
lands mid-sprawl (preemption is a decision), linger duration, whether the
screen dims during it (touches sessiond's dim/lock contract). Shape: an intent
reachable the way overview toggle is (qs -c souveraine ipc call …), plus a
routing policy over the existing notifications service. "A verb she cannot
reach is a defect."
A4. Dismissal and touch
Tap = open the notification's app or the sidebar surface; swipe = dismiss. These are gesture bindings — they come from sessiond's binding table, not hardcoded QML. Also: does the bar remain interactive while the island is sprawled (the three MouseAreas)?
A5. Does it replace the corner popup on the phone?
The ii-base NotificationPopup is the current home of banner text, and the
phone still uses the desktop one. The island replaces it for island-worthy
classes on the phone; toasts / OSK / IME are separate concerns. Decide
coexistence before building.
Part B — the bar's honest face (buildable now)
B1. Carrier name, tap-to-cycle
Drop the tech suffix: the bar shows operatorName only — "Fido", no "LTE".
Tapping the name cycles Fido → Casey → Fimeg — a display alias, "just for
fun": the SIM still reports the real operator; the alias list is local.
Questions: persist (an existing settings key?) or per-session? Where does the
tap live — the carrier row needs its own MouseArea ahead of the left region's
sidebar-toggle press.
B2. A live network-type indicator
"LTE/Wifi should be the indicator on what type of network we have running
live." The pill's wifi glyph never reflects cellular: wifi disconnected shows
a scan glyph while LTE is the live connection. The indicator should pick the
active network: wifi connected → the wifi strength glyph (existing
Network.materialSymbol); wifi not connected but cellular has service → the
tech (LTE/H/3G/5G via Cellular.accessTech); neither → the disconnected/off
glyph. The tech label thus moves out of the carrier name and into the
indicator — one source of truth, live.
Acceptance (measured, on the phone)
Part B (buildable now):
- The bar shows "Fido" — no "LTE" suffix.
- Tapping the carrier cycles Fido → Casey → Fimeg, wraps, and the alias survives per the persistence decision.
- The network indicator shows the live type: wifi glyph on wifi, tech label (LTE/…) when wifi is down but cellular is up, off-glyph when neither — and it flips on connection change without a shell restart.
- The left-region sidebar toggle still works on its own area.
Part A (once the questions are answered):
- A banner arrives and the bar clears space for it — sections compress, nothing hides.
- Sessiond can put content in the island through a reachable intent — no hardcoded QML text paths.
- Dismissal and open behave per the binding table; a second banner mid-sprawl does the decided thing.
- The phone island grows downward, the laptop island sideways from the center — one surface.
- No hyprctl anywhere in the path.
Connects to
TASK-55 (the same bar region; gesture bindings and the sheet's dismissal
rules), TASK-30/31 (verb tables as the single source of what the agent can
drive — the island intent joins them), TASK-50 (the agent's touch path is the
mirror image of the island's), TASK-53 (one decider — a banner the agent
cannot influence is the same defect class), TASK-14/51 (the overview and the
bar's windows), doctrine §12 (the island is a surface, not a daemon — it reads
a binding table, never decides), §13 (the agent owns the device; "a verb she
cannot reach is a defect"), VIEWTOP-AND-DENIAL.md (in-process vs client
shell shapes where the island is drawn).