cmux-next: add your own background from a link, and manage your images
Phase 3 of the backgrounds plan (briefs/next-backgrounds-plan.md): an easier way to add your own background.
What changes
Settings > Background:
- Add from a Link tile: paste an https link to an image or video.
- It downloads into the backgrounds folder and becomes the background, the same way a picked file does.
- A refused link says why:
- not https
- not an image or a video this Mac can play
- too big: 50 MB for an image, 500 MB for a video
- could not be downloaded
- Your images gets:
- what the images take on disk
- Show in Finder
- a remove (×) button on each image, shown on hover or focus. It's disabled on the background in use, so the window never goes blank.
- Drop is no longer gated. Dropping an image or movie on Settings used to work only with
experimentalAppearanceon, even though the picker already said "Or drop an image anywhere on this page."
Checks before a file is copied in. This covers picked, dropped and linked files, through BackdropUserImages.adoptChecked:
- a picture must decode (ImageIO)
- a movie must be playable and have a video track (AVFoundation)
Before this, a broken file was copied in, listed, and then showed nothing.
Links:
BackdropUserImages.downloadtakes https only.- A download delegate stops it once it passes the cap. The size is checked again on disk.
- The file is named for its bytes: ImageIO's type for a picture, the server's movie MIME type, or the link's movie extension. Anything else is refused.
Where the code lives.
BackdropImagesPageProvider(CmuxNextPages) serves the new ops on the longest prefix,cmux.settings.backdrop.image.:link,remove,revealandusage.- For a link, it downloads to a temp file and then calls the App's existing
useBackdropImage, so the check and the settings write are shared with the picker. SettingsBackdropImagesmoved to CmuxNextPages with it.- CmuxNextApp source lines go down by 3.
Strings
10 new settingsWindow.backdropPicker.* keys, all 21 locales, in CmuxNextSettingsWindow/Localizable.xcstrings. generated/strings.json is regenerated with gen-strings.mjs.
Tests
CmuxNextDesignTests/BackdropImportTests:- a broken
.pngis refused and never listed - adopt, usage and remove
- only the folder's own images can be removed
- http, file and ftp links are refused
- a stubbed URLSession checks that PNG bytes behind an extensionless link are named
.png, HTML behind.pngis refused, and a 404 fails
- a broken
CmuxNextPagesTests/BackdropImagesPageProviderTests: the ops, refusal codes, own-images-only remove and reveal, and folder reveal.webviews/.../hostCards.test.tsx: the link form's refusals, adding sets and lists the image, the in-use image can't be removed and another can, and Show in Finder.
Verification
bun test src/pages/settings: 128 pass.vp lintandvp fmton the changed files: clean.tsc: no errors in settings. The only 2 errors are files outside my sparse checkout.lint-ios-package-conventions.sh: clean.check-text-focus-rings.py: only the known base red (DaemonRecoveryControls.swift:98).- Swift: not built locally (no Mac in this lane), so CI is the first compile.
- Not dogfooded.
Not in this PR
- Hover-to-play video thumbnails in the picker. They need a video resource route in the App's
SettingsBackdropThumbnails, and the App can't grow, so that waits for a slot. - The 4K / over-60 fps "uses more power" note. It needs async video probing in the catalog listing.
- Built-in videos in
art/manifest.jsonbelong to phase 5, since they change the schema's accepted samples.
WINDOW
None. No settings schema, catalog or Package.swift change. The ops are page ops, not settings keys.
Changelog
Added: Add a background from a web link, and remove your own background images or show them in Finder.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Adds Settings > Background the ability to add your own background from an https link, and management for your own images: remove (not the one in use), size on disk, and Show in Finder. Picked, dropped, and linked files are checked to decode or play before they are copied in, and dropping no longer requires the experimental appearance flag.
- Link downloads stream under a cap (50 MB images, 500 MB videos) checked against both the declared length and the running count, stay https-only (redirects off https are refused), and are refused with a reason when not playable or too large. A body that starts like a picture gets the picture cap regardless of the declared type.
- Link names are sanitized (folders, colons, and leading dots stripped; the extension drops at the last dot) and kept in the download's folder; idle and total timeouts are covered, and the temporary folder is removed on every failure.
- The new ops (
link,remove,reveal,usage) are served by a newBackdropImagesPageProviderinCmuxNextPages, shrinkingCmuxNextAppand importing every type it uses so the fleet compile passes. Removing the background in use is refused natively, and both folder size and Finder reveal run off the main thread. - Adds 10 new localized strings, a settings gallery entry for the link form, and tests covering import checks, page ops, and the link form.