Commit Graph
7 Commits
Author SHA1 Message Date
Cameron CordesandClaude Opus 5.5 bfc3c1c21a feat(dates): calendar-day date filters in the owner's display zone (#152)
/photos, /photos/exif and unified search take date_from_day /
date_to_day (YYYY-MM-DD): the server turns them into the first day's
start and the last day's end in the owner's display zone, the same days
/memories groups by. Each replaces its instant counterpart. Clients stop
computing midnights in the device's zone, which drifted by the travel
offset whenever the phone's zone differed from display_tz.

e2e check: every fixture is included by its display-zone day and
excluded by the days either side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 03:24:50 +00:00
Cameron CordesandClaude Opus 5.5 a6d7b8f3a0 docs(e2e): note native Linux support and E2E_PORT
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:45:01 -04:00
Cameron CordesandClaude Opus 5.5 b7943be022 chore(e2e): run the e2e dev server on native Linux
e2e.sh and gen_fixtures.py assumed WSL driving the Windows toolchain.
They now detect WSL (a microsoft kernel with cargo.exe available) and
otherwise use native tools:

- e2e.sh: cargo/curl instead of cargo.exe/curl.exe, pgrep/pkill
  instead of tasklist/taskkill, Linux paths in the generated .env, and
  binaries without the .exe suffix.
- gen_fixtures.py: picks the first ffmpeg that has the drawtext filter
  (a minimal build earlier on PATH may not; E2E_FFMPEG overrides), finds
  a monospace font with fc-match, and only translates paths with wslpath
  for .exe tools.
- Quote USER_NAME in the generated .env: the unquoted space made the
  dotenv parser reject the line.
- Mark the scripts executable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:27:47 -04:00
Cameron CordesandClaude Opus 5.5 19fbf43d40 feat(dates): photo date filters on the true instant (#152)
date_from / date_to on /photos, /photos/exif and unified search ran on
the legacy mixed-convention date_taken, so a photo could display inside
a range yet be filtered out of it by up to its UTC offset (or by years,
for rows the filename class re-dated).

The filter lives in the shared ExifDao::query_by_exif, so it's fixed
once there:

- query_by_exif takes Option<date_view::InstantRange> (bounds + display
  and server zones) instead of raw date_from / date_to.
- SQL pre-filter: converted rows on date_utc exactly; unconverted rows
  (drain pending, permanent floor) on date_taken widened by
  LEGACY_INSTANT_BAND_SECS (±15 h, now shared with /memories). Converted
  rows are deliberately not bounded by date_taken: a re-dated row's
  legacy value can sit years from its instant.
- Exact pass in Rust via InstantRange::contains → row_true_instant, so
  every returned row's true instant is inside the range.

Calendar days now mean the owner's days: nl_query::iso_to_unix builds
day bounds in the display zone (it used UTC midnights, which only lined
up with the legacy wall-as-UTC column), and unified search's "today" is
the owner's today rather than UTC's. The midnight-with-DST-gap fallback
moves from memories_anchor into date_view::day_start_instant.

Compatibility: clients already sending real instants (Apollo's
/photos/exif windows) get correct edges with no change. Clients sending
UTC-midnight day bounds see ranges shift by up to the UTC offset until
they send display-zone bounds.

No index on date_utc; the OR clause scans, which is milliseconds at
personal-library scale (same as /memories today).

dev/e2e check gains /photos/exif wall_clock + true_instant assertions and
range-edge checks ([t, t] in, [.., t-1] and [t+1, ..] out). Not run here:
the harness needs the WSL + Windows toolchain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:52:48 -04:00
Cameron CordesandClaude Opus 5.5 9269b5c9fd Dates: true_instant on metadata responses for instant matching
The mobile viewer anchored its "messages around this photo" window on
the legacy date_taken (a wall clock stored as UTC for EXIF rows), while
SMS-API dates are true instants: the window was off by the photo's UTC
offset (4-5 h for photos taken at home; ImageApi #113 user story 3).
Verified SMS-API side: importers store backup epochs as UTC, and 40/40
sampled rows equal their source epochs exactly.

`/image/metadata` (+ GPS / date mutation responses) now carries
`true_instant` from `date_view::file_true_instant`: `row_true_instant`,
else the filename-class instant, else the earliest fs time. Server-side
for the same reason as `wall_clock`: the drain's permanent floor rows
have no `date_utc`. `set_capture_dates` fills both fields at all four
response sites.

dev/e2e: the manifest records each fixture's expected instant (the wall
read in its GPS zone, else America/New_York) and `e2e.sh check` asserts
it (97/97).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:55:29 -04:00
Cameron CordesandClaude Opus 5.5 bc41c737e5 dev/e2e: wall_clock regression check + deterministic fixture dates
`e2e.sh check` compares every indexed fixture's manifest wall clock with
the `wall_clock` reported by /image/metadata, /memories and
/photos/gps-summary; any disagreement fails.

- Fixture videos are stamped like phone containers: the America/New_York
  wall as a UTC creation_time (the label previously showed the UTC time).
- mtimes are pinned in America/New_York instead of the host's zone.
- The e2e env sets TZ=America/New_York (the #120 preflight): the Windows
  exe has no /etc/timezone, so server_zone() was otherwise None.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:54:47 -04:00
Cameron CordesandClaude Opus 5.5 f00a309a24 dev/e2e: disposable server for app e2e / agent UI testing
`dev/e2e/e2e.sh up` runs an isolated ImageApi (port 8090, own build dir,
db, thumbnails, HLS) next to a real local server, serving a copy of a
synthetic fixture library. Every fixture image has its path, date and
scenario burned into the pixels; manifest.json records expected dates,
GPS, cameras, tags and counts. `reset` restores the baseline.

- LOCAL_BIND_URL makes the hardcoded localhost:8088 listener
  configurable (default unchanged; empty disables it) so a second
  instance can start.
- create_user bin: the server has no registration route; idempotent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 13:02:49 -04:00