Lets operators fix corrupted capture dates at scale. Adds an editable Date Taken field with a folder/filename-derived suggestion hint, a bulk Date Taken section in the multi-select sidebar that either applies one date to the whole selection or infers a per-photo date from each path, a warning badge on thumbnails whose stored date disagrees with the path, and a "Date issues" filter pill so suspicious photos can be surfaced and fixed as a group. Edits are written back to EXIF on disk so rescans don't clobber the fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
50 lines
1.5 KiB
Python
50 lines
1.5 KiB
Python
"""photos has_date_warning flag
|
|
|
|
Revision ID: 0008_photos_date_warning
|
|
Revises: 0007_folder_hidden
|
|
Create Date: 2026-04-11
|
|
|
|
Adds `photos.has_date_warning` — a denormalized boolean that's true when
|
|
the scanner's folder/filename date guesser disagrees with the stored
|
|
taken_at by more than 24h (or taken_at is missing and the path would
|
|
provide a date). Surfacing this as a real column means the filter bar
|
|
can restrict the timeline to suspicious photos without the client
|
|
recomputing the heuristic for every row.
|
|
|
|
Indexed because the filter is meant to run on top of the existing
|
|
taken_at / folder queries that dominate the timeline, and we want the
|
|
partial `WHERE has_date_warning` scan to stay cheap as the library
|
|
grows.
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision: str = "0008_photos_date_warning"
|
|
down_revision: Union[str, None] = "0007_folder_hidden"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.add_column(
|
|
"photos",
|
|
sa.Column(
|
|
"has_date_warning",
|
|
sa.Boolean(),
|
|
nullable=False,
|
|
server_default=sa.false(),
|
|
),
|
|
)
|
|
op.create_index(
|
|
"ix_photos_has_date_warning",
|
|
"photos",
|
|
["has_date_warning"],
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_photos_has_date_warning", table_name="photos")
|
|
op.drop_column("photos", "has_date_warning")
|