call : accept/reject incoming calls

- removes contacts as sources for the smartList.
- creates smartListItems, and set them as sources for the smartList.
  SmartListItem is a UI control, not a model.
- adds contacts and calls (associated) inside smartListItem.
- removes some UI property from contact class (model).
- adds a new filter : Controls, where smartListItems belongs.

Tuleap: #1014
Change-Id: Ia7679c2328f9dc85b6265c5e518aad08805230fb
diff --git a/CallsViewModel.cpp b/CallsViewModel.cpp
index 02a4933..f5dd3d2 100644
--- a/CallsViewModel.cpp
+++ b/CallsViewModel.cpp
@@ -66,4 +66,14 @@
 void RingClientUWP::ViewModel::CallsViewModel::clearCallsList()

 {

     CallsList_->Clear();

-}
\ No newline at end of file
+}

+

+Call^

+CallsViewModel::findCall(String^ callId)

+{

+    for each (Call^ call in CallsList_)

+        if (call->callId == callId)

+            return call;

+

+    return nullptr;

+}

diff --git a/CallsViewModel.h b/CallsViewModel.h
index 553455e..4bc06a3 100644
--- a/CallsViewModel.h
+++ b/CallsViewModel.h
@@ -41,7 +41,8 @@
     /* functions */

     Call^ addNewCall(String^ accountId, String^ callId, String^ from);

     void clearCallsList();

-    void setState(String^ callId, String^ state, int code);

+    void setState(String^ callId, String^ state, int code); // used ?

+    Call^ findCall(String^ callId);

 

     /* properties */

     property Vector<Call^>^ CallsList

@@ -58,7 +59,7 @@
 

 private:

     CallsViewModel(); // singleton

-    Vector<Call^>^ CallsList_;

+    Vector<Call^>^ CallsList_; // refacto : change C to c

 

 };

 }

diff --git a/ContactsViewModel.cpp b/ContactsViewModel.cpp
index 7ac6dc8..e0b43f5 100644
--- a/ContactsViewModel.cpp
+++ b/ContactsViewModel.cpp
@@ -64,28 +64,9 @@
             saveContactsToFile();

         }

     });

-    CallsViewModel::instance->callRecieved += ref new RingClientUWP::CallRecieved([&](

-    Call^ call) {

-        auto from = call->from;

-        auto contact = findContactByName(from);

-

-        if (contact == nullptr)

-            contact = addNewContact(from, from); // contact checked inside addNewContact.

-

-        bool isNotSelected = (contact != ContactsViewModel::instance->selectedContact) ? true : false;

-

-        if (contact == nullptr) {

-            ERR_("contact not handled!");

-            return;

-        }

-        contact->_call = call;

-        contact->_contactBarHeight = 50;

-

-    });

-

 }

 

-Contact^

+Contact^ // refacto : remove "byName"

 ContactsViewModel::findContactByName(String^ name)

 {

     for each (Contact^ contact in contactsList_)

@@ -103,6 +84,7 @@
         Contact^ contact = ref new Contact(trimedName, trimedName, nullptr, 0);

         contactsList_->Append(contact);

         saveContactsToFile();

+        contactAdded(contact);

         return contact;

     }

 

@@ -196,7 +178,9 @@
                 guid = contactObject->GetNamedString(GUIDKey);

                 unreadmessages = static_cast<uint16_t>(contactObject->GetNamedNumber(unreadMessagesKey));

             }

-            contactsList_->Append(ref new Contact(name, ringid, guid, unreadmessages));

+            auto contact = ref new Contact(name, ringid, guid, unreadmessages);

+            contactsList_->Append(contact);

+            contactAdded(contact);

         }

     }

 }

diff --git a/ContactsViewModel.h b/ContactsViewModel.h
index 13cf1fb..7359a84 100644
--- a/ContactsViewModel.h
+++ b/ContactsViewModel.h
@@ -31,6 +31,7 @@
 delegate void ScreenConversationMessage(String^ accountId, String^ from, String^ payload);

 delegate void NotifyNewConversationMessage();

 delegate void ShowContactBar();

+delegate void ContactAdded(Contact^);

 

 namespace ViewModel {

 public ref class ContactsViewModel sealed

@@ -86,6 +87,7 @@
     event ScreenConversationMessage^ screenConversationMessage;

     event NotifyNewConversationMessage^ notifyNewConversationMessage;

     event ShowContactBar^ showContactBar;

+    event ContactAdded^ contactAdded;

 

 private:

     ContactsViewModel(); // singleton

diff --git a/SmartPanel.xaml b/SmartPanel.xaml
index 65d0543..307c9c1 100644
--- a/SmartPanel.xaml
+++ b/SmartPanel.xaml
@@ -19,6 +19,7 @@
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

       xmlns:local="using:RingClientUWP"

+      xmlns:controls="using:RingClientUWP.Controls"

       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

       mc:Ignorable="d">

@@ -148,6 +149,63 @@
                            Text="{x:Bind ringID_}"/>

             </Grid>

         </DataTemplate>

+        <!-- template for calls. -->

+        <DataTemplate x:Key="CallTemplate" x:DataType="local:Call">

+            <Grid Width="320"

+                      HorizontalAlignment="Left"

+

+                      Background="DarkGray">

+                <Grid.RowDefinitions>

+                    <RowDefinition Height="30"/>

+                    <RowDefinition Height="30"/>

+                </Grid.RowDefinitions>

+                <TextBlock x:Name="_contactCallStatus_"

+                           Grid.Row="0"

+                           Foreground="White"

+                           Text="{x:Bind state, Mode=OneWay}"

+                           Visibility="Visible"

+                           HorizontalAlignment="Center">

+                </TextBlock>

+                <StackPanel Orientation="Horizontal"

+                            Grid.Row="1"

+                            HorizontalAlignment="Center">

+                    <Button x:Name="_acceptIncomingCallBtn_"

+                            Click="_acceptIncomingCallBtn__Click"

+                            VerticalAlignment="Center"

+                            HorizontalAlignment="Center"

+                            Content="Accept"/>

+                    <Button x:Name="_rejectIncomingCallBtn_"

+                            Click="_rejectIncomingCallBtn__Click"

+                            VerticalAlignment="Center"

+                            HorizontalAlignment="Center"

+                            Content="Reject"/>

+                </StackPanel>

+            </Grid>

+        </DataTemplate>

+        <!-- template for smartpanelitems. -->

+        <DataTemplate x:Key="SmartPanelItemsTemplate"

+                      x:DataType="controls:SmartPanelItem">

+            <Grid>

+                <Grid.RowDefinitions>

+                    <RowDefinition Height="auto"/>

+                    <RowDefinition Height="auto"/>

+                </Grid.RowDefinitions>

+                <ListBoxItem x:Name="_contactItem_"

+                             Padding="0"

+                             Margin="0"

+                             IsHitTestVisible="False"

+                             Grid.Row="0"

+                             ContentTemplate="{StaticResource ContactTemplate}"

+                             Content="{x:Bind _contact, Mode=OneWay}"/>

+                <ListBoxItem x:Name="_callItem_"

+                             Grid.Row="1"

+                             Visibility="{x:Bind _callBar, Mode=OneWay}"

+                             Padding="0"

+                             Margin="0"

+                             ContentTemplate="{StaticResource CallTemplate}"

+                             Content="{x:Bind _call, Mode=OneWay}"/>

+            </Grid>

+        </DataTemplate>

     </Page.Resources>

 

     <Grid>

@@ -338,9 +396,9 @@
                 </Grid>

             </Grid>

         </Grid>

-        <!-- contact list and settings. -->

+        <!-- smartList and settings. -->

         <Grid Grid.Row="1">

-            <!-- contacts list. -->

+            <!-- contacts + calls => smartpanelitems. -->

             <Grid x:Name="_smartGrid_"

                   Grid.Row="0">

                 <Grid.RowDefinitions>

@@ -364,7 +422,7 @@
                          ScrollViewer.HorizontalScrollBarVisibility="Auto"

                          ScrollViewer.HorizontalScrollMode="Enabled"

                          ItemContainerStyle="{StaticResource contactsListBoxStyle}"

-                         ItemTemplate="{StaticResource ContactTemplate}"/>

+                         ItemTemplate="{StaticResource SmartPanelItemsTemplate}"/>

             </Grid>

             <!-- settings. -->

             <Grid x:Name="_settings_"

diff --git a/SmartPanel.xaml.cpp b/SmartPanel.xaml.cpp
index db4bf79..8ac82bd 100644
--- a/SmartPanel.xaml.cpp
+++ b/SmartPanel.xaml.cpp
@@ -17,12 +17,13 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *

  **************************************************************************/

 #include "pch.h"

-

+#include <string> // move it

 #include "SmartPanel.xaml.h"

 

 using namespace Platform;

 

 using namespace RingClientUWP;

+using namespace RingClientUWP::Controls;

 using namespace RingClientUWP::Views;

 using namespace RingClientUWP::ViewModel;

 using namespace Windows::Media::Capture;

@@ -42,6 +43,12 @@
 {

     InitializeComponent();

 

+    _accountsList_->ItemsSource = AccountsViewModel::instance->accountsList;

+

+    /* populate the smartlist */

+    smartPanelItemsList_ = ref new Vector<SmartPanelItem^>();

+    _smartList_->ItemsSource = smartPanelItemsList_;

+

     /* connect delegates */

     Configuration::UserPreferences::instance->selectIndex += ref new SelectIndex([this](int index) {

         _accountsList_->SelectedIndex = index;

@@ -56,9 +63,52 @@
         _accountsListScrollView_->UpdateLayout();

         _accountsListScrollView_->ScrollToVerticalOffset(_accountsListScrollView_->ScrollableHeight);

     });

+    CallsViewModel::instance->callRecieved += ref new RingClientUWP::CallRecieved([&](

+    Call^ call) {

+        auto from = call->from;

+        auto contact = ContactsViewModel::instance->findContactByName(from);

 

-    _accountsList_->ItemsSource = AccountsViewModel::instance->accountsList;

-    _smartList_->ItemsSource = ContactsViewModel::instance->contactsList;

+        if (contact == nullptr)

+            contact = ContactsViewModel::instance->addNewContact(from, from); // contact checked inside addNewContact.

+

+        if (contact == nullptr) {

+            ERR_("contact not handled!");

+            return;

+        }

+

+        auto item = findItem(contact);

+        item->_call = call;

+    });

+    RingD::instance->stateChange += ref new StateChange([this](String^ callId, String^ state, int code) {

+        auto call = CallsViewModel::instance->findCall(callId);

+

+        if (call == nullptr)

+            return;

+

+        auto item = findItem(call);

+

+        if (!item) {

+            WNG_("item not found");

+            return;

+        }

+

+        if (call->state == "incoming call")

+            item->_callBar = Windows::UI::Xaml::Visibility::Visible;

+

+        if (call->state == "CURRENT")

+            item->_callBar = Windows::UI::Xaml::Visibility::Collapsed;

+

+        if (call->state == "")

+            item->_callBar = Windows::UI::Xaml::Visibility::Collapsed;

+    });

+

+

+    ContactsViewModel::instance->contactAdded += ref new ContactAdded([this](Contact^ contact) {

+        auto smartPanelItem = ref new SmartPanelItem();

+        smartPanelItem->_contact = contact;

+        smartPanelItemsList_->Append(smartPanelItem);

+    });

+

 }

 

 void

@@ -177,7 +227,8 @@
 SmartPanel::_smartList__SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e)

 {

     auto listbox = safe_cast<ListBox^>(sender);

-    auto contact = safe_cast<Contact^>(listbox->SelectedItem);

+    auto item = safe_cast<SmartPanelItem^>(listbox->SelectedItem);

+    auto contact = safe_cast<Contact^>(item->_contact);

     ContactsViewModel::instance->selectedContact = contact;

 }

 

@@ -217,20 +268,37 @@
 void RingClientUWP::Views::SmartPanel::_rejectIncomingCallBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)

 {

     auto button = dynamic_cast<Button^>(e->OriginalSource);

-    auto contact = dynamic_cast<Contact^>(button->DataContext);

-    auto call = contact->_call;

+    auto call = dynamic_cast<Call^>(button->DataContext);

 

     call->refuse();

-    contact->_contactBarHeight = 0;

 }

 

 

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

 {

     auto button = dynamic_cast<Button^>(e->OriginalSource);

-    auto contact = dynamic_cast<Contact^>(button->DataContext);

-    auto call = contact->_call;

+    auto call = dynamic_cast<Call^>(button->DataContext);

 

     call->accept();

-    contact->_contactBarHeight = 0;

 }

+

+SmartPanelItem^

+SmartPanel::findItem(Contact^ contact)

+{

+    for each (SmartPanelItem^ item in smartPanelItemsList_)

+        if (item->_contact == contact)

+            return item;

+

+    return nullptr;

+}

+

+

+SmartPanelItem^

+SmartPanel::findItem(Call^ call)

+{

+    for each (SmartPanelItem^ item in smartPanelItemsList_)

+        if (item->_call == call)

+            return item;

+

+    return nullptr;

+}
\ No newline at end of file
diff --git a/SmartPanel.xaml.h b/SmartPanel.xaml.h
index 1b2f63f..9128fe3 100644
--- a/SmartPanel.xaml.h
+++ b/SmartPanel.xaml.h
@@ -32,6 +32,8 @@
 public:

     SmartPanel();

     void updatePageContent();

+    Controls::SmartPanelItem^ findItem(Contact^ contact);

+    Controls::SmartPanelItem^ findItem(Call^ call);

 

 internal:

     enum class Mode { Minimized, Normal };

@@ -41,6 +43,7 @@
     void setMode(RingClientUWP::Views::SmartPanel::Mode mode);

 

 private:

+    /* functions */

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

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

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

@@ -55,6 +58,9 @@
     void _ringTxtBx__KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e);

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

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

+

+    /* members */

+    Vector<Controls::SmartPanelItem^>^ smartPanelItemsList_;

 };

 }

 }
\ No newline at end of file
diff --git a/SmartPanelItem.cpp b/SmartPanelItem.cpp
new file mode 100644
index 0000000..7d91b2a
--- /dev/null
+++ b/SmartPanelItem.cpp
@@ -0,0 +1,46 @@
+/**************************************************************************

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

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

+* Author: Traczyk Andreas <traczyk.andreas@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    *

+* the Free Software Foundation; either version 3 of the License, or       *

+* (at your option) any later version.                                     *

+*                                                                         *

+* This program is distributed in the hope that it will be useful,         *

+* but WITHOUT ANY WARRANTY; without even the implied warranty of          *

+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *

+* GNU General Public License for more details.                            *

+*                                                                         *

+* You should have received a copy of the GNU General Public License       *

+* along with this program.  If not, see <http://www.gnu.org/licenses/>.   *

+**************************************************************************/

+#include "pch.h"

+

+#include "SmartPanelItem.h"

+

+using namespace Windows::ApplicationModel::Core;

+using namespace Platform;

+using namespace Windows::Data::Json;

+using namespace Windows::UI::Core;

+

+using namespace RingClientUWP;

+using namespace RingClientUWP::Controls;

+using namespace ViewModel;

+

+SmartPanelItem::SmartPanelItem()

+{}

+

+void

+SmartPanelItem::NotifyPropertyChanged(String^ propertyName)

+{

+    CoreApplicationView^ view = CoreApplication::MainView;

+    view->CoreWindow->Dispatcher->RunAsync(

+        CoreDispatcherPriority::Normal,

+        ref new DispatchedHandler([this, propertyName]()

+    {

+        PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));

+    }));

+}

+

diff --git a/SmartPanelItem.h b/SmartPanelItem.h
new file mode 100644
index 0000000..a651d15
--- /dev/null
+++ b/SmartPanelItem.h
@@ -0,0 +1,70 @@
+#pragma once

+/**************************************************************************

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

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

+* Author: Traczyk Andreas <traczyk.andreas@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    *

+* the Free Software Foundation; either version 3 of the License, or       *

+* (at your option) any later version.                                     *

+*                                                                         *

+* This program is distributed in the hope that it will be useful,         *

+* but WITHOUT ANY WARRANTY; without even the implied warranty of          *

+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *

+* GNU General Public License for more details.                            *

+*                                                                         *

+* You should have received a copy of the GNU General Public License       *

+* along with this program.  If not, see <http://www.gnu.org/licenses/>.   *

+**************************************************************************/

+using namespace Platform;

+using namespace Windows::Data::Json;

+using namespace Windows::UI::Xaml;

+using namespace Windows::UI::Xaml::Data;

+

+namespace RingClientUWP

+{

+namespace Controls {

+public ref class SmartPanelItem sealed : public INotifyPropertyChanged

+{

+public:

+    SmartPanelItem();

+

+    virtual event PropertyChangedEventHandler^ PropertyChanged;

+

+    property Contact^ _contact;

+    property Visibility _callBar

+    {

+        Visibility get()

+        {

+            return callBar_;

+        }

+        void set(Visibility value)

+        {

+            callBar_ = value;

+            PropertyChanged(this, ref new PropertyChangedEventArgs("_callBar"));

+        }

+    }

+    property Call^ _call

+    {

+        Call^ get()

+        {

+            return call_;

+        }

+        void set(Call^ value)

+        {

+            call_ = value;

+            PropertyChanged(this, ref new PropertyChangedEventArgs("_call"));

+        }

+    }

+

+protected:

+    void NotifyPropertyChanged(String^ propertyName);

+

+private:

+    Visibility callBar_ = Visibility::Collapsed;

+    Call^ call_;

+};

+}

+}

+

diff --git a/pch.h b/pch.h
index 3860e31..b21842f 100644
--- a/pch.h
+++ b/pch.h
@@ -32,6 +32,7 @@
 #include "ContactsViewModel.h"

 #include "Conversation.h"

 #include "MainPage.xaml.h"

+#include "SmartPanelItem.h"

 

 /* ensure to be accessed from anywhere */

 #include "RingD.h"

diff --git a/ring-client-uwp.vcxproj b/ring-client-uwp.vcxproj
index b164c1f..21f4625 100644
--- a/ring-client-uwp.vcxproj
+++ b/ring-client-uwp.vcxproj
@@ -189,6 +189,7 @@
     <ClInclude Include="SmartPanel.xaml.h">

       <DependentUpon>SmartPanel.xaml</DependentUpon>

     </ClInclude>

+    <ClInclude Include="SmartPanelItem.h" />

     <ClInclude Include="UserPreferences.h" />

     <ClInclude Include="Utils.h" />

     <ClInclude Include="VideoPage.xaml.h">

@@ -301,6 +302,7 @@
     <ClCompile Include="SmartPanel.xaml.cpp">

       <DependentUpon>SmartPanel.xaml</DependentUpon>

     </ClCompile>

+    <ClCompile Include="SmartPanelItem.cpp" />

     <ClCompile Include="UserPreferences.cpp" />

     <ClCompile Include="VideoPage.xaml.cpp">

       <DependentUpon>VideoPage.xaml</DependentUpon>

diff --git a/ring-client-uwp.vcxproj.filters b/ring-client-uwp.vcxproj.filters
index f738d4a..974321d 100644
--- a/ring-client-uwp.vcxproj.filters
+++ b/ring-client-uwp.vcxproj.filters
@@ -35,6 +35,9 @@
     <Filter Include="Model">

       <UniqueIdentifier>{8ea3251c-a70e-4de5-9f26-8db3df45c2c4}</UniqueIdentifier>

     </Filter>

+    <Filter Include="Controls">

+      <UniqueIdentifier>{2cffcd5e-0546-4629-a152-37efd9c1128f}</UniqueIdentifier>

+    </Filter>

   </ItemGroup>

   <ItemGroup>

     <ApplicationDefinition Include="App.xaml" />

@@ -80,6 +83,9 @@
     <ClCompile Include="Call.cpp">

       <Filter>Model</Filter>

     </ClCompile>

+    <ClCompile Include="SmartPanelItem.cpp">

+      <Filter>Controls</Filter>

+    </ClCompile>

   </ItemGroup>

   <ItemGroup>

     <ClInclude Include="pch.h" />

@@ -125,6 +131,9 @@
     <ClInclude Include="Call.h">

       <Filter>Model</Filter>

     </ClInclude>

+    <ClInclude Include="SmartPanelItem.h">

+      <Filter>Controls</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <Image Include="Assets\LockScreenLogo.scale-200.png">