Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

## [Unreleased]

## [1.0.5] — 2026-05-17

Source-folder validation fix: the "Choose source folder" pre-flight check no longer rejects collections whose media lives in subfolders, and now accepts the same set of extensions (including RAW) as the importer itself.

### Fixed
- **Recursive source-folder validation**: the UI pre-flight check (`_has_media_files`) walked only the top level of the chosen folder via `Path.iterdir()`, which rejected sources whose photos lived in nested subfolders (e.g. year/month layouts). Validation now walks the tree with `os.walk`, early-exits on first match, and skips hidden directories, `@eaDir` (Synology) and dotfiles — mirroring the scanner's traversal exactly. Nested subfolder layouts up to arbitrary depth are now accepted.
- **RAW format parity between validator and scanner**: the validator used a local `MEDIA_EXTENSIONS` constant that had drifted from `scanner.SUPPORTED_FORMATS`. RAW folders (`.cr2`, `.nef`, `.arw`, `.dng`, `.raw`) were silently rejected by the UI even though the scanner would happily import them. The validator now imports `SUPPORTED_FORMATS` directly from `icloudphotonator.scanner`, so photo + video extensions stay in lockstep with the importer.

### Internal
- Single source of truth for media-extension definitions (`scanner.SUPPORTED_FORMATS`); local `MEDIA_EXTENSIONS` constant removed from `icloudphotonator/ui/app.py`.
- +10 unit tests covering empty/top-level/nested (1–5 levels) folders, hidden-dir/`@eaDir`/dotfile skipping, sidecar/text-only rejection, Canon RAW detection and mixed-case extensions. Full suite: 266 → 276 passing, 0 regressions.

## [1.0.4] — 2026-05-16

FDA registration UX fix: app now appears reliably in System Settings → Privacy & Security → Full Disk Access on fresh macOS Tahoe installs, without requiring users to manually drag the bundle into the FDA pane via the "+" button.
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file documents non-obvious facts and conventions for AI assistants (and hum

## Landing Page (GitHub Pages)

- Public URL: https://hanselstner.github.io/icloudphotonator/
- Public URL: [https://hanselstner.github.io/icloudphotonator/](https://hanselstner.github.io/icloudphotonator/)
- Source: `main` branch, `/docs` folder (legacy Pages build, no Actions workflow)
- Single file: `docs/index.html` (no Jekyll, no build step)
- Download button URL is hardcoded — must be updated on every release to point at the new DMG asset
Expand Down Expand Up @@ -41,6 +41,6 @@ Additionally, `icloudphotonator/__main__.py` runs an early FDA-attribution probe

- Coordinator-agent workflow: spec note + delegated implementor agents; no direct edits by Coordinator
- Auto-commit is enabled in the workspace
- README.md has a hardcoded version badge (currently shows v1.0.2 — non-blocking, update opportunistically)
- Tests: `pytest` from repo root, 266+ passing as of v1.0.4
- README.md version badge is auto-updated by `scripts/build_release.sh` Step 8 on every release
- Tests: `pytest` from repo root, 276+ passing as of v1.0.5
- Python: 3.13+
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.

## Changelog

### v1.0.5 — May 17, 2026

- "Choose source folder" now accepts collections organised into subfolders (year/month, event-named, multi-level — up to arbitrary depth). Previously the picker rejected sources whose media lived only one level down.
- RAW formats (`.cr2`, `.nef`, `.arw`, `.dng`, `.raw`) are now recognised by the source-folder check, matching what the importer already supported.

### v1.0.4 — May 16, 2026

- Full Disk Access UI visibility fix on macOS Tahoe: bundle now declares the full standard set of `NS*UsageDescription` keys, so the app reliably appears in System Settings → Privacy & Security → Full Disk Access
Expand Down
2 changes: 1 addition & 1 deletion iCloudPhotonator.spec
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import customtkinter
from PyInstaller.utils.hooks import collect_all

APP_NAME = "iCloudPhotonator"
APP_VERSION = "1.0.4"
APP_VERSION = "1.0.5"
BUNDLE_IDENTIFIER = "com.hanselstner.icloudphotonator"
PROJECT_ROOT = Path(SPECPATH)
ENTRYPOINT = PROJECT_ROOT / "icloudphotonator" / "__main__.py"
Expand Down
2 changes: 1 addition & 1 deletion icloudphotonator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .job import Job
from .state import FileStatus, InvalidTransitionError, JobState, transition

__version__ = "1.0.3"
__version__ = "1.0.5"

__all__ = [
"Database",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "icloudphotonator"
version = "1.0.4"
version = "1.0.5"
description = "Intelligent photo migration helper for Apple Photos on macOS"
requires-python = ">=3.13"
dependencies = [
Expand Down
2 changes: 1 addition & 1 deletion tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


def test_package_version() -> None:
assert __version__ == "1.0.3"
assert __version__ == "1.0.5"
2 changes: 1 addition & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def test_version_works() -> None:
result = CliRunner().invoke(main, ["--version"])

assert result.exit_code == 0
assert "1.0.3" in result.output
assert "1.0.5" in result.output


def test_import_photos_help_shows_expected_options() -> None:
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading