Drag-and-drop from Nautilus on Wayland was broken by two issues:
- DropTarget only accepted COPY action, but Wayland compositor
pre-selects MOVE, causing GTK4 to silently reject all drops
- Two competing DropTarget controllers on the same widget caused
the gchararray target to match Nautilus formats first, swallowing
the drop before the FileList target could receive it
Merged both drop targets into a single controller that tries
FileList first, then File, then falls back to URI text parsing.
File manager integration was broken by wrong command syntax
(non-existent --files flag) and wrong binary path resolution
inside AppImage. Split into separate GTK/CLI binary resolution
with APPIMAGE env var detection.
- Add 18 screenshots sorted by workflow order to data/screenshots/
- Update metainfo with actual screenshot entries and correct dimensions
- Fix build script to copy all hicolor icon sizes and use linuxdeploy --output
- Add exported icon PNGs to icons/
- 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
M8: Pre-compile regex once before rename preview loop instead of
recompiling per file. Adds apply_simple_compiled() to RenameConfig.
M9: Cache font data in watermark module using OnceLock (default font)
and Mutex<HashMap> (named fonts) to avoid repeated filesystem walks
during preview updates.
M12: Add 150ms debounce to watermark opacity, rotation, margin, and
scale sliders to avoid spawning preview threads on every pixel of
slider movement.
M13: Add 150ms debounce to compress per-format quality sliders (JPEG,
PNG, WebP, AVIF) for the same reason.
M14: Move thumbnail loading to background threads instead of blocking
the GTK main loop. Each thumbnail is decoded via image crate in a
spawned thread and delivered to the main thread via channel polling.
CLI: add UTC suffix to timestamps, validate image extensions on
single-file input, canonicalize watch paths for reliable matching,
derive counter_enabled from template presence, warn when undo count
exceeds available batches.
Core: apply space/special-char transforms in template rename path,
warn on metadata preservation for unsupported formats, derive AVIF
speed from compress preset quality level.
GTK: use buffer size for apples-to-apples compress preview comparison,
shorten approximate format labels, cache file sizes to avoid repeated
syscalls on checkbox toggle, add batch-update guard to prevent O(n^2)
in select/deselect all, use widget names for reliable progress/log
lookup, add unique suffix for duplicate download filenames.
CLI now stores Unix seconds (matching GTK) so age-based history
pruning works correctly. Human-readable formatting applied only
at display time in cmd_history and cmd_undo.
- cleanup_placeholder now removes 1-byte marker files on error (regression)
- {width}/{height} template vars replaced with "0" when dimensions unavailable
- Text watermark width multiplier 0.6->1.0 to prevent CJK/wide char clipping
- cmd_undo preserves history entries when trash operations fail
- cmd_watch_remove exits on write failure instead of silent discard
- PNG chunk parsing overflow protection with checked arithmetic
- Font directory traversal bounded with global result limit
- find_unique_path TOCTOU race fixed with create_new + marker byte
- Watch mode "processed" dir exclusion narrowed to prevent false skips
- Metadata copy now checks format support before little_exif calls
- Clipboard temp files cleaned up on app exit
- Atomic writes for file manager integration scripts
- BMP format support added to encoder and convert step
- Regex DoS protection with DFA size limit
- Watermark NaN/negative scale guard
- Selective EXIF stripping for privacy/custom metadata modes
- CLI watch mode: file stability checks, per-file history saves
- High contrast toggle preserves and restores original theme
- Image list deduplication uses O(1) HashSet lookups
- Saturation/trim/padding overflow guards in adjustments
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
- Add rotate_watermark_image() using imageproc rotate_about_center
for 45/-45 degree rotations and image::rotate90 for 90 degrees
- Add render_text_to_image() helper that renders text to a
transparent buffer for rotation before compositing
- Apply rotation to single text, tiled text, single image, and
tiled image watermark modes
- Fix tiled image watermark to use actual overlay dimensions
(which change after rotation) instead of pre-rotation values
- Move watermark step after compress in processing pipeline to match
design doc order (resize, adjustments, convert, compress, metadata,
watermark, rename)
- Implement selective EXIF metadata stripping for Privacy and Custom
modes using little_exif tag filtering (GPS, camera, software,
timestamps, copyright categories)
- Add case conversion support to rename (none/lower/upper/title)
- Add regex find-and-replace on original filenames
- Wire case and regex controls in rename step UI to JobConfig
- Add regex crate dependency to pixstrip-core
Support {date}, {exif_date}, {camera}, and {original_ext} in rename
templates. Reads DateTimeOriginal and Model from EXIF metadata via
little_exif when these variables are used in templates.
Active watch folders from settings are now monitored using the notify
crate. When new images appear, they are automatically processed using
the folder's linked preset. Toast notifications inform the user.
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.
Wire tiled, margin, and scale UI controls to JobConfig and pass
through to WatermarkConfig. Add tiled text and image watermark
implementations that repeat across the full image. Add font family
filesystem search for named fonts. Add WatermarkRotation enum.
Toggle button in the header bar reveals a bottom panel showing active
watch folders with their linked presets and watching status. The add
button opens Settings for full watch folder configuration.
Users can now choose between subfolder-next-to-originals or a fixed
output folder in Settings > General. The fixed path is selectable via
a folder picker dialog and persisted across sessions.
PNG files now embed pHYs chunk for DPI when output_dpi is set, matching
the existing JPEG DPI support. Also fixed FontDialogButton signal handler
to properly unwrap the Option<FontDescription>.
Font picker using GTK FontDialog/FontDialogButton lets users choose
any installed system font for text watermarks. The selected font family
is passed through the processing pipeline and used to find the matching
font file on disk.
- When overwrite behavior is "Ask", show dialog before processing
listing conflicting files with Overwrite/Skip/Auto-rename options
- Workflow page accepts .pixstrip-preset file drag-and-drop for import
- Split run_processing into two phases to support async dialog
- Workflow page accepts .pixstrip-preset file drops
- Dropped preset files are imported and applied to current config
- Saved to user presets automatically on successful import
- User preset rows now have export and delete action buttons
- Export opens file save dialog for .pixstrip-preset files
- Delete removes preset from storage and UI
- Single-instance via GIO HANDLES_OPEN for file manager integration
- Screen reader announcements on step navigation
- Announce step number and name when navigating between steps
- Add accessible label to batch queue toggle button
- Add accessible label to navigation view with shortcut hint
- Step transitions update accessible property for screen readers
- App flag HANDLES_OPEN enables receiving files from file manager
- connect_open handler filters for image files and activates window
- load-external-files action receives paths and adds to loaded files
- Auto-navigates to step 2 (images) when files arrive externally
- Second instance sends files to existing window instead of launching
- History entries now use ExpanderRow with detailed sub-rows
- Show formatted timestamp, input/output directories, size breakdown
- Clickable output directory row opens file manager
- Per-entry undo and open folder action buttons
- Error count shown for batches with failures
- Add output_dpi field to EncoderOptions
- Set JFIF pixel density header in JPEG output when DPI > 0
- Wire output_dpi from ProcessingJob through to encoder in both
parallel and sequential execution paths
- After a batch completes, automatically start next pending batch
- Mark completed/failed batches in queue with correct status
- Failed batches don't block the queue - next pending batch starts
- Queue processes batches in order, one at a time
- New settings page: Watch Folders with add/remove/edit controls
- Each watch folder has: path, linked preset dropdown, recursive toggle,
active/inactive switch, and remove button
- Watch folder config persisted in AppConfig
- Empty state message when no folders configured
- Rename step: quick-fill buttons for common patterns (Date+Name,
EXIF Date+Name, Sequential, Dimensions, Camera+Date, Web-safe)
- Watermark step: color picker in advanced options using ColorDialogButton
- Add watermark_color field to JobConfig, wire through to core
Users can now drag image URLs from web browsers into the image
step. URLs ending in common image extensions are downloaded to a
temp directory and added to the batch. Uses GIO for the download
in a background thread.
Users can now click different batch images in a thumbnail strip to
switch which image is used for the quality comparison preview and
watermark position preview. Shows up to 10 thumbnails with accent
highlight on the selected one.
Replace single-line arrow-delimited summary with a proper ListBox
showing each enabled operation as its own row with check icons.
Dynamically rebuilt when navigating to the output step. Also make
walk_widgets public for cross-module use.
Queue panel with OverlaySplitView sidebar. Users can add batches
from the results page via "Add to Queue" action. Queue shows
pending/active/completed batches with status icons. Toggle via
header bar button. Batches can be removed while pending.
Semi-transparent dialog-based tour with 6 stops covering step
indicator, workflow selection, image adding, navigation, menu,
and a final ready message. Skippable at any time. State persisted
via tutorial_complete flag in AppConfig.
Replace simple alert dialog with full dialog showing workflow summary,
new preset name entry, and option to update existing user presets.
Never overwrites built-in presets.
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.
Shows a thumbnail of the first batch image with the watermark text
overlaid. Preview updates in real-time as user changes text, position
(9-point grid), and opacity.
Implements actual extension file creation for Nautilus (Python
extension), Nemo (.nemo_action files), Thunar (custom actions XML),
and Dolphin (KDE service menu .desktop). Each extension creates a
"Process with Pixstrip" submenu with all presets listed. Toggle
switches in welcome wizard and settings now call install/uninstall.
- 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
- Play system notification sound via canberra-gtk-play when enabled
- Implement preserve_directory_structure in output_path_for to maintain
relative paths from input directory in output
- Add history_max_entries (default 50) and history_max_days (default 30)
to AppConfig
- Add prune() method to HistoryStore that removes old entries by age
and count limits
- Call prune after each history entry is added in the GUI
- Preserve history settings through settings dialog save/load cycle
Support resize algorithm selection (lanczos3/catmullrom/bilinear/nearest)
and overwrite behavior (auto-rename/overwrite/skip) in the CLI process
command, matching the GUI functionality.
- 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
- Parse stored format/quality/metadata strings back to enum values on launch
- Remove duplicate help button handler
- Session now properly round-trips all wizard state between launches
- Add EncoderOptions struct with progressive_jpeg and avif_speed fields
- Pass encoder options through ProcessingJob to PipelineExecutor
- mozjpeg set_progressive_mode() called when progressive JPEG enabled
- AVIF encoder speed now configurable (was hardcoded to 6)
- run_processing uses CompressConfig::Custom when user overrides preset defaults
- Executor properly handles AVIF quality and PNG level in Custom mode
Connect the header bar help button to the existing show_step_help
function, showing context-aware help for the current wizard step.
Remove duplicate function definition.
Rotation, flip, brightness, contrast, and other adjustment operations
only appear in the output step summary when the adjustments step is
enabled in the workflow configuration.
Track last_seen_version in session state. Show the What's New dialog
automatically when the version changes, but not on very first run
(where the welcome wizard is shown instead).
Steps for disabled operations (resize, adjustments, convert, compress,
metadata, watermark, rename) are automatically skipped when navigating
forward or backward. Jump-to-step also respects skip logic.
Build FormatMapping when per-format overrides are set in the convert
step advanced options, falling back to SingleFormat when no overrides
are configured.
- Add adjustments_enabled field and guard rotation/flip/adjustments behind it
- Wire adjustments toggle in workflow step
- Wire progressive JPEG toggle in convert and compress steps
- Wire format mapping ComboRows (JPEG/PNG/WebP/TIFF) in convert step
- Wire AVIF quality, WebP effort, AVIF speed controls in compress step
- Initialize all new controls from current config values
Split-view comparison showing original vs compressed image side by
side. Draggable vertical divider with handle circle. Shows file sizes
and savings percentage. Compresses a sample image in a background
thread and renders via cairo with pixbuf clipping.
New AdjustmentsConfig with brightness, contrast, saturation, sharpen,
grayscale, sepia, crop to aspect ratio, trim whitespace, and canvas
padding. All wired from UI through to executor.
- Saturation uses luminance-based color blending
- Sepia uses standard matrix transformation
- Crop calculates center crop from aspect ratio
- Trim whitespace detects uniform border by corner pixel comparison
- Canvas padding adds white border around image
Executor now applies rotation, flip, resize, watermark, format
conversion, compression, renaming, and metadata handling. Previously
only resize, convert, and compress were active.
- Rotation: CW90/180/270 via image crate methods
- Flip: horizontal/vertical via image crate methods
- Watermark: text (imageproc + ab_glyph) and image overlay with
alpha blending, positioned via WatermarkPosition enum
- Rename: apply_simple or template-based renaming with counter
- Metadata: re-encoding strips EXIF; KeepAll copies back via little_exif
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.
Upgrade the Add Images step from a plain ListBox to a GtkGridView
with thumbnail rendering. Each item shows a scaled thumbnail with
a checkbox overlay for include/exclude, and filename label below.
Thumbnails load asynchronously using Pixbuf at reduced size.
Uses GObject subclass (ImageItem) for the list model.
The executor now uses rayon's thread pool for parallel processing when
thread_count > 1. Progress updates are sent via mpsc channel from worker
threads. Falls back to sequential processing for thread_count = 1.
Screen readers now announce progress bar value with descriptive
text like "Processing 5 of 47: sunset.jpg" during batch processing,
instead of just reporting the fraction.
The PipelineExecutor now stores thread_count and pause_on_error
fields. When pause_on_error is enabled, the executor sets the
pause flag on failures so the user can review errors. The GUI
reads these settings from AppConfig before starting processing.
Screen readers now announce the purpose and range of brightness,
contrast, saturation, and compression quality sliders. The
watermark position grid frame also has a descriptive label.
A "?" button in the header bar shows an AlertDialog with help
text specific to the current wizard step, explaining what each
step does and key shortcuts available.
Reads image textures from the system clipboard, saves as temporary
PNG files, and adds them to the batch. Shows toast notification
on success or when no image is found.
Escape now goes to previous wizard step (cancel/go back). When
a folder with subfolders is dropped on the images step, an alert
dialog asks whether to include subfolder images. The choice is
remembered for the rest of the session.
- 9-point position grid using ToggleButtons in a Grid layout
- Visual feedback with radio-checked/radio-symbolic icons
- Position label below grid shows current selection name
- Much better UX than ComboRow for spatial position selection
- Ctrl+Z moves output files from last batch to system trash via GIO
- Select all / deselect all actions now registered as window actions
- Shortcuts registered: Ctrl+A, Ctrl+Shift+A, Ctrl+Z
- Register select-all-images and deselect-all-images actions
- Wire Ctrl+A to clear exclusion set, Ctrl+Shift+A to exclude all
- Both shortcuts update checkbox state and count label in images step
- Make set_all_checkboxes_in public for cross-module access
- Output step now shows only included (non-excluded) image count and size
- Navigate-to-step refresh accounts for exclusions
- Process action checks for included images, not just loaded files
- Settings now has a File Manager Integration group with toggle rows
for each detected file manager (Nautilus, Nemo, Thunar, Dolphin)
- Added Reset to Defaults button that restores all settings to defaults
- Each image row now has a CheckButton for include/exclude from processing
- Select All clears exclusion set, Deselect All adds all files to it
- Count label shows "X/Y images selected" when some are excluded
- Processing respects excluded files - only processes checked images
- Clear All also resets exclusion set
- AppState gains excluded_files HashSet for tracking
Add fourth welcome wizard page that detects installed file managers
(Nautilus, Nemo, Thunar, Dolphin) and offers integration toggles for
each. Follows the design doc specification for the first-run experience.
Add What's New dialog accessible from hamburger menu showing version
changelog. Add accessible property labels to step indicator for screen
reader support with current step/total announcements. Add focus
management on step transitions - focus moves to first interactive
element when navigating to a new step.
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.
Add crop to aspect ratio (8 ratios), trim whitespace, and canvas padding
controls to the adjustments step per design doc. Wire brightness,
contrast, saturation, sharpen, grayscale, and sepia to JobConfig. Add
Select All / Deselect All toolbar buttons to images step. Include new
adjustment operations in output step summary.
Add Photographer mode to metadata step that keeps copyright and camera
model while stripping GPS and software data. Improve compress quality
descriptions with estimated file size reduction percentages.
Workflow step: replace the auto-advancing Custom card with a proper
operation checklist using SwitchRow toggles for each operation (Resize,
Adjustments, Convert, Compress, Metadata, Watermark, Rename). Wired
to job config so selections persist through the wizard.
Output step: show actual file size alongside image count. Refresh
both count and size dynamically when navigating to the output step.
Convert step: replace ComboRow with visual format card grid showing
icon, name, and description for each format. Much more beginner-friendly.
Images step: add per-image remove button on each file row so users
can exclude individual images from the batch.
Shortcuts: use adw::Dialog with structured layout since GtkShortcutsWindow
is deprecated in GTK 4.18+. Add file management and undo shortcuts.
Settings: wire thread count selection to actually save/restore the
ThreadCount config value instead of always defaulting to Auto.
Rename step now shows preview for first 5 loaded files (or fallback
examples) with incrementing counters instead of a single line.
Watermark step gains an advanced expander with rotation, tiling,
margin, and scale options alongside the existing opacity control.
- Window size/position remembered between sessions via SessionStore
- Step indicator dots now clickable to navigate directly to that step,
with keyboard shortcut hints in tooltips
- File list in add-files dialog shows format and size per image,
header shows total count and total size
- Welcome dialog now saves skill level choice to config
- SessionState extended with window_width, window_height, window_maximized
- Images step: folder drag-and-drop with recursive image scanning, per-file
list with format and size info, total file size in header, supported
formats label in empty state
- Compress step: per-format quality controls moved into AdwExpanderRow,
improved quality level descriptions
- Output step: dynamic image count with total size from loaded_files,
initial overwrite behavior from config
- Workflow step: properly handle MetadataConfig::Custom in preset import,
mapping all custom metadata fields to JobConfig
- New step_adjustments: rotation (5 options) and flip (3 options)
- New step_watermark: text/image watermark with position, opacity, font size
- New step_rename: prefix/suffix/counter with live preview and template engine
- Updated step_metadata: added Custom mode with per-category checkboxes
(GPS, camera, software, timestamps, copyright) with show/hide toggle
- Expanded JobConfig with all operation fields (watermark, rename, metadata custom)
- Updated wizard from 7 to 10 steps in correct pipeline order
- Fixed page index references from 6 to 9 for output step
- Added MetadataMode::Custom handling in preset builder and output summary
- Workflow preset cards now apply their config to JobConfig on selection
- User presets section shows saved custom presets from PresetStore
- Import Preset button opens file dialog and imports JSON presets
- Save as Preset button in results page saves current workflow
- Images step supports drag-and-drop for image files
- Images loaded state shows file list and clear button
- Output step dynamically shows operation summary when navigated to
- Output step wires preserve directory structure and overwrite behavior
- Results page displays individual error details in expandable section
- Pause button toggles visual state on processing page
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).
- Load current settings from ConfigStore on dialog open
- All switches, combos, and entries reflect saved values
- Save all settings back to ConfigStore on dialog close
- Covers: output, overwrite, skill level, threads, errors,
accessibility, and notification preferences
- Welcome dialog buttons navigate between pages
- Done button closes dialog and marks first_run_complete
- Show welcome dialog on first launch only
- Add first_run_complete field to AppConfig with serde(default)
- Browse Files button triggers win.add-files action
- Add More button in loaded state triggers win.add-files action
- Preset card activation (click) advances to next wizard step
- Custom workflow card activation advances to next step
- Choose output folder button opens folder dialog
- Output step shows current image count when navigated to
- Clean up dead code in update_count_in_box
- Settings menu opens PreferencesDialog
- History menu shows HistoryStore entries in a dialog
- Add Files (Ctrl+O) opens FileDialog with image MIME filters
- Process button runs PipelineExecutor in background thread
- Progress bar updates via mpsc channel polled with glib timeout
- Cancel button sets AtomicBool flag to stop processing
- Results page shows real stats (images, sizes, savings, time)
- Open Output Folder launches default file manager
- Process Another Batch resets wizard to step 1
- Toast notifications via ToastOverlay for feedback
- History entries saved after each processing run
- Remove dead_code allows from processing.rs and settings.rs
First-run welcome dialog with skill level and output location setup.
Desktop entry file for GNOME app launcher integration.
Nautilus Python extension with dynamic 'Process with Pixstrip' submenu
that reads both built-in and user presets.
inotify-based folder watcher using the notify crate that detects new
image files, ignores non-image files, and supports start/stop lifecycle.
WatchFolder config struct for preset-linked watched directories.
Process command discovers images, builds pipeline from preset or CLI
flags (--resize, --format, --quality, --strip-metadata, --recursive),
executes with progress output, prints results with size savings, and
saves to history. Preset list/export/import use the storage module.
Processing screen with progress bar, activity log, and pause/cancel.
Results screen with stats summary, error section, and action buttons.
Settings dialog with General, Processing, Accessibility, Notifications.
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.
7-step wizard flow (Workflow, Images, Resize, Convert, Compress,
Metadata, Output) with AdwNavigationView, step indicator dots,
Back/Next buttons, keyboard shortcuts (Alt+arrows, Alt+1-9),
and hamburger menu with Settings and History placeholders.
Preset save/load/list/delete/import/export, config JSON persistence,
session state save/restore, and processing history log with append/clear.
All stored as JSON under ~/.config/pixstrip/.
ImageLoader: load image info (dimensions, format, file size) and pixels.
Discovery: find image files by extension, flat or recursive, single file or directory.
All 9 tests passing.
@@ -23,7 +23,7 @@ All in one wizard - or one command.
---
## 🧭 What is Pixstrip
## 🧭 What Is Pixstrip
Pixstrip is a batch image processor for Linux built with GTK4 and libadwaita. It exists because preparing images for the web, for clients, for print, or for sharing shouldn't require proprietary software, cloud uploads, or a subscription.
@@ -270,7 +270,7 @@ pixstrip watch start
pixstrip watch remove ~/incoming
```
## 📁 File manager integration
## 📁 File Manager Integration
Right-click any image (or selection of images) in your file manager to process them directly with Pixstrip. A submenu lists all your presets for one-click processing, plus an "Open in Pixstrip" option for the full wizard.
@@ -283,7 +283,7 @@ Right-click any image (or selection of images) in your file manager to process t
Toggle each integration on or off in Settings. The extensions are installed into the standard locations for each file manager.
## 🏗️ Building from source
## 🏗️ Building from Source
Pixstrip is written in Rust and builds with standard Cargo tooling.
@@ -312,7 +312,7 @@ The included script downloads `linuxdeploy` with its GTK plugin, bundles all sha
# Output: Pixstrip-x86_64.AppImage (~39 MB)
```
## 🗂️ Project structure
## 🗂️ Project Structure
Pixstrip is a Cargo workspace with three crates that share a common core.
@@ -332,7 +332,7 @@ Pixstrip is built in the open and contributions are welcome. The project uses [C
File bugs, suggest features, or submit patches through the [issue tracker](https://git.lashman.live/lashman/pixstrip/issues). The codebase is straightforward Rust with GTK4 bindings - if you can read Rust, you can contribute.
## 🔒 Privacy and trust
## 🔒 Privacy and Trust
Pixstrip processes everything on your machine. It never phones home, never uploads your images, never tracks what you do with it. There is no analytics, no crash reporting, no update checker, no account system. The binary does exactly what you tell it to and nothing else.
@@ -343,3 +343,4 @@ Your images are yours. Your metadata is yours. Your workflow is yours. The tool
**CC0 1.0 - Public Domain.** No rights reserved. This work is dedicated to the public domain worldwide. You can copy, modify, distribute, and use it for any purpose, commercial or otherwise, without asking permission and without owing anyone anything.
Good tools should be freely available to everyone who needs them.
This project is developed with the help of a locally-run LLM via opencode for scaffolding, planning, and routine code tasks. Architecture and design decisions are my own.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.