AerialDropApp
Creates the shared AppModel, hosts the SwiftUI window, and defines app commands and the Settings scene. Open AerialDropApp.swift
Developer guideSwift 6.2+macOS 26+
A quick map of the app, its native wallpaper integration, the files that own each part, and the checks to run when you change them.
For the full manual QA matrix, see TESTING.md.
Start at the app entry point, then follow the injected model into focused services. Each card links to the implementation.
Creates the shared AppModel, hosts the SwiftUI window, and defines app commands and the Settings scene. Open AerialDropApp.swift
ContentView hosts the Library/Import destinations. ImportPane owns import controls and preview presentation; LibraryPane drives catalogue actions. ContentView · Views directory
The main-actor observable coordinator for selected media, import progress, catalogue state, preferences, activation, and recovery. It injects the video processor and wallpaper service so model behavior can be tested. Open AppModel.swift
The protocol is consumed by AppModel; VideoProcessor validates sources, composes short loops, writes the native MOV, validates its samples, and creates the preview image. Protocol · Implementation
Reads and mutates Aerial entries, creates managed video and preview records, validates writes, and keeps recovery backups. Open ManifestStore.swift
SystemWallpaperService applies the linked selection, refreshes wallpaper processes, and verifies macOS’s result. WallpaperProcessController owns restart and fresh-agent checks. Service · Process controller
Owns the private linked wallpaper selection format. It has its own compare-before-write and backup contract, separate from the manifest. Open WallpaperSelectionStore.swift
VideoGeometry handles preferred transforms and display dimensions. ConversionOptions clamps output size and resolves crop and quality choices without upscaling. Geometry · Conversion options
The model commits user choices before starting work, then installs media before activation.
The view gathers a source and conversion choices. Geometry and output policy stay in the pure VideoGeometry and ConversionOptions types.
AppModel.importSelectedVideo() checks readiness, source validity, available storage, and the Tahoe requirement before writing the installed media.
VideoProcessor normalizes the video to an 80-second native stream. Short sources are encoded once and repeated by passthrough export.
ManifestStore adds the managed video and preview to the Aerial manifest after validating the candidate and creating a backup.
When requested, the wallpaper service updates the linked selection, refreshes macOS wallpaper processes, and verifies the selected asset.
Before catalogue installation, failed imports remove their incomplete files. After installation, activation failures preserve the wallpaper and expose a retry path.
The landing page has the user-facing seven-step import walkthrough; this map names the code boundaries behind it.
Both formats belong to macOS. Keep their mutations and recovery rules separate.
aerials/manifest/entries.jsonManifestStore owns managed catalogue entries. It round-trips through JSONSerialization to preserve unknown keys, checks that the file has not changed before writing, compares foreign entries semantically, and backs up before each write. Backups are under aerials/AerialDropBackups.
Store/Index.plistWallpaperSelectionStore owns the private selection plist. It compares the binary plist before writing, preserves unrelated selection values, verifies the written selection, and backs up under Store/AerialDropBackups.
WallpaperPaths(homeDirectory:) centralizes both store locations. Tests pass a temporary home directory; preference tests use isolated UserDefaults. Never aim tests at a real user's wallpaper catalogue.
These details are coupled to macOS’s private Aerial reader and catalogue. Check the implementation and testing notes before changing them.
The output is HEVC Main10 at 30 fps, 10-bit full-range YUV, Rec.709, with temporal sub-layers and a 15 fps base layer. It uses a closed 1.9-second GOP. The validator requires a stream at least 79.5 seconds long that starts at PTS zero and has a sync sample at every repeated-loop boundary. Short loops are snapped to whole 30 fps frames before passthrough repetition. See VideoProcessor.
The thumbnail contains HEIF image data and deliberately uses a .png catalogue filename suffix to match Apple’s assets. Tahoe detects the image by its contents; do not change the suffix based on the codec. See thumbnail generation.
Do not convert manifest handling to Codable. Unknown Apple keys must survive round trips. Every mutation validates foreign entries, refuses a concurrent file change, and writes a safety backup before the atomic replacement. See manifest mutation.
VideoProcessor has no unit tests for real encoded streams. On a macOS Tahoe test account, import both short and longer MP4/MOV sources, exercise lock/unlock playback, and inspect WallpaperAerialsExtension logs for VideoSampleReadingErrors. Day/Night application is also gated to verified system builds; imported-pair playback and natural solar switching remain unverified. Follow the current manual testing matrix.
Find the narrowest owner and its tests before changing a shared flow.
Start in ConversionOptions or VideoGeometry; see conversion and geometry tests.
Start in AppModel and the Import view; see AppModel wallpaper tests.
Keep mutations inside ManifestStore; cover them in ManifestStoreTests.
Trace WallpaperSelectionStore and SystemWallpaperService; see service tests.
Change the relevant type in Views; keep workflow state and side effects in AppModel.
Check VideoProcessor and the manual playback matrix; unit tests cannot establish native playback compatibility.
Use macOS Tahoe 26, the macOS 26 SDK, and Swift 6.2 or newer. The project uses Swift 6 language mode and strict concurrency.
swift build
swift test
swift build -c releaseRun a focused suite with swift test --filter ManifestStoreTests. If XCTest is missing under Command Line Tools, select Xcode with DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer.
Scripts/build-app.shThis creates dist/AerialDrop.app and wipes .build first. Read build-app.sh before using packaging wrappers that also clear dist/.
The authoritative command list and manual scenarios live in TESTING.md. The existing CI workflow runs on macOS 26 and includes Swift build, tests, packaging, and distribution checks.
Use the README for the product and setup path, and TESTING.md for the full manual matrix.