From 73cd42d18a82762b39468a6c9cca447148a51910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sackers?= Date: Thu, 14 Dec 2023 18:56:19 +0100 Subject: [PATCH 1/2] Impreovements --- .../Client/Components/ClipViewer.razor | 34 +++-- .../Client/Components/ClipViewer.razor.cs | 141 +++++++++++++----- .../Client/Components/VideoPlayer.razor | 10 ++ .../TeslaCamPlayer.BlazorHosted.Client.csproj | 8 +- .../wwwroot/scss/components/_viewer.scss | 14 +- .../Server/Services/ClipsService.cs | 20 ++- .../Server/Services/FfProbeService.cs | 7 +- .../TeslaCamPlayer.BlazorHosted.Server.csproj | 14 +- .../Shared/Models/ClipVideoSegment.cs | 6 +- .../TeslaCamPlayer.BlazorHosted.Shared.csproj | 2 +- 10 files changed, 187 insertions(+), 69 deletions(-) diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor index a28bead..0690fd1 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor +++ b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor @@ -2,30 +2,34 @@
- +
- - - + + +
- +
- -
+
@_clip?.StartDate.ToString("hh:mm:ss tt")
+
+ +
+
+
@_clip?.EndDate.ToString("hh:mm:ss tt")
\ No newline at end of file diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs index 5f79c46..e7ec83d 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs +++ b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs @@ -1,4 +1,8 @@ -using System.Timers; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Timers; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using MudBlazor; @@ -31,14 +35,11 @@ private double TimelineValue } private Clip _clip; - private string _frontVideoSrc; - private string _leftRepeaterVideoSrc; - private string _rightRepeaterVideoSrc; - private string _backVideoSrc; private VideoPlayer _videoPlayerFront; private VideoPlayer _videoPlayerLeftRepeater; private VideoPlayer _videoPlayerRightRepeater; private VideoPlayer _videoPlayerBack; + private int _videoLoadedEventCount = 0; private bool _isPlaying; private ClipVideoSegment _currentSegment; private MudSlider _timelineSlider; @@ -48,6 +49,7 @@ private double TimelineValue private bool _isScrubbing; private double _timelineValue; private System.Timers.Timer _setVideoTimeDebounceTimer; + private CancellationTokenSource _loadSegmentCts = new(); protected override void OnInitialized() { @@ -59,8 +61,32 @@ protected override void OnAfterRender(bool firstRender) { if (!firstRender) return; + + _videoPlayerFront.Loaded += () => + { + Console.WriteLine("Loaded: Front"); + _videoLoadedEventCount++; + }; + _videoPlayerLeftRepeater.Loaded += () => + { + Console.WriteLine("Loaded: Left"); + _videoLoadedEventCount++; + }; + _videoPlayerRightRepeater.Loaded += () => + { + Console.WriteLine("Loaded: Right"); + _videoLoadedEventCount++; + }; + _videoPlayerBack.Loaded += () => + { + Console.WriteLine("Loaded: Back"); + _videoLoadedEventCount++; + }; } + private static Task AwaitUiUpdate() + => Task.Delay(100); + public async Task SetClipAsync(Clip clip) { _clip = clip; @@ -68,37 +94,64 @@ public async Task SetClipAsync(Clip clip) _timelineMaxSeconds = (clip.EndDate - clip.StartDate).TotalSeconds; _currentSegment = _clip.Segments.First(); - SetCurrentSegmentVideos(); + if (!await SetCurrentSegmentVideosAsync()) + return; if (_isPlaying) { // Let elements update - await Task.Delay(100); + await AwaitUiUpdate(); await ToggleSetPlayingAsync(true); } } - private void SetCurrentSegmentVideos() + private async Task SetCurrentSegmentVideosAsync() { if (_currentSegment == null) - return; + return false; + + await _loadSegmentCts.CancelAsync(); + _loadSegmentCts = new(); - _frontVideoSrc = _currentSegment.CameraFront?.Url; - _leftRepeaterVideoSrc = _currentSegment.CameraLeftRepeater?.Url; - _rightRepeaterVideoSrc = _currentSegment.CameraRightRepeater?.Url; - _backVideoSrc = _currentSegment.CameraBack?.Url; + _videoLoadedEventCount = 0; + var cameraCount = _currentSegment.CameraAnglesCount(); - StateHasChanged(); + _videoPlayerFront.Src = _currentSegment.CameraFront?.Url; + _videoPlayerLeftRepeater.Src = _currentSegment.CameraLeftRepeater?.Url; + _videoPlayerRightRepeater.Src = _currentSegment.CameraRightRepeater?.Url; + _videoPlayerBack.Src = _currentSegment.CameraBack?.Url; + + if (_loadSegmentCts.IsCancellationRequested) + return false; + + await InvokeAsync(StateHasChanged); + + var timeout = Task.Delay(10000); + var completedTask = await Task.WhenAny(Task.Run(async () => + { + while (_videoLoadedEventCount < cameraCount && !_loadSegmentCts.IsCancellationRequested) + await Task.Delay(10, _loadSegmentCts.Token); + + Console.WriteLine("Loading done"); + }, _loadSegmentCts.Token), timeout); + + if (completedTask == timeout) + { + Console.WriteLine("Loading timed out"); + return false; + } + + return !_loadSegmentCts.IsCancellationRequested; } - private async Task ExecuteOnPlayers(Func player) + private async Task ExecuteOnPlayers(Func action) { try { - await player(_videoPlayerFront); - await player(_videoPlayerLeftRepeater); - await player(_videoPlayerRightRepeater); - await player(_videoPlayerBack); + await action(_videoPlayerFront); + await action(_videoPlayerLeftRepeater); + await action(_videoPlayerRightRepeater); + await action(_videoPlayerBack); } catch { @@ -106,30 +159,41 @@ private async Task ExecuteOnPlayers(Func player) } } - private async Task ToggleSetPlayingAsync(bool? play = null) + private Task ToggleSetPlayingAsync(bool? play = null) { play ??= !_isPlaying; _isPlaying = play.Value; - await ExecuteOnPlayers(async p => await (play.Value ? p.PlayAsync() : p.PauseAsync())); + return ExecuteOnPlayers(async p => await (play.Value ? p.PlayAsync() : p.PauseAsync())); } private Task PlayPauseClicked() => ToggleSetPlayingAsync(); - private async Task FrontVideoEnded() + private async Task VideoEnded() { + await ToggleSetPlayingAsync(false); + if (_currentSegment == _clip.Segments.Last()) + return; + + var nextSegment = _clip.Segments + .SkipWhile(s => s != _currentSegment) + .Skip(1) + .FirstOrDefault() + ?? _clip.Segments.FirstOrDefault(); + + if (nextSegment == null) { _isPlaying = false; return; } - _currentSegment = _clip.Segments - .SkipWhile(s => s != _currentSegment) - .Skip(1) - .First(); - SetCurrentSegmentVideos(); - await Task.Delay(10); + _currentSegment = nextSegment; + + if (!await SetCurrentSegmentVideosAsync()) + return; + + await AwaitUiUpdate(); await ToggleSetPlayingAsync(true); } @@ -156,15 +220,18 @@ private async Task TimelineSliderMouseDown() await ToggleSetPlayingAsync(false); // Allow value change event to trigger, then scrub before user releases mouse click - await Task.Delay(10); + await AwaitUiUpdate(); await ScrubToSliderTime(); } - private async Task TimelineSliderMouseUp() + private Task TimelineSliderMouseUp() { _isScrubbing = false; - if (_wasPlayingBeforeScrub) - await ToggleSetPlayingAsync(true); + + if (!_isPlaying && _wasPlayingBeforeScrub) + return ToggleSetPlayingAsync(true); + + return Task.CompletedTask; } private async void ScrubVideoDebounceTick(object _, ElapsedEventArgs __) @@ -180,11 +247,17 @@ private async Task ScrubToSliderTime() try { var scrubToDate = _clip.StartDate.AddSeconds(TimelineValue); - var segment = _clip.SegmentAtDate(scrubToDate); + var segment = _clip.SegmentAtDate(scrubToDate) + ?? _clip.Segments.Where(s => s.StartDate > scrubToDate).MinBy(s => s.StartDate); + + if (segment == null) + return; + if (segment != _currentSegment) { _currentSegment = segment; - await InvokeAsync(SetCurrentSegmentVideos); + if (!await SetCurrentSegmentVideosAsync()) + return; } var secondsIntoSegment = (scrubToDate - segment.StartDate).TotalSeconds; diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/Components/VideoPlayer.razor b/src/TeslaCamPlayer.BlazorHosted/Client/Components/VideoPlayer.razor index 11a4c85..11a97b1 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/Components/VideoPlayer.razor +++ b/src/TeslaCamPlayer.BlazorHosted/Client/Components/VideoPlayer.razor @@ -1,10 +1,12 @@  @code { @@ -23,6 +25,10 @@ [Parameter] public EventCallback TimeUpdate { get; set; } + public delegate void LoadedHandler(); + + public event LoadedHandler Loaded; + private ElementReference _player; public ValueTask PlayAsync() @@ -42,4 +48,8 @@ private Task TimeUpdateHandler() => TimeUpdate.InvokeAsync(); + + private void OnLoadedData() + => Loaded?.Invoke(); + } \ No newline at end of file diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/TeslaCamPlayer.BlazorHosted.Client.csproj b/src/TeslaCamPlayer.BlazorHosted/Client/TeslaCamPlayer.BlazorHosted.Client.csproj index 08ad67b..b19a2d9 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/TeslaCamPlayer.BlazorHosted.Client.csproj +++ b/src/TeslaCamPlayer.BlazorHosted/Client/TeslaCamPlayer.BlazorHosted.Client.csproj @@ -1,15 +1,15 @@ - net7.0 + net8.0 warnings enable - - - + + + diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss index 1c218dd..d3ad82f 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss +++ b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss @@ -46,9 +46,10 @@ } .seeker-slider-container { - position: relative; display: flex; + flex-direction: row; width: 80%; + align-items: center; .event-marker { $size: 20px; @@ -61,6 +62,17 @@ background-color: adjust-color(#f64e62ff, $alpha: -0.5); pointer-events: none; } + + .time-container { + flex-shrink: 0; + } + + .slider-container { + margin: 0 15px; + position: relative; + flex-grow: 1; + display: flex; + } } } } \ No newline at end of file diff --git a/src/TeslaCamPlayer.BlazorHosted/Server/Services/ClipsService.cs b/src/TeslaCamPlayer.BlazorHosted/Server/Services/ClipsService.cs index 81d175b..347871c 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Server/Services/ClipsService.cs +++ b/src/TeslaCamPlayer.BlazorHosted/Server/Services/ClipsService.cs @@ -1,4 +1,9 @@ -using System.Text.RegularExpressions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; using Newtonsoft.Json; using Serilog; using TeslaCamPlayer.BlazorHosted.Server.Providers.Interfaces; @@ -31,16 +36,25 @@ private async Task GetCachedAsync() public async Task GetClipsAsync(bool refreshCache = false) { - if (!refreshCache && (_cache ??= await GetCachedAsync()) != null) + _cache ??= await GetCachedAsync(); + + if (!refreshCache && _cache != null) return _cache; + _cache ??= []; + + var knownVideoFiles = _cache + .SelectMany(c => c.Segments.SelectMany(s => s.VideoFiles)) + .Where(f => f != null) + .ToDictionary(v => v.FilePath, v => v); + var videoFiles = (await Task.WhenAll(Directory .GetFiles(_settingsProvider.Settings.ClipsRootPath, "*.mp4", SearchOption.AllDirectories) .AsParallel() .Select(path => new { Path = path, RegexMatch = FileNameRegex.Match(path) }) .Where(f => f.RegexMatch.Success) .ToList() - .Select(async f => await TryParseVideoFileAsync(f.Path, f.RegexMatch)))) + .Select(async f => knownVideoFiles.TryGetValue(f.Path, out var knownVideo) ? knownVideo : await TryParseVideoFileAsync(f.Path, f.RegexMatch)))) .AsParallel() .Where(vfi => vfi != null) .ToList(); diff --git a/src/TeslaCamPlayer.BlazorHosted/Server/Services/FfProbeService.cs b/src/TeslaCamPlayer.BlazorHosted/Server/Services/FfProbeService.cs index 4b1e486..3ac6802 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Server/Services/FfProbeService.cs +++ b/src/TeslaCamPlayer.BlazorHosted/Server/Services/FfProbeService.cs @@ -7,12 +7,14 @@ namespace TeslaCamPlayer.BlazorHosted.Server.Services; public abstract class FfProbeService : IFfProbeService { protected abstract string ExePath { get; } - - + + public async Task GetVideoFileDurationAsync(string videoFilePath) { try { + Log.Information("Get video duration for video {Path}", videoFilePath); + var process = new Process { StartInfo = new ProcessStartInfo(ExePath) @@ -36,7 +38,6 @@ public abstract class FfProbeService : IFfProbeService return null; } } - } public class FfProbeServiceWindows : FfProbeService diff --git a/src/TeslaCamPlayer.BlazorHosted/Server/TeslaCamPlayer.BlazorHosted.Server.csproj b/src/TeslaCamPlayer.BlazorHosted/Server/TeslaCamPlayer.BlazorHosted.Server.csproj index e9116d8..e0124c5 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Server/TeslaCamPlayer.BlazorHosted.Server.csproj +++ b/src/TeslaCamPlayer.BlazorHosted/Server/TeslaCamPlayer.BlazorHosted.Server.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 warnings enable @@ -11,13 +11,13 @@ - - - - + + + + - - + + diff --git a/src/TeslaCamPlayer.BlazorHosted/Shared/Models/ClipVideoSegment.cs b/src/TeslaCamPlayer.BlazorHosted/Shared/Models/ClipVideoSegment.cs index c29aa1c..aa90d69 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Shared/Models/ClipVideoSegment.cs +++ b/src/TeslaCamPlayer.BlazorHosted/Shared/Models/ClipVideoSegment.cs @@ -8,5 +8,9 @@ public class ClipVideoSegment public VideoFile CameraLeftRepeater { get; init; } public VideoFile CameraRightRepeater { get; init; } public VideoFile CameraBack { get; init; } - + + public VideoFile[] VideoFiles => [CameraFront, CameraLeftRepeater, CameraRightRepeater, CameraBack]; + + public int CameraAnglesCount() => VideoFiles.Count(f => f != null); + } \ No newline at end of file diff --git a/src/TeslaCamPlayer.BlazorHosted/Shared/TeslaCamPlayer.BlazorHosted.Shared.csproj b/src/TeslaCamPlayer.BlazorHosted/Shared/TeslaCamPlayer.BlazorHosted.Shared.csproj index aa761e2..cd45212 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Shared/TeslaCamPlayer.BlazorHosted.Shared.csproj +++ b/src/TeslaCamPlayer.BlazorHosted/Shared/TeslaCamPlayer.BlazorHosted.Shared.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 warnings enable From 6f216c2fe5b36aa7c52afa6595b95a4c9b47c9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sackers?= Date: Thu, 14 Dec 2023 19:24:28 +0100 Subject: [PATCH 2/2] Verygud --- .../Client/Components/ClipViewer.razor | 18 +++-- .../Client/Components/ClipViewer.razor.cs | 65 ++++++++++--------- .../wwwroot/scss/components/_blazor.scss | 5 +- .../wwwroot/scss/components/_viewer.scss | 20 +++++- .../wwwroot/scss/components/_z-index.scss | 5 ++ 5 files changed, 74 insertions(+), 39 deletions(-) create mode 100644 src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_z-index.scss diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor index 0690fd1..cc02a95 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor +++ b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor @@ -2,12 +2,12 @@
- +
- - - + + +
@@ -25,9 +25,13 @@ Step="0.01" @bind-Value="@TimelineValue" Variant="Variant.Filled" - @onpointerdown="@TimelineSliderMouseDown" - @onpointerup="@TimelineSliderMouseUp"/> -
+ @onpointerdown="@TimelineSliderPointerDown" + @onpointerup="@TimelineSliderPointerUp"/> +
+ @foreach (var segment in _clip?.Segments ?? Array.Empty()) + { +
+ }
@_clip?.EndDate.ToString("hh:mm:ss tt")
diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs index e7ec83d..d9503b5 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs +++ b/src/TeslaCamPlayer.BlazorHosted/Client/Components/ClipViewer.razor.cs @@ -94,15 +94,7 @@ public async Task SetClipAsync(Clip clip) _timelineMaxSeconds = (clip.EndDate - clip.StartDate).TotalSeconds; _currentSegment = _clip.Segments.First(); - if (!await SetCurrentSegmentVideosAsync()) - return; - - if (_isPlaying) - { - // Let elements update - await AwaitUiUpdate(); - await ToggleSetPlayingAsync(true); - } + await SetCurrentSegmentVideosAsync(); } private async Task SetCurrentSegmentVideosAsync() @@ -115,6 +107,10 @@ private async Task SetCurrentSegmentVideosAsync() _videoLoadedEventCount = 0; var cameraCount = _currentSegment.CameraAnglesCount(); + + var wasPlaying = _isPlaying; + if (wasPlaying) + await TogglePlayingAsync(false); _videoPlayerFront.Src = _currentSegment.CameraFront?.Url; _videoPlayerLeftRepeater.Src = _currentSegment.CameraLeftRepeater?.Url; @@ -141,6 +137,9 @@ private async Task SetCurrentSegmentVideosAsync() return false; } + if (wasPlaying) + await TogglePlayingAsync(true); + return !_loadSegmentCts.IsCancellationRequested; } @@ -159,7 +158,7 @@ private async Task ExecuteOnPlayers(Func action) } } - private Task ToggleSetPlayingAsync(bool? play = null) + private Task TogglePlayingAsync(bool? play = null) { play ??= !_isPlaying; _isPlaying = play.Value; @@ -167,16 +166,17 @@ private Task ToggleSetPlayingAsync(bool? play = null) } private Task PlayPauseClicked() - => ToggleSetPlayingAsync(); + => TogglePlayingAsync(); private async Task VideoEnded() { - await ToggleSetPlayingAsync(false); - if (_currentSegment == _clip.Segments.Last()) return; + await TogglePlayingAsync(false); + var nextSegment = _clip.Segments + .OrderBy(s => s.StartDate) .SkipWhile(s => s != _currentSegment) .Skip(1) .FirstOrDefault() @@ -184,17 +184,14 @@ private async Task VideoEnded() if (nextSegment == null) { - _isPlaying = false; + await TogglePlayingAsync(false); return; } _currentSegment = nextSegment; - - if (!await SetCurrentSegmentVideosAsync()) - return; - + await SetCurrentSegmentVideosAsync(); await AwaitUiUpdate(); - await ToggleSetPlayingAsync(true); + await TogglePlayingAsync(true); } private async Task FrontVideoTimeUpdate() @@ -213,25 +210,25 @@ private async Task FrontVideoTimeUpdate() TimelineValue = secondsSinceClipStart; } - private async Task TimelineSliderMouseDown() + private async Task TimelineSliderPointerDown() { _isScrubbing = true; _wasPlayingBeforeScrub = _isPlaying; - await ToggleSetPlayingAsync(false); + await TogglePlayingAsync(false); // Allow value change event to trigger, then scrub before user releases mouse click await AwaitUiUpdate(); await ScrubToSliderTime(); } - private Task TimelineSliderMouseUp() + private async Task TimelineSliderPointerUp() { + Console.WriteLine("Pointer up"); + await ScrubToSliderTime(); _isScrubbing = false; if (!_isPlaying && _wasPlayingBeforeScrub) - return ToggleSetPlayingAsync(true); - - return Task.CompletedTask; + await TogglePlayingAsync(true); } private async void ScrubVideoDebounceTick(object _, ElapsedEventArgs __) @@ -269,14 +266,24 @@ private async Task ScrubToSliderTime() } } + private double DateTimeToTimelinePercentage(DateTime dateTime) + { + var percentage = Math.Round(dateTime.Subtract(_clip.StartDate).TotalSeconds / _clip.TotalSeconds * 100, 2); + return Math.Clamp(percentage, 0, 100); + } + + private string SegmentStartMargerStyle(ClipVideoSegment segment) + { + var percentage = DateTimeToTimelinePercentage(segment.StartDate); + return $"left: {percentage}%"; + } + private string EventMarkerStyle() { if (_clip?.Event?.Timestamp == null) return "display: none"; - var percentageOfClipAtTimestamp = Math.Round(_clip.Event.Timestamp.Subtract(_clip.StartDate).TotalSeconds / _clip.TotalSeconds * 100, 2); - percentageOfClipAtTimestamp = Math.Clamp(percentageOfClipAtTimestamp, 0, 100); - - return $"left: {percentageOfClipAtTimestamp}%"; + var percentage = DateTimeToTimelinePercentage(_clip.Event.Timestamp); + return $"left: {percentage}%"; } } \ No newline at end of file diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_blazor.scss b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_blazor.scss index 375f3d3..1b698ec 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_blazor.scss +++ b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_blazor.scss @@ -1,4 +1,5 @@ - +@import "z-index"; + #blazor-error-ui { background: lightyellow; bottom: 0; @@ -8,7 +9,7 @@ padding: 0.6rem 1.25rem 0.7rem 1.25rem; position: fixed; width: 100%; - z-index: 1000; + z-index: $z-blazor-error-ui; } #blazor-error-ui .dismiss { diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss index d3ad82f..9f9f0e6 100644 --- a/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss +++ b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_viewer.scss @@ -1,4 +1,6 @@ -.viewer { +@import "z-index"; + +.viewer { min-width: 0; height: 100%; display: flex; @@ -61,6 +63,18 @@ transform: translate(-50%, -50%); background-color: adjust-color(#f64e62ff, $alpha: -0.5); pointer-events: none; + z-index: $z-timeline-event-marker; + } + + .segment-marker { + position: absolute; + width: 1px; + transform: translateX(-50%); + pointer-events: none; + top: 0; + bottom: 0; + background-color: #424242; + z-index: $z-timeline-segment-marker; } .time-container { @@ -73,6 +87,10 @@ flex-grow: 1; display: flex; } + + .mud-slider { + z-index: $z-timeline; + } } } } \ No newline at end of file diff --git a/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_z-index.scss b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_z-index.scss new file mode 100644 index 0000000..b958d84 --- /dev/null +++ b/src/TeslaCamPlayer.BlazorHosted/Client/wwwroot/scss/components/_z-index.scss @@ -0,0 +1,5 @@ +$z-timeline-segment-marker: 1; +$z-timeline: 2; +$z-timeline-event-marker: 3; + +$z-blazor-error-ui: 2000; \ No newline at end of file