Brings the Qt uploader to parity with the web /manage page and the Android
app. Adds a stacked Manage page (reached from the post page) that lists
posts via GET /api/photos with thumbnails from GET /api/thumb/<slug>, edits
caption/date/tags in a QDialog via POST /api/edit, and deletes to trash via
POST /api/delete with a QMessageBox confirm. As a non-browser client it sends
no Origin and so passes the server's same-origin CSRF check.
Tag autocomplete now backs every tags field (post cards and the edit dialog)
via a per-token TagCompleter (QCompleter subclass, MatchContains) fed from
the unguarded GET /api/tags.json.
New files: managepostwidget.{h,cpp}, tagcompleter.{h,cpp}; network methods
and a RemotePhoto struct added to uploadclient. Built and linked clean; not
yet runtime-tested on a real display.
Each photo card gains a free-text tags input, sent as a raw
comma-separated `tags` form field on upload. The server normalizes it
(parseTags), so the clients stay dumb — no tag parsing on-device.
- Android: PickedItem.tags + setTags; threaded through UploadQueue →
UploadWorker → UploadClient's multipart.
- Desktop: a tags QLineEdit per PhotoItemWidget; UploadClient.upload sends
it.
The CMake target stays 'uploader' but the output binary is now 'photog',
matching the package and app, so 'nix run' and the desktop entry resolve
it (nix run looked for bin/photog and failed on bin/uploader). Also set
meta.mainProgram.
Wayland is Linux-only and refuses to evaluate on darwin, so qtwayland is
now added only on Linux (macOS uses the Cocoa QPA plugin in qtbase). The
package, dev shell, and plugin search path all build from one platform-
guarded module list. Evaluates on aarch64-darwin; Linux is unchanged.
- Web: favicon.ico + png icons under static/, served from the site root
and linked from every page head.
- Android: the artwork becomes the launcher icon — the 432px adaptive
foreground over the gruvbox background, replacing the placeholder vector
drawables.
- Desktop: the icon is the Qt window/taskbar icon (embedded via app.qrc),
and the app is now an installable package — a wrapped binary, a
photog.desktop entry, and hicolor icons — so `nix profile install
./desktop` puts "Photog" in the application menu.
Mirror the Android bulk feature in the Qt uploader: choose several photos
at once, each a card with its own caption, date, and upload status, and
post the batch.
- Per-photo cards (PhotoItemWidget) in a scrollable list; retry re-posts
only the failures.
- One upload per photo with a per-item UUID slug suffix so a batch posted
in the same second cannot collide.
- Image prep runs off the UI thread via QtConcurrent so the window stays
responsive.
- A "Simultaneous uploads" setting (1–8, default 3) caps how many photos
are prepared/uploaded at once; the rest queue and fill freed slots.
A native Qt6/C++ desktop client for the gallery's POST /upload API, in
desktop/ with its own flake (kept separate from the Go server module the
same way android/ is). Single-photo parity with the Android app:
- multipart upload with preemptive HTTP Basic auth and retry-aware outcome
classification (uploadclient)
- JPEG/PNG metadata stripped byte-for-byte to drop embedded GPS, EXIF
orientation baked in, and a quality/scale valve for the 20M nginx cap;
HEIC decodes via the qtimageformats plugin (imageprep)
- base URL / username in QSettings, password in the system keychain via
qtkeychain; https required and a trailing /upload stripped (settings)
- settings and post screens in a QStackedWidget (mainwindow)
Native Wayland or xcb is selected at runtime. Bulk upload, EXIF
capture-date prefill, and moving image prep off the UI thread are left as
follow-ups.