cmux-next: place a Chief's picture in its circle, and go back to the default

Merged
TE
17d ago
+1585-45

Phase 4 of the backgrounds plan (briefs/next-backgrounds-plan.md): custom Chief pictures.

What changes

Chief sheet (named Chiefs, home-channels page):

  • Place a still in the circle. After choosing a PNG, JPEG or WebP, a circular preview appears. Drag to move the picture, and use the Zoom slider (1×–4×).
    • On save, the placed square is drawn at 512 px (never scaled up), as PNG, or as JPEG if a busy photo's PNG would pass 1 MB.
    • So a photo up to 20 MB now fits the daemon's 1 MB. Before, anything over 1 MB was refused.
  • GIFs keep their motion. A GIF is sent as it is (still capped at 1 MB) and drawn centered, as before. Placing it would mean re-encoding the animation.
  • Use Default Picture clears the picture. chief.profile.avatar.set gets clear: true, which the daemon already accepts, and the bundled default shows again.
  • The crop math is pure (picture.ts: cropSquare and dragCrop), and preparePicture takes the renderer as a parameter, so tests run without a canvas.

Chief Settings (the default Chief, native):

  • Choose Picture… draws a still at 512 px as avatar.png, or copies a GIF of up to 5 MB as avatar.gif, next to optchat/profile.json, and points avatar at it. Choosing again replaces the old file.
  • Use Default Picture clears the avatar and removes those files.
  • A file that isn't a picture says so in the panel's error line and changes nothing.
  • GIF and WebP now show in the header and tile. HomeChiefFiles.namesPicture used to accept only PNG, JPEG and HEIC, so a GIF or WebP named in the profile showed as nothing.
  • HomeHostView.onAvatar now just re-reads the avatar (header and tile) after the write finishes, instead of guessing from the text field. That makes the App 2 source lines smaller.

Strings

All 21 locales:

  • Home page catalog: 4 keys (chief.picture.zoom, cropHint, useDefault, tooBig).
  • Home.xcstrings: 3 keys (home.engine.choosePicture, useDefaultPicture, pictureUnreadable).
  • generated/strings.json is regenerated.

Tests

  • webviews/test/home-chief-picture.test.ts:
    • crop square clamping at every zoom and drag
    • drag direction and the edge stop
    • a 5 MB still is drawn rather than refused, at its crop and 512 px
    • a still over 20 MB, a GIF over 1 MB, and SVG are refused
    • a GIF passes through untouched
    • Use Default sends clear: true with no data
  • CmuxNextAppTests/ChiefPictureFilesTests:
    • GIF and WebP names are accepted
    • a 3000×2000 photo becomes 512 px
    • a 3-frame GIF is kept byte for byte and replaces the old PNG
    • a non-picture changes nothing
    • Use Default goes back to the cat

Verification

  • Web:
    • new tests pass (4/4)
    • vp lint and vp fmt are clean on the changed files
    • tsc has no errors in home-channels
    • check:browser-lanes is OK
    • the existing test/home* suites pass, except one fixture outside my sparse checkout
  • Swift: not built locally (no Mac in this lane), so CI is the first compile. lint-ios-package-conventions.sh is clean.
  • Not dogfooded.

Not in this PR (follow-ups)

  • Native crop for the default Chief. The native panel draws the picture centered. Placing it there needs an AppKit crop sheet.
  • Using the Chief's picture as the agent-pane dock mascot, and as notification thumbnails. Both touch the agent pane and App notification code, so they'll be separate PRs.
  • The "animate Chief pictures" toggle (Always / On hover / Never) is in phase 5, the settings PR that Leo reviews first.

WINDOW

None. No settings schema, catalog or Package.swift change.

Changelog

Added: Place your own picture for a Chief in its circle, or go back to the default picture; GIF and WebP pictures show on the Home header.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Phase 4 of the backgrounds plan: users can now place a Chief's picture in its circle on the web, and choose or clear the default Chief's picture in native settings.

Web Chief sheet

  • A chosen PNG, JPEG or WebP is shown in a circle with drag and a 1×–4× zoom slider; on save it is drawn at 512 px as PNG, or as JPEG when a busy photo's PNG would pass the daemon's 1 MB limit.
  • Stills up to 20 MB are now accepted; anything over 1 MB was refused before.
  • GIFs are sent as-is (still capped at 1 MB) and keep their motion, drawn centered.
  • Use Default Picture sends clear: true, which the daemon already accepts.

Native Chief Settings

  • Choose Picture… writes a still at 512 px as avatar.png or copies a GIF up to 5 MB as avatar.gif, and points the profile's avatar at it; choosing again replaces the old file.
  • GIF and WebP pictures now show in the header and tile; only PNG, JPEG and HEIC were recognized before.
  • Use Default Picture clears the avatar and removes the written files; an unreadable file reports an error and changes nothing.

All 21 locales get the 4 new web keys and 3 new native keys. Tests cover crop clamping and dragging, drawn size and format, GIF passthrough, and clearing.