| Age | Commit message (Collapse) | Author | Files | Lines |
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
An edit now rewrites only the fields that changed. A save with nothing
changed used to rebuild the alarm, turning ACTION:AUDIO into DISPLAY
and dropping ACKNOWLEDGED, re-anchor the start to the local zone, and
strip SUMMARY's parameters; the test edits a foreign event unchanged and
checks every one survives.
get, edit and delete name the calendar the event is in. The same invite
synced into two calendars has one UID, and the panel acted on whichever
file came first, so editing one copy could overwrite or delete the
other.
A custom rule's date cannot be moved from the panel: BYDAY=MO stayed on
Monday while the start moved, and the series lost the day shown.
UNTIL is read back in local time, so a 22:30 series keeps its last
occurrence. Files are written 0644 like vdirsyncer's. Enter in the title
no longer bypasses the busy guard, which could create an event twice,
and a throwing callback no longer leaks its Process.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The island README gains the panel. AGENTS.md records why calctl reads
the vdir itself, the local-time recurrence rule, the system Python it
needs, and two traps the build hit: a QML method named escape fails to
load, and a pill expanding for any panel grew beside the calendar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Checking a day's reminders meant opening each event. The bell shows
when the event carries its own VALARM, preset or custom. cal-notif's
per-calendar defaults are not reflected: they are its configuration,
not a property of the event.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
It expanded for any panel, which was right while it hosted every panel
there was. The calendar panel lives in the clock pill, so the status
pill grew into an empty box beside it. It now expands for its own two.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A click on the pill opens the panel in its capsule, 620px wide, growing
left from the gap so the status pill does not move. Focus goes into the
panel so its text fields and Escape work; Escape closes the editor
before the panel.
The Escape hook is back(), not escape(): QML rejects a method named
escape with "Illegal method name", since it shadows the global JS
function, and the reload failed until it was renamed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Six weeks from Monday, a dot per calendar with something that day, today
and the selection marked. The agenda lists the selected day, all-day
first; a click opens the event in the editor, and while the editor is
open the grid picks its dates instead of the selection. Escape closes
the editor before the panel.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Dates come from the month grid beside it; times are typed or scrolled in
15-minute steps. Repeat and alarm offer the presets and show custom,
unselectable, for an event carrying something richer, which the save
then leaves alone. A failed save keeps the form open with calctl's line.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Runs calctl, one Process per call so a reload and a save never collide,
and drops a list that a newer one overtook. Watches the calendar
directories the way the mail count watches xapian, so an edit from khal
or a cron sync repaints the panel too.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Month cells from Monday, which days an event covers, the day's agenda
order, the grid's dots, time stepping, and the editor's draft in both
directions. Days are strings and arithmetic is in UTC, so the DST change
at the end of October never moves a day; the test steps across it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Edits change only what the form owns: a custom rule, extra alarms and
properties this tool does not know survive, which the test checks on an
event with BYDAY, two alarms and an X- property. Writes go through a
temporary file and a rename so khal, cal-notif and vdirsyncer never read
half a file, and a vdirsyncer sync is started detached afterwards.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
The calendar list comes from khal's config, so there is no second list.
Recurrence is expanded with dateutil in naive local time, which keeps a
weekly 09:00 at 09:00 across the DST change; the test pins that on 26
October. A rule richer than a plain FREQ, or alarms other than one
preset, read as custom, which is what lets an edit leave them alone.
A file that fails to parse is skipped rather than blanking the month.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Edit mode let a right-click and the wheel through to the tile, so a
right-click opened the drawer and scroll changed volume, against the
spec. The drag area now takes both buttons and the wheel.
A scroll up on a level already above the cap, such as a mic set to 120%
elsewhere, snapped it down to the cap. The cap now only stops a step up.
Prefs logs a failed write, which printErrors off had silenced: the new
order would otherwise vanish at the next restart with no trace. Its
parsed object is renamed from data to doc, so it cannot shadow a base
property of that name.
The spec now says what was built: JSON.parse rather than a JsonAdapter,
and the helper list as it is.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The island README gains the panel. AGENTS.md records that a bare SUPER
release bind is cancelled by drag and scroll on Hyprland 0.56.2, which
was the open risk in the spec, and that FileView creates parent
directories while Quickshell.stateDir is per-shell.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A settings icon in the status pill opens the controls panel in the same
capsule the sound panel uses. Right-click on a tile closes the panel and
opens its drawer page. The island IPC target reveals the island and
toggles the panel, for the SUPER release bind.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Four columns, the visible list from Prefs. Edit mode puts a MouseArea
over each tile that drags it and drops it into the slot under its
centre, a × that hides it, and a strip of hidden tiles with a + each.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Wifi and bluetooth through the Quickshell services, DND, presentation and
auto-lock through the Status registry, output and mic through the sound
module's tracked nodes. A tile whose backing object has not arrived yet
is dimmed and ignores input, which covers the two seconds before
Networking and Bluetooth populate.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
The first preference is the controls panel's visible tiles. The file is
written only on a change and keeps keys it does not know, so a broken or
newer file is never clobbered by a shell that only read it. State home
rather than the runtime dir because it must survive a reboot, rather
than ~/.config because the shell writes it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
The controls panel's tiles, their icons and drawer pages, and every
operation on the visible list: normalize, hide, show, move, the drop
slot under a dragged tile, the audio fill and the scroll step. All pure,
so the edit mode's logic is tested under node rather than by dragging.
normalize keeps an empty list: hiding every tile is a choice, and only
a value that is not a list falls back to the default.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
It is a handle for revealing the pills, so it gives way to them. While
something captures it stays, being the only privacy indicator.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
AGENTS.md describes the hybrid model (desktop/ hosts drawer and island) and
gains the gotchas found while building the island: UseQApplication for tray
menus, WheelHandler vs MouseArea, accent colliding with green, xkb layout
switching, and the tray popup un-hovering the island. The Blur waybar
measurement becomes history. READMEs drop their present-tense waybar
references.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The island replaces both bars: clock and VM dots in the clock pill, volume,
tray, layout flag and privacy in the status pill and its sliver, mail count
in the drawer. The icon switch no longer regenerates or reloads waybar, and
the mail pill's watcher script goes with it. Workspaces and the taskbar have
no persistent view by decision: the flick and the expose cover them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Two icons side by side read as two apps. The desktop one is boxed, the
number fallback with it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The sliver was the accent at rest, and udt had snapped the accent to the
same colour as the mic indicator (#36d190), so an idle sliver read as a
live microphone. It is Theme.overlay at rest now; captures keep their
colours whatever the wallpaper does.
The flag's WheelHandler never fired. MouseArea.onWheel, which SoundPage
already uses, does; scroll now switches layout, one step per notch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A fixed overlay strip that never resizes: the pills animate inside it and
the input mask follows their rectangles, so resizing a layer surface during
a morph never happens. Hidden behind a sliver that also carries the privacy
colours; the clock pill drops alone for a workspace or app-open flick.
shell.qml gains the UseQApplication pragma, which tray menus need, and the
island holds itself shown while a tray menu is open, since the menu is a
separate popup that would otherwise un-hover the pills and let the hide
timer fire. The hold ends at the next hover.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
- The flag switches once per wheel notch; a touchpad's stream of small
deltas switched an erratic number of times.
- The flick decides on resolved icon paths, so a name the icon theme lacks
falls back to the workspace number instead of a blank slot.
- Layout switching uses Hyprland's 'current' keyboard rather than looking
up the main device in a subshell.
- The capsule radius reaches half the rest height, a real capsule.
- privacy.sh exits non-zero when pw-dump fails, so Privacy keeps its last
reading instead of reporting nothing captured.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The tray makes the island the session's StatusNotifier host, which waybar
was until now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The flag follows whichever keyboard Hyprland marks main, looked up on every
activelayout event and every switch. wb-lang read a fixed device name and
went blank when the keyboard moved from its dongle to USB. Flags copied
from waybar-theme-udt, which goes away with waybar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Ported from waybar-theme-udt's privacy_dots.sh, because the island's sliver
takes over that indicator when waybar goes. pw-dump stays for mic and
screen: PwNode has no running state to tell capture from an idle source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The island's clock pill shows the same desktop icon the window switcher
does. One map, symlinked into both components like Theme.qml, rather than
a second copy that would drift.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
NaN and undefined fail every comparison, so they fell through to the high
icon. A node can report before its volume is populated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The island's decisions that do not need a running shell: which volume icon,
which colour a VM dot takes, which flag a keymap shows, the order of the
privacy segments, and how an openwindow event splits. Kept out of QML so
node can check them.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
|
|
Accounts counted only at shell start and when the mail page opened, so the
drawer tile drifted behind the inbox for the rest of the session: it read 14
while notmuch and the waybar pill both said 16. The waybar pill never drifted
because waybar-mail.sh watches the database; the drawer had no watcher.
Accounts now runs its own inotifywait -m on the xapian directory (the
directory, because Xapian replaces files on commit) and refreshes 300ms after
a commit burst settles. The watcher respawns after 5s if it exits, since a
dead one reproduces the drift with no visible error.
This is the prerequisite for removing waybar: the drawer becomes the only
place the unread count is shown.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Engines are read-only, since stopping llama-server or sd-server takes
its web UI down too. Apps start and stop through their own controls,
detached so a start outlives a quickshell reload. Fanfictioner has no
start (a run needs a story) and stops by pid, children first, so its
sd-cli runs go with it and nothing else does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
fanfictioner runs sd-cli one-shot, not through sd-server, so the sd row
read down while a CLI run held VRAM and generated. A running sd-cli now
reads up and busy, its model marked (sd-cli), and outranks the web UI.
The model is the first --diffusion-model/-m: sd-cli's prompt follows and
is free text that may contain "-m".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Six TSV lines per sweep: llama and sd engines, four apps. llama's slot
probe passes autoload=false, since a plain /slots?model= loads the model
into VRAM. sd-server has no progress endpoint, so busy is its log
having been written in the last 5s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Qt's atomic write builds the file as an unnamed O_TMPFILE. When the
target does not exist yet it links that straight into place, and the
only event naming the file is IN_CREATE: no close_write, no moved_to.
statusctl watch did not listen for create, so the first write of each
mode in a session went unseen. On a fresh session that is the write
that matters: a Teams call started an hour in left the waybar pill
reading off until some later rename happened to redraw it.
The test reproduces the event with a hard link, which is what the
linkat from Qt's temp file looks like to inotify.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
It was a hand-installed copy, which can drift from the tested source
silently. Replaced with a symlink after confirming the two were
identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The auto-detector now sets presentation while Teams holds a mic stream,
alongside the game checks. Teams runs for the whole session, so its
process alone is no signal and would have kept lock, DND and the
breaktimer off all day. A call is Teams holding a source-output, which
pactl lists tagged with application.process.binary = "teams-for-linux";
verified matching during a live call.
It reuses status.gaming rather than status.presentation, so a call
ending clears only the automatic half and never a manual toggle. The
statusctl tooltip for that state said "game running", which is now
wrong, so it reads "auto: game or call". The file and waybar class keep
the gaming name: renaming them touches four places for no behaviour
change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Balloon and drawer bodies switch from RichText to Qt's MarkdownText
(CommonMark plus GitHub extensions). Raw HTML still goes through Qt's
HTML importer, so body-markup senders keep working.
Markdown images fetch their destination the same way an <img> does,
which the existing sanitize filter would miss since it only inspects
tags. sanitize now escapes every "![" so the syntax renders as literal
text, local or remote; parsing CommonMark destinations and reference
definitions to allow local ones is not worth the grammar. Verified in
the shell log: before the filter reached the running shell, a test
body fetched https://example.org/a.png; after, a second one did not.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The crossfade only brought a loaded cover to the front when the image's
source compared equal to the wanted URL. It never did for a title with
spaces or brackets: the URL carries the title as a percent-encoded
fragment cache buster, and QUrl reads it back decoded, so "#Foo%20Bar"
came back as "#Foo Bar". The load finished, loaded() bailed, and the old
cover stayed. Confirmed with a standalone qml test.
The slot being loaded is now tracked by index instead. Stale status
changes cannot match: only the back image is ever reloaded, and a newer
want resets it before assigning.
Seen working on screen by the user.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The OSD background held one Image, so a track change swapped covers in a
single frame. Two images now take turns: the new cover loads into the
hidden one and is brought to the front only once it reports Ready, then
both fade over 300ms. Waiting for Ready is what keeps a slow or remote
art server from fading through black.
The blur, scrim, sheen and grain are grouped under one item whose
opacity follows artOn. It goes false when the player has no art or the
cover for the current track errors, so the panel fades back to its plain
translucent look instead of snapping, or keeping a stale cover that
reads as a fault. It goes true again only when a new cover has loaded,
so returning from plain never flashes the previous one.
The back image's source is cleared before being set, so a URL it
already holds still reloads and reports a status. onWantChanged misses
the value at load, hence the Component.onCompleted call.
Not yet seen on screen: the shell reloaded it cleanly but the fade was
not watched through a track change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The art background is opaque, so Hyprland's blur behind the OSD cannot
show through it; making the art translucent to let it through would
also thin the scrim that keeps light covers legible. Fake the frosted
glass instead: a faint top-down sheen in Theme.text and a fixed grain,
painted once by a Canvas and masked to the panel's rounded corners.
The grain is a Canvas rather than a ShaderEffect because a shader needs
a compiled .qsb beside it; the Canvas repaints only on resize.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
When the current track has art, the volume OSD now draws it across the
whole panel, blurred (MultiEffect blur 0.5, default blurMax) and masked
to the panel's rounded corners, since clip only cuts to the bounding box.
The thumbnail in the track row stays sharp on top.
A dark scrim (Theme.base at 0.82) sits over the art. The palette is dark
and the text light, so a light cover made the panel unreadable, and more
blur did not fix that; only darkening did. The scrim is a sibling of the
MultiEffect, not a child: nested inside it, it did not paint at all, which
is why raising its alpha first appeared to change nothing.
Without art the panel keeps its translucent, compositor-frosted look.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A Loader keeps the height of its last item after active goes false. When
a browser tab playing media was closed, its MPRIS player vanished,
Player.active dropped and the window shrank to 100px, but the Loader
still reserved 46px plus the Column spacing on top. The volume row was
pushed down and clipped at the bottom edge, which is the "stuck" OSD a
hot reload used to cure: a fresh Loader starts at zero height.
Hiding the Loader while inactive makes the Column skip it. Both the
retained height and the collapse were confirmed with headless qml6 runs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
libvirt reports "running" as soon as QEMU is up, long before the guest
has booted, so the panel had no way to say when a VM is actually usable.
After a successful start, a detached script polls the VM's sshd and
sends a notification once it accepts connections, or a warning after
five minutes.
Host and port come from `ssh -G <vm>`: a Host alias named after the VM
may put sshd on a non-default port (buildsystem listens on 2290, and a
probe of port 22 never succeeded). Without an alias `ssh -G` echoes the
name back, and the guest agent's IPv4 address on port 22 is used. The
probe is a plain `nc -z`, so no authentication or key is involved.
Detached rather than a Process so several VMs can wait at once and the
wait survives a shell reload. Only starts issued from the panel are
watched; a VM started from virt-manager or the CLI is not.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|