diff --git a/CallsViewModel.cpp b/CallsViewModel.cpp index 02a493344ea34e7b9cff5fcf07c609bff3a35f44..f5dd3d2fc57f25bb6a41028e70615fc74bb1a433 100644 --- a/CallsViewModel.cpp +++ b/CallsViewModel.cpp @@ -66,4 +66,14 @@ RingClientUWP::ViewModel::CallsViewModel::addNewCall(String^ accountId, String^ 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 553455e423d2fafd78f1f22c073aba9c89bed56d..4bc06a317ba76e7467690b886dd88ac22068c2c0 100644 --- a/CallsViewModel.h +++ b/CallsViewModel.h @@ -41,7 +41,8 @@ internal: /* 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 @@ internal: private: CallsViewModel(); // singleton - Vector<Call^>^ CallsList_; + Vector<Call^>^ CallsList_; // refacto : change C to c }; } diff --git a/ContactsViewModel.cpp b/ContactsViewModel.cpp index 7ac6dc8a57ce03c2e9909e88acc5f2c4effd9e21..e0b43f5eb288cce5f8a760493282db61b4f16da7 100644 --- a/ContactsViewModel.cpp +++ b/ContactsViewModel.cpp @@ -64,28 +64,9 @@ ContactsViewModel::ContactsViewModel() 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 @@ ContactsViewModel::addNewContact(String^ name, String^ ringId) Contact^ contact = ref new Contact(trimedName, trimedName, nullptr, 0); contactsList_->Append(contact); saveContactsToFile(); + contactAdded(contact); return contact; } @@ -196,7 +178,9 @@ ContactsViewModel::Destringify(String^ data) 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 13cf1fb74c8c4ec1a41ea0ca81d315ed24357a94..7359a84f12bfc3fbc427070fb78f4134a00defc6 100644 --- a/ContactsViewModel.h +++ b/ContactsViewModel.h @@ -31,6 +31,7 @@ delegate void NoContactSelected(); 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 @@ internal: event ScreenConversationMessage^ screenConversationMessage; event NotifyNewConversationMessage^ notifyNewConversationMessage; event ShowContactBar^ showContactBar; + event ContactAdded^ contactAdded; private: ContactsViewModel(); // singleton diff --git a/SmartPanel.xaml b/SmartPanel.xaml index 65d05435c8a82b63c0dfb96d2a3f5ec5311122a2..307c9c13416f913b7f12a6068f15d8d1b5385d3e 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 db4bf7958aab7ea4f5a23c7eb9f7542cee886d20..8ac82bd66b38e6799cd267a8e247b84f67255d93 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 @@ SmartPanel::SmartPanel() { 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 @@ SmartPanel::SmartPanel() _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); + + 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); + }); - _accountsList_->ItemsSource = AccountsViewModel::instance->accountsList; - _smartList_->ItemsSource = ContactsViewModel::instance->contactsList; } void @@ -177,7 +227,8 @@ void 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::_ringTxtBx__KeyDown(Platform::Object^ sen 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 1b2f63f12a1afc820094da32d137807157d040dd..9128fe303695f3fb30ebce78d001038de717f3aa 100644 --- a/SmartPanel.xaml.h +++ b/SmartPanel.xaml.h @@ -32,6 +32,8 @@ public ref class SmartPanel sealed public: SmartPanel(); void updatePageContent(); + Controls::SmartPanelItem^ findItem(Contact^ contact); + Controls::SmartPanelItem^ findItem(Call^ call); internal: enum class Mode { Minimized, Normal }; @@ -41,6 +43,7 @@ internal: 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 @@ private: 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 0000000000000000000000000000000000000000..7d91b2abd6f8d6556e3a2519e85c7f83b695d2ce --- /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 0000000000000000000000000000000000000000..a651d154073c6f944c2be10adf2df84e3c3d3158 --- /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 3860e3191f41b358f8cd46b88b51fbf8b3b876c9..b21842f4c37e0b9cd1e476513286eaa4044fc39a 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 b164c1f806245d02a3e3ec79a61f99569d195379..21f46252ea5b78c1c2c9de1e7e705df31c8dec6c 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 f738d4a12c1577ef8ba0782bbe4df68cc9250d33..974321d7610d809da21421bb4b405006cdbfee7b 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">