Changed SummaryView logic.
authorAndrzej Krawczyk <a.krawczyk@samsung.com>
Tue, 27 Jul 2021 05:58:11 +0000 (07:58 +0200)
committerPiotr Czaja <p.czaja@samsung.com>
Tue, 14 Sep 2021 11:01:34 +0000 (13:01 +0200)
Fitness/Services/NavigationService.cs
Fitness/ViewModels/ExercisingViewModel.cs
Fitness/ViewModels/LoadingViewModel.cs
Fitness/ViewModels/SummaryType.cs
Fitness/ViewModels/SummaryViewModel.cs [deleted file]
Fitness/Views/ExercisingView.xaml.cs
Fitness/Views/LoadingView.cs
Fitness/res/layout/ExercisingView.xaml
Fitness/res/layout/SummaryView.xaml

index 5aa7baf498733a9f535f5713175b69326ed1c500..03d3cbf2cb6ddc858a3ad6d720fc244021697261 100644 (file)
@@ -71,15 +71,6 @@ namespace Fitness.Services
             }
         }
 
-        public void NavigateToSummaryView(SummaryType summaryType, WorkoutViewModel workoutViewModel)
-        {
-            var view = new SummaryView()
-            {
-                BindingContext = new SummaryViewModel(summaryType, workoutViewModel),
-            };
-            navigation.Push(view);
-        }
-
         public void Pop()
         {
             navigation.Pop();
index 384b05f1dd8b75666ab3e0cde9836633e15dec6e..47e24b8b57f30926828eabe45d5fcc90820a120f 100644 (file)
@@ -3,6 +3,7 @@ using System.Windows.Input;
 using Fitness.Models;
 using Fitness.Services;
 using Tizen.Multimedia.Vision;
+using Tizen.NUI;
 using Tizen.NUI.Binding;
 
 namespace Fitness.ViewModels
@@ -12,11 +13,21 @@ namespace Fitness.ViewModels
     /// </summary>
     public class ExercisingViewModel : ChangeWorkoutViewModel
     {
+        private const string EndWorkoutSummaryTitle = "The current session will be stopped.";
+        private const string ChangeWorkoutSummaryTitle = "Do you want to change workout?";
+        private const string TryAgainSummaryTitle = "Do you want to try again?";
+        private const string TimeIsUpSummaryTitle = "Great job!";
+        private const string DefaultSummaryTitle = "Summary";
+
         private WorkoutState state;
         private int score;
         private int hold;
         private int repetitions;
         private Landmark[,] poseLandmarks;
+        private bool isSummaryVisible;
+        private ICommand summaryOkCommand;
+        private string summaryTitle;
+        private bool isLoading;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ExercisingViewModel"/> class.
@@ -25,8 +36,8 @@ namespace Fitness.ViewModels
         public ExercisingViewModel(WorkoutViewModel workoutViewModel)
         {
             PauseResumeWorkout = new Command(TriggerPauseResumeWorkout);
-            TryAgain = new Command(ExecuteTryAgain);
-            EndWorkout = new Command(ExecuteEndWorkout);
+            TryAgain = new Command(ConfirmTryAgain);
+            EndWorkout = new Command(ConfirmEndWorkout);
             State = WorkoutState.Playing;
             CurrentWorkout = workoutViewModel;
             SquatService = new SquatService()
@@ -34,6 +45,48 @@ namespace Fitness.ViewModels
                 HoldTimeThreshold = 1200,
             };
             SquatService.ExerciseStateUpdated += SquatService_ExerciseStateUpdated;
+            SummaryBackCommand = new Command(ExecuteCloseSummary);
+        }
+
+        public ICommand SummaryBackCommand { get; private set; }
+
+        public ICommand SummaryOkCommand
+        {
+            get => summaryOkCommand;
+            private set
+            {
+                if (value != summaryOkCommand)
+                {
+                    summaryOkCommand = value;
+                    RaisePropertyChanged();
+                }
+            }
+        }
+
+        public bool IsLoading
+        {
+            get => isLoading;
+            set
+            {
+                if (value != isLoading)
+                {
+                    isLoading = value;
+                    RaisePropertyChanged();
+                }
+            }
+        }
+
+        public string SummaryTitle
+        {
+            get => summaryTitle;
+            private set
+            {
+                if (value != summaryTitle)
+                {
+                    summaryTitle = value;
+                    RaisePropertyChanged();
+                }
+            }
         }
 
         /// <summary>
@@ -53,6 +106,17 @@ namespace Fitness.ViewModels
         }
 
         /// <summary>
+        /// Gets AverageScore.
+        /// </summary>
+        public int AverageScore { get; private set; } = 98;
+
+        /// <summary>
+        /// Gets TotalCount.
+        /// </summary>
+        public int TotalCount { get; private set; } = 27;
+
+        /// <summary>
+        /// Repetitions made in current Workout
         /// Gets the property specifying the correctness of the exercise - values ranging from 0 to 100.
         /// </summary>
         public int Score
@@ -100,6 +164,11 @@ namespace Fitness.ViewModels
             }
         }
 
+        /// <summary>
+        /// Gets TotalTime.
+        /// </summary>
+        public TimeSpan TotalTime { get; private set; } = new TimeSpan(0, 3, 39);
+
         /// <summary>
         /// Gets the TimeLeft in workout.
         /// </summary>
@@ -111,7 +180,7 @@ namespace Fitness.ViewModels
         public WorkoutState State
         {
             get => state;
-            private set
+            set
             {
                 if (state != value)
                 {
@@ -136,15 +205,18 @@ namespace Fitness.ViewModels
         /// </summary>
         public string PreviewVideoUrl { get; private set; }
 
-        /// <summary>
-        /// Gets Prev Command.
-        /// </summary>
-        public ICommand Prev { get; private set; }
-
-        /// <summary>
-        /// Gets Next Command.
-        /// </summary>
-        public ICommand Next { get; private set; }
+        public bool IsSummaryVisible
+        {
+            get => isSummaryVisible;
+            private set
+            {
+                if (value != isSummaryVisible)
+                {
+                    isSummaryVisible = value;
+                    RaisePropertyChanged();
+                }
+            }
+        }
 
         /// <summary>
         /// Gets PauseWorkout Command.
@@ -172,25 +244,63 @@ namespace Fitness.ViewModels
         public IExerciseService SquatService { get; private set; }
 
         /// <inheritdoc />
-        protected override void GoPrevious()
+        protected override void GoPrevious() => ConfirmChangeWorkout(-1);
+
+        /// <inheritdoc />
+        protected override void GoNext() => ConfirmChangeWorkout(1);
+
+        private void ConfirmChangeWorkout(int offset)
         {
             if (State == WorkoutState.Playing)
             {
                 State = WorkoutState.Paused;
             }
 
-            Services.NavigationService.Instance.NavigateToSummaryView(SummaryType.ChangeToPreviousWorkout, CurrentWorkout);
+            SummaryOkCommand = new Command(() => { ExecuteChangeWorkout(offset); });
+            SummaryTitle = GetSummaryTitle(SummaryType.ChangeWorkout);
+            IsSummaryVisible = true;
         }
 
-        /// <inheritdoc />
-        protected override void GoNext()
+        private void ExecuteCloseSummary()
         {
-            if (State == WorkoutState.Playing)
+            State = WorkoutState.Playing;
+            IsSummaryVisible = false;
+        }
+
+        private void ExecuteChangeWorkout(int offset = 0)
+        {
+            int idx = Workouts.IndexOf(CurrentWorkout) + offset;
+            if (idx >= 0 && idx < Workouts.Count)
             {
-                State = WorkoutState.Paused;
+                CurrentWorkout = Workouts[idx];
             }
 
-            Services.NavigationService.Instance.NavigateToSummaryView(SummaryType.ChangeToNextWorkout, CurrentWorkout);
+            StartNewWorkout();
+        }
+
+        private void StartNewWorkout()
+        {
+            State = WorkoutState.Playing;
+            IsSummaryVisible = false;
+            IsLoading = true;
+        }
+
+        private string GetSummaryTitle(SummaryType type)
+        {
+            switch (type)
+            {
+                case SummaryType.EndWorkout:
+                    return EndWorkoutSummaryTitle;
+                case SummaryType.ChangeWorkout:
+                    return ChangeWorkoutSummaryTitle;
+                case SummaryType.TryAgain:
+                    return TryAgainSummaryTitle;
+                case SummaryType.TimeIsUp:
+                    return TimeIsUpSummaryTitle;
+                default:
+                    Services.Logger.Warn($"Unable to find summary title for type: {type}");
+                    return DefaultSummaryTitle;
+            }
         }
 
         private void SquatService_ExerciseStateUpdated(object sender, ExerciseEventArgs e)
@@ -213,14 +323,18 @@ namespace Fitness.ViewModels
             }
         }
 
-        private void ExecuteTryAgain()
+        private void ConfirmTryAgain()
         {
-            Services.NavigationService.Instance.NavigateToSummaryView(SummaryType.TryAgain, CurrentWorkout);
+            SummaryOkCommand = new Command(() => { ExecuteChangeWorkout(0); });
+            SummaryTitle = GetSummaryTitle(SummaryType.TryAgain);
+            IsSummaryVisible = true;
         }
 
-        private void ExecuteEndWorkout()
+        private void ConfirmEndWorkout()
         {
-            Services.NavigationService.Instance.NavigateToSummaryView(SummaryType.EndWorkout, CurrentWorkout);
+            SummaryOkCommand = new Command(Services.NavigationService.Instance.PopToRoot);
+            SummaryTitle = GetSummaryTitle(SummaryType.EndWorkout);
+            IsSummaryVisible = true;
         }
     }
 }
index 1b353a5085b5ddfeb1c09d0a97c4d71957e1a502..3fa022271cecfdf8d63e079376f4c45324ae265a 100644 (file)
@@ -81,7 +81,7 @@ namespace Fitness.ViewModels
             }
         }
 
-        private void StartCounting()
+        public void StartCounting()
         {
             int count = 0;
             timer = new Timer(TickIntervalInMilliseconds);
index dde1ebcb54f534d96aab8599a0b28ee055e06db4..02a6337db95855f5abcd2c107f9543f672dca643 100644 (file)
         /// </summary>
         EndWorkout,
 
-        /// <summary>
-        /// Change to the next workout.
-        /// </summary>
-        ChangeToNextWorkout,
-
         /// <summary>
         /// Change to the previous workout.
         /// </summary>
-        ChangeToPreviousWorkout,
+        ChangeWorkout,
 
         /// <summary>
         /// Try again.
diff --git a/Fitness/ViewModels/SummaryViewModel.cs b/Fitness/ViewModels/SummaryViewModel.cs
deleted file mode 100644 (file)
index 4be5282..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Windows.Input;
-using Fitness.Models;
-using Fitness.Services;
-using Tizen.NUI.Binding;
-
-namespace Fitness.ViewModels
-{
-    /// <summary>
-    /// SummaryViewModel class.
-    /// </summary>
-    public class SummaryViewModel : BaseViewModel
-    {
-        private const string EndWorkoutTitle = "The current session will be stopped.";
-        private const string ChangeWorkoutTitle = "Do you want to change workout?";
-        private const string TryAgainTitle = "Do you want to try again?";
-        private const string TimeIsUpTitle = "Great job!";
-
-        private SummaryType currentSummaryType;
-        private string title;
-        private Dictionary<SummaryType, string> summaryTitleMap;
-        private ICommand ok;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SummaryViewModel"/> class.
-        /// </summary>
-        public SummaryViewModel(SummaryType summaryType, WorkoutViewModel workoutViewModel)
-        {
-            Back = new Command(() => { NavigationService.Instance.Pop(); });
-            InitializeTitleMap();
-            UpdateTitle();
-            SetOkCommand();
-            CurrentSummaryType = summaryType;
-            CurrentWorkout = workoutViewModel;
-            Workouts = WorkoutRepository.Instance.GetAll();
-        }
-
-        /// <summary>
-        /// Gets back command.
-        /// </summary>
-        public ICommand Back { get; private set; }
-
-        /// <summary>
-        /// Gets Ok command.
-        /// </summary>
-        public ICommand Ok
-        {
-            get => ok;
-            private set
-            {
-                if (ok != value)
-                {
-                    ok = value;
-                    RaisePropertyChanged();
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets the current summary type.
-        /// </summary>
-        public SummaryType CurrentSummaryType
-        {
-            get => currentSummaryType;
-            set
-            {
-                if (value != currentSummaryType)
-                {
-                    currentSummaryType = value;
-                    RaisePropertyChanged();
-                }
-
-                UpdateTitle();
-                SetOkCommand();
-            }
-        }
-
-        /// <summary>
-        /// Gets list of all available workouts.
-        /// </summary>
-        public IList<WorkoutViewModel> Workouts { get; private set; }
-
-        /// <summary>
-        /// Gets title.
-        /// </summary>
-        public string Title
-        {
-            get => title;
-            private set
-            {
-                if (title != value)
-                {
-                    title = value;
-                    RaisePropertyChanged();
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets TotalTime.
-        /// </summary>
-        public TimeSpan TotalTime { get; private set; } = new TimeSpan(0, 3, 39);
-
-        /// <summary>
-        /// Gets TotalCount.
-        /// </summary>
-        public int TotalCount { get; private set; } = 27;
-
-        /// <summary>
-        /// Gets AverageScore.
-        /// </summary>
-        public int AverageScore { get; private set; } = 98;
-
-        /// <summary>
-        /// Gets current workout.
-        /// </summary>
-        public WorkoutViewModel CurrentWorkout { get; internal set; }
-
-        private void InitializeTitleMap()
-        {
-            summaryTitleMap = new Dictionary<SummaryType, string>
-            {
-                { SummaryType.EndWorkout, EndWorkoutTitle },
-                { SummaryType.ChangeToPreviousWorkout, ChangeWorkoutTitle },
-                { SummaryType.ChangeToNextWorkout, ChangeWorkoutTitle },
-                { SummaryType.TryAgain, TryAgainTitle },
-                { SummaryType.TimeIsUp, TimeIsUpTitle },
-            };
-        }
-
-        private void UpdateTitle()
-        {
-            if (summaryTitleMap.TryGetValue(currentSummaryType, out string title))
-            {
-                Title = title;
-            }
-        }
-
-        private void SetOkCommand()
-        {
-            switch (currentSummaryType)
-            {
-                case SummaryType.ChangeToPreviousWorkout:
-                    Ok = new Command(() => { ChangeWorkout(-1); });
-                    break;
-                case SummaryType.ChangeToNextWorkout:
-                    Ok = new Command(() => { ChangeWorkout(1); });
-                    break;
-                case SummaryType.TryAgain:
-                    Ok = new Command(() => { ChangeWorkout(); });
-                    break;
-                default:
-                    Ok = new Command(() =>
-                    {
-                        NavigationService.Instance.NavigateToMainView();
-                    });
-                    break;
-            }
-        }
-
-        private void ChangeWorkout(int offset = 0)
-        {
-            WorkoutViewModel nextWorkout;
-
-            int idx = Workouts.IndexOf(CurrentWorkout) + offset;
-            if (idx >= 0 && idx < Workouts.Count)
-            {
-                nextWorkout = Workouts[idx];
-            }
-            else
-            {
-                nextWorkout = CurrentWorkout;
-            }
-
-            NavigationService.Instance.Pop();
-            NavigationService.Instance.Pop();
-            _ = NavigationService.Instance.NavigateToExercisingView(nextWorkout);
-        }
-    }
-}
index 3efc5f4afe4f9a0ba616ad475d082a88869f5f87..2424caf6c1906d50297209e45850cc71cc528e77 100644 (file)
@@ -19,9 +19,17 @@ namespace Fitness.Views
             true,
             propertyChanged: OnIsPlayingChanged);
 
+        public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(
+            "IsLoading",
+            typeof(bool),
+            typeof(ExercisingView),
+            true,
+            propertyChanged: OnIsLoadingChanged);
+
         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 =
         (
@@ -76,6 +84,19 @@ namespace Fitness.Views
             }
         }
 
+        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();
+                }
+            }
+        }
+
         private static (Task, Task) Animate(View view, Coordinates from, Coordinates to, CancellationToken token)
         {
             Task Scale()
@@ -116,6 +137,7 @@ namespace Fitness.Views
         private void Initialize()
         {
             InitializeComponent();
+            LoadingView.Loaded += OnLoaded;
 
             PlayingView.PreviewStub.Relayout += OnPlayingViewRelayout;
             cameraView.Preview += DetectPreview;
@@ -137,7 +159,10 @@ namespace Fitness.Views
 
                     PauseView.Hide();
                     PlayingView.Show();
-                    Preview.Play();
+                    if (!isLoading)
+                    {
+                        Preview.Play();
+                    }
                 }
                 else
                 {
@@ -161,12 +186,21 @@ namespace Fitness.Views
         {
             UpdatePositionAndSize();
             isInitialized = true;
+        }
 
-            LoadingView.Loaded += OnLoaded;
+        private void RestartLoading()
+        {
+            Preview.Stop();
+            LoadingView.StartLoading();
         }
 
         private void OnLoaded(object sender, System.EventArgs e)
         {
+            if (BindingContext is ExercisingViewModel viewModel)
+            {
+                viewModel.IsLoading = false;
+            }
+
             Preview.Play();
         }
 
index 7ecb42a9477c97c832d6ccf4cf4de4635502475b..31657fbbc3b59812703145158da94efccf1e6a06 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using Fitness.Controls;
+using Fitness.ViewModels;
 using Tizen.NUI;
 using Tizen.NUI.BaseComponents;
 
@@ -29,5 +30,14 @@ namespace Fitness.Views
                 Hide();
             }
         }
+
+        public void StartLoading()
+        {
+            if (BindingContext is LoadingViewModel viewModel)
+            {
+                Show();
+                viewModel.StartCounting();
+            }
+        }
     }
 }
index 2188c39e626f63d7f4b1d29fd69e39932a07ab42..fa866e516765603eff4289dd8c81a26dae06c232 100644 (file)
@@ -6,13 +6,15 @@
            xmlns:ctrl="clr-namespace:Fitness.Controls"
            xmlns:views="clr-namespace:Fitness.Views"
            xmlns:converters="clr-namespace:Fitness.Views.Converters"
+           xmlns:behaviors="clr-namespace:Fitness.Views.Behaviors"
            x:Name="Root"
            BackgroundColor="#EEEFF1"
-           IsPlaying="{Binding State, Converter={x:Static converters:WorkoutStateToBoolConverter.Converter}}">
-    
+           IsPlaying="{Binding State, Converter={x:Static converters:WorkoutStateToBoolConverter.Converter}}"
+           IsLoading="{Binding IsLoading}">
+
     <views:PlayingView x:Name="PlayingView"
                        BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}"/>
-    
+
     <!--Layer-->
 
     <View x:Name="cameraOverlayView" PositionX="796" PositionY="152" SizeWidth="640" SizeHeight="480">
     </View>
 
     <!--Layer-->
-    
+
     <VideoView x:Name="Preview"
                Underlay="False"
                ResourceUrl="{Binding CurrentWorkout.VideoUrl}"
                Looping="True"/>
-    
+
     <!--Layer-->
-    
+
     <views:PauseView x:Name="PauseView"
                      BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}"/>
     
@@ -52,5 +54,8 @@
                    Title="{Binding CurrentWorkout.Title}"/>
     
     <views:LoadingView x:Name="LoadingView"/>
-    
+
+    <views:SummaryView x:Name="SummaryView"
+                       behaviors:VisibilitySetter.IsVisible="{Binding IsSummaryVisible}"/>
+
 </ctrl:Page>
index 966b4cd8bd9cb568511db36bd103614e7c732a30..f583d6f56a4cc7f1f47a1da18b02c0150f0a1b2e 100644 (file)
@@ -26,9 +26,9 @@
             
             <View Size="{views:SizeInUnits Height=10}"
                   HeightSpecification="{Static LayoutParamPolicies.MatchParent}"/>
-            
+
             <TextLabel BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}"
-                       Text="{Binding Title}"
+                       Text="{Binding SummaryTitle}"
                        PixelSize="40"
                        WidthSpecification="{Static LayoutParamPolicies.MatchParent}"
                        HeightSpecification="{Static LayoutParamPolicies.MatchParent}"
@@ -66,7 +66,7 @@
                 </View>
                 
                 <View Size="{views:SizeInUnits Width=11}"/>
-                
+
                 <TextLabel BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}"
                            Text="{Binding TotalTime, StringFormat='{0:m\\:ss}'}"
                            HorizontalAlignment="Begin"
                 </View.Layout>
                 
                 <View Size="{views:SizeInUnits Width=20, Height=26}"/>
-                
+
                 <ctrl:NinePatchButton Text="Back"
                                       Size="{views:SizeInUnits Width=100, Height=26}"
                                       BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}"
-                                      Command="{Binding Back}"
+                                      Command="{Binding SummaryBackCommand}"
                                       behaviors:StyleSetter.Style="{Binding Source={x:Static styles:Buttons.Outline}}"/>
                 
                 <View Weight="1"
                       HeightSpecification="{Static LayoutParamPolicies.MatchParent}"
                       WidthSpecification="{Static LayoutParamPolicies.MatchParent}"/>
-                
+
                 <ctrl:NinePatchButton Text="Ok"
                                       Size="{views:SizeInUnits Width=100, Height=26}"
                                       BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}"
-                                      Command="{Binding Ok}"
+                                      Command="{Binding SummaryOkCommand}"
                                       behaviors:StyleSetter.Style="{Binding Source={x:Static styles:Buttons.Inverse}}"/>
                 
                 <View Size="{views:SizeInUnits Width=20, Height=24}"/>