aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)AuthorFilesLines
10 daysfix(island): review findings in the controls panelDanilo M.5-9/+25
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>
10 daysdocs: the controls panel, its preferences file and bindDanilo M.2-2/+35
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>
10 daysfeat(island): controls panel in the status pill, island IPCDanilo M.3-7/+56
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>
10 daysfeat(island): controls grid with an edit modeDanilo M.1-0/+175
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>
10 daysfeat(island): a control tile bound to its live stateDanilo M.1-0/+143
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>
10 daysfeat(desktop): preferences file under the state homeDanilo M.1-0/+69
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>
10 daysfeat(island): pure tile table and order helpers for controlsDanilo M.2-0/+197
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>
10 daysdocs(spec): controls panel uses named icons and a plain dragDanilo M.1-4/+15
Planning found two places where the spec diverged from the island it extends. Icons go through the icon theme like every other island icon, and drag is one MouseArea per tile with a pure drop-slot helper, which is less code than DragHandler and DropArea and can be tested under node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 daysdocs(plan): controls panel implementation planDanilo M.1-0/+1063
Nine tasks: two spec corrections found while planning, the pure helpers with their node test, the preferences singleton, the tile, the panel, the island and IPC wiring, the SUPER release bind with its fallback, a visual pass with the user, and docs. The plan's test was run against the plan's Controls.js before committing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 daysdocs(spec): controls panel and preferences storeDanilo M.1-0/+147
Sub-project 2. A grid of seven toggles opened from the status pill and by a bare SUPER release, with an edit mode to reorder, hide and show tiles. The visible list lives in a JSON file under the state home, so a tile added to the code later starts hidden rather than appearing unasked. The drawer keeps the detail: right-click on a tile opens its page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07fix(island): the handle fades out while the pills are shownDanilo M.1-0/+3
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>
2026-10-07docs(agents): a branch switch can drop a component until restartDanilo M.1-0/+7
Seen merging the island: the shell reloaded while desktop/island/ did not exist, and stayed without it after the fast-forward restored the files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07docs: the island, and waybar goneDanilo M.8-106/+209
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>
2026-10-07chore: remove waybarDanilo M.4-84/+12
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>
2026-10-07feat(island): the flick's desktop icon sits in a badgeDanilo M.1-12/+33
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>
2026-10-07fix(island): neutral idle sliver, flag scroll via MouseAreaDanilo M.3-10/+18
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>
2026-10-07feat(island): the island window on DP-1Danilo M.3-1/+221
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>
2026-10-07fix(island): review findings in the pill componentsDanilo M.5-14/+26
- 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>
2026-10-07feat(island): status pill with volume, tray and layout flagDanilo M.1-0/+108
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>
2026-10-07feat(island): sound panel with output and input levelsDanilo M.1-0/+113
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07feat(island): clock pill with VM dots and flick contentDanilo M.1-0/+103
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07feat(island): the animated capsule both pills are made ofDanilo M.1-0/+51
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07feat(island): keyboard layout of the main keyboardDanilo M.3-0/+78
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>
2026-10-07feat(island): privacy detection for mic, camera, location, screenDanilo M.2-0/+96
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>
2026-10-07refactor: move the workspace icon map to a shared singletonDanilo M.4-21/+44
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>
2026-10-07fix(island): an unpopulated volume reads as muted, not highDanilo M.2-1/+6
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>
2026-10-07feat(island): pure logic for icons, dot colours and eventsDanilo M.2-0/+114
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>
2026-10-07docs(plan): island core implementation planDanilo M.2-6/+1471
Twelve tasks from pure logic to waybar removal. The spec is corrected on two points found while reading the code: Quickshell's PwNode has no running state, so mic and screen detection poll pw-dump like the waybar script did, and the VM dot rule now agrees with its own table on saved VMs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07docs(spec): island flag follows whichever keyboard is mainDanilo M.1-1/+4
The same keyboard appears as a different device over USB and over its dongle, so the main device is resolved per event, never cached. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07docs(agents): point at the Modesty reference cloneDanilo M.1-0/+9
The island work borrows Modesty's ideas. A local clone makes it reachable from later sessions, and the note carries the licence constraint with it: Modesty is GPLv3, this repo GPLv2-only, so it is read and never copied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07docs(spec): island core designDanilo M.1-0/+213
Sub-project 1 of the move toward a Modesty-style integrated desktop: a top-centre island on DP-1 hidden behind a sliver, a clock pill and a status pill that slide out of it, a sound panel, and the removal of waybar. Records the decisions taken while brainstorming: the island floats over windows with no exclusive zone, privacy capture recolours the sliver rather than revealing the pills, the clock pill flicks the desktop icon, app icon and app name on workspace change and app open but not on focus change, the volume icon has no gestures beyond opening its panel, and the flag images move into this repo. Modesty is GPLv3, so only its ideas are used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07fix(mail): recount unread when the notmuch database commitsDanilo M.2-0/+28
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>
2026-10-06feat(appearance): launch wallhaven-dl instead of the TinEye searchDanilo M.2-42/+14
The reverse image search never worked in practice: the clipboard-and-paste route to TinEye was the only one left after scripted uploads hit bot and consent walls, and it still left finding and replacing the file by hand. wallhaven-dl, a separate app, does both the search for a larger copy and general wallpaper search and download, so the button now launches it and the TinEye code is removed rather than hidden. The button is always shown, not only for a low-res staged image, since the app is useful beyond upscaling. It launches through gtk-launch and the app's desktop entry, which needs no ~/bin on quickshell's PATH and keeps the app's taskbar icon, and closes the panel so the window does not open under the overlay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06feat(appearance): find a larger version of a low-res wallpaperDanilo M.2-0/+47
When the image staged for the targeted screen gets a yellow or red quality note, a button under the mock screens copies it to the clipboard and opens TinEye in the browser, where Ctrl+V runs the reverse search and the matches can be sorted by size. It acts on the staged image, not the hovered one, because the pointer leaves the thumbnail to reach it. The image goes through the clipboard because a search engine takes no local file in a URL, and scripted uploads did not get through: TinEye answered 403 to curl and 405 with a browser user agent, and Google Lens redirected to its consent page, dropping the image. The paste in the browser is the upload, and only on the user's click. The copy is converted to PNG with magick. Copied as itself, a JPEG put only image/jpeg on the clipboard and Firefox pasted nothing into the page; it hands web content image/png. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06feat(appearance): wallpapers by folder, system ones, quality bordersDanilo M.3-64/+321
The wallpaper tab showed every image under ~/Pictures/wallpapers in one grid. It now groups them by top-level folder, each behind a header that opens and closes it, and adds the distribution's /usr/share/wallpapers: its loose images as "system", its Plasma packages as "Plasma". A package carries one picture at several resolutions under contents/images/, some with a dark version under contents/images_dark/, so it shows once, the dark version where there is one and the largest of those, labelled with the package name rather than "5120x2880.png". Groups are keyed apart from their names, so a local folder called "system" does not share open state with the system group. Open state lives in the Wallpapers singleton, because the panel is destroyed on close. The list is one flat ListView of rows, a header or a row of thumbnails, so only rows in view (plus cacheBuffer) are instantiated and decode. A first version made each folder one delegate, which loaded every image of a folder as soon as it opened; the system group alone is 727. The rows live in a ListModel and a toggle inserts or removes only that folder's rows: assigning a fresh JS array instead resets the view, which loses the scroll position and re-decodes everything visible. cacheBuffer is clamped at 0 because the column's width reads negative before layout and the ListView warns on each negative value. The scan's find calls go through a small shell function rather than eval. Each thumbnail's 2px border tells how it will look on the targeted screen. `file -N -0` reads every image's size from its header after each scan, ~0.6s for 1161; the NUL keeps names containing ": " intact, and the size is the last WxH in the description because a JPEG's "density 72x72" comes first. wallp runs swaybg -m fill, which scales to cover, so the measure is the enlargement factor: <=1 green, <=1.33 yellow, else red, in the udt palette colours. A note under the mock screens, in that colour, gives the size, the factor and why it will look soft or pixelated, for the hovered image or else the staged one. The staged image keeps its accent border. Screen sizes are fixed, as the mock's already were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06feat(notifications): window border on the balloonsDanilo M.2-5/+95
The balloons now wear the Hyprland window border: 2px, the udt gradient read from ~/.cache/udt/udt-border.lua (the file look_and_feel.lua reads, watched so a wallpaper change follows), rotating, with the windows' corners. A Rectangle border takes one colour and its radius is circular, while the windows use rounding 15 at rounding_power 4, a superellipse. So the body and the border are both drawn by a Shape from an SVG path whose corners are the cubic fit to |x|^4 + |y|^4 = 1, and the border is a ring filled odd-even, which keeps the translucent body from showing the gradient through. One angle drives every balloon, so they turn together, and the animation runs only while the stack is mapped. Hyprland's borderangle (speed 30) reads as 3s a turn, which looked slow on a balloon that size, so the turn is 1.5s, tuned by eye. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05docs(agents): llama-server /slots autoloads the modelDanilo M.1-0/+6
A slot query for an unloaded model loads it into VRAM, so any status probe against the router needs autoload=false. Found when a probe during the ai module's design reloaded Gemma. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05docs(ai): module README, drawer module listDanilo M.2-1/+53
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05feat(ai): drawer page for the local AI stackDanilo M.5-0/+336
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>
2026-10-05fix(ai): count a running sd-cli as the sd engineDanilo M.3-8/+37
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>
2026-10-05feat(ai): state sweep for the AI stackDanilo M.3-3/+245
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>
2026-10-05docs(ai): implementation plan for the AI moduleDanilo M.1-0/+836
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05docs(ai): design for the AI stack drawer moduleDanilo M.1-0/+94
Engines (llama.cpp, sd.cpp) read-only, apps get start/stop through their existing controls. Records that /slots?model= autoloads an unloaded model unless autoload=false is passed, found when a design probe reloaded one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03fix(status): watch for create, so a mode's first write is seenDanilo M.3-5/+29
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>
2026-10-03docs(status): ~/bin/statusctl is a symlink to the repo copyDanilo M.1-1/+1
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>
2026-10-03feat(status): present during a Teams callDanilo M.2-2/+6
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>
2026-09-29docs(agents): hot reload does not follow symlinksDanilo M.1-0/+7
An edit to shared/Notify.qml was never picked up by the running shells, while an edit in the same pass to a component's own file did reload, so the shell looked current and ran the old sanitize. Record that shared/ edits need a forced reload of each linking component. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29feat(notifications): render bodies as MarkdownDanilo M.3-3/+10
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>
2026-09-29fix(sound): swap background cover when the track changesDanilo M.1-4/+9
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>
2026-09-29feat(sound): crossfade album art, fade to plain without itDanilo M.2-59/+113
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>