Broaden avatar/image support:
- Add libwebp (FetchContent, static, decode-only) so WebP loads. Built from
source for Linux / mingw-Windows / macOS-osxcross identically — the cross
sysroots have no webp, so vendoring from source is the one portable path;
encode/tool builds are disabled to avoid pulling in libpng/zlib. Linked as
webp + webpdemux (the latter for animated WebP, wired next).
- texture_loader routes all decode through DecodeImageRGBA: sniffs the RIFF/
WEBP header and uses libwebp (WebPDecodeRGBAInto into a free()-able buffer),
else stb — so every existing caller (avatars, QR, thumbnails) gains WebP for
free with no allocator mismatch.
- Enable stb's TGA / PSD / PNM / PIC decoders and add .webp/.tga/.psd/.pnm/
.ppm/.pgm/.pic to the image-picker + avatar-library extension lists.
Verified: libwebp builds static and a real .webp decodes to correct RGBA.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix the thumbnail grid to a constant 6 columns whose square cells scale to the
available width, instead of fixed 96px cells that left dead space on the right.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Smooth (lerped) wheel scrolling via ApplySmoothScroll on the list, matching
the app's other modal lists.
- The list is now a bordered/rounded outer frame whose 6px padding insets the
scrollbar so it clears the card's rounded corners; the inner scroll child is
transparent (the frame draws the single background — no more box-in-a-box
from the ChildBg being left on the stack across both BeginChild calls).
- Folders render as a 2-column grid of thin rounded rectangles (folder icon +
name) instead of full-width rows, so more folders are visible at a glance.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Wrap the picker body in a padded inner child so the filled directory list and
thumbnail grid keep a clear margin from the card's rounded corners instead of
running edge-to-edge past them.
- Center the Use image / Cancel buttons and drop the stray separator line above
them (the faint artifact at the footer's left edge).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebuild the add/edit contact dialog on the portfolio-editor design language:
- A live preview card at the top shows the contact exactly as it renders in the
list (avatar + name + address), updating as you type and pick an avatar.
- An avatar picker (Badge / Icon / Image segmented control) lets you keep the
default Z/T type badge, choose a Material wallet icon from a searchable grid,
or set a custom image. The picker area is fixed-height so the modal doesn't
jump when switching modes.
- Custom images go through a new in-app ImagePicker (image_picker.h): a
Material overlay that browses the filesystem starting at the user's Pictures
folder, shows a thumbnail grid (decoded to raw pixels, box-downscaled to a
small texture, cached per directory and freed on navigate/close, budgeted a
few decodes per frame so large folders don't hitch), and returns the chosen
path. The chosen image is copied into <config>/contact-avatars/ (named by an
FNV hash of the source path, so re-picking is idempotent) and stored as
"img:<path>". Like FolderPicker, it takes over the modal surface while open.
- Paste is now available on both add and edit; buttons are content-sized.
Adds three sweep surfaces (contacts-edit-{icon,badge,image}) that open the
dialog on a seeded contact in each avatar mode, plus i18n keys (+ 8-language
translations; reworded two zh/ja strings to stay within the existing CJK
subset, so no font rebuild).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>