UI/accounts: adds a loading screen during account loading

- adds faded loading pages with a spinner animation
- starts and stops the load page during account creation and loading
- resizes the loading graphics when window is resized
- adds an event handler for DPI and scale factor changes
- removes stretching from welcome page image
- clears account creation alias box after account creation clicked

Change-Id: I5046e0bc820e91c8b2f91ca223534d93ddf916f1
Tuleap: #1010
diff --git a/MainPage.xaml b/MainPage.xaml
index 31d3e27..7dc2143 100644
--- a/MainPage.xaml
+++ b/MainPage.xaml
@@ -1,6 +1,7 @@
 <!-- **********************************************************************

 * Copyright (C) 2016 by Savoir-faire Linux                                *

 * Author: Jäger Nicolas<nicolas.jager@savoirfairelinux.com>               *

+* Author: Traczyk Andreas<andreas.traczyk@savoirfairelinux.com>           *

 *                                                                         *

 * This program is free software; you can redistribute it and/or modify    *

 * it under the terms of the GNU General Public License as published by    *

@@ -23,18 +24,57 @@
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

       mc:Ignorable="d">

 

+    <Page.Resources>

+        <Storyboard x:Name="_fadeOutStoryboard_">

+            <DoubleAnimation

+            Storyboard.TargetName="_loadingOverlay_"

+            Storyboard.TargetProperty="Opacity"

+            From="1.0" To="0.0" Duration="0:0:1" Completed="hideLoadingOverlay"/>

+        </Storyboard>

+        <Storyboard x:Name="_fadeInModalStoryboard_">

+            <DoubleAnimation

+            Storyboard.TargetName="_loadingOverlay_"

+            Storyboard.TargetProperty="Opacity"

+            From="0.0" To="0.85" Duration="0:0:0.25"/>

+        </Storyboard>

+    </Page.Resources>

+

     <Grid>

+        <Grid   x:Name="_loadingOverlay_"

+                Canvas.ZIndex="4"

+                Visibility="Collapsed">

+            <Rectangle  x:Name="_loadingOverlayRect_"

+                        Canvas.ZIndex="5"

+                        Fill="Black"

+                        Opacity="0.85"

+                        Width="auto"

+                        Height="auto">

+            </Rectangle>

+            <Canvas  Canvas.ZIndex="6">

+                <Image  x:Name="_loadingImage_"

+                        Source="Assets/Tests/logo-ring.scale-100.png"

+                        Width="620"

+                        Height="300"/>

+                <ProgressRing   Foreground="#19a0b7"

+                                Name="_splashProgressRing_"

+                                IsActive="True"

+                                MaxWidth="200"

+                                MaxHeight="200"

+                                Width="118"

+                                Height="118"/>

+            </Canvas>

+        </Grid>

         <SplitView x:Name="_outerSplitView_"

                    IsPaneOpen="False">

-        <SplitView.Pane>

-            <Frame x:Name="_consolePanel_"/>

-        </SplitView.Pane>

-        <SplitView.Content>

-            <SplitView x:Name="_innerSplitView_"

+            <SplitView.Pane>

+                <Frame x:Name="_consolePanel_"/>

+            </SplitView.Pane>

+            <SplitView.Content>

+                <SplitView x:Name="_innerSplitView_"

                        IsPaneOpen="True"

                        CompactPaneLength="60"

                        DisplayMode="CompactInline">

-                <SplitView.Pane>

+                    <SplitView.Pane>

                         <Grid>

                             <Grid.RowDefinitions>

                                 <RowDefinition Height="32"/>

@@ -62,7 +102,7 @@
                             </Frame>

                         </Grid>

                     </SplitView.Pane>

-                <SplitView.Content>

+                    <SplitView.Content>

                         <Grid x:Name="_navGrid_">

                             <Grid.RowDefinitions>

                                 <!-- stores the hidden frames. -->

@@ -81,8 +121,8 @@
                                    Visibility="Visible"/>

                         </Grid>

                     </SplitView.Content>

-            </SplitView>

-        </SplitView.Content>

-    </SplitView>

+                </SplitView>

+            </SplitView.Content>

+        </SplitView>

     </Grid>

 </Page>

diff --git a/MainPage.xaml.cpp b/MainPage.xaml.cpp
index d6b4bb9..5e30336 100644
--- a/MainPage.xaml.cpp
+++ b/MainPage.xaml.cpp
@@ -51,6 +51,8 @@
 {

     InitializeComponent();

 

+    Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &MainPage::OnResize);

+

     _welcomeFrame_->Navigate(TypeName(RingClientUWP::Views::WelcomePage::typeid));

     _smartPanel_->Navigate(TypeName(RingClientUWP::Views::SmartPanel::typeid));

     _consolePanel_->Navigate(TypeName(RingClientUWP::Views::RingConsolePanel::typeid));

@@ -64,6 +66,10 @@
     ContactsViewModel::instance->noContactSelected += ref new NoContactSelected([&]() {

         showFrame(_welcomeFrame_);

     });

+

+    DisplayInformation^ displayInformation = DisplayInformation::GetForCurrentView();

+    dpiChangedtoken = (displayInformation->DpiChanged += ref new TypedEventHandler<DisplayInformation^,

+        Platform::Object^>(this, &MainPage::DisplayProperties_DpiChanged));

 }

 

 void

@@ -109,4 +115,91 @@
 RingClientUWP::MainPage::OnNavigatedTo(NavigationEventArgs ^ e)

 {

     RingD::instance->startDaemon();

+    showLoadingOverlay(true, false);

+}

+

+void

+RingClientUWP::MainPage::showLoadingOverlay(bool load, bool modal)

+{

+    if (!isLoading && load) {

+        isLoading = true;

+        _loadingOverlay_->Visibility = Windows::UI::Xaml::Visibility::Visible;

+        if (modal) {

+            _fadeInModalStoryboard_->Begin();

+            auto blackBrush = ref new Windows::UI::Xaml::Media::SolidColorBrush(Windows::UI::Colors::Black);

+            _loadingOverlayRect_->Fill = blackBrush;

+        }

+        else {

+            auto whiteBrush = ref new Windows::UI::Xaml::Media::SolidColorBrush(Windows::UI::Colors::White);

+            _loadingOverlayRect_->Fill = whiteBrush;

+            _loadingOverlayRect_->Opacity = 1.0;

+        }

+        OnResize(nullptr, nullptr);

+    }

+    else if (!load) {

+        isLoading = false;

+        _fadeOutStoryboard_->Begin();

+    }

+}

+

+void

+RingClientUWP::MainPage::PositionImage()

+{

+    bounds = ApplicationView::GetForCurrentView()->VisibleBounds;

+

+    auto img = ref new Image();

+    auto bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();

+    Windows::Foundation::Uri^ uri;

+

+    if (bounds.Width < 1200)

+        uri = ref new Windows::Foundation::Uri("ms-appx:///Assets/TESTS/logo-ring.scale-200.png");

+    else

+        uri = ref new Windows::Foundation::Uri("ms-appx:///Assets/TESTS/logo-ring.scale-150.png");

+

+    bitmapImage->UriSource = uri;

+    img->Source = bitmapImage;

+    _loadingImage_->Source = img->Source;

+

+    _loadingImage_->SetValue(Canvas::LeftProperty, bounds.Width * 0.5 - _loadingImage_->Width * 0.5);

+    _loadingImage_->SetValue(Canvas::TopProperty, bounds.Height * 0.5 - _loadingImage_->Height * 0.5);

+}

+

+void

+RingClientUWP::MainPage::PositionRing()

+{

+    double left;

+    double top;

+    if (bounds.Width < 1200) {

+        _splashProgressRing_->Width = 118;

+        _splashProgressRing_->Height = 118;

+        left = bounds.Width * 0.5 - _loadingImage_->Width * 0.5 - 145;

+        top = bounds.Height * 0.5 - _loadingImage_->Height * 0.5 - 60;

+    }

+    else {

+        _splashProgressRing_->Width = 162;

+        _splashProgressRing_->Height = 162;

+        left = bounds.Width * 0.5 - _loadingImage_->Width * 0.5 - 195;

+        top = bounds.Height * 0.5 - _loadingImage_->Height * 0.5 - 84;

+    }

+    _splashProgressRing_->SetValue(Canvas::LeftProperty, left + _loadingImage_->Width * 0.5);

+    _splashProgressRing_->SetValue(Canvas::TopProperty, top + _loadingImage_->Height * 0.5);

+}

+

+void

+RingClientUWP::MainPage::OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e)

+{

+    PositionImage();

+    PositionRing();

+}

+

+void

+RingClientUWP::MainPage::DisplayProperties_DpiChanged(DisplayInformation^ sender, Platform::Object^ args)

+{

+    OnResize(nullptr, nullptr);

+}

+

+void

+RingClientUWP::MainPage::hideLoadingOverlay()

+{

+    _loadingOverlay_->Visibility = Windows::UI::Xaml::Visibility::Collapsed;

 }
\ No newline at end of file
diff --git a/MainPage.xaml.h b/MainPage.xaml.h
index 7b9691b..aa76667 100644
--- a/MainPage.xaml.h
+++ b/MainPage.xaml.h
@@ -20,6 +20,7 @@
 

 using namespace Windows::UI::Xaml::Controls;

 using namespace Windows::UI::Xaml::Input;

+using namespace Windows::Foundation;

 

 namespace RingClientUWP

 {

@@ -29,11 +30,25 @@
 {

 public:

     MainPage();

+    void showLoadingOverlay(bool load, bool modal);

+    void hideLoadingOverlay();

+

+    property bool isLoading;

 

 protected:

     virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;

     virtual void OnKeyDown(KeyRoutedEventArgs^ e) override;

+

+    void PositionImage();

+    void PositionRing();

+    void OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e);

+

 private:

+    // Multi-monitor, DPI, scale factor change, and window resize detection

+    void DisplayProperties_DpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);

+    Windows::Foundation::EventRegistrationToken dpiChangedtoken;

+    Rect bounds;

+

     void _toggleSmartBoxButton__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);

     void showFrame(Windows::UI::Xaml::Controls::Frame^ frame);

 };

diff --git a/RingD.cpp b/RingD.cpp
index 3abac15..b52c2e2 100644
--- a/RingD.cpp
+++ b/RingD.cpp
@@ -207,10 +207,11 @@
                         int detailsCode, const std::string& detailsStr)

             {

                 MSG_("<RegistrationStateChanged>: ID = " + account_id + "state = " + state);

-                if (state == DRing::Account::States::UNREGISTERED) {

+                if (state == DRing::Account::States::REGISTERED) {

                     CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,

                     ref new DispatchedHandler([=]() {

-                        reloadAccountList();

+                        auto frame = dynamic_cast<Frame^>(Window::Current->Content);

+                        dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(false, false);

                     }));

                 }

             }),

diff --git a/SmartPanel.xaml.cpp b/SmartPanel.xaml.cpp
index 2366bec..db4bf79 100644
--- a/SmartPanel.xaml.cpp
+++ b/SmartPanel.xaml.cpp
@@ -130,7 +130,6 @@
     _shareMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed;

 }

 

-

 void RingClientUWP::Views::SmartPanel::_addAccountBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)

 {

     _accountsMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed;

@@ -143,6 +142,11 @@
     {

     case 0:

     {

+        CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,

+        ref new DispatchedHandler([=]() {

+            auto frame = dynamic_cast<Windows::UI::Xaml::Controls::Frame^>(Window::Current->Content);

+            dynamic_cast<RingClientUWP::MainPage^>(frame->Content)->showLoadingOverlay(true, true);

+        }));

         RingD::instance->createRINGAccount(_aliasTextBox_->Text);

         _accountCreationMenuGrid_->Visibility = Windows::UI::Xaml::Visibility::Collapsed;

         _accountsMenuButton__Checked(nullptr, nullptr);

@@ -159,6 +163,7 @@
     default:

         break;

     }

+    _aliasTextBox_->Text = "";

 }

 

 

diff --git a/UserPreferences.cpp b/UserPreferences.cpp
index 026f749..2307c78 100644
--- a/UserPreferences.cpp
+++ b/UserPreferences.cpp
@@ -59,22 +59,25 @@
         .then([this,preferencesFile](bool contacts_file_exists)

     {

         if (contacts_file_exists) {

-            RingDebug::instance->print("opened preferences file");

             try {

                 create_task(ApplicationData::Current->LocalFolder->GetFileAsync(preferencesFile))

                     .then([this](StorageFile^ file)

                 {

-                    create_task(FileIO::ReadTextAsync(file))

-                        .then([this](String^ fileContents){

-                        RingDebug::instance->print("reading preferences file");

-                        if (fileContents != nullptr) {

-                            Destringify(fileContents);

-                            // select account index after loading preferences

-                            selectIndex(PREF_ACCOUNT_INDEX);

-                            if (PREF_PROFILE_PHOTO)

-                                loadProfileImage();

-                        }

-                    });

+                    try {

+                        create_task(FileIO::ReadTextAsync(file))

+                            .then([this](String^ fileContents){

+                            if (fileContents != nullptr) {

+                                Destringify(fileContents);

+                                // select account index after loading preferences

+                                selectIndex(PREF_ACCOUNT_INDEX);

+                                if (PREF_PROFILE_PHOTO)

+                                    loadProfileImage();

+                            }

+                        });

+                    }

+                    catch (Exception^ e) {

+                        RingDebug::instance->print("Exception while reading preferences file");

+                    }

                 });

             }

             catch (Exception^ e) {

diff --git a/WelcomePage.xaml b/WelcomePage.xaml
index f9aa112..d4f01f6 100644
--- a/WelcomePage.xaml
+++ b/WelcomePage.xaml
@@ -23,15 +23,18 @@
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

       mc:Ignorable="d">

 

-    <StackPanel HorizontalAlignment="Center"

-                VerticalAlignment="Center">

+    <Grid x:Name="_welcomePage_"

+        >

         <!--<TextBlock x:Uid="_welcomeMsg"

                    x:Name="_welcomeMsg_"

                    Style="{StaticResource TextStyle1}"

                    HorizontalAlignment="Center"

                    VerticalAlignment="Center"

                    TextWrapping="Wrap" />-->

-        <Image Source="Assets\TESTS\logo-ring.scale-125.png"/>

-    </StackPanel>

+        <Image x:Name="_welcomeImage_"

+            Source="Assets\TESTS\logo-ring.square-100.png"

+               Width="310"

+               Height="310"/>

+    </Grid>

 

 </Page>

diff --git a/WelcomePage.xaml.cpp b/WelcomePage.xaml.cpp
index 7112811..1a22547 100644
--- a/WelcomePage.xaml.cpp
+++ b/WelcomePage.xaml.cpp
@@ -25,4 +25,23 @@
 WelcomePage::WelcomePage()

 {

     InitializeComponent();

-};
\ No newline at end of file
+    Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &WelcomePage::OnResize);

+    OnResize(nullptr, nullptr);

+};

+

+void

+WelcomePage::PositionImage()

+{

+    Rect imageBounds;

+    imageBounds.Width = _welcomePage_->ActualWidth;

+    imageBounds.Height = _welcomePage_->ActualWidth;

+

+    _welcomeImage_->SetValue(Canvas::LeftProperty, imageBounds.Width * 0.5 - _welcomeImage_->Width * 0.5);

+    _welcomeImage_->SetValue(Canvas::TopProperty, imageBounds.Height * 0.5 - _welcomeImage_->Height * 0.5);

+}

+

+void

+WelcomePage::OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e)

+{

+    PositionImage();

+}
\ No newline at end of file
diff --git a/WelcomePage.xaml.h b/WelcomePage.xaml.h
index 29cb127..1f37c15 100644
--- a/WelcomePage.xaml.h
+++ b/WelcomePage.xaml.h
@@ -26,6 +26,9 @@
 {

 public:

     WelcomePage();

+protected:

+    void PositionImage();

+    void OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e);

 };

 }

 }
\ No newline at end of file
diff --git a/pch.h b/pch.h
index daba861..3860e31 100644
--- a/pch.h
+++ b/pch.h
@@ -18,8 +18,8 @@
 **************************************************************************/

 

 /* standard system include files. */

-#include <ppltasks.h>

 #include <iomanip>

+#include <ppltasks.h>

 #include <queue>

 

 /* required by generated headers. */

@@ -31,9 +31,10 @@
 #include "Contact.h"

 #include "ContactsViewModel.h"

 #include "Conversation.h"

+#include "MainPage.xaml.h"

 

 /* ensure to be accessed from anywhere */

 #include "RingD.h"

 #include "RingDebug.h"

 #include "Utils.h"

-#include "UserPreferences.h"

+#include "UserPreferences.h"
\ No newline at end of file