258 lines
7.7 KiB
Markdown
258 lines
7.7 KiB
Markdown
# Timeline & Photos
|
|
|
|
This document describes the photo timeline, asset display, and related functionality.
|
|
|
|
## Timeline Overview
|
|
|
|
The timeline is the main view of the app, displaying all photos and videos in chronological order (newest first).
|
|
|
|
## Asset Types
|
|
|
|
### Asset States
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Asset States │
|
|
├───────────────┬───────────────┬─────────────────────────────┤
|
|
│ LOCAL │ REMOTE │ MERGED │
|
|
├───────────────┼───────────────┼─────────────────────────────┤
|
|
│ On device │ On server │ Both device and server │
|
|
│ Not uploaded │ Not on device │ Linked by checksum │
|
|
│ localId set │ remoteId set │ Both IDs set │
|
|
└───────────────┴───────────────┴─────────────────────────────┘
|
|
```
|
|
|
|
### Asset Model
|
|
```
|
|
Asset {
|
|
id: String // Unique identifier
|
|
name: String // Filename
|
|
type: AssetType // image, video, audio, other
|
|
createdAt: DateTime // When created/taken
|
|
updatedAt: DateTime // Last modified
|
|
checksum: String? // File hash for deduplication
|
|
width: Integer? // Image/video width
|
|
height: Integer? // Image/video height
|
|
durationInSeconds: Int? // Video duration
|
|
isFavorite: Boolean // Marked as favorite
|
|
isArchived: Boolean // Hidden from timeline
|
|
isTrashed: Boolean // In trash
|
|
livePhotoVideoId: String? // Paired video for live photos
|
|
|
|
// State indicators
|
|
localId: String? // Device gallery ID
|
|
remoteId: String? // Server asset ID
|
|
storage: AssetState // local, remote, or merged
|
|
}
|
|
```
|
|
|
|
### Asset Types Enum
|
|
| Type | Description |
|
|
|------|-------------|
|
|
| image | Photos (JPEG, PNG, HEIC, etc.) |
|
|
| video | Videos (MP4, MOV, etc.) |
|
|
| audio | Audio files |
|
|
| other | Other file types |
|
|
|
|
### Playback Styles
|
|
| Style | Description |
|
|
|-------|-------------|
|
|
| image | Static image |
|
|
| video | Full video |
|
|
| imageAnimated | GIF or animated image |
|
|
| livePhoto | Photo with motion component |
|
|
| videoLooping | Short looping video |
|
|
|
|
## Timeline Display
|
|
|
|
### Grid Configuration
|
|
- **Tiles per row**: Configurable (default: 4)
|
|
- **Dynamic layout**: Optional variable row heights
|
|
- **Group by**: Day, Month, or None
|
|
|
|
### Date Headers
|
|
Assets are grouped by date with section headers:
|
|
```
|
|
December 2024
|
|
├── Dec 15 (if grouping by day)
|
|
│ └── [asset grid]
|
|
├── Dec 14
|
|
│ └── [asset grid]
|
|
...
|
|
```
|
|
|
|
### Asset Thumbnail Display
|
|
Each asset shows:
|
|
- Thumbnail image
|
|
- Video duration (if video)
|
|
- Live photo indicator (if motion photo)
|
|
- Favorite indicator (heart icon)
|
|
- Selection checkbox (in multi-select mode)
|
|
- Stack indicator (if part of stack)
|
|
|
|
## Loading Strategy
|
|
|
|
### Pagination
|
|
- Timeline loads in batches (default: 1024 assets)
|
|
- Additional assets loaded when scrolling
|
|
- Opposite direction pre-loading (64 assets)
|
|
|
|
### Thumbnail Loading
|
|
1. Check local cache first
|
|
2. Load from local device if available
|
|
3. Fetch from server with thumbhash placeholder
|
|
4. Cache for future use
|
|
|
|
### Image Quality Levels
|
|
| Level | Use Case | Resolution |
|
|
|-------|----------|------------|
|
|
| Thumbhash | Instant placeholder | ~4x4 blurred |
|
|
| Thumbnail | Grid view | ~250px |
|
|
| Preview | Full screen initial | ~1080px |
|
|
| Original | Full zoom | Full resolution |
|
|
|
|
## Multi-User Timeline
|
|
|
|
When partner sharing is enabled:
|
|
- Timeline can include multiple users' assets
|
|
- Assets are merged chronologically
|
|
- User indicator shows asset owner
|
|
|
|
## Multi-Select Mode
|
|
|
|
### Activation
|
|
- Long press on any asset
|
|
- Or tap select button in app bar
|
|
|
|
### Available Actions
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ [X] Cancel Selected: 5 │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ ♥ Favorite │ 📦 Archive │ 🗑 Delete │ 📤 Share │ ⋮ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Actions Available
|
|
| Action | Description |
|
|
|--------|-------------|
|
|
| Favorite | Toggle favorite status |
|
|
| Archive | Move to archive |
|
|
| Delete | Move to trash |
|
|
| Share | Share via system share |
|
|
| Download | Download to device |
|
|
| Add to Album | Add to existing/new album |
|
|
| Create Stack | Stack selected assets |
|
|
| Move to Locked | Move to locked folder |
|
|
|
|
## Pull to Refresh
|
|
|
|
### Refresh Behavior
|
|
1. Single pull: Incremental sync
|
|
2. Double pull (within 4 seconds): Full refresh
|
|
- Clears local cache
|
|
- Re-fetches all data
|
|
|
|
### Sync Process
|
|
1. Check server for new assets
|
|
2. Download metadata for new assets
|
|
3. Update local database
|
|
4. Refresh album data
|
|
5. Update UI
|
|
|
|
## Memory Lane
|
|
|
|
### Display
|
|
- Horizontal scrolling widget at top of timeline
|
|
- Shows "X years ago" cards
|
|
- Only visible if user has memories enabled
|
|
|
|
### Memory Card
|
|
```
|
|
┌─────────────────┐
|
|
│ [Thumbnail] │
|
|
│ │
|
|
│ 2 years ago │
|
|
└─────────────────┘
|
|
```
|
|
|
|
### Memory API
|
|
```
|
|
GET /memories?for={today's date}
|
|
|
|
Response: Array of Memory objects
|
|
{
|
|
"id": "memory-id",
|
|
"data": {
|
|
"year": 2022
|
|
},
|
|
"assets": [...]
|
|
}
|
|
```
|
|
|
|
## Scroll Scrubber
|
|
|
|
### Features
|
|
- Appears on right side when scrolling
|
|
- Shows date labels
|
|
- Drag to quickly navigate
|
|
- Snaps to month boundaries (if enough history)
|
|
|
|
### Configuration
|
|
- Enabled when timeline spans 12+ months
|
|
- Custom scroll controller for smooth navigation
|
|
|
|
## Asset Visibility
|
|
|
|
Assets can have different visibility states:
|
|
|
|
| State | Timeline | Archive | Trash | Locked |
|
|
|-------|----------|---------|-------|--------|
|
|
| Normal | ✓ | | | |
|
|
| Archived | | ✓ | | |
|
|
| Trashed | | | ✓ | |
|
|
| Hidden/Locked | | | | ✓ |
|
|
|
|
## Asset Stacks
|
|
|
|
Multiple similar assets can be "stacked":
|
|
- Only primary asset shown in timeline
|
|
- Stack indicator shows count
|
|
- Tap to view stack contents
|
|
- Can unstack to separate
|
|
|
|
## Real-time Updates
|
|
|
|
Via WebSocket connection:
|
|
- New uploads appear immediately
|
|
- Deletions remove assets from view
|
|
- Updates refresh asset metadata
|
|
|
|
### WebSocket Events
|
|
| Event | Action |
|
|
|-------|--------|
|
|
| on_upload_success | Add new asset to timeline |
|
|
| on_asset_delete | Remove asset |
|
|
| on_asset_trash | Move to trash |
|
|
| on_asset_restore | Restore from trash |
|
|
| on_asset_update | Refresh metadata |
|
|
| on_asset_hidden | Hide from timeline |
|
|
|
|
## Performance Optimizations
|
|
|
|
1. **Virtualized list**: Only renders visible items
|
|
2. **Image caching**: Configurable cache size
|
|
3. **Lazy loading**: Load data as needed
|
|
4. **Debounced scroll**: Reduce render calls
|
|
5. **Background prefetching**: Load ahead
|
|
|
|
### Cache Settings
|
|
| Setting | Default | Description |
|
|
|---------|---------|-------------|
|
|
| thumbnailCacheSize | 10000 | Max cached thumbnails |
|
|
| imageCacheSize | 350 | Max cached full images |
|
|
| albumThumbnailCacheSize | 200 | Max album thumbs |
|
|
|
|
---
|
|
|
|
[Previous: Main Navigation](./main-screens.md) | [Next: Search](./search.md)
|