ui(duplicates): show parent folder + full-path tooltip on each thumbnail
Two copies of IMG_1234.jpg sitting in different folders looked identical on the duplicates grid — same filename, same dimensions, same Best heuristic. The user had no way to pick which copy to keep without opening each in the preview overlay. Backend: include filepath in the per-member payload from GET /api/v1/library/duplicates/groups (was filename-only). Frontend: a black 65% strip at the bottom of every duplicate thumbnail showing the parent folder name (the actual discriminator when filenames match), with the full filepath surfaced via the native title tooltip on hover. The dimensions chip moves from bottom-left to top-left so the bottom strip can run edge-to-edge. memberToPhoto stops faking filepath=filename (a years-old workaround that broke any code path needing the real path); the synthetic Photo the grid hands to PhotoThumbnail now carries the real filepath. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -733,6 +733,7 @@ async def get_duplicate_groups(
|
||||
select(
|
||||
Photo.id,
|
||||
Photo.filename,
|
||||
Photo.filepath,
|
||||
Photo.taken_at,
|
||||
Photo.file_size,
|
||||
Photo.width,
|
||||
@@ -751,22 +752,25 @@ async def get_duplicate_groups(
|
||||
)
|
||||
).all()
|
||||
|
||||
# Bucket members by group_id.
|
||||
# Bucket members by group_id. filepath is included so the
|
||||
# Duplicates view can show "which folder does this copy live in"
|
||||
# — the discriminator the user needs to pick a winner.
|
||||
groups: dict[str, list[dict]] = {}
|
||||
for row in rows:
|
||||
member = {
|
||||
"id": row[0],
|
||||
"filename": row[1],
|
||||
"taken_at": row[2].isoformat() if row[2] else None,
|
||||
"file_size": row[3],
|
||||
"width": row[4],
|
||||
"height": row[5],
|
||||
"thumb_small": row[6],
|
||||
"file_hash": row[7],
|
||||
"folder_id": row[8],
|
||||
"media_type": row[9],
|
||||
"filepath": row[2],
|
||||
"taken_at": row[3].isoformat() if row[3] else None,
|
||||
"file_size": row[4],
|
||||
"width": row[5],
|
||||
"height": row[6],
|
||||
"thumb_small": row[7],
|
||||
"file_hash": row[8],
|
||||
"folder_id": row[9],
|
||||
"media_type": row[10],
|
||||
}
|
||||
groups.setdefault(row[10], []).append(member)
|
||||
groups.setdefault(row[11], []).append(member)
|
||||
|
||||
def earliest(g: list[dict]) -> str:
|
||||
# Used as a secondary sort key. Photos with no taken_at sort last
|
||||
|
||||
Reference in New Issue
Block a user