Backend (Rust/Actix-web): - Add video_preview_clips table and PreviewDao for tracking preview generation - Add ffmpeg preview clip generator: 10 equally-spaced 1s segments at 480p with CUDA NVENC auto-detection - Add PreviewClipGenerator actor with semaphore-limited concurrent processing - Add GET /video/preview and POST /video/preview/status endpoints - Extend file watcher to detect and queue previews for new videos - Use relative paths consistently for DB storage (matching EXIF convention) Frontend (React Native/Expo): - Add VideoWall grid view with 2-3 column layout of looping preview clips - Add VideoWallItem component with ActiveVideoPlayer sub-component for lifecycle management - Add useVideoWall hook for batch status polling with 5s refresh - Add navigation button in grid header (visible when videos exist) - Use TextureView surface type to fix Android z-ordering issues - Optimize memory: players only mount while visible via FlatList windowSize - Configure ExoPlayer buffer options and caching for short clips - Tap to toggle audio focus, long press to open in full viewer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
185 lines
4.1 KiB
Rust
185 lines
4.1 KiB
Rust
// @generated automatically by Diesel CLI.
|
|
|
|
diesel::table! {
|
|
calendar_events (id) {
|
|
id -> Integer,
|
|
event_uid -> Nullable<Text>,
|
|
summary -> Text,
|
|
description -> Nullable<Text>,
|
|
location -> Nullable<Text>,
|
|
start_time -> BigInt,
|
|
end_time -> BigInt,
|
|
all_day -> Bool,
|
|
organizer -> Nullable<Text>,
|
|
attendees -> Nullable<Text>,
|
|
embedding -> Nullable<Binary>,
|
|
created_at -> BigInt,
|
|
source_file -> Nullable<Text>,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
daily_conversation_summaries (id) {
|
|
id -> Integer,
|
|
date -> Text,
|
|
contact -> Text,
|
|
summary -> Text,
|
|
message_count -> Integer,
|
|
embedding -> Binary,
|
|
created_at -> BigInt,
|
|
model_version -> Text,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
favorites (id) {
|
|
id -> Integer,
|
|
userid -> Integer,
|
|
path -> Text,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
image_exif (id) {
|
|
id -> Integer,
|
|
file_path -> Text,
|
|
camera_make -> Nullable<Text>,
|
|
camera_model -> Nullable<Text>,
|
|
lens_model -> Nullable<Text>,
|
|
width -> Nullable<Integer>,
|
|
height -> Nullable<Integer>,
|
|
orientation -> Nullable<Integer>,
|
|
gps_latitude -> Nullable<Float>,
|
|
gps_longitude -> Nullable<Float>,
|
|
gps_altitude -> Nullable<Float>,
|
|
focal_length -> Nullable<Float>,
|
|
aperture -> Nullable<Float>,
|
|
shutter_speed -> Nullable<Text>,
|
|
iso -> Nullable<Integer>,
|
|
date_taken -> Nullable<BigInt>,
|
|
created_time -> BigInt,
|
|
last_modified -> BigInt,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
knowledge_embeddings (id) {
|
|
id -> Integer,
|
|
keyword -> Text,
|
|
description -> Text,
|
|
category -> Nullable<Text>,
|
|
embedding -> Binary,
|
|
created_at -> BigInt,
|
|
model_version -> Text,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
location_history (id) {
|
|
id -> Integer,
|
|
timestamp -> BigInt,
|
|
latitude -> Float,
|
|
longitude -> Float,
|
|
accuracy -> Nullable<Integer>,
|
|
activity -> Nullable<Text>,
|
|
activity_confidence -> Nullable<Integer>,
|
|
place_name -> Nullable<Text>,
|
|
place_category -> Nullable<Text>,
|
|
embedding -> Nullable<Binary>,
|
|
created_at -> BigInt,
|
|
source_file -> Nullable<Text>,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
message_embeddings (id) {
|
|
id -> Integer,
|
|
contact -> Text,
|
|
body -> Text,
|
|
timestamp -> BigInt,
|
|
is_sent -> Bool,
|
|
embedding -> Binary,
|
|
created_at -> BigInt,
|
|
model_version -> Text,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
photo_insights (id) {
|
|
id -> Integer,
|
|
file_path -> Text,
|
|
title -> Text,
|
|
summary -> Text,
|
|
generated_at -> BigInt,
|
|
model_version -> Text,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
search_history (id) {
|
|
id -> Integer,
|
|
timestamp -> BigInt,
|
|
query -> Text,
|
|
search_engine -> Nullable<Text>,
|
|
embedding -> Binary,
|
|
created_at -> BigInt,
|
|
source_file -> Nullable<Text>,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
tagged_photo (id) {
|
|
id -> Integer,
|
|
photo_name -> Text,
|
|
tag_id -> Integer,
|
|
created_time -> BigInt,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
tags (id) {
|
|
id -> Integer,
|
|
name -> Text,
|
|
created_time -> BigInt,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
users (id) {
|
|
id -> Integer,
|
|
username -> Text,
|
|
password -> Text,
|
|
}
|
|
}
|
|
|
|
diesel::table! {
|
|
video_preview_clips (id) {
|
|
id -> Integer,
|
|
file_path -> Text,
|
|
status -> Text,
|
|
duration_seconds -> Nullable<Float>,
|
|
file_size_bytes -> Nullable<Integer>,
|
|
error_message -> Nullable<Text>,
|
|
created_at -> Text,
|
|
updated_at -> Text,
|
|
}
|
|
}
|
|
|
|
diesel::joinable!(tagged_photo -> tags (tag_id));
|
|
|
|
diesel::allow_tables_to_appear_in_same_query!(
|
|
calendar_events,
|
|
daily_conversation_summaries,
|
|
favorites,
|
|
image_exif,
|
|
knowledge_embeddings,
|
|
location_history,
|
|
message_embeddings,
|
|
photo_insights,
|
|
search_history,
|
|
tagged_photo,
|
|
tags,
|
|
users,
|
|
video_preview_clips,
|
|
);
|