- Redesign tutorial tour from modal dialogs to popovers pointing at actual UI elements
- Add beginner-friendly improvements: help buttons, tooltips, welcome wizard enhancements
- Add AppStream metainfo with screenshots, branding, categories, keywords, provides
- Update desktop file with GTK category and SingleMainWindow
- Add hicolor icon theme with all sizes (16-512px)
- Fix debounce SourceId panic in rename step
- Various step UI improvements and bug fixes
Critical fixes:
- Prevent path traversal via rename templates (sanitize_filename)
- Prevent input == output data loss (paths_are_same check)
- Undo now uses actual executor output paths instead of scanning directory
- Filter empty paths from output_files (prevents trashing CWD on undo)
- Sanitize URL download filenames to prevent path traversal writes
High severity fixes:
- Fix EXIF orientation 5/7 transforms per spec
- Atomic file creation in find_unique_path (TOCTOU race)
- Clean up 0-byte placeholder files on encoding failure
- Cap canvas padding to 10000px, total dimensions to 65535
- Clamp crop dimensions to minimum 1px
- Clamp DPI to 65535 before u16 cast in JPEG encoder
- Force pixel path for non-JPEG/TIFF metadata stripping
- Fast path now applies regex find/replace on rename stem
- Add output_dpi to needs_pixel_processing check
- Cap watermark image scale dimensions to 16384
- Cap template counter padding to 10
- Cap URL download size to 100MB
- Fix progress bar NaN when total is zero
- Fix calculate_eta underflow when current > total
- Fix loaded.len()-1 underflow in preview callbacks
- Replace ListItem downcast unwrap with if-let
- Fix resize preview division by zero on degenerate images
- Clamp rename cursor position to prevent overflow panic
- Watch mode: skip output dirs to prevent infinite loop
- Watch mode: drop tx sender so channel closes on exit
- Watch mode: add delay for partially-written files
- Watch mode: warn and skip unmatched files instead of wrong preset
- Clean temp download directory on app close
- Replace action downcast unwrap with checked if-let
- Add BatchResult.output_files for accurate undo tracking
- Implement auto_orient_from_exif() that reads EXIF Orientation tag
and applies the correct rotation/flip for all 8 EXIF orientations
- Add aspect ratio lock toggle to resize step Width/Height mode
- When lock is active, changing width auto-calculates height from
the first loaded image's aspect ratio, and vice versa
- Uses recursive update guard (Cell<bool>) to prevent infinite loops
Each ExpanderRow now remembers its expanded state between sessions
using a per-section key stored in SessionState. Replaces the global
detailed_mode toggle with granular per-section persistence.
Add output_dpi field to JobConfig, ProcessingJob, and Preset.
Connect the DPI SpinRow in the resize step's advanced options to
update the config value.
- Add detailed_mode to AppState, derived from skill_level setting
- Expand advanced option sections by default in Detailed mode
(resize, convert, compress, watermark steps)
- Fix high contrast to use HighContrast GTK theme
- Add completion sound via canberra-gtk-play
- Add ResizeAlgorithm enum (Lanczos3/CatmullRom/Bilinear/Nearest) to core
- Thread algorithm selection from UI ComboRow through ProcessingJob to resize_image
- Add OverwriteBehavior enum (AutoRename/Overwrite/Skip) to core
- Implement overwrite handling in executor with auto-rename suffix logic
- Wire overwrite behavior from output step through to processing job
- Fix rotation/flip to apply when resize step is enabled, not just adjustments
Show proportional rectangles comparing original image dimensions
(gray) vs target output dimensions (blue). Preview updates live
as the user changes width/height values. Uses first loaded image
for actual dimensions when available.
Add per-format mapping rows in convert step advanced options so each
input format can target a different output format. Move basic
orientation controls (rotate/flip) into the resize step per design doc
specification that these should be folded into the resize step.
All four configurable steps (resize, convert, compress, metadata) now
have signal handlers that update the shared JobConfig via AppState.
The run_processing function builds ProcessingJob from actual user
choices instead of hardcoded values. Fixed clippy warnings (collapsed
if-let chain, removed needless borrow).
Full Adwaita widget-based layouts for all 7 wizard steps with
PreferencesGroups, SwitchRows, SpinRows, ComboRows, FlowBoxes,
ExpanderRows for social media presets, quality slider with named
marks, metadata radio group, and output configuration.