Skip to content

Live pty output, 11 themes, bug fixes, and desktop entry - #1

Merged
padovanl merged 4 commits into
mainfrom
develop
Aug 14, 2026
Merged

Live pty output, 11 themes, bug fixes, and desktop entry#1
padovanl merged 4 commits into
mainfrom
develop

Conversation

@padovanl

Copy link
Copy Markdown
Owner

Summary

  • Install/remove/upgrade now run in an embedded pty (live output box) instead of taking over the terminal
  • 11 built-in color themes, browsable live with ←/β†’ in settings
  • Fixes: selected-row status bullet losing its color, held marker missing in the Upgradable view, crash on mouse click below the list/on an empty list, header scrolling off screen when entering search via "/"
  • App icon + .desktop entry, wired into both the .deb and .snap
  • README: friendlier formatting, wider demo GIFs (apt + snap), documented 256-color terminal requirement

…radable

Selected rows were rendered as one flat badge-text-on-highlight span, so
the status bullet (green/yellow/red/muted) lost its color and blended
into the row the moment it was selected β€” the only place that signal
mattered least, since it's the one thing that lets you tell installed
from upgradable from security-update at a glance down the list. The
bullet now keeps its own foreground color (with the row's background
still applied to it) while the rest of the row stays uniform, without
reintroducing the original problem this design was avoiding: mixing
segments that each carry their own ANSI reset with an outer Style.Width()
wrap, which only paints background up to the first reset and leaves the
rest of the row un-highlighted. Padding to fill the row width is now done
on plain text before styling, sidestepping that entirely.

Separately: the Upgradable view never showed the held (β—†) marker, even
for a package that's both upgradable and held, because
parseUpgradableOutput built packages straight from "apt list --upgradable"
output, which says nothing about hold state. It now cross-references
dpkg's own selection state (already fetched for the Installed view) the
same way ListInstalled does.
A left-click's row was computed from the click's Y position and handed
straight to list.Select() without checking it was actually a valid item
index. bubbles/list doesn't validate that itself, so an out-of-range
cursor later panicked inside its own render (a slice-bounds crash in
list.Model.populatedView) β€” reproducible with a single click anywhere
on an empty list (search with no results, an empty view), or a few
clicks below the last row of a short one, matching exactly what was
reported live: 'basta cliccare sulle voci in fondo, bastano 3 click, su
una pagina vuota anche meno.'

Fix is a bounds check before calling Select; added a regression test
covering both the empty-list and short-list-click-past-the-end cases.
A plain TERM=xterm (no -256color suffix, and no COLORTERM) gets detected
as a 16-color terminal, which downsamples every theme's 256-color codes
to the nearest basic ANSI color β€” several can end up looking similar or
low-contrast. Reported live from a minimal Docker/SSH session; not a
pkgtui bug (forcing a wider palette on a terminal that actually can't
show it would just produce different garbage), but worth documenting
since it's an easy trap to fall into outside a real desktop terminal.
pkgtui now installs a .desktop launcher (opening in a terminal, since
it's a TUI) and an icon, so it shows up in a desktop environment's app
menu after installing the .deb or .snap; a headless/server install just
never looks at either file, no detection logic needed on our end.

- assets/icon.svg: a small isometric-box mark (256x256, scales cleanly
  down to launcher sizes), used as-is for the hicolor icon theme.
- assets/pkgtui.desktop: the launcher entry, passes desktop-file-validate.
- .goreleaser.yaml: installs both into the .deb via nfpm's contents list
  (/usr/share/applications, /usr/share/icons/hicolor/scalable/apps), plus
  a postinstall/postremove pair (scripts/deb/) that refreshes the desktop
  and icon caches so the launcher entry appears without a re-login.
- snap/snapcraft.yaml: adds the top-level icon field and the app's
  desktop field. The go plugin only installs the built binary, so an
  override-build step copies the .desktop file into the part's install
  directory β€” snapcraft's desktop-file generation reads it from there,
  not from the source tree, and errors out otherwise.

Verified for real, not just by reading the config: built both packages
locally (goreleaser snapshot + snapcraft pack --destructive-mode),
installed each, and confirmed the launcher entry and icon land exactly
where the desktop/snapd tooling expects β€” /usr/share/applications +
hicolor for the deb, meta/gui + snapd's own desktop registration for the
snap β€” then removed both test installs and all build artifacts.
@padovanl padovanl self-assigned this Aug 14, 2026
@padovanl
padovanl merged commit d764543 into main Aug 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant