Some checks failed
CI / skip-ci-check (pull_request) Successful in 7s
CI / python-lint (pull_request) Has been cancelled
CI / test-backend (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / secret-scanning (pull_request) Has been cancelled
CI / dependency-scan (pull_request) Has been cancelled
CI / sast-scan (pull_request) Has been cancelled
CI / workflow-summary (pull_request) Has been cancelled
CI / lint-and-type-check (pull_request) Has been cancelled
- Added media_type to PhotoSearchResult interface to distinguish between images and videos. - Updated PhotoViewer component to support video playback, including URL handling and preloading logic. - Modified openPhoto function in Search page to open videos correctly. - Enhanced backend API to serve video files with range request support for better streaming experience. These changes improve the user experience by allowing seamless viewing of both images and videos in the application.
51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""Search schemas for Phase 5."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date
|
|
from typing import List, Optional
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class SearchPhotosQuery(BaseModel):
|
|
"""Query parameters for searching photos."""
|
|
|
|
person_ids: Optional[List[int]] = Field(None, description="Filter by person IDs")
|
|
tag_ids: Optional[List[int]] = Field(None, description="Filter by tag IDs")
|
|
date_from: Optional[date] = Field(None, description="Filter by date taken (from)")
|
|
date_to: Optional[date] = Field(None, description="Filter by date taken (to)")
|
|
min_quality: Optional[float] = Field(None, ge=0.0, le=1.0, description="Minimum face quality score")
|
|
folder_path: Optional[str] = Field(None, description="Filter by folder path prefix")
|
|
sort_by: str = Field("date_taken", description="Sort column: date_taken, date_added, filename, path")
|
|
sort_dir: str = Field("desc", description="Sort direction: asc|desc")
|
|
page: int = Field(1, ge=1, description="Page number")
|
|
page_size: int = Field(50, ge=1, le=200, description="Page size")
|
|
|
|
|
|
class PhotoSearchResult(BaseModel):
|
|
"""Photo search result item."""
|
|
|
|
id: int
|
|
path: str
|
|
filename: str
|
|
date_taken: Optional[date] = None
|
|
date_added: date
|
|
processed: bool
|
|
media_type: Optional[str] = "image" # "image" or "video"
|
|
person_name: Optional[str] = None # For name search
|
|
tags: List[str] = Field(default_factory=list) # All tags for the photo
|
|
has_faces: bool = False
|
|
face_count: int = 0
|
|
is_favorite: bool = False # Whether photo is favorited by current user
|
|
|
|
|
|
class SearchPhotosResponse(BaseModel):
|
|
"""Response for photo search."""
|
|
|
|
items: List[PhotoSearchResult]
|
|
page: int
|
|
page_size: int
|
|
total: int
|
|
|