aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)AuthorFilesLines
7 daysnotes: delete asks before it destroysDanilo M.3-18/+29
The confirm was on the second click, after the first had already removed the file and the entry, so the 'Confirm?' label promised a check that had already happened and one stray click lost the note. The first click now only arms the button; the second removes and pushes the removal.
7 daysnotes: write and commit failures are reported, not assumedDanilo M.6-73/+157
A review of the branch found four ways the page could report success for work that never happened, all reachable in ordinary use. Writes: setText is asynchronous unless blockWrites, and its saved()/saveFailed() do not fire for every write (a second setText to the same path loses the signal, which stranded the callback), so a save was reported before it landed and a failed db.json or body write was never seen. Both views now block and carry the outcome, so writeDb and writeBody know the result when they return; a failed create therefore leaves no index entry. The create path also loads the body before the index, so a failed body write cannot leave an entry with no text. Commits: the sync chain swallowed every commit failure with '|| true', so a failing pre-commit hook or a signing failure pushed an unchanged HEAD and reported success. It now stages, commits only when something is staged, and lets 'set -e' fail the chain, with stderr folded in for the whole chain rather than just the push. Duplicate notes: the 'awaiting commit' state lived only in a 3 second timer, so a slower second click re-entered create() and appended a second note. It is now a page property that outlives the timer, and the button follows it. Preview: the shared Switch writes checked itself, dropping the binding, so the switch stopped following page.preview; resynced on change, the way StatusRow.qml does. Also validates a note's file name as digits before read, write or rm, and clears the index error once the index reads again.
7 daysnotes: component READMEDanilo M.1-0/+53
7 daysnotes: in-drawer editor with commit-on-save and git pullDanilo M.5-82/+577
The editor, and the write and git path behind it. Save is two clicks and each does one thing: the first writes the note and only then arms the button as 'Commit & push?', so a quick second click cannot commit a note the first has not written yet. The write path refuses when db.json cannot be read as the index. That is not hypothetical: git pull --rebase --autostash resolves a remote db.json change against a local uncommitted one, the stash pop conflicts, git still exits 0, and the file is left full of merge markers. Reading that as 'no notes' and writing it back deleted every title in a probe; Notes.valid now distinguishes it from an empty store and the write reports instead. parse stays tolerant for display. Stamping lastpull also only follows a pull that worked, and only when git is on at all. Db reads that a write is based on go through reload() plus waitForJob(): blockLoading does not make reload() blocking, contrary to the note in AGENTS.md, and reading text() straight after reload() returns the old contents. A body is written with a plain setText, which needs no prior load; only reading text() before a load would.
7 daysnotes: drawer tile with count and the note listDanilo M.3-0/+245
The module resolves notes.sh's own paths by sourcing its rc, so a changed BASEDIR moves the page with it, and notes.sh's git test is the same one the page uses. A Module is a plain QtObject with no default property, so the config Process and the db.json FileView are typed properties, the shape UpdatesModule uses for its own Process. db.json is watched rather than read on open: the tile's count has to move when a note is added from either side, the CLI included, which is the same call mail makes for its unread count. The list reads db.json.notes rather than walking notes/, because that is where the titles are; entries sort newest first on the file timestamp and a title search filters them.
7 daysnotes: pure db.json helpers, node-testedDanilo M.2-0/+183
The parsing, sorting and transforms the notes page needs, kept free of any file or process so node can test them. Ids and files stay strings: notes.sh writes them with jq --arg and looks a note up with select(.id == $i), so a number would stop the CLI finding a note the page wrote. sorted() copies rather than reorders, and an entry whose file is missing or non-numeric sorts last and formats as blank instead of NaN.
7 daysdocs: notes drawer module spec and planDanilo M.2-0/+651
A drawer tile and page for bash-notes: browse, write, edit and delete notes in the page, sharing notes.sh's store so both tools work on the same notes. Git follows notes.sh's shape, pull before write, commit and push after, with two departures the page needs: an unconfirmed Save leaves db.json uncommitted (write and commit are two clicks here, one invocation there), so the pulls carry --autostash, and lastpull is stamped after the pull rather than before it, which notes.sh does and then ignores the failed pull that follows.
7 daysfix(assistant): lit tile opaque over the glowDanilo M.1-2/+4
The Do tile's hover and press fills were Qt.alpha colours, and the Glow sits beneath the tile (z: -1), so the translucent fill let it wash out the icon and the label. Qt.tint over Theme.surface keeps the fill opaque, so the glow reads as a glow around a solid tile rather than through it.
7 daysfix(assistant): review of the Do row and fileopsDanilo M.7-42/+180
The canvas: a To .md ended any other way than its own Stop (the footer Stop, a question, a drop, a daemon restart, an older daemon refusing the command) left the card at Working forever. The footer Stop goes through stopOp(), asking and dropping end the operation first, a disconnect ends it, and an error while nothing else runs is taken as its outcome. Each fileops run gets its own Process, so a stopped run's late answer is never read as the next one's. To .md takes one PDF, as one file is written. Compress... no longer flips back when file(1) refines a kind, long errors are elided, and a desktop with no documents folder gets Documents/Assistant rather than ~/Assistant. fileops: an animated GIF to PNG or JPEG left one file per frame under names the rename never found; the first frame is taken. JPEG flattens transparency onto white. Zipping a folder holding the output folder read its own growing archive without end; only regular files outside it are added, which also skips FIFOs and dangling links. qpdf warnings no longer fail a merge. A folder's free name keeps its dots, a lone .gz or .xz is decompressed rather than refused, and a dotfile's archive is not hidden. Tools die with fileops even when it is killed outright, a killed run's leftovers are swept on the next run, a stop between fork and bookkeeping cannot miss the child, and a late stop cannot add a second answer. Error lines lose bsdtar's doubled prefix and its delayed-exit noise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): Ask and Do as captioned tile grids with iconsDanilo M.3-66/+135
The actions sat as buttons bunched at the left of the card. Each group is now a grid of equal tiles across the card's width, icon over label, about 150 px a column, with a small Ask or Do caption. Icons are Font Awesome and Octicons codepoints checked in Inconsolata Nerd Font's cmap; a saved preset without one gets a fallback. The lists referenced from QML are var, since a library's top-level const is not reliably exposed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): the Do row of file operationsDanilo M.5-6/+273
Conversions, extraction, merge and compression on the staged files from the file state, one at a time, with Stop; Compress… opens its formats. To .md goes through the daemon's write, the rest through fileops. The card keeps the result line, Saved name with Open and Folder, or the error, so another operation can follow on the same files. Results land in Documents/Assistant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): fileops, the Do row's local operationsDanilo M.3-2/+368
One CLI for converting, extracting, merging and compressing staged files, answering with one JSON line. Results are written under a temporary name and renamed to the first free one, so a failure or a stop leaves nothing half written, and a stop kills the tool's whole process group. This ffmpeg has no libx264 and no AAC encoder, so MP4 is H.264 through VAAPI with MP3 audio, and audio extraction copies AAC, MP3 and Opus tracks as they are. The test builds its inputs and checks every result's type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs: spec the Do row of file operationsDanilo M.1-0/+86
Local conversions, extraction, merge and compression through a small fileops CLI, results in Documents/Assistant, and To .md through the daemon's new write command. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): tell a nameless file's kind from its contentDanilo M.4-7/+67
A script with no suffix staged as 'other' and was refused. A staged file the name says nothing about is now handed to file(1) once, and its mime type gives the kind, so a shell script is code and gets Explain and Review. The daemon makes its own call on the content. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): Ask presets in the file stateDanilo M.8-13/+171
A row of canned questions matching every staged file's kind, plus Compare for two or more files: one click asks it, Shift+click puts it in the input to edit first. Defaults live in Presets.js and the list in use in Prefs, so a future drawer settings page can edit it; a saved list that does not validate reads as the defaults. Each prompt asks for an answer in the document's language. Code and configuration get their own kind, so a script is offered Explain and Review rather than Summarize. Button's clicked signal carries the mouse event for the Shift check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs: spec the Ask presetsDanilo M.1-0/+73
Canned questions per staged kind in the file state, stored in Prefs with built-in defaults so a future settings page can edit them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs: the entry line and file drop are implementedDanilo M.1-1/+1
Checked by hand: resume rule, island drop and its refusal message, the file state, Chat about it, the picker, and the Escape order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(island): say why a drop is refusedDanilo M.2-6/+24
A drop offering no local file:// URL was refused silently: the bubble vanished and nothing happened. Measured on the first report: the file manager offers a trashed file as trash:, with no path to read. The bubble now shows the reason for a moment, Trash named as such, and the refusal is logged with the URL schemes and offered formats (never the paths). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(assistant): keep state across reloads, refusals and long repliesDanilo M.6-14/+41
From review. A shell reload reconnected with lastActive at 0, so the next SUPER+Home started a new conversation thirty seconds into one; hello with turns now counts as activity. show() could send new under a reply still running, which stops it unsaved; it waits while busy. ask() cleared the chips before the daemon accepted them, so a refused file (unreadable, too big, a model without vision) dropped them and collapsed the card to the entry line; the user event clears them now, and chatting holds the layout while a PDF is read. In the picker, folders ignore name filters and sorted first, so filter then Enter opened a folder; folders hide while filtering. Folder URLs are encoded, so a '#' in a name no longer cuts the path, and glob characters typed in the filter are taken literally. The card says the assistant is not running in every state, panels sit under the chat header instead of over it, and History and the picker no longer open together. Dropped file://localhost/ URLs are accepted, other hosts refused, and the island receptor keeps the sliver's width at rest so it takes no clicks beside it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(island): take a file drop for the assistantDanilo M.3-0/+64
A DropArea over the sliver grows into a bubble while a file drag is over it and hands file:// paths to the canvas. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): entry line, file state, staged files and a pickerDanilo M.6-29/+415
The card has three states: an entry line, a file state for staged files with Chat about it, and the chat. SUPER+Home resumes a conversation active in the last 10 minutes and otherwise starts a new one. The paperclip opens a picker drawn in the card, since a system dialog would open beneath the overlay that holds the keyboard. Button gains a font alias for the paperclip glyph, and the canvas a socketPath property so a check can point it at a scratch daemon. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): file kinds and dropped URLsDanilo M.2-0/+95
Files.js decides what the card offers for a staged file; the daemon decides what chat accepts, so the text and image lists match its own. Dropped URLs become paths only for file:// ones. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
7 daysdocs: plan the entry line, file state, picker and island dropDanilo M.1-0/+1345
Four tasks: file kinds, the three card states with staging and the in-card picker, the island receptacle, and the handover. The card files ran in a scratch harness against the attachment daemon first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs: attach files from the chat through an in-card pickerDanilo M.1-1/+27
A system file dialog would open under the overlay that holds the keyboard, so the picker is drawn in the card, over the transcript, from Qt.labs.folderlistmodel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs: spec the entry line and file drop on the islandDanilo M.1-0/+92
Three card states: an entry line, a file state offering what to do with dropped files, and the chat. A drop always starts a new task, and asking about a file is one of the choices rather than the only one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs: the assistant canvas is implementedDanilo M.1-1/+1
All nine visual checks passed by hand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 dayschore(assistant): retire the voice overlayDanilo M.9-358/+8
desktop-assistant is a text daemon now (its voice version is the tag voice-v1), and the canvas in desktop/assistant/ is its front end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(assistant): keep focus in the card, scope errors, guard linksDanilo M.7-15/+55
From review of the canvas. Escape stopped working in three ways, each leaving the keyboard grabbed with nothing to receive it: the history field hiding took focus with it, a disabled input could not hold focus while the daemon was down, and a click in a streaming reply focused text the next flush destroyed. The card now gives focus back to the input whenever it falls out, and the input is read-only rather than disabled. Only an error the daemon marks as ending the reply (turn) closes the live row; a command error, possibly another client's, used to freeze the reply mid-stream. The running tool comes from state events, hello included. Scrolling up during a stream no longer snaps back, since following stops when a movement starts. History snippets go through Notify.sanitize like any model output, links open only for http, https and mailto, and a line opening with inline triple-backtick code is no longer taken as a fence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(desktop): host the assistant canvasDanilo M.1-0/+11
Inside the desktop process rather than its own shell: it needs no keepalive window of its own and restarts with the rest of the desktop. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): the canvas, a view over the assistant daemonDanilo M.6-0/+783
The socket, the turn model and the window live in Assistant.qml, outside the window's loader, so closing the card loses nothing and a reply keeps streaming while it is closed. Tokens reach the model on a 50 ms tick rather than per token. Prose goes through Notify.sanitize, because model output can quote a search result and a remote image in it would be fetched on render. Code blocks get a copy button once their fence closes. The history panel lists conversations and searches them through the daemon's full-text index. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
7 daysfeat(assistant): split messages into prose and fenced codeDanilo M.2-0/+104
Qt's markdown renders a fence but gives no per-block hook, so a copy button per code block needs the fences found first. An unclosed fence is open code, which is every fence while a reply streams; a fence inside a list item keeps its indent out of the copied text. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
7 daysdocs: plan the assistant canvasDanilo M.1-0/+1279
Five tasks: the markdown splitter, the canvas components, hosting them in the desktop shell, the switch-over (voice overlay out, hypr-theme bind, autostart and blur), and the user's visual check. Every file was run in a scratch harness against the real daemon before planning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs: spec the assistant canvasDanilo M.1-0/+108
A Luma-style overlay on SUPER+Home, inside the desktop process, as a pure view over desktop-assistant's socket. It replaces the voice overlay in assistant/ and stands in for llamachat while it is tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(island): a media pill left of the clockDanilo M.3-2/+183
Shows album art and a scrolling "artist · album · title" while a player is playing or paused, using the sound module's Player so the browser proxy duplicates are already filtered. Hovering swaps the text for a progress bar, swapped in place rather than growing the pill; MPRIS does not push position, so it is re-read every second while hovered, and a click seeks only when the player reports canSeek and a known length. The wheel steps tracks one per notch, as the layout flag does, so a touchpad does not skip several. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(git): add keys per section with a + beside each headingDanilo M.2-102/+131
The single Add line at the bottom took a full section.key and left the user to type the section right. Each heading now carries a + that opens a key and value row under it; git config --add writes the key into that existing section, among its neighbours, rather than at the end of the file. The typed text lives on the page, not in the fields, so a failed add keeps it across the reload that rebuilds every row. A new section is made in the editor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfix(git): refuse duplicate values, show list errors, Escape on AddDanilo M.4-9/+71
Review findings. With a key holding the same value twice, --fixed-value --replace-all rewrote both and merged two rows into one, and --unset failed on both; gitcfg now counts the matches and refuses anything but exactly one, pointing at the editor. A file git cannot parse made list print nothing, which the page drew as an empty config; list now prints git's error as an error= line and the page shows it. Escape in the Add fields clears the typed text before it leaves the page, as a row's edit is undone first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysdocs(git): the git config page, and replace-all appending on no matchDanilo M.5-2/+33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7 daysfeat(user): open the git config page from the Git sectionDanilo M.2-1/+11
A "More git settings" button under the Git fields. The page emits moreGit and the module turns it into Page.go("git"), since the page itself has no reach into the drawer. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysfeat(git): the global git config pageDanilo M.3-0/+289
Every global value as a row under its section, in file order: Enter saves, Escape undoes, Remove drops that one value, and an Add row takes section.key and a value. Each write goes through gitcfg and is followed by a fresh list, so a row shows what git holds; a failure shows git's reason under its row. "Edit in editor" opens ~/.gitconfig in Sublime Text. No tile: up is "user", so back returns to the user page it opens from. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7 daysfeat(desktop): pages can open other pages and step back to themDanilo M.3-7/+16
Page gains go(name), wired to the drawer's show(). Module gains up, the page back() returns to, empty for the grid as before. The back arrow now calls back() instead of clearing the page itself, so the arrow, Escape and the mouse's back button agree. For the git page, opened from the user page. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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>