diff --git a/AZKiServer/Services/AZKiRpcService.cs b/AZKiServer/Services/AZKiRpcService.cs index 69cfb96..b5118be 100644 --- a/AZKiServer/Services/AZKiRpcService.cs +++ b/AZKiServer/Services/AZKiRpcService.cs @@ -32,15 +32,15 @@ public class AZKiRpcService(MediaService mediaService) : RPC.AZKi.AZKiBase { CameraId = c.Key, }; - result.Images.AddRange(images); - result.Videos.AddRange(videos); + result.Images.AddRange(images.OrderBy(i => i.Date)); + result.Videos.AddRange(videos.OrderBy(i => i.Date)); return result; }); var playback = new PlaybackInfo { Date = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(from), }; - playback.Channels.AddRange(channels); + playback.Channels.AddRange(channels.OrderBy(c => c.CameraId)); return playback; } } diff --git a/AZKiServer/Services/FileScannerService.cs b/AZKiServer/Services/FileScannerService.cs index 36c7fa1..5a64285 100644 --- a/AZKiServer/Services/FileScannerService.cs +++ b/AZKiServer/Services/FileScannerService.cs @@ -6,6 +6,8 @@ using FFMpegCore; using MaybeError; using MaybeError.Errors; +using SharpCompress.Common; + using SixLabors.ImageSharp; using System.Collections.Frozen; @@ -55,11 +57,17 @@ public class FileScannerService(MediaService mediaService, IConfiguration config { var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories); var existingFiles = await mediaService.GetExistingFilePathsAsync(cancellationToken); + var upToDateFiles = existingFiles.Where(e => e.Value == MediaEntry.CUR_VERSION) + .Select(e => e.Key) + .ToFrozenSet(); + var filesToProcess = files.Where(f => !upToDateFiles.Contains(Path.GetRelativePath(path, f))).ToArray(); var total = 0; - foreach (var chunk in files.Chunk(50)) + var prog = 0; + foreach (var chunk in filesToProcess.Chunk(50)) { + prog += chunk.Length; total += await ScanFileChunkAsync(path, chunk, existingFiles, cancellationToken); - logger.LogInformation("Added {updated} of {count} [{percentage}%]", total, files.Length, Math.Round(((float)total/ files.Length) * 100)); + logger.LogInformation("Added {updated} of {count} [{percentage}%]", total, filesToProcess.Length, Math.Round(((float)prog/ filesToProcess.Length) * 100)); } } catch (Exception ex) diff --git a/client/src/components/playback/player.rs b/client/src/components/playback/player.rs index f88c4df..bb9902a 100644 --- a/client/src/components/playback/player.rs +++ b/client/src/components/playback/player.rs @@ -21,6 +21,7 @@ pub fn Player() -> Element { Some(Date::from_ordinal_date(now.year(), now.ordinal() as u16).unwrap()) }); let mut zoom = use_signal(|| 1.0 as f32); + let mut time = use_signal(|| 0 as i64); let playbackResult = use_resource(use_reactive!(|(selected_date)| async move { let mut client = get_rpc_client(); info!("Load data"); @@ -75,7 +76,7 @@ pub fn Player() -> Element { } } Viewport { } - Timeline { playbackInfo: info, zoom } + Timeline { playbackInfo: info, zoom, time } } } } diff --git a/client/src/components/playback/timeline.rs b/client/src/components/playback/timeline.rs index 7c693f1..e6b23af 100644 --- a/client/src/components/playback/timeline.rs +++ b/client/src/components/playback/timeline.rs @@ -3,23 +3,30 @@ use dioxus::prelude::*; use crate::rpc::azki::{MediaChannel, MediaEntry, PlaybackInfo}; #[component] -pub fn Timeline(playbackInfo: Option, zoom: Signal) -> Element { +pub fn Timeline(playbackInfo: Option, zoom: Signal, time: Signal) -> Element { return match playbackInfo { Some(info) => rsx! { div{ id: "timeline", + PlayHead { time, zoom } TrackList { channels: info.channels, start: info.date.unwrap().seconds, zoom } } }, None => rsx! { div{ id: "timeline", + PlayHead { time, zoom } TrackList { channels: Vec::new(), start: 0, zoom } } }, }; } +#[component] +fn PlayHead(time: Signal, zoom: Signal) -> Element { + rsx! {} +} + #[component] fn TrackList(channels: Vec, start: i64, zoom: Signal) -> Element { rsx! { @@ -62,7 +69,6 @@ fn Clip(media: MediaEntry, start: i64) -> Element { let timestamp = date.seconds - start; let duration = (meta.duration as f32 / SEC_PER_DAY) * 100.0; let offset = (timestamp as f32 / SEC_PER_DAY) * 100.0; - let time = date.to_string(); rsx! { div{ class: "clip",