picfetch

command module
v0.2.15 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 10 Imported by: 0

README

PicFetch

CI Release Go version Last commit Downloads Buy Me A Coffee macOS Windows Linux Website English Deutsch

Header

A small Fyne desktop app for quickly viewing images. Drop one or more images onto the window to view them, and step through the set with the keyboard.

usage demo (click for longer demo video)

PicFetch demo

Features

  • Drag-and-drop viewing of JPEG, PNG, GIF, WebP, BMP, TIFF, ICO, XPM, HEIC, AVIF, SVG, and camera RAW (.jpg, .jpeg, .jpe, .jfif, .png, .gif, .webp, .bmp, .tif, .tiff, .ico, .xpm, .heic, .heif, .avif, .svg, .cr2, .cr3, .nef, .arw, .dng, .orf, .rw2, .raf, and other common RAW extensions, or anything reporting a matching image/* MIME type). RAW files show the camera's embedded JPEG preview — marked (preview) in the title and info overlay — with no demosaic engine. HEIC/AVIF decode through embedded WASM (no cgo), so they need no system libraries and don't complicate cross-compilation. SVG is rasterized on the fly and re-rendered as you zoom, so it stays sharp at any zoom level

  • On macOS, the same format list also opens through Finder's Open With, a drop on the Dock icon, open -a, or double-clicking a file already associated with PicFetch — whether PicFetch is already running or being launched cold by that click, and a folder can be dropped on the Dock icon too

  • Animated GIFs play back frame-by-frame at their encoded speed, correctly compositing each frame per its disposal method (a partial-region update won't leave stale pixels or wrongly clear the whole frame); playback stops automatically as soon as you navigate away

  • EXIF orientation correction for JPEGs (auto-rotate/flip per the file's orientation tag)

  • EXIF data window (E, or a link in the info overlay) showing camera make/model, lens, exposure, aperture, ISO, focal length, capture date, and the capture coordinates, for files that carry them — plus a collapsible OpenStreetMap view pinned at the capture location for photos with GPS tags (collapsed on every open, so no map tiles are fetched unasked)

  • Drop one image to step through the other images in the same folder with the arrow keys (wraps around at both ends), or drop several files / a folder to walk that set; jump to the first/last with Home/End

  • G opens a full-window thumbnail grid for jumping around a large drop by sight instead of arrowing through it; click a thumbnail, or use the arrow keys to move a highlight and Return to open it. Thumbnails are generated lazily and with bounded concurrency, in a separate small LRU cache from the full-size decode cache, so opening it on a several-thousand-file folder doesn't spawn a decode per file

  • Favorites remember named file lists; each entry shows how many files it holds (Holiday 2024 (128)), and Manage Favorites… (also Cmd/Ctrl+Shift+F) is fully keyboard-navigable — arrow keys move a ring over the rows and their Open/Remove buttons, Return activates whichever is ringed. Add Current List to Favorites… is also Opt/Alt+Shift+F. The Add to Favorites… and Replace Favorite prompts are keyboard-driven too, with the name field auto-focused on open. Opening or saving a favorite also saves its grid previews to disk under that favorite's own folder in the background, so reopening it paints the grid without re-decoding the originals (toggle this off in Settings)

  • Zoom via +/-/1/0, or scroll (mouse wheel/trackpad) to zoom anchored at the cursor; click-drag or Shift+scroll to pan once zoomed in. No native pinch gesture — Fyne's desktop driver (GLFW) has no magnify/ gesture callback, only scroll wheel, so Shift+scroll is the stand-in

  • A plain drop replaces the current set; press M to toggle merge mode, which makes drops add to the set instead (no dedup — dropping the same file twice adds it twice). The title bar shows a [merge] prefix while it's on. It's a standing toggle rather than a drag modifier because drag-and-drop from the file manager never focuses the window, so OS-level modifier keys (Shift, etc.) held during the drag aren't observable

  • Files are naturally sorted by name by default (IMG_2.jpg before IMG_10.jpg), not just the raw order the OS handed them over in; press S to cycle through capture date, modification time, file size, and the raw scan/drop order, and back to name. The title bar shows which one is active ([sort: date], [unsorted], etc.) except for the default

  • Drop a mix of files and folders — folders are scanned recursively for supported images, with a spinner and a live counter shown while scanning large trees

  • A file that fails to decode only once you navigate to it is dropped from the set and the next one is loaded automatically (wrapping around if it was the last), instead of leaving the title/position stuck on a file that isn't actually shown

  • Escape closes the window

  • Built-in end-user manual (manual.md, embedded at build time and rendered in its own scrollable window) via F1 or Help → Manual (F1 is shown next to that menu item); the window has a search bar at the top — Enter finds and highlights matches and scrolls to the first, Enter again jumps to the next. Escape closes just the manual window. Fyne's markdown renderer has no table extension, so keep manual.md table-free

  • Window auto-resizes to fit the image, capped at 1500x950

  • Image decoding happens off the UI thread so large files don't freeze the window; an indeterminate progress bar shows along the top edge while a decode is in flight

  • Localized UI strings via translations/*.json (fyne.io/fyne/v2/lang), currently shipping English and German

  • Merge mode, sort order, the picture-frame slideshow interval, and the (empty-dropzone) window size are remembered across launches, via Fyne's Preferences API

Trane mit Bilderrahmen

Download

Pre-built binaries for Linux, Windows, and macOS are published on the Releases page — no Go toolchain required. macOS builds are published for both Apple Silicon (picfetch-macos-arm64.zip) and Intel (picfetch-macos-x86_64.zip), and Windows builds for both x64 (picfetch-windows-amd64.zip) and ARM64 (picfetch-windows-arm64.zip); grab the one matching your machine. See Building below to build from source instead.

Windows (WinGet)
winget install io.github.frathe.picfetch

Releases are immutable. GitHub issues a Sigstore release attestation that binds each archive's SHA-256 to the tag. The in-app updater, when enabled, refuses to install a build that fails that check.

macOS: "app is damaged" warning

The release build isn't signed with an Apple Developer ID or notarized, so Gatekeeper quarantines it after download and shows this message. The app isn't actually corrupted — to open it anyway:

  • Right-click (Control-click) PicFetch.appOpen → confirm in the dialog that appears, or
  • Run xattr -cr "/path/to/PicFetch.app" in Terminal to clear the quarantine flag, then open it normally.

Trane mit Bilderrahmen

Requirements

  • Go 1.26.6 or newer (see the go directive in go.mod)
  • A C toolchain for cgo (Fyne's OpenGL bindings require it) — Xcode Command Line Tools on macOS, gcc + libgl1-mesa-dev/xorg-dev on Linux
  • Docker — used by make test/make verify so tests and golden comparisons run on Linux/amd64 like CI, and also needed for cross-compilation and make golden
  • govulncheck and the GitHub CLI (gh) — only needed for the make security* targets. govulncheck is installed by make install-tools; gh must be installed separately (e.g. brew install gh) and authenticated via gh auth login

Running

make run
# or
go run .

Building

All build tasks are defined in the Makefile. Run make help to list them.

Command Description
make build Native binary for the current OS/arch, output to bin/picfetch
make package-mac macOS .app bundle, output to bin/PicFetch.app (no Docker required)
make package-windows Windows .exe files, cross-compiled via fyne-cross/Docker, to bin/picfetch-windows-<arch>.exe
make package-linux Linux binaries, cross-compiled via fyne-cross/Docker, to bin/picfetch-linux-<arch>
make build-all Runs package-mac, package-windows, and package-linux
make install-tools Installs the fyne, fyne-cross, and govulncheck CLIs used by the package/security targets

Packaging is done with the fyne CLI (native OS builds) and fyne-cross (Windows and Linux, via Docker containers with the appropriate cross toolchain — cgo can't be cross-compiled from macOS without it). package-windows and package-linux each build one binary per architecture listed in WIN_ARCHES and LINUX_ARCHES respectively (both default to amd64 arm64), named bin/picfetch-windows-<arch>.exe and bin/picfetch-linux-<arch> so they don't collide; override on the command line for a single arch, e.g. make package-linux LINUX_ARCHES=arm64 or make package-windows WIN_ARCHES=amd64. fyne-cross windows also supports 386, and fyne-cross linux also supports 386 and arm.

Note: running an amd64 Linux binary under an x86 emulator (e.g. Box64) on ARM hardware is unreliable for OpenGL apps like this one — build the matching arm64 binary for ARM boards instead of emulating.

There are also -debug variants (package-windows-debug, package-linux-debug) that build an unstripped binary with debug symbols kept in, useful for diagnosing startup failures that only show up in a packaged build.

Note: fyne package bumps the Build field in FyneApp.toml on every run. That's expected Fyne behavior, not a bug — decide for yourself whether to commit those bumps.

Other development commands
Command Description
make fmt goimports -local github.com/frathe/picfetch all Go source files
make fmt-check Fail if any file differs from that goimports (CI format gate)
make vet go vet ./...
make test Run go test -timeout 20m ./... in Linux/amd64 Docker, matching CI and golden rendering
make test-native Run the same suite directly on the host (goldens can differ outside Linux/amd64)
make verify The same gate CI runs; its race-test step uses the make test Linux/amd64 container
make tidy go mod tidy — tidy go.mod / go.sum
make security Run all security checks (govulncheck + GitHub Dependabot alerts)
make security-govulncheck Scan dependencies for known Go vulnerabilities with govulncheck
make security-github List open GitHub Dependabot alerts via gh (needs gh auth login)
make clean Remove bin/, fyne-cross/, and any stray packaged app/zip

Note: make security-github requires the GitHub CLI (gh) to be installed and authenticated (gh auth login), and it must be run from a checkout with a GitHub origin remote.

Releasing
make release              # patch bump, e.g. 0.1.7 -> 0.1.8
make release PART=minor   # or PART=major

make release is the whole flow. It refuses to start unless you're on main (override with RELEASE_BRANCH=), the working tree is clean, and HEAD matches origin/main; it also refuses if the tag it would create already exists locally or on the remote. After a confirmation prompt (YES=1 skips it) it runs make verify, bumps Version/Build in FyneApp.toml, writes GitHub release notes from the ## Done section of todos.md (empty categories dropped, plus a Full Changelog compare link) into .github/release-notes.md, clears those Done items so they are not reused, commits that as Release vX.Y.Z, tags the commit, and pushes the branch and the tag. The confirmation prompt prints the notes first; a Done section with no list items aborts. If the GitHub CLI (gh) is installed it then finds the Release workflow run for that tag (without prompting you to pick among the simultaneous CI run on main) and follows it until the artifacts are published.

Pushing the tag is what publishes: .github/workflows/release.yml re-runs the full CI suite as a gate, then packages macOS, Windows, and Linux artifacts and attaches them to a GitHub release whose body is .github/release-notes.md from the tagged commit. Nothing is published if that run goes red — the tag just sits there, and you can delete it and try again. The download links on the website point at releases/latest, so they need no edit per release.

make bump-version does only the FyneApp.toml edit (no commit, no tag, no push) for the rare case where you want the version bumped by itself.

Testing

make test runs everything in an Ubuntu 24.04 Linux/amd64 container: unit tests colocated with the code they cover (internal/ui/*_test.go, internal/imaging/*_test.go, and so on) plus the end-to-end suite below. It keeps Docker volumes for the Go build and module caches, so later runs reuse the downloaded toolchain and dependencies. make test-native is the direct host equivalent when platform-specific behavior is the point, but its golden pixels can differ outside Linux/amd64. Shared test fixtures — synthetic images in every supported format, temp files, and stubs for the OS-level seams — live in internal/uitest.

End-to-end suite (internal/ui/e2e_test.go)

Rather than a hand-copied replica of the UI that could drift out of sync, the e2e tests drive the real app: buildViewer(application fyne.App, startup startupState) in internal/ui/build.go is the exact top-level widget/handler wiring Run uses, including the ordered feature construction in internal/ui/features.go, after internal/ui/startup.go loads startup state. Every test in the package mirrors that load/build/geometry-restoration path through newTestUI, then drives it the way a user would — handleDrop for a drop, handleKeyEvent for a key press — and checks two things:

  • Statev.files, v.index, and widget visibility (.Visible()). Fast, exact, and portable; this is the real regression guard.
  • A screenshot — the full window, captured via win.Canvas() and compared against a golden master PNG in internal/ui/testdata/ using Fyne's own test.AssertRendersToImage. This catches appearance/z-order bugs state alone can't see — it's what caught the "stale image left behind an error toast" regression during development.

Run just this suite natively with the command below. On a non-Linux/amd64 host, use make golden when the screenshot verdict itself matters.

go test -run TestE2E -v ./...

Updating a golden master: if a legitimate visual change makes one stale, regenerate it with make golden rather than a plain go test - Fyne's software rasterizer renders slightly different anti-aliased pixels depending on CPU architecture (its own test harness even special-cases darwin/arm64 for this), so a master captured by running go test directly on a non-amd64-Linux machine can pass there and still fail in CI, which runs on ubuntu-latest/amd64 with no such leniency. make golden renders inside a linux/amd64 container matching CI exactly (needs Docker), so the result is never machine-dependent. Either way, the new render lands at internal/ui/testdata/failed/<name>.png (gitignored — never committed) and the failure reports that path. Inspect it, and if it looks right, copy it over internal/ui/testdata/<name>.png to accept it as the new baseline.

Known gap: F1/the manual window isn't covered. Fyne's test theme only defines fonts for 6 specific TextStyle combinations, and the manual's markdown produces at least one combination outside that set, so measuring it panics on a nil font resource — a limitation in Fyne's test theme, not in this app.

A note on background goroutines: go test runs a package as one process, and Fyne's test driver runs fyne.Do callbacks inline on the calling goroutine rather than marshaling them to a UI thread — so a goroutine that outlives the test that started it will do UI work in the middle of a later, unrelated one. Every background operation therefore has a completion signal, and the suite has a helper to wait on it: settleToast after anything that raises a toast, settleThumbs/settleSlideshow/ settleChooser for the grid, picture-frame mode, and the file dialog, and dropAndWait (which covers the scan, the load, and its neighbor preloads) for a drop. Add the matching wait if you add a scenario that starts one.

Project layout

main.go                   Thin entry point: app setup, translations, CLI paths
internal/
  ui/                     Viewer state, app composition, and key dispatch
    run.go                Explicit startup/runtime/shutdown lifecycle
    startup.go            Startup state, defaults, and geometry restoration
    build.go              Top-level window and overlay composition
    components.go         App-owned widget clusters and layout
    features.go           Ordered construction of feature modules
    shortcuts.go          Global modified-key shortcut registration
    zoom/ grid/           Feature packages that own their widgets and state
    deletion/ slideshow/
    exifwin/ favorites/
    settingswin/ help/
    spiral/
    autoupdate/           Update orchestration and cached update state
    display/ infoview/    Viewer-decoupled display, info, and menu state
    menus/
    widgets/              Shared viewer-free UI mechanics
    assets/               Embedded placeholder and welcome artwork
    help/manual.md        Embedded end-user manual
    testdata/             Golden screenshots for the end-to-end suite
  imaging/                Probe, decode, orient, encode, and image caches
  update/                 Verified download, staging, and platform apply logic
  appearance/             Application-wide light/dark appearance handling
  preferences/ session/   Standing preferences and last-open file sets
  filescan/ filesort/     File discovery and ordering
  dupes/ selection/       Duplicate detection and selection helpers
  favstore/ favthumbs/    Favorite lists and their cached grid previews
  clipboard/ filepicker/  Platform integrations behind testable dispatchers
  trash/ wallpaper/
  openwith/               macOS Apple Event open queue
  completion/ decodepool/ Background-work coordination primitives
  wingesture/ winpos/     Window gesture and position tracking
  uitest/                 Shared fixtures, UI queues, and OS seam stubs
translations/             Embedded JSON translation bundles
assets/                   Application icon and README artwork
docs/agents/              Agent-facing domain and issue-triage guidance
scripts/                  Version, release, TUF, and WinGet automation
.github/                  CI/release workflows and community files
FyneApp.toml              Fyne app metadata: name, ID, version, and build
Makefile                  Build, package, verification, and release tasks
ARCHITECTURE.md           Authoritative package map and navigation index

Contributing

Bug reports, feature requests, and pull requests are welcome — see CONTRIBUTING.md for how to get set up and what CI checks for. This project follows a Code of Conduct. Found a security issue? See SECURITY.md instead of opening a public issue.

License

MIT — see LICENSE. Third-party dependencies are listed with their own licenses in THIRD-PARTY-NOTICES.md.

Development

Built with the assistance of Coffee and Claude Code.

Trane mit Bilderrahmen

Documentation

Overview

Command picfetch is a desktop image viewer: drop files or folders onto it (or open them from the file dialog) and page through them.

This file is the whole of package main - app setup, translations, and the command-line arguments. Everything else lives in internal/ui; see ARCHITECTURE.md for the package map.

Directories

Path Synopsis
internal
appearance
Package appearance defines PicFetch's application-wide appearance modes and applies them without replacing Fyne's underlying theme.
Package appearance defines PicFetch's application-wide appearance modes and applies them without replacing Fyne's underlying theme.
clipboard
Package clipboard puts image data onto the system clipboard as a real image - not a file reference - so it can be pasted into another app (Slack, an image editor, ...) as an image, the way a browser's own "Copy Image" works.
Package clipboard puts image data onto the system clipboard as a real image - not a file reference - so it can be pasted into another app (Slack, an image editor, ...) as an image, the way a browser's own "Copy Image" works.
completion
Package completion is the one-shot "this background operation has finished" signal that the viewer grew nine hand-rolled copies of, and that internal/ui/exifwin grew a tenth for the Location-section map prefetch: a channel replaced at the start of each request and closed when that request finishes, which the test suite waits on instead of polling widget state a producer goroutine may still be writing.
Package completion is the one-shot "this background operation has finished" signal that the viewer grew nine hand-rolled copies of, and that internal/ui/exifwin grew a tenth for the Location-section map prefetch: a channel replaced at the start of each request and closed when that request finishes, which the test suite waits on instead of polling widget state a producer goroutine may still be writing.
decodepool
Package decodepool bounds background decode work.
Package decodepool bounds background decode work.
dupes
Package dupes owns which files in a file set are duplicates of which other files: dHashes and native pixel sizes keyed by a stable string per file, the Hamming distance threshold that turns those hashes into groups, and the groups themselves.
Package dupes owns which files in a file set are duplicates of which other files: dHashes and native pixel sizes keyed by a stable string per file, the Hamming distance threshold that turns those hashes into groups, and the groups themselves.
favstore
Package favstore persists named lists of image files.
Package favstore persists named lists of image files.
favthumbs
Package favthumbs persists grid previews for a favorite's files under that favorite's own directory.
Package favthumbs persists grid previews for a favorite's files under that favorite's own directory.
filepicker
Package filepicker opens the current OS's own file/folder browser and returns the paths the user picked.
Package filepicker opens the current OS's own file/folder browser and returns the paths the user picked.
filescan
Package filescan gathers displayable image files from a dropped or opened set of paths.
Package filescan gathers displayable image files from a dropped or opened set of paths.
filesort
Package filesort orders a set of image files for display: by natural (numeric-aware) file name, by Exif capture date, by modification time, by size, or not at all.
Package filesort orders a set of image files for display: by natural (numeric-aware) file name, by Exif capture date, by modification time, by size, or not at all.
imaging
Package imaging reads, decodes, EXIF-orients, and caches the image files PicFetch displays: JPEG, PNG, GIF (including animated), WebP, BMP, TIFF, ICO, XPM, HEIC, AVIF, SVG, and camera RAW (embedded JPEG preview only — see raw.go).
Package imaging reads, decodes, EXIF-orients, and caches the image files PicFetch displays: JPEG, PNG, GIF (including animated), WebP, BMP, TIFF, ICO, XPM, HEIC, AVIF, SVG, and camera RAW (embedded JPEG preview only — see raw.go).
openwith
Package openwith buffers files the OS hands the process before the viewer is ready to receive them, and parses the file:// URLs LaunchServices delivers them as.
Package openwith buffers files the OS hands the process before the viewer is ready to receive them, and parses the file:// URLs LaunchServices delivers them as.
preferences
Package preferences persists and restores standing UI preferences - sort order, merge mode, application appearance, the picture-frame slideshow's interval and shuffle order, window size and position, whether the window stays a fixed size, and whether favorite previews are cached to disk - across launches, via Fyne's app-scoped Preferences store.
Package preferences persists and restores standing UI preferences - sort order, merge mode, application appearance, the picture-frame slideshow's interval and shuffle order, window size and position, whether the window stays a fixed size, and whether favorite previews are cached to disk - across launches, via Fyne's app-scoped Preferences store.
selection
Package selection is the multi-select model behind the grid overview's batch actions: which files are picked, and the anchor a range extension measures from.
Package selection is the multi-select model behind the grid overview's batch actions: which files are picked, and the anchor a range extension measures from.
session
Package session persists and restores the set of files that were open when the window last closed, via Fyne's app-scoped cache.
Package session persists and restores the set of files that were open when the window last closed, via Fyne's app-scoped cache.
trash
Package trash moves a file to the current OS's trash/recycle bin rather than deleting it permanently, so Shift+Delete in the app is as recoverable as a delete from Finder/Explorer/a Linux file manager already is.
Package trash moves a file to the current OS's trash/recycle bin rather than deleting it permanently, so Shift+Delete in the app is as recoverable as a delete from Finder/Explorer/a Linux file manager already is.
ui
Package ui is the application itself: the viewer, its widgets, and every feature wired onto it.
Package ui is the application itself: the viewer, its widgets, and every feature wired onto it.
ui/assets
Package assets holds the images the UI embeds into the binary.
Package assets holds the images the UI embeds into the binary.
ui/autoupdate
Package autoupdate owns the opt-in release-check/download policy, the staged-update lifecycle, and the What's-New cache (whatsnew.go).
Package autoupdate owns the opt-in release-check/download policy, the staged-update lifecycle, and the What's-New cache (whatsnew.go).
ui/copyselection
Package copyselection owns the transient interaction for selecting an image-space rectangle to copy, including crop and PNG encode of the captured source.
Package copyselection owns the transient interaction for selecting an image-space rectangle to copy, including crop and PNG encode of the captured source.
ui/deletion
Package deletion is the Shift+Delete confirmation flow: a dimmed scrim behind a centered card asking whether to move the file on screen to the Trash, and the trash.Move that follows if the user says yes.
Package deletion is the Shift+Delete confirmation flow: a dimmed scrim behind a centered card asking whether to move the file on screen to the Trash, and the trash.Move that follows if the user says yes.
ui/display
Package display owns what internal/ui's viewer currently has on the canvas: the current image's decoded frames, which of them is up, the view-only rotation, and the picture-frame crossfade.
Package display owns what internal/ui's viewer currently has on the canvas: the current image's decoded frames, which of them is up, the view-only rotation, and the picture-frame crossfade.
ui/exifwin
Package exifwin is the EXIF metadata window: a small panel listing the current image's camera settings, opened with the E key or the info overlay's "Show EXIF data" link.
Package exifwin is the EXIF metadata window: a small panel listing the current image's camera settings, opened with the E key or the info overlay's "Show EXIF data" link.
ui/favorites
Package favorites owns the Favorites menu and its dialogs.
Package favorites owns the Favorites menu and its dialogs.
ui/grid
Package grid is the full-window thumbnail overview (the G key): a virtualized grid of every loaded image, for jumping around a large drop by sight instead of arrowing through it one file at a time.
Package grid is the full-window thumbnail overview (the G key): a virtualized grid of every loaded image, for jumping around a large drop by sight instead of arrowing through it one file at a time.
ui/help
Package help is the app's documentation UI: the embedded end-user manual, the About box, and the Help menu that opens either.
Package help is the app's documentation UI: the embedded end-user manual, the About box, and the Help menu that opens either.
ui/infoview
Package infoview owns the persistent info overlay (the I key, see internal/ui/info.go's toggleInfoOverlay): its three widgets - the text label, the "Show EXIF data" link, and the card container - the current file's raw facts (byte size, EXIF presence, RAW-preview flag), and its own toggle preference and text formatting.
Package infoview owns the persistent info overlay (the I key, see internal/ui/info.go's toggleInfoOverlay): its three widgets - the text label, the "Show EXIF data" link, and the card container - the current file's raw facts (byte size, EXIF presence, RAW-preview flag), and its own toggle preference and text formatting.
ui/menus
Package menus owns the window menu bar's stateful items - the File, Window and Actions entries whose Checked/Disabled state has to move as the app's state moves - and computes that whole matrix in one place, as a pure function of a State value snapshot.
Package menus owns the window menu bar's stateful items - the File, Window and Actions entries whose Checked/Disabled state has to move as the app's state moves - and computes that whole matrix in one place, as a pure function of a State value snapshot.
ui/settingswin
Package settingswin is the Settings window, reachable from the File menu: one place to see and change every standing preference the app has - sort order, appearance, merge mode, picture-frame shuffle and interval, the folder-scan cap, the window-size cap, whether the window stays a fixed size, the three memory limits (image cache, thumbnail cache, maximum file size), and whether favorite previews are cached to disk - instead of only discovering them by stumbling onto their keyboard shortcuts.
Package settingswin is the Settings window, reachable from the File menu: one place to see and change every standing preference the app has - sort order, appearance, merge mode, picture-frame shuffle and interval, the folder-scan cap, the window-size cap, whether the window stays a fixed size, the three memory limits (image cache, thumbnail cache, maximum file size), and whether favorite previews are cached to disk - instead of only discovering them by stumbling onto their keyboard shortcuts.
ui/slideshow
Package slideshow is picture-frame mode (the P key): the window goes full-screen and, with more than one file loaded, advances to the next image on its own every few seconds - a photo frame rather than a viewer.
Package slideshow is picture-frame mode (the P key): the window goes full-screen and, with more than one file loaded, advances to the next image on its own every few seconds - a photo frame rather than a viewer.
ui/spiral
Package spiral is the Hypno Spiral easter egg: a full-screen, GPU-shader spiral in a window of its own, ported from a standalone Fyne demo into picfetch's package layout.
Package spiral is the Hypno Spiral easter egg: a full-screen, GPU-shader spiral in a window of its own, ported from a standalone Fyne demo into picfetch's package layout.
ui/widgets
Package widgets holds the viewer-free UI mechanics shared across the app's feature packages: the tappable area behind the drop zone, the singleton-window helper the secondary windows share, and the style values below.
Package widgets holds the viewer-free UI mechanics shared across the app's feature packages: the tappable area behind the drop zone, the singleton-window helper the secondary windows share, and the style values below.
ui/zoom
Package zoom is the zoom/pan view of the displayed image: the 0/1/+/- keys, click-and-drag panning, and scroll-to-zoom anchored at the pointer.
Package zoom is the zoom/pan view of the displayed image: the 0/1/+/- keys, click-and-drag panning, and scroll-to-zoom anchored at the pointer.
uitest
Package uitest provides test fixtures shared by this module's test suites: synthetic image files in every format the viewer reads, the temp files and URIs to hand them over by, and swap-in stubs for the OS-level seams (file chooser, image clipboard).
Package uitest provides test fixtures shared by this module's test suites: synthetic image files in every format the viewer reads, the temp files and URIs to hand them over by, and swap-in stubs for the OS-level seams (file chooser, image clipboard).
update
Package update talks to GitHub Releases, verifies GitHub immutable release attestations, and replaces the running binary.
Package update talks to GitHub Releases, verifies GitHub immutable release attestations, and replaces the running binary.
wallpaper
Package wallpaper sets the current OS's desktop wallpaper to an image file, for the Actions > "Set as Wallpaper" action.
Package wallpaper sets the current OS's desktop wallpaper to an image file, for the Actions > "Set as Wallpaper" action.
wingesture
Package wingesture recognises a spiral drawn by dragging a window around the desktop, and which way round it was drawn.
Package wingesture recognises a spiral drawn by dragging a window around the desktop, and which way round it was drawn.
winpos
Package winpos reads and writes the on-screen position of a Fyne desktop window.
Package winpos reads and writes the on-screen position of a Fyne desktop window.
scripts
plistdoctypes command
Command plistdoctypes inserts CFBundleDocumentTypes into a packaged macOS Info.plist.
Command plistdoctypes inserts CFBundleDocumentTypes into a packaged macOS Info.plist.
releasenotes command
Command releasenotes builds GitHub release notes from todos.md's ## Done section.
Command releasenotes builds GitHub release notes from todos.md's ## Done section.
synctuf command
Command synctuf checks or refreshes the GitHub TUF root embed used by the in-app updater.
Command synctuf checks or refreshes the GitHub TUF root embed used by the in-app updater.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL