/// <summary>
/// Is workout playing bindable property.
/// </summary>
- public static readonly BindableProperty IsPlayingProperty = BindableProperty.Create(
- "IsPlaying",
- typeof(bool),
+ public static readonly BindableProperty WorkoutStateProperty = BindableProperty.Create(
+ "WorkoutState",
+ typeof(WorkoutState),
typeof(ExercisingView),
- true,
- propertyChanged: OnIsPlayingChanged);
-
- /// <summary>
- /// Is workout loading bindable property.
- /// </summary>
- public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(
- "IsLoading",
- typeof(bool),
- typeof(ExercisingView),
- true,
- propertyChanged: OnIsLoadingChanged);
+ WorkoutState.Loading,
+ propertyChanged: OnWorkoutStateChanged);
private const int TransitionTime = 500;
private CancellationTokenSource source;
private bool isInitialized = false;
- private bool isLoading = false;
private (Coordinates Preview, Coordinates Camera) playing;
private (Coordinates Preview, Coordinates Camera) pause =
(
}
}
- private static void OnIsPlayingChanged(BindableObject bindable, object oldValue, object newValue)
+ private static void OnWorkoutStateChanged(BindableObject bindable, object oldValue, object newValue)
{
- if (newValue is bool isPlaying && bindable is ExercisingView view)
+ if (newValue is WorkoutState newState && oldValue is WorkoutState oldState && bindable is ExercisingView view)
{
- _ = view.TriggerStates(isPlaying);
- }
- }
-
- private static void OnIsLoadingChanged(BindableObject bindable, object oldValue, object newValue)
- {
- if (newValue is bool isLoading && bindable is ExercisingView view)
- {
- view.isLoading = isLoading;
-
- if (isLoading)
- {
- view.RestartLoading();
- }
+ view.ExecuteNewState(newState, oldState);
}
}
cameraView.Preview += DetectPreview;
}
- private async Task TriggerStates(bool isPlaying)
+ private void ExecuteNewState(WorkoutState newState, WorkoutState oldState)
+ {
+ if (!isInitialized)
+ {
+ return;
+ }
+
+ source?.Cancel();
+ source?.Dispose();
+ source = new CancellationTokenSource();
+
+ switch (newState)
+ {
+ case WorkoutState.Loading:
+ _ = ExecuteLoadingSate(oldState);
+ break;
+
+ case WorkoutState.Playing:
+ _ = ExecutePlayingSate(oldState);
+ break;
+
+ case WorkoutState.OnHold:
+ ExecuteOnHoldSate(oldState);
+ break;
+
+ case WorkoutState.Paused:
+ _ = ExecutePausedSate(oldState);
+ break;
+
+ default:
+ Services.Logger.Warn("unhandled workout state");
+ break;
+ }
+ }
+
+ private async Task ExecuteLoadingSate(WorkoutState oldState)
+ {
+ Preview.Stop();
+ LoadingView.Show();
+
+ switch (oldState)
+ {
+ case WorkoutState.OnHold:
+ break;
+
+ case WorkoutState.Paused:
+ (Task scalePreview, Task movePreview) = Animate(Preview, pause.Preview, playing.Preview, source.Token);
+ (Task scaleCamera, Task moveCamera) = Animate(cameraOverlayView, pause.Camera, playing.Camera, source.Token);
+
+ await Task.WhenAll(scalePreview, movePreview, scaleCamera, moveCamera);
+
+ PauseView.Hide();
+ PlayingView.Show();
+
+ if (!source.IsCancellationRequested)
+ {
+ SetPositionAndSize(WorkoutState.Playing);
+ }
+
+ break;
+
+ default:
+ Services.Logger.Warn("unhandled workout state");
+ break;
+ }
+
+ LoadingView.StartLoading();
+ LoadingView.Loaded += OnLoaded;
+ }
+
+ private async Task ExecutePlayingSate(WorkoutState oldState)
{
- if (isInitialized)
+ switch (oldState)
{
- source?.Cancel();
- source?.Dispose();
- source = new CancellationTokenSource();
+ case WorkoutState.Loading:
+ case WorkoutState.OnHold:
+ break;
- if (isPlaying)
- {
+ case WorkoutState.Paused:
(Task scalePreview, Task movePreview) = Animate(Preview, pause.Preview, playing.Preview, source.Token);
(Task scaleCamera, Task moveCamera) = Animate(cameraOverlayView, pause.Camera, playing.Camera, source.Token);
+
await Task.WhenAll(scalePreview, movePreview, scaleCamera, moveCamera);
PauseView.Hide();
PlayingView.Show();
- if (!isLoading)
+
+ if (!source.IsCancellationRequested)
{
- Preview.Play();
+ SetPositionAndSize(WorkoutState.Playing);
}
- }
- else
- {
+
+ break;
+
+ default:
+ Services.Logger.Warn("unhandled workout state");
+ break;
+ }
+
+ Preview.Play();
+ }
+
+ private void ExecuteOnHoldSate(WorkoutState oldState)
+ {
+ switch (oldState)
+ {
+ case WorkoutState.Playing:
+ Preview.Pause();
+ break;
+
+ default:
+ Services.Logger.Warn("unhandled workout state");
+ break;
+ }
+ }
+
+ private async Task ExecutePausedSate(WorkoutState oldState)
+ {
+ switch (oldState)
+ {
+ case WorkoutState.Playing:
+
Preview.Pause();
PlayingView.Hide();
PauseView.Show();
(Task scalePreview, Task movePreview) = Animate(Preview, playing.Preview, pause.Preview, source.Token);
(Task scaleCamera, Task moveCamera) = Animate(cameraOverlayView, playing.Camera, pause.Camera, source.Token);
+
await Task.WhenAll(scalePreview, movePreview, scaleCamera, moveCamera);
- }
- if (!source.IsCancellationRequested)
- {
- SetPositionAndSize(isPlaying);
- }
+ if (!source.IsCancellationRequested)
+ {
+ SetPositionAndSize(WorkoutState.Paused);
+ }
+
+ break;
+
+ default:
+ Services.Logger.Warn("unhandled workout state");
+ break;
}
}
private void OnPlayingViewRelayout(object sender, System.EventArgs e)
{
- UpdatePositionAndSize();
+ SetPositionAndSize();
+ PlayingView.PreviewStub.Relayout -= OnPlayingViewRelayout;
isInitialized = true;
}
- private void RestartLoading()
- {
- Preview.Stop();
- LoadingView.StartLoading();
- }
-
private void OnLoaded(object sender, System.EventArgs e)
{
if (BindingContext is ExercisingViewModel viewModel)
{
- viewModel.IsLoading = false;
+ viewModel.State = WorkoutState.Playing;
}
- Preview.Play();
+ LoadingView.Loaded -= OnLoaded;
}
- private void UpdatePositionAndSize()
+ private void SetPositionAndSize()
{
playing.Camera = new Coordinates()
{
pause.Camera.Scale = pause.Camera.Size.Width / playing.Camera.Size.Width;
pause.Preview.Scale = pause.Preview.Size.Width / playing.Preview.Size.Width;
- SetPositionAndSize((bool)GetValue(IsPlayingProperty));
+ SetPositionAndSize((WorkoutState)GetValue(WorkoutStateProperty));
}
- private void SetPositionAndSize(bool isPlaying)
+ private void SetPositionAndSize(WorkoutState state)
{
cameraOverlayView.Size = playing.Camera.Size;
Preview.Size = playing.Preview.Size;
- if (isPlaying)
- {
- cameraOverlayView.Position = playing.Camera.Position;
- cameraOverlayView.ScaleX = 1;
- cameraOverlayView.ScaleY = 1;
- Preview.Position = playing.Preview.Position;
- Preview.ScaleX = 1;
- Preview.ScaleY = 1;
-
- PauseView.Hide();
- PlayingView.Show();
- }
- else
+ if (state == WorkoutState.Paused)
{
var cameraScale = pause.Camera.Size.Width / playing.Camera.Size.Width;
cameraOverlayView.Position = pause.Camera.Position;
PlayingView.Hide();
PauseView.Show();
}
+ else
+ {
+ cameraOverlayView.Position = playing.Camera.Position;
+ cameraOverlayView.ScaleX = 1;
+ cameraOverlayView.ScaleY = 1;
+ Preview.Position = playing.Preview.Position;
+ Preview.ScaleX = 1;
+ Preview.ScaleY = 1;
+
+ PauseView.Hide();
+ PlayingView.Show();
+ }
}
private void DetectPreview(object sender, PreviewEventArgs e)