aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)AuthorFilesLines
7 daysfeat(git): parse git config -z --list for the pageDanilo M.2-0/+63
NUL between entries and the first newline between name and value, so values holding = or newlines survive. The key is after the last dot, so color.branch.remote groups under color.branch. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysfeat(git): gitcfg, global git config through git itselfDanilo M.2-0/+133
list, set, add and unset over git config --global. --fixed-value lets a write touch one value of a multi-valued key. set and unset check the old value is still there first: --replace-all with no match appends and exits 0, and the file may have changed in an editor since the page read it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysdocs(git): implementation plan for the git config pageDanilo M.1-0/+941
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs(git): design for the global git config pageDanilo M.1-0/+83
A drawer page, reached from the user page, listing every global git key and editing, adding and removing values through git config itself, so the file keeps its comments and quoting. --fixed-value lets each write target one value of a multi-valued key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(user): a random greeting on each drawer openDanilo M.4-4/+45
The greeting row picks one at random from ~/.config/quickshell/greetings, one per line with {user} for the login name, # comments and blank lines skipped; without the file, five built-in ones. The row is rebuilt on every drawer open, so the file is read then with no watch, and the last pick is kept in User.js, a shared .pragma library, so the same greeting never shows twice running. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs(user): location suggestions and the Git section in the READMEDanilo M.1-0/+6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(user): keyboard for the location suggestionsDanilo M.1-6/+29
Up and Down move through the list, wrapping, and light the row as hover does; Enter takes it; Escape closes the list. With no list open the keys pass on, so Escape still leaves the page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(user): location suggestions from OpenStreetMapDanilo M.3-4/+110
There is no place database on this machine, and the user chose Nominatim over a tz city list for coverage. It is asked 1s after typing stops (its policy: one request a second, an identifying User-Agent, nothing personal sent), from three characters, in the desktop's language, and a reply to an older query is dropped. places() turns its JSON into 'place, region, country' labels and treats an error page as no suggestions; test_user.js covers it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(user): a Git section with the values git will carryDanilo M.1-16/+35
The one-line preview became a section: the git name and email as read-only fields that follow the Name and Email edits as they are typed, and the signing key, which is git's too, moved under them. A derived field is computed from the draft and never saved on its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(shared): one faded glow for hovers across the shellsDanilo M.9-27/+101
Hover and attention effects were solid: a flat accent ring round the user page's avatar, a flat quarter-disc in the hot corner, and thick accent or white borders on window cards, keycaps and knobs. Glow.qml is a RectangularShadow in the accent, fading out from the shape's edge and in over 140ms, linked into desktop, window-switcher and keybinds like Theme.qml, and all five places use it. Selection borders in the appearance tabs stay: they mark state, not hover. The avatar also gains the hover cue in the first place: the hand cursor never showed under a hyprcursor-only theme, so without it the picture gave no sign it could be clicked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysstyle(user): a larger avatar and dropdowns in the themeDanilo M.1-5/+22
The avatar had room to spare at 96px; 160 fills the page better. The two ComboBoxes rendered in the default style's light colours on a dark page; a palette takes the theme into the control and its popup, and the background matches the text fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysstyle(user): the greeting is a header, not a cardDanilo M.1-3/+3
With a surface and a border it read as one more notification in the list under it. Only a faint hover tint remains. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(user): the avatar is ~/.user-icon.jpg, as hyprlock and SDDM useDanilo M.3-7/+32
The page showed AccountsService's icon, an older picture than the one the rest of the desktop uses: hyprlock, the udt SDDM theme (pointed at it by udt-accent) and the rofi power menu all read ~/.user-icon.jpg. get now prefers that file, and set converts the pick to JPEG there, through a temp file and a rename, before handing it to AccountsService so both agree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(user): the page retries partial saves and survives leaving mid-saveDanilo M.3-7/+15
A key whose write half-failed (AccountsService took it, git did not) reloads as unchanged and Save went dead. A key with an error now counts as changed, and editing a field clears its error. Processes were parented to the page, so leaving it mid-save killed userctl between stores. They hang off the module now, passed in as owner (not the module's id, which would bind to itself). busy now clears when the reload lands, so Save cannot be clicked again before saved is fresh, and the fields and avatar picker are disabled while busy. Avatar paths with # or % broke the preview under a bare file:// prefix; each segment is now URI-encoded for the Image source (page and row), while draft.avatar stays a plain path for userctl. Dropped a redundant saved clear in load. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysdocs(user): the module's README and the busctl escaping noteDanilo M.3-2/+37
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(user): a drawer page for the user's detailsDanilo M.3-0/+287
Name, email, avatar, language, location and the git signing key, each saved through userctl to every store that holds it. Only changed fields are sent; a field whose write failed keeps its edit and its error, so the next Save retries it. A failed userctl get reports a single error= line. The page shows it in red under the avatar, leaves saved and draft untouched, and disables Save until a later load succeeds. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysstyle(desktop): the notification comment back on its listDanilo M.1-3/+3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(desktop): a greeting row above the notificationsDanilo M.3-2/+115
Avatar, Hello <login> and the real name, re-read whenever the grid view shows again so an edit is visible on the way back from the page. Module gains tiled, so a module can own a page without a tile. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysfeat(user): helpers for the user pageDanilo M.2-0/+93
Parsing userctl's output and locale -a, and the git name preview, kept out of QML so node can test them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysfix(user): userctl survives leading dashes and reports failed readsDanilo M.2-15/+37
busctl and kwriteconfig6 parse a value starting with '-' as an option, so a location like '-x' failed; '--' before the value ends option parsing (checked against both binaries). get ran without pipefail, so a failing busctl gave empty fields and exit 0, which the page would show as a blank form. It now reads all fields first and, on failure, prints one error= line and exits 1. keys listed revoked, expired or invalid primaries, keys that cannot sign, and could label a key with a revoked uid. It now skips those. Unsetting the signing key uses --unset-all, since git exits 5 on a multi-valued key with --unset. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysfeat(user): userctl reads and writes the user's detailsDanilo M.2-0/+258
One writer for the stores other programs read: AccountsService (and with it the passwd GECOS LibreOffice prefills from), KDE's emaildefaults and the global git config, where the surname goes in as an initial. busctl is asked for JSON because its plain output escapes non-ASCII as octal. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysfeat(perf): the performance page moves to the drawer, with ~/.cacheDanilo M.11-156/+175
The island's performance icon and panel are gone: the drawer page covers them. With only one host left, the panel drops its three-column grid for one card per row at a larger size, since the page scrolls; temperatures get a card of their own as tiles. The files move from island/perf to modules/perf. A cache card ports conky's: ~/.cache and its five largest children, measured with du each time the page opens (28ms over 2 GiB here) rather than read from conky's 15-minute sampler file. The largest is yellow, red past half the total, as conky had it. The warning dot now shows only on the drawer tile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs(plan): user details implementation planDanilo M.1-0/+1054
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs(spec): user details picks the git signing keyDanilo M.1-7/+13
The git sync was meant to include user.signingkey and the spec had dropped it, claiming nothing reads a GPG key. git does. The page offers the secret keys gpg holds, plus None, and writes the fingerprint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs(spec): user details leaves the password outDanilo M.1-0/+4
passwd in a terminal already does it, AccountsService's SetPassword needs admin rights and a hash, and a change desyncs the login keyring. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs(spec): user details in the drawerDanilo M.5-0/+97
A drawer row greets the login user and opens a page that edits name, email, avatar, language and location, written where other programs already read them: AccountsService (and through it the passwd GECOS LibreOffice reads), KDE's emaildefaults and the global git config, with the surname shortened to an initial for git. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysdocs: PwNode.isSink reads true for a playback streamDanilo M.1-0/+4
Recorded because the inverted filter looked correct, linted clean and returned an empty list with no error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(sound): per-app volume on the drawer page, output to 150%Danilo M.3-84/+157
The island spec put per-app volume on the drawer page, and it was never built. Each application playing audio now gets a row with its name, what it is playing (two browser tabs are otherwise identical rows), a click-to-mute level and its own slider. Streams are matched on PwNodeType.AudioOutStream. Quickshell reports isSink true for a playback stream, so the obvious isStream && !isSink filter found nothing while Firefox played. Their properties are empty until bound, so the page carries a PwObjectTracker for them, which stops with the drawer. speech-dispatcher-dummy is always present and never audible, and is hidden. The output slider runs to 150%, the ceiling the volume keybind already uses (wpctl -l 1.5), with a tick at 100%. Input and apps stop at 100%: a boosted microphone only clips. The meter became an inline component shared by both, and wheel-up never lowers a level already past its maximum. Now playing is dropped from the page: the OSD already carries it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(desktop): the mouse back button steps out of the drawerDanilo M.2-5/+25
The side button (BTN_SIDE, Qt.BackButton) does what Escape does: closes the history, then leaves a page for the tiles, then closes the drawer. Both go through one back(). The first attempt let the press fall through to the full-surface click catcher under the panel, since nothing above it accepts that button; it never arrived while a page was open. A MouseArea on top with z: 1, taking only the back button, works, and left clicks still pass through it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(updates): a page that reads at a glanceDanilo M.1-30/+106
The first cut was small type in one long list: 471 Slackware upgrades pushed everything below them out of sight, and the repo tag, the versions and the name ran together across the row. Type is 2px larger and rows taller. A section over ten rows starts folded behind a clickable heading with its count. The version being moved to is bright, the one being left dim, both in Inconsolata so digits line up. Every other row is shaded to carry the eye across, and the repo is a pill in one colour per repo, never red, green, yellow or the accent, which mean something elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysdocs(updates): the module's READMEDanilo M.2-1/+33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(updates): the drawer tile and pageDanilo M.3-0/+230
The tile counts what can be installed now (Slackware and the binary repo) and what only needs a build, and goes accent when there is something to install. It runs updatesctl while the drawer is open and not otherwise; a result over 30 minutes old is followed by a refresh that runs nvchecker, never after a refresh, so a failing nvchecker cannot loop. The page has one section per next action: Slackware upgrades, new and removed first, then upgrade here, awaiting build, upstream newer, app updates, the order the work is done in. Each row names the package, the repo it comes from and the one version jump its action covers. A source that could not be read says so under the section it empties instead of reading as nothing pending. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfix(updates): review findings in updatesctlDanilo M.3-14/+29
A git hash starting with a letter (3.1-a59215d) ordered behind its base, because any trailing alphabetic chunk counted as a pre-release; only alpha, beta, rc, pre and dev do now. Trailing zeros (1.14 against 1.14.0) compare equal instead of reading as an upstream bump. A bad line in the slackpkg blacklist is skipped rather than crashing the script and leaving the drawer with nothing. An AppImage keeps its key over a flatpak of the same name, as the spec orders them, and flatpak list has a timeout. A Slackware upgrade compares version and build, so an arch change alone is not a row. The spec's prose now matches the code: the upstream comparison includes the installed version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfix(updates): drop a redundant clause, test the mirror blacklistDanilo M.2-2/+3
The awaiting-build branch also required the build to be older than upstream, which cannot fail there: a build newer than installed was already taken as an upgrade, so the build is at most the installed version, which is behind upstream whenever a row is emitted. Removing it left every test passing, which is how it was found. The blacklisted testing/ entry sat after the main one in the fixture, so setdefault kept the main one and the mirror-side blacklist was never exercised; it now comes first, and dropping the check fails the test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daystest(updates): a hung NFS read reports unreachableDanilo M.1-0/+12
A fifo with no writer blocks cat at open() the way a hard NFS mount blocks during a NAS outage. The repo section reports unreachable within the timeout and the mirror sections still fill. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
8 daysfeat(updates): Slackware upgrades, new and removed packagesDanilo M.2-1/+92
Compared mirror against installed, as upgrade-all does, not against slackpkg's local ChangeLog: `slackpkg update` replaces that without installing anything, so a diff against it reads clean after an update that was never applied. New and removed come from the mirror's ChangeLog, the newest Added or Removed line deciding, so a package added and later upgraded still counts as new. Blacklisted build tags and directories are skipped, as slackpkg skips them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
8 daysfeat(updates): sort tracked packages into the next actionDanilo M.2-1/+351
Each nvchecker stanza lands in one section: upgrade here when the binary repo's PACKAGES.TXT holds a newer build than installed, awaiting build when the recipe (the user's or SBo's) has caught up but the build has not, upstream newer when the recipe lags, app updates for AppImages and flatpaks. Built comes from PACKAGES.TXT rather than the .info, which is why gamescope and kitty no longer read as installable: the repo still held the old build. The repo is on a hard NFS mount, so it is read by a child the timeout can kill. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
8 daysfeat(updates): version order for updatesctlDanilo M.2-0/+117
nvtable compares versions for equality, which cannot tell an installed 2.1.278 from an SBo recipe of 2.1.267 that is older than it. vercmp orders numeric chunks as numbers and treats a trailing alphabetic chunk as a pre-release, so a kernel suffix or git hash orders as newer than its base and never reads as behind. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
8 daysdocs(plan): the updates module, and two spec correctionsDanilo M.2-12/+1213
Drafting the code found two holes in the spec. Awaiting build was limited to the user's own recipes, so an SBo package whose recipe had caught up but was not yet built (nessus) showed in no section; it now covers any recipe. And "the newest ChangeLog line decides" would never call a package new once it had been upgraded after being added; only Added and Removed lines count now. The prefix rule for kernel suffixes is dropped as redundant: version order already ranks a suffixed version newer, which is never behind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysdocs(spec): an updates module that names the next stepDanilo M.1-0/+149
The conky updates card copies nvtable's table, where installed-behind and repo-behind share a row and are told apart by colour, and it measured "shipped" as the .info version: gamescope and kitty read as ready to install while the binary repo still held the old build. The drawer module sorts each tracked package into one action, from PACKAGES.TXT of the binary repo rather than the recipe: upgrade here, awaiting build, upstream newer, app updates. Slackware is compared mirror against installed, not against slackpkg's local ChangeLog, which `slackpkg update` replaces without installing anything; new and removed packages come from the mirror's ChangeLog. NFS reads go through a timed-out child because the mount is hard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(desktop): performance and clipboard pages, a scrolling tile gridDanilo M.13-31/+492
The tile grid sits in a Flickable capped at three rows, so the fourth row the new modules bring scrolls inside that box instead of eating the notification space; a thin accent bar in the margin shows only when a row is hidden. Tiles are reordered with the everyday ones first. Performance shows the island's PerfPanel in a Page, with a tile line of CPU and RAM and the warning dot. Perf.detailed is now a count of live PerfPanel instances instead of a binding in the status pill: the island and the drawer both host the panel, and a bool with two writers would let one clear it under the other. Clipboard reads cliphist when its page opens: search, copy on click or Enter, delete per row, clear all behind a 3 second confirm, image entries as thumbnails decoded once onto tmpfs. Entries reach sh as $1, never inside a command string. A copy closes the drawer through a new Page.dismiss signal the drawer connects like back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(status): quiet mode mutes the Claude and opencode soundsDanilo M.7-10/+169
A new registry mode, status.quiet, with a row on the status page. Both tools will play their sounds through notify-sound, which asks statusctl and plays nothing while quiet is on, so their popups stay and only the sound goes. Presentation sets quiet and restores it afterwards, like dnd and nolock: a sound during a call or a game is what quiet is for. notify-sound ignores any argument it has no sound for, because the opencode notifier runs its command on every event, session_started and user_message included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysrefactor(island): the controls panel goesDanilo M.10-624/+21
Each of its seven tiles opened a drawer page that already existed, and it went unused. SUPER alone will open the drawer instead. Removed with it: the status pill's controls icon, Island.toggleControls, the island IPC target, Controls.js and its test, and the controls list in Prefs. Prefs now holds only the pinned IP; a controls key left in desktop.json is still kept on write, because writes merge into the parsed document. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysdocs(spec): the drawer as the control centerDanilo M.1-0/+129
The drawer keeps its look and takes over: the island's controls panel goes, since each of its tiles opened a drawer page that already existed, and SUPER alone opens the drawer instead. The tile grid scrolls inside a three-row box so new tiles do not eat the notification space. New: a performance page reusing the island's Perf service, a cliphist clipboard page replacing the rofi list, and a quiet mode in the status registry that mutes Claude and opencode sounds through one notify-sound script while their popups stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysdocs: the expose and its hot cornerDanilo M.2-38/+83
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(window-switcher): the expose replaces the grid, with a hot cornerDanilo M.4-134/+202
Previews are placed at their Expose.js rects and sized to them, so each keeps its window's shape and relative size. Title and close show on hover only, so the scatter stays clean; icon and workspace marker always show. The keyboard selection is gone: this is a pointer feature, and Escape is the one key left. The top-right corner of DP-1 opens it after a 250ms glow that grows out of the corner, which is the warning and the way out. Input is only the corner's 2x2 pixels, since a larger input region would eat clicks on the windows below. It re-arms only when the pointer leaves while the expose is closed, or an Escape with the pointer still in the corner reopens it. It hides while status.gaming is set, read straight from the file: linking shared/Status.qml would start a second game poll and fire presentation side effects twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(window-switcher): gravity pulls the scatter toward the centreDanilo M.2-22/+42
On screen the spiral alone read as loose: separation keeps the spiral's gaps, and the previews filled 24 to 30% of the screen. Thirty rounds now pull every window 15% closer to the centre and push them apart again, which fills 35 to 55% and makes each preview up to 1.5x larger. Twenty windows lay out in about 4ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysfeat(window-switcher): the expose scatter layoutDanilo M.3-16/+157
layout() seeds windows on a golden-angle spiral, most recent at the centre, pushes overlapping pairs apart along the axis that costs less screen, and fits the result with one scale so sizes stay relative. The spec's first seed, the windows' real positions, was prototyped and dropped: every window on this desk fills its monitor, so they started in one pile, and pushing a pile apart made a line that still overlapped after 300 passes and filled 8 to 15% of the screen. The spiral converged in 1 to 55 passes. Comparing overlaps in raw pixels stacked wide windows into a column, which is why the axis choice divides by the screen's width and height. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 daysdocs(spec): expose on ALT+TAB and a hot cornerDanilo M.1-0/+132
The window-switcher grid becomes a Mission Control scatter: previews keep their real shape and relative size, seeded from their real positions and pushed apart, then fitted with one scale. A top-right hot corner on DP-1 opens it after a 250ms glow that warns before it fires, and stays inert while gaming. shared/Status.qml is not linked into window-switcher because a second instance would run its own game poll and react to presentation twice; the corner reads status.gaming directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 daysdocs: the performance panelDanilo M.2-2/+48
What the panel shows, the dot's thresholds and their lack of hysteresis, why the public IP is pinned, and what is sampled always versus only while open. AGENTS.md gains two gotchas found building it: FileView reads /proc on reload(), and a hot reload does not resize an existing layer surface, which left the panel cut off after the height was raised. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>