Code/UI/VideoControlOverlay.razor.cs
using Sandbox.UI;
using System;
namespace Duccsoft;
/// <summary>
/// A Panel meant to stretch over an entire VideoPanel and provide a progress bar and buttons.
/// </summary>
public partial class VideoControlOverlay : Panel
{
/// <summary>
/// The VideoPanel instance that we will be controlling. You may replace this with any
/// <see cref="IVideoPanel"/> object that you that you wish to control using this UI.
/// </summary>
public IVideoPanel VideoPanel { get; set; }
/// <summary>
/// If true, the video controls will automatically be hidden after the AutoHideDelay period has elapsed
/// and the user is not hovering their mouse over this panel.
/// </summary>
public bool AutoHide { get; set; } = true;
/// <summary>
/// If AutoHide is true, this is the time in seconds that must elapse before this panel
/// will conceal the video controls.
/// </summary>
public float AutoHideDelay { get; set; } = 1f;
#region Presentation
private string OverlayClass
{
get
{
var overlayClass = VideoPanel?.IsLoading == true ? "loading" : string.Empty;
if ( !AutoHide )
return overlayClass;
var hovered = PseudoClass.HasFlag( PseudoClass.Hover );
if ( hovered )
{
_lastHovered = 0f;
return overlayClass;
}
return _lastHovered > AutoHideDelay ? $"{overlayClass} conceal" : overlayClass;
}
}
private string TimecodeAreaClass => ProgressSeconds > 3600 || DurationSeconds > 3600
? "big"
: string.Empty;
private string ProgressText => FormatTime( ProgressSeconds );
private string DurationText => FormatTime( DurationSeconds );
private string FormatTime( float seconds )
{
var time = TimeSpan.FromSeconds( seconds );
return time.Hours > 0
? time.ToString( "hh':'mm':'ss" )
: time.ToString( "mm':'ss" );
}
private string PlayButtonIcon
{
get
{
if ( !VideoPanel.IsValid() )
return "play_arrow";
return VideoPanel.IsPaused ? "play_arrow" : "pause";
}
}
private float ProgressSeconds => VideoPanel?.PlaybackTime ?? 0f;
private float DurationSeconds => VideoPanel?.Duration ?? 0f;
private string VolumeButtonIcon => VideoPanel?.Audio?.Muted == false ? "volume_up" : "volume_off";
#endregion
private RealTimeSince _lastHovered = 20f;
protected override int BuildHash()
{
return HashCode.Combine( VideoPanel?.IsPlaying, VideoPanel?.IsPaused, VideoPanel?.Audio?.Muted, (int)ProgressSeconds, TimecodeAreaClass, OverlayClass );
}
#region Controls
private float PlaybackTime
{
get => ProgressSeconds;
set => VideoPanel?.Seek( value );
}
private void ProgressBarChanged( float value )
{
PlaybackTime = value;
}
private void TogglePause() => VideoPanel?.TogglePause();
private void ToggleMute()
{
if ( !VideoPanel.IsValid() || VideoPanel.Audio is null )
return;
VideoPanel.Audio.Muted = !VideoPanel.Audio.Muted;
}
#endregion
}