Releases: vdavid/prvw
Releases · vdavid/prvw
Prvw v0.15.0
Browse mode: a native folder tree and thumbnail gallery to flip through a folder's photos, plus live folder sync so the
viewer and browser follow changes on disk.
Added
- Browse mode: press Enter to open a native folder sidebar and thumbnail gallery, flip through a folder's photos, and
open one back into the viewer. Arrow keys move through the tree and grid, Tab switches panes, double-click or Enter
opens, and Esc returns to the image you came from. Thumbnails stream in from QuickLook, and the tree and grid load off
the main thread so even a slow network share never freezes the UI
(7328c461,
59e19ebc,
3a48c9e0,
4acfca79,
27c497a6,
a0fe94fc,
a20f861b,
f81d2474,
de873204,
0ffa5bba,
c4fc7f48) - Launch straight into a folder: pass a directory on the command line and Prvw boots into browse at that folder
(32ee7e22) - Live folder sync: the viewer and browser follow changes on disk with no manual refresh — newly added images appear,
edits re-decode in place, and deleting the image you're on navigates to the next (or shows an empty state when the
folder runs out) (f88f3760,
e6f54379,
68418f2f,
f7384a2e)
Fixed
- Keep the image title and zoom readout readable in macOS Light mode — they were white text that vanished on the light
glass title bar (a598857d)
Non-app
- Rename the internal
thumbnailsmodule topreviews, freeing the name for the new grid-thumbnail cache
(1f5d358a) - Share the QuickLook worker through a second request path and add the headless grid-thumbnail plumbing behind the
browse grid (87729a9b,
fec427a1) - Make browse fully observable from the QA server and cover the flow with end-to-end integration tests
(de7602df) - Capture the native-AppKit-over-Metal layering gotcha and consolidate the browse-mode docs to shipped state
(5ea7f0bb,
0691865f,
e700eb9c,
d0151a33,
9718cd0e) - Upgrade the website to Astro 6, ESLint 10, and TypeScript 6, plus in-range dependency bumps
(6378682c,
c67d2996) - Gate Renovate dependency updates behind a 14-day release age to blunt supply-chain attacks
(8a9ec7bc) - Introduce CodeGraph code intelligence: gitignore its local index and document its call-graph reliability for prvw
(fce9f5ef,
700dacfa) - Gitignore
.claude/worktrees/(db459776)
Prvw v0.14.1
Window-chrome polish: the traffic lights stay put, the title bar fits on one line and zooms on double-click, and zoom
respects your settings in fullscreen.
Changed
- Double-click the title bar to zoom the window (fill the screen / restore) like a native macOS app, instead of toggling
the image fit (68bb58bc)
Fixed
- Keep the traffic-light buttons put across resizes, fullscreen, title changes, and navigation instead of snapping back
to the corner, and place them correctly from the very first frame
(2bd58a7e,
68bb58bc) - Keep the title bar text on a single ellipsized line at every window width, instead of wrapping to two lines in a band
of widths (ef26fe7c) - Re-fit the zoom when you turn on "Auto-fit window" on a zoomed-in image, so it no longer overflows the resized window
(5d9f06c3) - Respect "Enlarge small images" in fullscreen, and stop disabling the toggle when auto-fit is on
(c742b845)
Non-app
- Fix the website deploy silently failing on pnpm 11: the server-side Docker build choked on ignored build scripts,
leaving getprvw.com stuck on the old version (d627b9a0,
71b8af3a) - Finish the pnpm 11 migration so local dev, CI, and the deploy build all run the same pinned version
(bd432d7d) - Restore the non-macOS (Linux CI) build broken by the RAW-preview and thumbnail RAM-cap work, and clear the remaining
dead-code errors it exposed (ad008aa3,
dabbc466) - Force a clean install in the release checks so fresh-install failures surface locally, not just in CI
(cb6365f7) - Port release troubleshooting from Cmdr's guide: keep the Mac awake, create-dmg TCC degradation, and
latest.json
recovery (0ba51dd7) - The release agent pushes without asking when the release finishes clean
(453ece75)
Prvw v0.14.0
A slideshow, Copy and Print, and instant previews the moment you open a RAW. The viewer also picks up a Liquid Glass
frame on macOS 26.
Added
- Slideshow (⌘S): auto-advance through the folder with a crossfade, faster/slower on
]/[, and time, crossfade, and
loop settings; it waits for the next image to decode so there's no "Loading…" flash
(4012fde8,
3d916255) - Copy the image to the clipboard (⌘C, right-click): pastes the real file with full quality and EXIF, or pixels into
editors and chat apps (aa3750a8) - Print the current image (⌘P, right-click) through the system print dialog
(b7882b5f) - Show the camera's embedded preview instantly when you open a RAW (from Finder or by navigating), then snap to the
sharp develop — no more ~450 ms blank wait (175d01ef,
53927b9b) - Liquid Glass window frame on macOS 26, matching Quick Look, across the viewer, Settings, About, and Onboarding
(625b5907,
089b0376,
4988055d)
Changed
- Thumbnail cache size now scales with your Mac's RAM instead of a fixed window, keeping memory respectful on small
machines and generous on big ones (d8cae942) - Navigating away from a huge JPEG no longer blocks the next image, and a cancelled decode that finishes anyway is
salvaged into the cache instead of wasted (40f2f892,
65bfceec) - Decode JPEGs straight to RGBA: a 24 MP photo opens in ~80 ms instead of ~250 ms and uses about half the peak memory
(37f6691e) - Bump the Exif and histogram backdrop opacity so both panels stay legible over bright images
(8f6e5d5e) - Tidy the menu bar: Edit holds only "Copy image", macOS's auto-injected items are pruned, H/E/F shortcut hints show,
and a Help menu appears (15ccfa2d) - Quiet non-actionable RAW decode warnings (9bb360f0)
Fixed
- Show the photo's capture date in the Exif overlay again (it was blank on JPEG, HEIC, and WebP)
(a9ceb7ea) - Let WebP actually be set as Prvw's default format (it was registered under a UTI macOS never uses)
(8df9cf0f) - Stop the file-association toggle knob flying off its track when setting a default
(0a9305b4) - Stop showing macOS's generic file-type icons as cache-miss placeholders
(1dad2fb4)
Non-app
- Optimize the hot image dependencies in dev builds (the overrides were silently ignored in a member manifest)
(ed2f9430) - Fix the CI pnpm install broken by an upstream asset change, by switching mise to the npm backend
(c51af9e1) - Stop E2E test windows stealing the developer's focus, and add nextest retries to absorb GPU-contention flakes
(8ea24961) - Refresh the agent docs (commit-at-will, worktrees, naming)
(1b5c3a9a,
6297d580,
0c5c00d2)
Prvw v0.13.0
Added
- View → Sort by → {Name | Date | File type}. Name (natural alphanumeric, case-insensitive) is the default and fixes
thephoto_1, photo_10, photo_11, photo_2problem —photo_2now sorts beforephoto_10. All comparators ascending;
Name is the tiebreaker for Date (file mtime) and File type (lowercased extension, empty extension first). Persists
across launches. Changing the sort updates the in-memory cache transparently: in-window decoded images stay,
out-of-window entries get evicted, missing in-window slots get queued for preload — loop navigation respected. The
underlying path-keyed cache (refactor that makes this work) also unblocks a future directory-watcher rescan
(9a80ec3e,
bb95700e,
04ca1311).
Changed
- Release script runs full
./scripts/check.shbefore bumping the version, so lint/format/test regressions and the
changelog-linksvalidator (fabricated commit SHAs) abort the release before any tag exists. Also auto-detaches stale
/Volumes/Prvw*mounts and brings the self-hosted runner back up viasvc.sh startif its LaunchAgent died — both
scenarios broke v0.12.0's first attempt (eb9b4196). - Release skill caffeinates the MacBook through the build (
caffeinate -i, idle-sleep only) and verifies the GitHub
Release assets +https://getprvw.com/latest.jsonafter the run succeeds, surfacing webhook deploy failures without
blocking release success (d09d6471).
Fixed
- Flaky integration tests under load.
histogram_hover_bin_updatesandnarrow_window_overlays_dont_crashused
fixedsleep(100..200ms)between an MCP/HTTP command and the state-read assertion; under release-script load (full
check suite + nextest parallelism on a busy machine), processing exceeded the sleep budget and the assertion fired on
stale state. Both now poll via the existingwait_for_statehelper. Surfaced during v0.13.0 release prep
(5a567c0e).
Prvw v0.12.0
Added
- RGB histogram overlay. Toggle via View → Histogram or bare
H. Top-right of the window, rounded translucent
backdrop matching the existing pill style, off by default. Hover the histogram for per-bin R/G/B counts. Computed
lazily on first toggle and cached per-image; rayon-parallel scan handles 20+ MP buffers in a few ms. Persists
across launches (d811bb32,
a6c833c6). - EXIF info overlay. Toggle via View → Exif info or bare
E. Below the histogram with a small gap when both
visible, same width and backdrop. Curated photographer-friendly grouping: camera, exposure triplet
(1/250 s f/2.8 ISO 400), lens, date taken, image dimensions, software, GPS. Hidden entirely on formats with no
EXIF data. Long values wrap and grow the panel while preserving the row pitch. Backed bynom-exiffor JPEG /
Generic andrawler::RawMetadata::exiffor RAW (419c6d54,
a6c833c6,
6846416a). - Loop navigation. Toggle via Navigate → Loop navigation or bare
L. At the last image Next wraps to the first
and vice versa. The preloader is wrap-aware too — toggling on near a directory edge triggers preloads of the
wrap-side indices, toggling off evicts them, so the cache always matches the active window. Off by default,
persists (88b37740). - Home / End jump to first / last image. Navigate menu gains "Go to first" (Home) and "Go to last" (End)
entries, with separators grouping the menu by intent. Absolute jumps; loop navigation does not affect them
(1e8c316c). - Dev-only
screenshot_windowMCP tool that captures the entire native window — overlays, vibrancy, modal
panels — by shelling out to/usr/sbin/screencapture -l <windowID>. Compile-time gated to debug builds; release
builds neither register the tool nor link the dispatch arm. Requires Screen Recording permission on first use
(9954a91d). - Website download buttons now show the file size next to the architecture
(b3b17f46).
Changed
- Markdown / prose formatting unified across the monorepo via
oxfmt(Cmdr's setup). Replaces Prettier; runs
from repo root overdocs/, everyCLAUDE.md, root markdown, and website source. Auto-fixes locally, checks in
CI (a30c1e5d,
cdaa80af,
47742664). - Histogram and EXIF overlay backdrop alpha bumped from 0.55 to 0.66 for legibility against bright images
(6846416a). workflow_dispatchcan now trigger website deploys directly from the Actions tab
(446b8ae0).
Fixed
- Stale
prvw://statesnapshot on background preloads. Found while building loop navigation:poll_preloader
only updated shared state when aReadymatched the pending current index, so neighbor preloads left
cache_indices(and other fields) stale until the next user action. Now updated on every preload arrival
(88b37740). - Histogram briefly showed the previous image's curve on cache-miss navigation while the QuickLook thumbnail
placeholder was on screen.display_thumbnail_placeholdernow clears the cached histogram data so the right
histogram appears once the full image arrives (a6c833c6). - Pricing card on the website was clipping the Download dropdown via
overflow-hidden; the 1px accent line is now
inset within the rounded corners so the parent doesn't have to clip
(c1e467ec).
Prvw v0.11.0
Added
- Blurry thumbnail placeholder while the full image decodes. Cache-miss navigation now uploads the QuickLook thumbnail through the same display pipeline as the full image, so zoom, EDR, and auto-fit match. New
thumbnails/module with a centered-outward scheduler (80fa5102). - Parallel pixel-dimensions prefetcher. A 16-thread worker reads dimensions for every index in
current ± WINDOW_RADIUSupfront, so placeholder display drops from 200 ms – 1.3 s on slow shares to 1 – 2 ms post-warmup. Three-tier dispatcher:image::image_dimensionsfor PNG/GIF/BMP, a single-buffer JPEG parse for one SMB round trip, ImageIO for the rest (d02e61d7). - Updater now surfaces "update available" on no-file launches from Finder / Dock too; download is deferred to viewer init so an admin prompt can't interrupt onboarding (0ee6b337).
Changed
- Navigation no longer freezes on slow network shares. QuickLook submission moved off the main thread to a dedicated
prvw-thumbgenworker (was costing ~150 ms per submit on SMB), completion blocks batch into a shared queue so a 38-thumb burst wakes winit 1 – 2 times instead of 38, andmark_readyno longer pre-reads source dims (~7 s of main-thread blocking on a 38-thumb burst, now lazy) (16d63b46). - Thumbnail scheduler prioritises immediate neighbours first, then outside-window, then current. The previous order left the next-arrow target without a placeholder for ~5 s after launch on slow folders (d02e61d7).
- Updater bundle swap is now atomic via
renamex_np(RENAME_SWAP)— no window where the app is absent or partial, and a crash mid-update leaves one intact bundle either way (0b52f850). - Updater deregisters the old bundle from Launch Services before swapping so the "Open With" menu no longer shows both old and new Prvw side by side after an update (bb0bbbe0).
- Updater only runs on bundles installed in
/Applications; dev builds and~/Downloadscopies are skipped (0ee6b337). - Website tagline + features section refreshed (0664402f); terms and conditions updated (5bae3ce1).
Fixed
- Escape now closes About, Onboarding, and Settings windows again. The hidden Escape button was excluded from
performKeyEquivalent:traversal; switched to borderless + zero-size frame (dc8ee8da). - Integration tests no longer flake from a port-keyed
PRVW_DATA_DIR; eachTestAppnow gets its owntempfile::TempDir(5fd0f0de).
Prvw v0.10.0
Changed
- Navigation is now near-instant in RAW folders. End-to-end rework of the preloader to route the current image
through the background pipeline on a cache miss instead of blocking the main thread, so a fast key press never
freezes the UI. The pool switched from a custom rayon pool to a single dedicatedstd::threadworker — rawler's
internalpar_iterinherits the caller's pool, so a 1-thread custom pool was starving rawler's parallel stages
(demosaic, chroma_nr, sharpen) of cores. A plain OS thread isn't a rayon worker, sopar_iterfalls back to the
global pool and each 20 MP ARW preload now decodes in ~300-450 ms instead of ~2 s. Preload priority is now
direction-aware: forward navigation loadsN+1, N+2, N-1, N-2in that order, backward mirrors, and startup
interleaves. In-flight decodes for indices still wanted are no longer restarted across successiverequest_preload
calls — they keep their cancellation token and continue from where they left off. A 30 ms debounce coalesces wheel
spins: 20 fast clicks collapse into a singlenavigate_by(±20)jump with one decode. Cache entries outsideN±2
get evicted on every navigation (previously they lingered until the LRU budget pushed them out — visible on small
JPEGs where 50+ could fit the 512 MB budget). The wgpuTexturefor the currently-displayed image is now
explicitlydestroy()'d on image swap — fixes a 4 GB+ RSS bloat on long RAW sessions where Metal on unified memory
wasn't returning the backing just by replacing the bind group. File I/O moved to an abandonable detached thread
with channel-based polling, so a wedged network share (SMB, flaky NFS) can't block the caller —std::fs::File::read
has no timeout, so the old in-thread cancellation check did nothing until the kernel unblocked the syscall. - Preloader debug logs are now structured and greppable. Each preload task emits one line on start and one on
finish with the file name, position label (N+1,N-2, ...), 1-based directory position, and total wall time:
Initiated loading 9.jpg (N+1, 10/17)/Fully loaded 9.jpg (N+1, 10/17) in 25ms. Cache evictions log
Evicted 7.jpg (N-3) from memory - 2.5 MB freed (out of window)or... (LRU)depending on the trigger. Enable
withRUST_LOG=prvw::navigation=debug.
Fixed
- Scrolling through a folder of RAWs no longer stutters when decodes can't keep up. The old preloader kept
submitting low-priority neighbor decodes that shared CPU with the currently-needed image, so pressing right six
times at 400 ms intervals pushed the priority-zero decode from ~500 ms to 2-3 s. Navigation now defers the
priority-zero render until the decode lands on the main thread viapoll_preloader, with a clean "Loading…" title
in the meantime. Side effect: no more double-decoding of the same image (main thread + rayon) on cache miss. - Lens correction polarity was doubling distortion instead of correcting it on some lenses. The sign was
reversed inapply_distortion_resampleso barrel correction turned into barrel amplification and pincushion
correction turned into pincushion amplification. Fixed; distortion now goes the right way. - HDR / EDR output now actually renders HDR-bright on XDR displays (Phase 5.2). The original Phase 5.1 path decoded
RAWs into a half-float buffer but routed them throughmoxcmswith a gamma-encodedkCGColorSpaceExtendedDisplayP3
layer, which clipped above-1.0 linear values at ICC-transform time and left the EDR compositor with nothing above
display-white to brighten. Two fixes: (1) on the HDR path only, bypassmoxcmsand apply a direct linear Rec.2020 →
linear Display P3 3×3 matrix (color::profiles::rec2020_to_linear_display_p3_inplace) that preserves above-white
values. (2) Flip theCAMetalLayercolorspace tokCGColorSpaceExtendedLinearDisplayP3so the compositor
interprets the buffer's linear values correctly. SDR path still goes throughmoxcms→ user's display ICC and is
bit-identical to Phase 6.1. Trade-off to name: HDR output uses Display P3 rather than the user's calibrated display
profile, since the OS's EDR compositor takes over colorspace conversion on that path — inherent to going into EDR
mode, not a choice. Seedocs/notes/raw-support-phase5.md.
Added
- RAW per-stage timing + benchmark table (Phase 6.4):
decoding::raw::decodenow emits one DEBUG log line per
pipeline stage plus a comma-separated summary line, ready to grep. Enable withRUST_LOG=prvw::decoding::raw=debug.
apps/desktop/src/decoding/CLAUDE.mdships a reference table of typical warm-decode timings on a 20 MP ARW (M3 Max,
release, defaults) so agents and humans can spot regressions without a profiler. Pairs with a new
Settings → General → "Preload next/prev images" toggle that disables background preloading so single-image
cold-start decodes can be measured without concurrent work interfering. - HDR brightness gain (Phase 5.2): a new 0.5 – 4.0 slider in Settings → RAW → Output (default 2.0) pushes
scene-white content into the EDR headroom so HDR output reads genuinely "HDR-bright" on an XDR / OLED panel instead
of timidly preserving SDR brightness and only using headroom for sparse specular highlights. Matches the visual
brightness of Preview.app / Photos on the same display. Ignored on the SDR path;hdr_gain = 1.0restores the
pre-5.2 HDR behavior (above-white content preserved but no overall brightness lift). - Clarity (local contrast) for RAW (Phase 6.2): RAWs now get a larger-radius unsharp-mask pass on luminance before
capture sharpening. Lifts midtone features — shape silhouettes, textures, the mid-frequency content — that survive
display downscaling, so the image reads crisper at fit-to-window zoom, not just at 100 %. Same math as capture
sharpening, σ ≈ 10 px instead of 0.8 px, luminance-only. New "Clarity (local contrast)" toggle at the top of
Settings → RAW → Detail, with "Clarity radius" (2 – 50 px, default 10 px) and "Clarity amount" (0.00 – 1.00,
default 0.40) sliders directly beneath. On by default; toggling off reproduces pre-6.2 output. Closes the visible
"crispness gap" against Affinity's "Detail Refinement" pass. Adds ~200 – 400 ms to a 20 MP decode on Apple Silicon.
Seedocs/notes/raw-support-phase6.md.
Changed
- DCP ~1.6× faster (Phase 6.5): the per-camera
HueSatMap/LookTabletrilinear-interpolation LUT apply in
color::dcp::applyis now#[multiversion]-annotated (NEON / AVX2+FMA) with branchless HSV conversion,
f32::mul_addon all seven trilinear lerps, andrem_euclidcalls on the hot path replaced with compare-and-add
(the single biggest win —rem_euclid(6.0)inrgb_to_hsvinvokedfmodfper pixel). Processes pixels in
1024-wide rayon chunks to amortise scheduling overhead. ~36 ms → ~22 ms per 20 MP decode (Apple Silicon M3 Max,
release). Applies to bothHueSatMapandLookTablepaths since they shareapply_hue_sat_map. Output is
bit-equivalent to the scalar reference within float rounding (max channel Δ 1.79e-7 across a 256×256 synthetic
buffer; well below the golden regression's < 3.0 ΔE tolerance). - Clarity ~10× faster on 20 MP (Phase 6.4): the σ=10 local-contrast pass now takes ~14 ms instead of ~144 ms on a
20 MP image (Apple Silicon M3 Max, release). For σ ≥ 4 and images ≥ 1 MP, clarity now downsamples the luma plane 4×
(box average), blurs at σ' = σ/4 (~15-tap kernel instead of 61), then bilinearly upsamples — the Gaussian-blurred
signal is low-frequency by design, so the round-trip is near-invisible. Small σ and small images still take the
direct-convolution path for byte-identical output against pre-6.4. Total per-decode budget on a 20 MP HDR ARW drops
from ~650 ms to ~293 ms warm, a ~2.2× overall speedup when paired with the HDR-diagnostic log gating below. See
apps/desktop/src/decoding/CLAUDE.md§ "Per-stage timing" for the reference table. - HDR-diagnostic log scans now run only when info logging is active (Phase 6.4): the three post-pipeline
peak-value scans (peak linear value,peak post-ICC,peak f16) are now gated behindlog::log_enabled!(Info)
and, on the HDR branch, parallelized via rayon. ~40 ms saved per HDR decode when info logging is off; ~30 ms when
it's on. No observable behavior change — release builds that don't ship info logging pay nothing. - RAW defaults tuned against Affinity / Preview (Phase 6.1.1): the parametric RAW stages now ship with values
closer to Affinity Photo's per-camera-tuned output on our sample set —DEFAULT_SATURATION_BOOST0.08 → 0.18,
DEFAULT_MIDTONE_ANCHOR0.40 → 0.45, and a newbaseline_exposure_offsetslider (default +0.73 EV) adds a
user-controllable offset on top of the camera's baseline EV. The Settings → RAW layout co-locates each slider
under its matching toggle instead of the standalone "Tuning" section (saturation slider under the saturation
toggle, midtone slider under the default-tone-curve toggle, etc.) so the tune-by-eye UX is obvious. Flipping a
toggle off continues to reproduce pre-6.1.1 output bit-for-bit on a per-image basis. - Lens correction resampler is now SIMD-accelerated (Phase 6.3): the bilinear resampler inner loops in
apply_distortion_resampleandapply_tca_resampleare compiled for NEON (aarch64) and AVX2+FMA (x86-64)
viamultiversion. The sampler is now branchless (NaN/inf coords handled without a conditional early return)
and usesf32::mul_addfor FMA hints. The TCA path additionally extracts per-channel sampling into
sample_single_channel_bilinear_fast, eliminating 2/3 of the redundant channel computation the original
sample_rgb_bilinearcalls did. Measured per-row speedup on M-series Apple Silicon: distortion ~1.0×
(already memory-bandwidth-bound), TCA ~1.6×. Output is bit-identical within f32 FMA rounding tolerance. - **Capture sharpening now runs o...
Prvw v0.9.0
Added
- Camera RAW support via
rawler: open DNG, CR2, CR3, NEF, ARW, ORF, RAF, RW2, PEF, and SRW files. Decode pipeline
includes black/white level correction, PPG demosaic for Bayer sensors, bilinear for Fuji X-Trans, white balance,
camera color matrix with Bradford chromatic adaptation, and sRGB gamma. NEON SIMD on Apple Silicon, rayon
parallelism. Orientation is pulled from EXIF metadata sincerawlerhard-codesRawImage.orientation. Known limits
in this first pass: no DNGOpcodeListinterpretation (iPhone ProRAW gain maps), no DCP profiles, X-Trans demosaic
is bilinear. Seedocs/notes/raw-support-phase1.mdfor design decisions and the Phase 2/3 outlook
(b4bc775) - File associations for all 10 RAW formats: Finder now recognizes Prvw as a handler for DNG, CR2, CR3, NEF, ARW, ORF,
RAF, RW2, PEF, and SRW via their standard Apple UTIs.Info.plistcarries all 16 document types now (6 standard + 10
RAW) - Settings > File associations: redesigned into two sections, "Standard image formats" (JPEG, PNG, GIF, WebP, BMP,
TIFF) and "Camera RAW formats" (DNG, CR2 + CR3, NEF, ARW, ORF, RAF, RW2, PEF, SRW) with vendor labels. Each section
has a master "Set all" toggle with tri-state support: when some formats are on and others off, the master shows a
"Mixed" indicator; clicking mixed or off sets all on, clicking on sets all off. Per-format small toggles keep fine
control
Changed
- Onboarding window: redesigned into a four-step checklist (Install Prvw.app, Set as default viewer, Move to
/Applications, Open images). Each step uses a custom green checkmark (dimmed for pending steps) rendered at runtime
from the source SVG path viaNSBezierPath. Step 2 holds the "Set Prvw as the default viewer for all of these
files" button and shows a natural-language sentence summarizing which app currently opens each of the 16 supported
image formats. Step 3 checks whether the binary is in/Applications/and shows a drag hint when it isn't. Step 4's
copy adapts to step 2's state: "double-click any image" once Prvw is the default, or "right-click any image and
choose Open with → Prvw" beforehand. Content is left-aligned, the window is wider and taller to give the checklist
breathing room, and the title drops thevprefix ("Prvw 0.8.0") - Decoding module: single-file
decoding.rssplit into adecoding/module with per-backend files (jpeg.rs,
generic.rs,raw.rs) plus shareddispatch.rsandorientation.rs. Public API unchanged
(b4bc775) - CI: macOS-only modules (AppKit settings panels, color transform tests) gated behind
#[cfg(target_os = "macos")]
so cross-platform builds compile cleanly. Groundwork for Windows and Linux support later
(e9b5de4,
3f00979,
815b727,
96218dd)
Fixed
apply_orientationunderflowed on zero-width or zero-height input for EXIF orientation 2. Now early-returns
(b4bc775)- Restored per-row handler transparency in Settings > File associations: each format row again shows which app currently
handles it, or which app handled it before Prvw took over. Covers all 16 formats (6 standard + 10 RAW)
Prvw v0.8.0
Added
- Settings window: new sidebar layout with General, Zoom, Color, and File associations sections. Cross-dependencies
disable dependent toggles automatically (ICC off → Color match / Relative colorimetric disabled; Auto-fit on →
Enlarge disabled) (dc43505,
0dd4849) - File associations panel: per-UTI toggles, "Set all" master toggle, 1-second polling of handler state, previous
handler rollback when you turn a toggle off (0dd4849,
17b76a3) - Rendering intent toggle (View menu + Settings > Color, Cmd+Shift+R). Default is perceptual; toggle to relative
colorimetric. Disabled when ICC color management is off. Persisted asuse_relative_colorimetric
(b42814f) - Scroll-to-zoom toggle in Settings > General (off by default). When off, scroll navigates between images (down = next,
up = prev). Cmd+scroll always zooms regardless of the setting
(d55b7e9) - Pinch-to-zoom on trackpad, cursor-centered. Works with auto-fit window resize, same as scroll zoom
(ef8d0bf) - Keyboard shortcuts for zoom: Cmd+= (zoom in), Cmd+- (zoom out), Cmd+0 (actual size)
(ec2aba4) - Title bar toggle in Settings > General (on by default): reserves a 32px strip at the top so the filename and zoom
pills don't cover the image. Screenshot-friendly when off
(64e0d87) - Title bar vibrancy: Liquid Glass on macOS 26, classic frosted glass on older versions. The area around the image
(when the image doesn't fill the window) gets a darker HUD-style vibrancy. Fullscreen switches both to opaque black
so screenshots and projector-style viewing aren't distracted by the desktop blurring through
(7eede14) - Integration test suite (17 tests): Settings open/close/switch, zoom in/out, fit/actual, auto-fit toggle, navigate,
refresh, window geometry. Each test spawns its own app instance on a dynamic port
(0dd4849)
Changed
- Source layout: flat
src/with infrastructure (app/,render/,platform/) and features (about,color,
decoding,navigation,onboarding,qa,settings,window,zoom, …) as siblings. Each feature owns its
runtime state via aStatestruct onAppinstead of ~20 flat fields. No behavior change
(27eca5e,
e88027b)
Fixed
- Closing the onboarding window now quits the app. Previously, a no-file launch (Dock or
cargo runwith no args)
left the event loop running with nothing visible after the user clicked Close, because the onboarding is a raw
AppKit window and doesn't generate a winit close event
(e81bbdf) - CGColor / CGColorSpace encoding crashes in
setColorspace:(display profile) and the Settings separator:
msg_send!encoded these as^vinstead of^{CGColorSpace=}/^{CGColor=}. Fix uses rawobjc_msgSendto
bypass the type check (17b76a3)
Prvw v0.7.0
Added
- ICC color management: embedded source profiles (JPEG, PNG, TIFF, WebP) are transformed to accurate output colors.
Level 1 converts to sRGB, Level 2 targets the actual display profile via CoreGraphics FFI
(CGDisplayCopyColorSpace). Images without profiles assumed sRGB. Display changes flush the cache and re-decode
(ee226ac,
94820a8) - View menu toggles: "ICC color management" (Cmd+Shift+I) and "Color match display" (Cmd+Shift+C), both persisted in
settings. Disabling ICC grays out color matching (L2 depends on L1)
(a088330,
b952b64)
Changed
- ICC engine: replaced lcms2 (C bindings) with moxcms (pure Rust, NEON SIMD). 24MP transform: 247ms -> 45ms on M3 Max.
No C toolchain needed for cross-compilation
(f568b18)