Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a6445b9
implemented the memory feature backend
dehydrated-bear Dec 13, 2025
109b438
package json files
dehydrated-bear Dec 13, 2025
7f7012f
feat: enhance Memories UI with improved titles and event bubbling fix
dehydrated-bear Dec 14, 2025
a362967
style: format code with Black and Prettier
dehydrated-bear Dec 14, 2025
9eba77c
docs: add comprehensive Memories feature documentation
dehydrated-bear Dec 14, 2025
d5ad544
orrect DBSCAN clustering and API configuration issues
dehydrated-bear Dec 14, 2025
1b7ee7b
correct DBSCAN clustering and API configuration issues
dehydrated-bear Dec 14, 2025
536455c
Add the missing /placeholder-image.png asset to frontend/public/
dehydrated-bear Dec 14, 2025
32cabca
Merge branch 'AOSSIE-Org:main' into feat/memories-backend-implementation
dehydrated-bear Jan 26, 2026
c5f1a6a
fix:resolved the iamge viewer error
dehydrated-bear Jan 26, 2026
22659e2
Merge remote-tracking branch 'upstream/main' into feat/memories-backe…
dehydrated-bear Jan 26, 2026
ef58dae
fix:nullable values and migration guard
dehydrated-bear Jan 26, 2026
0b07cc3
Merge remote-tracking branch 'origin/feat/memories-backend-implementa…
dehydrated-bear Jan 26, 2026
719bbc4
minor fixes and linting and formatting
dehydrated-bear Jan 26, 2026
a1815ef
fix: minor tweaks and port update to 52123
dehydrated-bear Jan 26, 2026
b65de08
fix:improved date handling and added timeouts
dehydrated-bear Jan 27, 2026
38d30d8
fix:improved zsuffix handling
dehydrated-bear Jan 27, 2026
b999b80
fix:changed async def to def
dehydrated-bear Jan 27, 2026
665357a
fix:improved encapsulation and changed the date tolerance
dehydrated-bear Jan 27, 2026
ab28916
fix:docs fixfor consitency
dehydrated-bear Jan 27, 2026
8e924b5
fix:type error prevention
dehydrated-bear Jan 27, 2026
6557238
fix:using hashlib to improve memmory_id production
dehydrated-bear Jan 27, 2026
1833d86
Merge remote-tracking branch 'upstream/main' into feat/memories-backe…
dehydrated-bear Feb 3, 2026
99e0eff
fix: remove invalid ignoreDeprecations from tsconfig.json
dehydrated-bear Feb 3, 2026
3bb6895
style: apply black and ruff formatting to backend
dehydrated-bear Feb 3, 2026
d045895
feat: add type field to Memory schema for location/date distinction
dehydrated-bear Feb 3, 2026
82b3b49
Merge branch 'AOSSIE-Org:main' into feat/memories-backend-implementation
dehydrated-bear Feb 5, 2026
6b6a6e0
standardized the ui and linting
dehydrated-bear Feb 11, 2026
b4e2be5
fix: preserve 0.0 coordinates and improve memories UX
dehydrated-bear Feb 12, 2026
2432065
frontend linting fix
dehydrated-bear Feb 15, 2026
f95e863
addressed teh pr reviews
dehydrated-bear Feb 15, 2026
1091dd8
addressed the pr chagnes tanquery and deleted migrate files
dehydrated-bear Feb 15, 2026
d0380f2
fixed frontend linting
dehydrated-bear Feb 15, 2026
7e1bd9e
fixed the build errorMessage
dehydrated-bear Feb 15, 2026
36bc3bb
review comments addressed
dehydrated-bear Feb 15, 2026
2d9e5c2
review comments addressed
dehydrated-bear Feb 15, 2026
de0df78
linting and formatiing change
dehydrated-bear Feb 15, 2026
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
496 changes: 490 additions & 6 deletions backend/app/database/images.py

Large diffs are not rendered by default.

435 changes: 435 additions & 0 deletions backend/app/routes/memories.py

Large diffs are not rendered by default.

415 changes: 415 additions & 0 deletions backend/app/utils/extract_location_metadata.py

Large diffs are not rendered by default.

60 changes: 49 additions & 11 deletions backend/app/utils/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import datetime
import json
import logging
from typing import List, Tuple, Dict, Any, Mapping
from typing import List, Tuple, Dict, Any, Mapping, Optional
from PIL import Image, ExifTags
from pathlib import Path

Expand All @@ -19,6 +19,7 @@
from app.models.FaceDetector import FaceDetector
from app.models.ObjectClassifier import ObjectClassifier
from app.logging.setup_logging import get_logger
from app.utils.extract_location_metadata import MetadataExtractor

logger = get_logger(__name__)

Expand Down Expand Up @@ -141,6 +142,7 @@ def image_util_prepare_image_records(
) -> List[Dict]:
"""
Prepare image records with thumbnails for database insertion.
Automatically extracts GPS coordinates and capture datetime from metadata.

Args:
image_files: List of image file paths
Expand All @@ -150,6 +152,8 @@ def image_util_prepare_image_records(
List of image record dictionaries ready for database insertion
"""
image_records = []
extractor = MetadataExtractor()

for image_path in image_files:
folder_id = image_util_find_folder_id_for_image(image_path, folder_path_to_id)

Expand All @@ -166,16 +170,50 @@ def image_util_prepare_image_records(
if image_util_generate_thumbnail(image_path, thumbnail_path):
metadata = image_util_extract_metadata(image_path)
logger.debug(f"Extracted metadata for {image_path}: {metadata}")
image_records.append(
{
"id": image_id,
"path": image_path,
"folder_id": folder_id,
"thumbnailPath": thumbnail_path,
"metadata": json.dumps(metadata),
"isTagged": False,
}
)

# Automatically extract GPS coordinates and datetime from metadata
# Don't fail upload if extraction fails
metadata_json = json.dumps(metadata)
latitude, longitude, captured_at = None, None, None

try:
latitude, longitude, captured_at = extractor.extract_all(metadata_json)

# Log GPS extraction results
if latitude and longitude:
logger.info(
f"GPS extracted for {os.path.basename(image_path)}: ({latitude}, {longitude})"
)
if captured_at:
logger.debug(
f"Date extracted for {os.path.basename(image_path)}: {captured_at}"
)
except Exception as e:
logger.warning(
f"GPS extraction failed for {os.path.basename(image_path)}: {e}"
)
# Continue without GPS - don't fail the upload

# Build image record with GPS data
# ALWAYS include latitude, longitude, captured_at (even if None)
# to satisfy SQL INSERT statement named parameters
image_record = {
"id": image_id,
"path": image_path,
"folder_id": folder_id,
"thumbnailPath": thumbnail_path,
"metadata": metadata_json,
"isTagged": False,
"latitude": latitude, # Can be None
"longitude": longitude, # Can be None
"captured_at": (
captured_at.isoformat()
if isinstance(captured_at, datetime.datetime) and captured_at
else captured_at
), # Can be None
}

image_records.append(image_record)

return image_records

Expand Down
Loading