From c551c365e83c768ba053189063b29b6a4de1256f Mon Sep 17 00:00:00 2001
From: Nicolas Jager <nicolas.jager@savoirfairelinux.com>
Date: Sat, 1 Oct 2016 19:24:50 -0400
Subject: [PATCH] smartpanel : refactoring

Change-Id: Iea01dd8242270e1c080cd95030da4d211638d993
Tuleap: #1202
---
 Call.cpp                   |   9 +-
 Call.h                     |  18 +++-
 CallsViewModel.cpp         |  45 ++++-----
 CallsViewModel.h           |   1 +
 Contact.cpp                |  28 +-----
 Contact.h                  |  21 ++--
 ContactsViewModel.cpp      |  24 ++---
 ContactsViewModel.h        |  27 -----
 MainPage.xaml.cpp          |  96 ++++++++++++------
 MainPage.xaml.h            |   6 ++
 MessageTextPage.xaml.cpp   |  24 ++---
 RingD.cpp                  |  29 +++++-
 RingD.h                    |   3 +-
 SmartPanel.xaml            | 201 +++++++++++++++++++++++--------------
 SmartPanel.xaml.cpp        | 139 +++++++++++++++++++------
 SmartPanel.xaml.h          |  39 ++++++-
 SmartPanelItem.cpp         |   5 +-
 SmartPanelItem.h           |  49 +++------
 SmartPanelItemsViewModel.h |  14 ++-
 Styles.xaml                |  15 +++
 VideoPage.xaml.cpp         |  19 ++--
 21 files changed, 493 insertions(+), 319 deletions(-)

diff --git a/Call.cpp b/Call.cpp
index b756033..6cc2fe3 100644
--- a/Call.cpp
+++ b/Call.cpp
@@ -35,17 +35,10 @@ Call::Call(String^ accountIdz, String^ callIdz, String^ fromz)
 
     isOutGoing = false; // by default, we consider the call incomming, REFACTO : add this to the constructor params...
 
-    this->state = "incoming call";
+    this->state = CallStatus::NONE;
     this->code = -1;
 }
 
-void RingClientUWP::Call::stateChange(String ^ state, int code)
-{
-    this->state = state;
-    PropertyChanged(this, ref new PropertyChangedEventArgs("state"));
-    this->code = code;
-}
-
 void
 Call::NotifyPropertyChanged(String^ propertyName)
 {
diff --git a/Call.h b/Call.h
index fb5be0b..dfebe21 100644
--- a/Call.h
+++ b/Call.h
@@ -21,12 +21,15 @@ using namespace Windows::UI::Xaml::Data;
 
 namespace RingClientUWP
 {
+/* enumerations. */
+public enum class CallStatus { NONE, INCOMING_RINGING, OUTGOING_RINGING, SEARCHING, IN_PROGRESS, ENDED };
+
 public ref class Call sealed : public INotifyPropertyChanged
 {
 public:
+
     /* functions */
     Call(String^ accountId, String^ callId, String^ from);
-    void stateChange(String^ state, int code);
 
     /* properties */
     virtual event PropertyChangedEventHandler^ PropertyChanged;
@@ -34,7 +37,15 @@ public:
     property String^ accountId;
     property String^ callId;
     property String^ from;
-    property String^ state;
+    property CallStatus state {
+        CallStatus get() {
+            return state_;
+        }
+        void set(CallStatus value) {
+            state_ = value;
+            PropertyChanged(this, ref new PropertyChangedEventArgs("state"));
+        }
+    }
     property bool isOutGoing;
     property int code;
 
@@ -49,6 +60,9 @@ internal:
     void accept();
     void cancel();
 
+private:
+    CallStatus state_;
+
 };
 }
 
diff --git a/CallsViewModel.cpp b/CallsViewModel.cpp
index b714790..07e9019 100644
--- a/CallsViewModel.cpp
+++ b/CallsViewModel.cpp
@@ -34,32 +34,10 @@ CallsViewModel::CallsViewModel()
     RingD::instance->incomingCall += ref new RingClientUWP::IncomingCall([&](
     String^ accountId, String^ callId, String^ from) {
         auto call = addNewCall(accountId, callId, from);
-        // REFACTO : add if call == nullptr
-        callRecieved(call);
-    });
-
-    RingD::instance->stateChange += ref new RingClientUWP::StateChange([&](
-    String^ callId, String^ state, int code) {
-        for each (auto call in CallsList_) {
-            if (call->callId == callId) {
-                if (state == "OVER") {
-                    delete call;
-                    call->stateChange("", code);
-                    callEnded();
-                    callStatusUpdated(call); // used ?
-                    RingD::instance->hangUpCall(call);
-                    return;
-                }
-                else if (state == "CURRENT") {
-                    callStarted();
-                }
-                call->stateChange(state, code);
-                callStatusUpdated(call); // same...
-                return;
-            }
-        }
-        WNG_("Call not found");
+        if (call)
+            callRecieved(call);
     });
+    RingD::instance->stateChange += ref new RingClientUWP::StateChange(this, &RingClientUWP::ViewModel::CallsViewModel::OnstateChange);
 }
 
 Call^
@@ -87,3 +65,20 @@ CallsViewModel::findCall(String^ callId)
 
     return nullptr;
 }
+
+
+void RingClientUWP::ViewModel::CallsViewModel::OnstateChange(Platform::String ^callId, RingClientUWP::CallStatus state, int code)
+{
+    auto call = findCall(callId);
+
+    if (!call)
+        return;
+
+    switch (state)
+    {
+    case CallStatus::ENDED:
+        RingD::instance->hangUpCall(call);
+    default:
+        break;
+    }
+}
diff --git a/CallsViewModel.h b/CallsViewModel.h
index 4938249..24ddbb0 100644
--- a/CallsViewModel.h
+++ b/CallsViewModel.h
@@ -66,6 +66,7 @@ private:
     CallsViewModel(); // singleton
     Vector<Call^>^ CallsList_; // refacto : change C to c
 
+    void OnstateChange(Platform::String ^callId, RingClientUWP::CallStatus state, int code);
 };
 }
 }
diff --git a/Contact.cpp b/Contact.cpp
index fd463af..155a7ff 100644
--- a/Contact.cpp
+++ b/Contact.cpp
@@ -65,28 +65,6 @@ Contact::Contact(String^ name,
         notificationNewMessage = Windows::UI::Xaml::Visibility::Visible;
         PropertyChanged(this, ref new PropertyChangedEventArgs("unreadMessages"));
     }
-
-    /* connect to delegate */
-    ContactsViewModel::instance->notifyNewConversationMessage += ref new NotifyNewConversationMessage([&] (
-    bool isContactNotSelected) {
-        if (isContactNotSelected)
-            PropertyChanged(this, ref new PropertyChangedEventArgs("unreadMessages"));
-    });
-    ContactsViewModel::instance->newContactSelected += ref new RingClientUWP::NewContactSelected([&]() {
-        if (ContactsViewModel::instance->selectedContact == this) {
-            PropertyChanged(this, ref new PropertyChangedEventArgs("unreadMessages"));
-            notificationNewMessage = Windows::UI::Xaml::Visibility::Collapsed;
-            unreadMessages_ = 0;
-            ContactsViewModel::instance->saveContactsToFile();
-        }
-    });
-}
-
-void
-Contact::addNotifyNewConversationMessage()
-{
-    notificationNewMessage = Windows::UI::Xaml::Visibility::Visible;
-    unreadMessages_++;
 }
 
 void
@@ -169,4 +147,8 @@ Contact::saveConversationToFile()
             file.close();
         }
     }
-}
\ No newline at end of file
+}
+
+
+
+
diff --git a/Contact.h b/Contact.h
index a88d648..d2cdf28 100644
--- a/Contact.h
+++ b/Contact.h
@@ -64,23 +64,16 @@ public:
             PropertyChanged(this, ref new PropertyChangedEventArgs("notificationNewMessage"));
         }
     }
-    property String^ unreadMessages
+    property uint32 _unreadMessages
     {
-        String^ get()
+        uint32 get()
         {
-            return unreadMessages_.ToString();
+            return unreadMessages_;
         }
-    }
-    property Call^ _call
-    {
-        Call^ get()
-        {
-            return call_;
-        }
-        void set(Call^ call)
+        void set(uint32 value)
         {
-            call_ = call;
-            PropertyChanged(this, ref new PropertyChangedEventArgs("_call"));
+            unreadMessages_ = value;
+            PropertyChanged(this, ref new PropertyChangedEventArgs("_unreadMessages"));
         }
     }
     property Windows::UI::Xaml::GridLength _contactBarHeight
@@ -100,7 +93,6 @@ internal:
     void        saveConversationToFile();
     String^     StringifyConversation();
     void        DestringifyConversation(String^ data);
-    void        addNotifyNewConversationMessage();
 
 protected:
     void NotifyPropertyChanged(String^ propertyName);
@@ -110,7 +102,6 @@ private:
     Visibility notificationNewMessage_;
     unsigned int unreadMessages_;
     Windows::UI::Xaml::GridLength contactBarHeight_ = 0;
-    Call^ call_;
 };
 }
 
diff --git a/ContactsViewModel.cpp b/ContactsViewModel.cpp
index e49ea1c..cb98f58 100644
--- a/ContactsViewModel.cpp
+++ b/ContactsViewModel.cpp
@@ -39,13 +39,13 @@ ContactsViewModel::ContactsViewModel()
 
     /* connect delegates. */
     RingD::instance->incomingAccountMessage += ref new IncomingAccountMessage([&](String^ accountId,
-    String^ from, String^ payload) {
-        auto contact = findContactByName(from);
+    String^ fromRingId, String^ payload) {
+        auto contact = findContactByName(fromRingId);
 
         if (contact == nullptr)
-            contact = addNewContact(from, from); // contact checked inside addNewContact.
+            contact = addNewContact(fromRingId, fromRingId); // contact checked inside addNewContact.
 
-        bool isNotSelected = (contact != ContactsViewModel::instance->selectedContact) ? true : false;
+        auto item = SmartPanelItemsViewModel::instance->_selectedItem;
 
         if (contact == nullptr) {
             ERR_("contact not handled!");
@@ -57,15 +57,13 @@ ContactsViewModel::ContactsViewModel()
         /* save contacts conversation to disk */
         contact->saveConversationToFile();
 
-        if (contact->ringID_ == from) {
-            // increment contact's unread message count
-            if (isNotSelected) {
-                contact->addNotifyNewConversationMessage();
-                // save to disk
-                saveContactsToFile();
-            }
-            // update the xaml for all contacts
-            notifyNewConversationMessage(isNotSelected);
+
+        auto selectedContact = (item) ? item->_contact : nullptr;
+
+        if (contact->ringID_ == fromRingId && contact != selectedContact) {
+            contact->_unreadMessages++;
+            /* saveContactsToFile used to save the notification */
+            saveContactsToFile();
         }
     });
 }
diff --git a/ContactsViewModel.h b/ContactsViewModel.h
index 8350f6d..ab7e56d 100644
--- a/ContactsViewModel.h
+++ b/ContactsViewModel.h
@@ -26,11 +26,6 @@ namespace RingClientUWP
 {
 
 /* delegates */
-delegate void NewContactSelected();
-delegate void NoContactSelected();
-delegate void ScreenConversationMessage(String^ accountId, String^ from, String^ payload);
-delegate void NotifyNewConversationMessage(bool isContactNotSelected);
-delegate void ShowContactBar();
 delegate void ContactAdded(Contact^);
 
 namespace ViewModel {
@@ -56,23 +51,6 @@ internal:
     void        Destringify(String^ data);
 
     /* properties */
-    property Contact^ selectedContact
-    {
-        Contact^ get()
-        {
-            return currentItem_;
-        }
-        void set(Contact^ value)
-        {
-            oldItem_ = currentItem_;
-            currentItem_ = value;
-            if (value)
-                newContactSelected();
-            else
-                noContactSelected();
-        }
-    }
-
     property Vector<Contact^>^ contactsList
     {
         Vector<Contact^>^ get()
@@ -82,11 +60,6 @@ internal:
     }
 
     /* events */
-    event NewContactSelected^ newContactSelected;
-    event NoContactSelected^ noContactSelected;
-    event ScreenConversationMessage^ screenConversationMessage;
-    event NotifyNewConversationMessage^ notifyNewConversationMessage;
-    event ShowContactBar^ showContactBar;
     event ContactAdded^ contactAdded;
 
 private:
diff --git a/MainPage.xaml.cpp b/MainPage.xaml.cpp
index 67ec540..191ae3b 100644
--- a/MainPage.xaml.cpp
+++ b/MainPage.xaml.cpp
@@ -60,36 +60,13 @@ MainPage::MainPage()
     _messageTextFrame_->Navigate(TypeName(RingClientUWP::Views::MessageTextPage::typeid));
 
     /* connect to delegates */
-    ContactsViewModel::instance->newContactSelected += ref new NewContactSelected([&]() {
-        Contact^ selectedContact = ContactsViewModel::instance->selectedContact;
-        auto call = selectedContact?
-                    SmartPanelItemsViewModel::instance->findItem(selectedContact)->_call:
-                    nullptr;
-        if (call != nullptr) {
-            if (call->state == "CURRENT")
-                showFrame(_videoFrame_);
-            else
-                showFrame(_messageTextFrame_);
-        }
-        else {
-            showFrame(_messageTextFrame_);
-        }
-    });
-    ContactsViewModel::instance->noContactSelected += ref new NoContactSelected([&]() {
-        showFrame(_welcomeFrame_);
-    });
-    CallsViewModel::instance->callStarted += ref new CallStarted([&]() {
-        showFrame(_videoFrame_);
-    });
-    CallsViewModel::instance->callEnded += ref new CallEnded([&]() {
-        auto contact = ContactsViewModel::instance->selectedContact;
-
-        if(contact)
-            showFrame(_messageTextFrame_);
-        else
-            showFrame(_welcomeFrame_);
-
-    });
+    RingD::instance->stateChange += ref new RingClientUWP::StateChange(this, &RingClientUWP::MainPage::OnstateChange);
+    auto smartPanel = dynamic_cast<SmartPanel^>(_smartPanel_->Content);
+    smartPanel->summonMessageTextPage += ref new RingClientUWP::SummonMessageTextPage(this, &RingClientUWP::MainPage::OnsummonMessageTextPage);
+    smartPanel->summonWelcomePage += ref new RingClientUWP::SummonWelcomePage(this, &RingClientUWP::MainPage::OnsummonWelcomePage);
+    smartPanel->summonVideoPage += ref new RingClientUWP::SummonVideoPage(this, &RingClientUWP::MainPage::OnsummonVideoPage);
+    auto videoPage = dynamic_cast<VideoPage^>(_videoFrame_->Content);
+    videoPage->pressHangUpCall += ref new RingClientUWP::PressHangUpCall(this, &RingClientUWP::MainPage::OnpressHangUpCall);
 
     DisplayInformation^ displayInformation = DisplayInformation::GetForCurrentView();
     dpiChangedtoken = (displayInformation->DpiChanged += ref new TypedEventHandler<DisplayInformation^,
@@ -132,7 +109,6 @@ RingClientUWP::MainPage::showFrame(Windows::UI::Xaml::Controls::Frame^ frame)
         dynamic_cast<VideoPage^>(_videoFrame_->Content)->updatePageContent();
     } else if (frame == _messageTextFrame_) {
         _navGrid_->SetRow(_messageTextFrame_, 1);
-        dynamic_cast<MessageTextPage^>(_messageTextFrame_->Content)->updatePageContent();
     }
 }
 
@@ -227,4 +203,60 @@ void
 RingClientUWP::MainPage::hideLoadingOverlay()
 {
     _loadingOverlay_->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
-}
\ No newline at end of file
+}
+
+void RingClientUWP::MainPage::OnsummonMessageTextPage()
+{
+    auto messageTextPage = dynamic_cast<MessageTextPage^>(_messageTextFrame_->Content);
+    messageTextPage->updatePageContent();
+    showFrame(_messageTextFrame_);
+
+}
+
+
+void RingClientUWP::MainPage::OnsummonWelcomePage()
+{
+    showFrame(_welcomeFrame_);
+}
+
+
+void RingClientUWP::MainPage::OnsummonVideoPage()
+{
+    auto videoPage = dynamic_cast<VideoPage^>(_videoFrame_->Content);
+    videoPage->updatePageContent();
+    showFrame(_videoFrame_);
+}
+
+
+void RingClientUWP::MainPage::OnpressHangUpCall()
+{
+    OnsummonMessageTextPage();
+}
+
+
+
+void RingClientUWP::MainPage::OnstateChange(Platform::String ^callId, RingClientUWP::CallStatus state, int code)
+{
+    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
+
+    switch (state) {
+    /* send the user to the peer's message text page */
+    case CallStatus::ENDED:
+    {
+        if (item)
+            OnsummonMessageTextPage();
+        break;
+    }
+    /* if the state changes to IN_PROGRESS for any peer, show the video page.
+       nb : the peer is currently selected from the SmartPannel. */
+    case CallStatus::IN_PROGRESS:
+    {
+        if (item)
+            OnsummonVideoPage();
+        break;
+    }
+    default:
+        break;
+    }
+
+}
diff --git a/MainPage.xaml.h b/MainPage.xaml.h
index aa76667..d97fd59 100644
--- a/MainPage.xaml.h
+++ b/MainPage.xaml.h
@@ -24,6 +24,7 @@ using namespace Windows::Foundation;
 
 namespace RingClientUWP
 {
+
 namespace Views {
 }
 public ref class MainPage sealed
@@ -51,5 +52,10 @@ private:
 
     void _toggleSmartBoxButton__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
     void showFrame(Windows::UI::Xaml::Controls::Frame^ frame);
+    void OnsummonMessageTextPage();
+    void OnsummonWelcomePage();
+    void OnsummonVideoPage();
+    void OnpressHangUpCall();
+    void OnstateChange(Platform::String ^callId, RingClientUWP::CallStatus state, int code);
 };
 }
\ No newline at end of file
diff --git a/MessageTextPage.xaml.cpp b/MessageTextPage.xaml.cpp
index aca763d..aa539a1 100644
--- a/MessageTextPage.xaml.cpp
+++ b/MessageTextPage.xaml.cpp
@@ -16,8 +16,8 @@
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
 **************************************************************************/
 #include "pch.h"
-
 #include "ContactsViewModel.h"
+
 #include "MainPage.xaml.h"
 
 #include "MessageTextPage.xaml.h"
@@ -44,25 +44,19 @@ MessageTextPage::MessageTextPage()
 {
     InitializeComponent();
 
-    /* connect delegates. */
-    // REFACTO : useless ?
+    /* connect to delegates */
     RingD::instance->incomingAccountMessage += ref new IncomingAccountMessage([&](String^ accountId,
-    String^ from, String^ payload) {
-    });
-    ContactsViewModel::instance->notifyNewConversationMessage += ref new NotifyNewConversationMessage([&](
-    bool isContactNotSelected) {
-        if (!isContactNotSelected) {
-            /* if the contact is selected that means we should scroll down */
-            scrollDown();
-        }
-
+    String^ fromRingId, String^ payload) {
+        scrollDown();
     });
 }
 
 void
 RingClientUWP::Views::MessageTextPage::updatePageContent()
 {
-    auto contact = ContactsViewModel::instance->selectedContact;
+    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
+    auto contact = item->_contact;
+
     if (!contact)
         return;
 
@@ -96,7 +90,9 @@ RingClientUWP::Views::MessageTextPage::_messageTextBox__KeyDown(Platform::Object
 void
 RingClientUWP::Views::MessageTextPage::sendMessage()
 {
-    auto contact = ContactsViewModel::instance->selectedContact;
+    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
+    auto contact = item->_contact;
+
     auto txt = _messageTextBox_->Text;
 
     /* empty the textbox */
diff --git a/RingD.cpp b/RingD.cpp
index 3187639..2508fb8 100644
--- a/RingD.cpp
+++ b/RingD.cpp
@@ -67,7 +67,8 @@ void RingClientUWP::RingD::sendAccountTextMessage(String^ message)
     std::string accountId3(accountId2.begin(), accountId2.end());
 
     /* recipient */
-    auto contact = ContactsViewModel::instance->selectedContact;
+    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
+    auto contact = item->_contact;
     auto toRingId = contact->ringID_;
     std::wstring toRingId2(toRingId->Begin());
     std::string toRingId3(toRingId2.begin(), toRingId2.end());
@@ -197,7 +198,7 @@ RingClientUWP::RingD::startDaemon()
                     CoreDispatcherPriority::Normal, ref new DispatchedHandler([=]()
                 {
                     incomingCall(accountId2, callId2, from2);
-                    stateChange(callId2, "incoming call", 0);
+                    stateChange(callId2, CallStatus::INCOMING_RINGING, 0);
                 }));
             }),
             DRing::exportable_callback<DRing::CallSignal::StateChange>([this](
@@ -213,11 +214,13 @@ RingClientUWP::RingD::startDaemon()
                 auto callId2 = toPlatformString(callId);
                 auto state2 = toPlatformString(state);
 
+                auto state3 = getCallStatus(state2);
+
 
                 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
                     CoreDispatcherPriority::Low, ref new DispatchedHandler([=]()
                 {
-                    stateChange(callId2, state2, code);
+                    stateChange(callId2, state3, code);
                 }));
             }),
             DRing::exportable_callback<DRing::ConfigurationSignal::IncomingAccountMessage>([&](
@@ -414,3 +417,23 @@ RingD::dequeueTasks()
         tasksList_.pop();
     }
 }
+
+CallStatus RingClientUWP::RingD::getCallStatus(String^ state)
+{
+    if (state == "INCOMING")
+        return CallStatus::INCOMING_RINGING;
+
+    if (state == "CURRENT")
+        return CallStatus::IN_PROGRESS;
+
+    if (state == "OVER")
+        return CallStatus::ENDED;
+
+    if (state == "RINGING")
+        return CallStatus::OUTGOING_RINGING;
+
+    if (state == "CONNECTING")
+        return CallStatus::SEARCHING;
+
+    return CallStatus::NONE;
+}
diff --git a/RingD.h b/RingD.h
index 0bcfbdb..06334a6 100644
--- a/RingD.h
+++ b/RingD.h
@@ -24,7 +24,7 @@ namespace RingClientUWP
 
 /* delegate */
 delegate void IncomingCall(String^ accountId, String^ callId, String^ from);
-delegate void StateChange(String^ callId, String^ state, int code);
+delegate void StateChange(String^ callId, CallStatus state, int code);
 delegate void IncomingAccountMessage(String^ accountId, String^ from, String^ payload);
 delegate void Calling(Call^ call);
 
@@ -104,6 +104,7 @@ private:
     /* functions */
     RingD(); // singleton
     void dequeueTasks();
+    CallStatus getCallStatus(String^ state);
 
     /* members */
     std::string localFolder_;
diff --git a/SmartPanel.xaml b/SmartPanel.xaml
index 4431fcc..3876183 100644
--- a/SmartPanel.xaml
+++ b/SmartPanel.xaml
@@ -21,11 +21,18 @@
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:local="using:RingClientUWP"
       xmlns:controls="using:RingClientUWP.Controls"
+      xmlns:views="using:RingClientUWP.Views"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d">
 
     <Page.Resources>
+        <!-- converters -->
+        <views:NewMessageBubleNotification x:Key="_NewMessageBubleNotification_" />
+        <views:IncomingVisibility x:Key="_IncomingVisibility_" />
+        <views:OutGoingVisibility x:Key="_OutGoingVisibility_" />
+        <views:HasAnActiveCall x:Key="_HasAnActiveCall_" />
+
         <Style x:Key="addContactTextBoxStyle"
            TargetType="TextBox">
             <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}"/>
@@ -146,15 +153,6 @@
                             <TranslateTransform X="17" Y="-14"/>
                         </Border.RenderTransform>
                     </Border>
-                    <Border x:Name="_visualNotificationNewMessage_"
-                            Visibility="{x:Bind notificationNewMessage, Mode=OneWay}"
-                            Style="{StaticResource BorderStyle2}">
-                        <TextBlock Text="{x:Bind unreadMessages, Mode=OneWay}"
-                                   Style="{StaticResource TextStyle3}"/>
-                        <Border.RenderTransform>
-                            <TranslateTransform X="-17" Y="-14"/>
-                        </Border.RenderTransform>
-                    </Border>
                     <Grid Grid.Column="1">
                         <Grid.RowDefinitions>
                             <RowDefinition Height="30"/>
@@ -166,42 +164,8 @@
                                     Text="{x:Bind name_}"
                                     TextTrimming="CharacterEllipsis">
                         </TextBlock>
-                        <!-- call status. REFACTO : REMOVE CODE BELOW -->
-                        <!--<StackPanel MaxWidth="240"
-                                    MinWidth="240"
-                                    Grid.Row="1"
-                                    HorizontalAlignment="Left">
-                            <TextBlock x:Name="_contactCallStatus_"
-                                       Foreground="DarkGray"
-                                       Text="{x:Bind _call.state, Mode=OneWay}"
-                                       Visibility="Visible"
-                                       HorizontalAlignment="Center">
-                            </TextBlock>
-                        </StackPanel>-->
                     </Grid>
                 </Grid>
-                <!-- REFACTO : REMOVE CODE BELOW -->
-                <!-- button bar for accept/reject or cancel call. -->
-                <!-- nb : dont use Visibility with the grid, use the height of the hosting row (_contactBar_). -->
-                <!--<Grid Width="320"
-                      HorizontalAlignment="Left"
-                      Grid.Row="2"
-                      Background="DarkGray">
-                    <StackPanel Orientation="Horizontal"
-                                Grid.Row="0"
-                                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>-->
             </Grid>
         </DataTemplate>
         <!-- template for accounts. -->
@@ -303,40 +267,127 @@
                       x:DataType="controls:SmartPanelItem">
             <Grid PointerEntered="Grid_PointerEntered" PointerExited="Grid_PointerExited">
                 <Grid.RowDefinitions>
+                    <!-- row definition for the contact. -->
                     <RowDefinition Height="auto"/>
+                    <!-- row definition for the incoming call bar. -->
+                    <RowDefinition Height="auto"/>
+                    <!-- row definition for the outgoing call bar. -->
                     <RowDefinition Height="auto"/>
                 </Grid.RowDefinitions>
-                <ListBoxItem x:Name="_contactItem_"
-                             Padding="0"
-                             Margin="0"
-                             Grid.Row="0"
-                             PointerReleased="_contactItem__PointerReleased"
-                             ContentTemplate="{StaticResource ContactTemplate}"
-                             Content="{x:Bind _contact, Mode=OneWay}"/>
-                <ListBoxItem Grid.Row="1"
-                             Visibility="{x:Bind _IncomingCallBar, Mode=OneWay}"
-                             Padding="0"
-                             Margin="0"
-                             ContentTemplate="{StaticResource IncomingCallTemplate}"
-                             Content="{x:Bind _call, Mode=OneWay}"/>
-                <Button Grid.Row="0"
-                        HorizontalAlignment="Left"
-                        Visibility="{x:Bind _callBar, Mode=OneWay}"
-                        Content="call"
-                        Padding="0"
-                        Click="_callContact__Click"
-                        VerticalAlignment="Bottom"
-                        Margin="10">
-                    <Button.RenderTransform>
-                        <TranslateTransform X="160"/>
-                    </Button.RenderTransform>
-                </Button>
-                <ListBoxItem Grid.Row="1"
-                             Visibility="{x:Bind _OutGoingCallBar, Mode=OneWay}"
-                             Padding="0"
-                             Margin="0"
-                             ContentTemplate="{StaticResource OutGoingCallTemplate}"
-                             Content="{x:Bind _call, Mode=OneWay}"/>
+                <!--helper to detect mouse overing-->
+                <Rectangle Fill="Transparent" Grid.Row="0"/>
+                <!-- contact. -->
+                <Grid Grid.Row="0">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="310"/>
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="60"/>
+                        <!-- use the height of _contactBar_ to make it visible or collapsed. -->
+                        <RowDefinition x:Name="_contactBar_"
+                                       Height="{x:Bind _contact._contactBarHeight, Mode=OneWay}"/>
+                    </Grid.RowDefinitions>
+                    <Grid Grid.Row="0">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="60"/>
+                            <ColumnDefinition Width="*"
+                                              MinWidth="200"/>
+                        </Grid.ColumnDefinitions>
+                        <Image x:Name="_contactAvatar_"
+                               VerticalAlignment="Center"
+                               HorizontalAlignment="Center"
+                               Grid.Column="0"
+                               Width="55"
+                               Height="55"
+                               Source="Assets\TESTS\contactAvatar.png"/>
+                        <!-- visual notifications. -->
+                        <Border x:Name="_visualNotificationVideoChat_"
+                            Visibility="Collapsed"
+                            Style="{StaticResource BorderStyle1}">
+                            <TextBlock Text="&#xE8AA;"
+                                   Style="{StaticResource TextSegoeStyle1}"/>
+                            <Border.RenderTransform>
+                                <TranslateTransform X="17" Y="-14"/>
+                            </Border.RenderTransform>
+                        </Border>
+                        <Border x:Name="_visualNotificationNewMessage_"
+                            Visibility="{x:Bind _contact._unreadMessages, Converter={StaticResource _NewMessageBubleNotification_}, Mode=OneWay}"
+                            Style="{StaticResource BorderStyle2}">
+                            <TextBlock Text="{x:Bind _contact._unreadMessages, Mode=OneWay}"
+                                   Style="{StaticResource TextStyle3}"/>
+                            <Border.RenderTransform>
+                                <TranslateTransform X="-17" Y="-14"/>
+                            </Border.RenderTransform>
+                        </Border>
+
+                        <Grid Grid.Column="1">
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="30"/>
+                                <RowDefinition Height="30"/>
+                            </Grid.RowDefinitions>
+                            <!-- name of the contact. -->
+                            <TextBlock  x:Name="_contactName_"
+                                    Grid.Row="0"
+                                    Text="{x:Bind _contact.name_}"
+                                    TextTrimming="CharacterEllipsis">
+                            </TextBlock>
+                            <!-- call button. -->
+                            <Button Grid.Row="0"
+                                    Visibility="{x:Bind _hovered, Mode=OneWay}"
+                                    Click="_callContact__Click"
+                                    VerticalAlignment="Bottom"
+                                    HorizontalAlignment="Left"
+                                    Margin="10,0"
+                                    Style="{StaticResource roundButtonTemplate}"
+                                    FontFamily="Segoe MDL2 Assets"
+                                    Content="&#xE116;">
+                                <Button.RenderTransform>
+                                    <TranslateTransform X="90" Y="25"/>
+                                </Button.RenderTransform>
+                            </Button>
+                        </Grid>
+                    </Grid>
+                </Grid>
+                <!-- incomming call bar. -->
+                <Grid Width="320"
+                      Grid.Row="1"
+                      HorizontalAlignment="Left"
+                      Background="DarkGray">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="auto"/>
+                        <RowDefinition Height="auto"/>
+                    </Grid.RowDefinitions>
+                    <TextBlock x:Name="_incommingCallStatus_"
+                           Grid.Row="0"
+                           Foreground="White"
+                           Text="{x:Bind _call.state, Mode=OneWay}"
+                           Visibility="{x:Bind _call.state, Converter={StaticResource _HasAnActiveCall_}, Mode=OneWay}"
+                           HorizontalAlignment="Center">
+                    </TextBlock>
+                    <StackPanel Orientation="Horizontal"
+                                Visibility="Visible"
+                                Grid.Row="1"
+                                HorizontalAlignment="Center">
+                        <Button x:Name="_acceptIncomingCallBtn_"
+                            Click="_acceptIncomingCallBtn__Click"
+                            Visibility="{x:Bind _call.state, Converter={StaticResource _IncomingVisibility_}, Mode=OneWay}"
+                            VerticalAlignment="Center"
+                            HorizontalAlignment="Center"
+                            Content="Accept"/>
+                        <Button x:Name="_rejectIncomingCallBtn_"
+                            Click="_rejectIncomingCallBtn__Click"
+                            Visibility="{x:Bind _call.state, Converter={StaticResource _IncomingVisibility_}, Mode=OneWay}"
+                            VerticalAlignment="Center"
+                            HorizontalAlignment="Center"
+                            Content="Reject"/>
+                        <Button x:Name="_cancelCallBtn_"
+                            Click="_cancelCallBtn__Click"
+                            Visibility="{x:Bind _call.state, Converter={StaticResource _OutGoingVisibility_}, Mode=OneWay}"
+                            VerticalAlignment="Center"
+                            HorizontalAlignment="Center"
+                            Content="Cancel"/>
+                    </StackPanel>
+                </Grid>
             </Grid>
         </DataTemplate>
     </Page.Resources>
@@ -409,7 +460,7 @@
             </Grid>
 
             <!--sub menus like the accounts list or the share menu are just below, technicaly they are nested inside the
-            same row. To sumon them we use the visibility of their own grid, by linking it to a toggle button-->
+            same row. To summon them we use the visibility of their own grid, by linking it to a toggle button-->
 
             <!-- accounts menu. -->
             <Grid x:Name="_accountsMenuGrid_"
diff --git a/SmartPanel.xaml.cpp b/SmartPanel.xaml.cpp
index a61c161..8aec15d 100644
--- a/SmartPanel.xaml.cpp
+++ b/SmartPanel.xaml.cpp
@@ -77,8 +77,9 @@ SmartPanel::SmartPanel()
 
         auto item = SmartPanelItemsViewModel::instance->findItem(contact);
         item->_call = call;
+
     });
-    RingD::instance->stateChange += ref new StateChange([this](String^ callId, String^ state, int code) {
+    RingD::instance->stateChange += ref new StateChange([this](String^ callId, CallStatus state, int code) {
         auto call = CallsViewModel::instance->findCall(callId);
 
         if (call == nullptr)
@@ -91,18 +92,11 @@ SmartPanel::SmartPanel()
             return;
         }
 
-        if (call->state == "incoming call")
-            item->_IncomingCallBar = Windows::UI::Xaml::Visibility::Visible;
+        call->state = state;
 
-        if (call->state == "CURRENT") {
-            item->_IncomingCallBar = Windows::UI::Xaml::Visibility::Collapsed;
-            item->_OutGoingCallBar = Windows::UI::Xaml::Visibility::Collapsed;
-        }
+        if (state == CallStatus::IN_PROGRESS)
+            _smartList_->SelectedIndex = SmartPanelItemsViewModel::instance->getIndex(call);
 
-        if (call->state == "") {
-            item->_IncomingCallBar = Windows::UI::Xaml::Visibility::Collapsed;
-            item->_OutGoingCallBar = Windows::UI::Xaml::Visibility::Collapsed;
-        }
     });
 
 
@@ -129,10 +123,8 @@ SmartPanel::SmartPanel()
             return;
         }
 
-        /* use underscore to differentiate states from UI, we need to think more about states management */
-        call->state = "_calling_";
+        call->state = CallStatus::SEARCHING;
 
-        item->_OutGoingCallBar = Windows::UI::Xaml::Visibility::Visible;
         item->_call = call;
     });
 
@@ -253,12 +245,31 @@ void RingClientUWP::Views::SmartPanel::_createAccountNo__Click(Platform::Object^
 void
 SmartPanel::_smartList__SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e)
 {
-    auto listbox = safe_cast<ListBox^>(sender);
-    auto item = safe_cast<SmartPanelItem^>(listbox->SelectedItem);
+    auto listbox = dynamic_cast<ListBox^>(sender);
+    auto item = dynamic_cast<SmartPanelItem^>(listbox->SelectedItem);
+    SmartPanelItemsViewModel::instance->_selectedItem = item;
+
+    if (!item) {
+        summonWelcomePage();
+        return;
+    }
 
-    Contact^ contact = (item) ? safe_cast<Contact^>(item->_contact) : nullptr;
+    auto call = item->_call;
+    if (call) {
+        auto state = call->state;
+        if (state == CallStatus::IN_PROGRESS) {
+            summonVideoPage();
+            return;
+        }
+    }
 
-    ContactsViewModel::instance->selectedContact = contact;
+    auto contact = item->_contact;
+    if (contact) {
+        summonMessageTextPage();
+        contact->_unreadMessages = 0;
+        ContactsViewModel::instance->saveContactsToFile();
+        return;
+    }
 }
 
 void
@@ -303,7 +314,8 @@ void RingClientUWP::Views::SmartPanel::_ringTxtBx__Click(Platform::Object^ sende
 void RingClientUWP::Views::SmartPanel::_rejectIncomingCallBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
 {
     auto button = dynamic_cast<Button^>(e->OriginalSource);
-    auto call = dynamic_cast<Call^>(button->DataContext);
+    auto item = dynamic_cast<SmartPanelItem^>(button->DataContext);
+    auto call = item->_call;
 
     call->refuse();
 }
@@ -312,9 +324,8 @@ void RingClientUWP::Views::SmartPanel::_rejectIncomingCallBtn__Click(Platform::O
 void RingClientUWP::Views::SmartPanel::_acceptIncomingCallBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
 {
     auto button = dynamic_cast<Button^>(e->OriginalSource);
-    auto call = dynamic_cast<Call^>(button->DataContext);
-
-    _smartList_->SelectedIndex = SmartPanelItemsViewModel::instance->getIndex(call);
+    auto item = dynamic_cast<SmartPanelItem^>(button->DataContext);
+    auto call = item->_call;
 
     call->accept();
 }
@@ -326,8 +337,6 @@ SmartPanel::_callContact__Click(Platform::Object^ sender, Windows::UI::Xaml::Rou
     auto item = dynamic_cast<SmartPanelItem^>(button->DataContext);
     auto contact = item->_contact;
 
-    _smartList_->SelectedIndex = SmartPanelItemsViewModel::instance->getIndex(contact);
-
     RingD::instance->placeCall(contact);
 }
 
@@ -335,7 +344,8 @@ SmartPanel::_callContact__Click(Platform::Object^ sender, Windows::UI::Xaml::Rou
 void RingClientUWP::Views::SmartPanel::_cancelCallBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
 {
     auto button = dynamic_cast<Button^>(e->OriginalSource);
-    auto call = dynamic_cast<Call^>(button->DataContext);
+    auto item = dynamic_cast<SmartPanelItem^>(button->DataContext);
+    auto call = item->_call;
 
     call->cancel();
 }
@@ -347,7 +357,7 @@ void RingClientUWP::Views::SmartPanel::Grid_PointerEntered(Platform::Object^ sen
     auto listBoxItem = dynamic_cast<ListBoxItem^>(sender);
     auto item = dynamic_cast<SmartPanelItem^>(grid->DataContext);
 
-    item->_callBar = Windows::UI::Xaml::Visibility::Visible;
+    item->_hovered = Windows::UI::Xaml::Visibility::Visible;
 }
 
 
@@ -357,7 +367,7 @@ void RingClientUWP::Views::SmartPanel::Grid_PointerExited(Platform::Object^ send
     auto grid = dynamic_cast<Grid^>(sender);
     auto item = dynamic_cast<SmartPanelItem^>(grid->DataContext);
 
-    item->_callBar = Windows::UI::Xaml::Visibility::Collapsed;
+    item->_hovered = Windows::UI::Xaml::Visibility::Collapsed;
 }
 
 
@@ -371,4 +381,77 @@ void RingClientUWP::Views::SmartPanel::_contactItem__PointerReleased(Platform::O
     else
         _smartList_->SelectedItem = nullptr;
 
-}
\ No newline at end of file
+}
+
+Object ^ RingClientUWP::Views::IncomingVisibility::Convert(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    auto state = static_cast<CallStatus>(value);
+    if (state == CallStatus::INCOMING_RINGING)
+        return  Windows::UI::Xaml::Visibility::Visible;
+    else
+        return  Windows::UI::Xaml::Visibility::Collapsed;
+}
+
+Object ^ RingClientUWP::Views::IncomingVisibility::ConvertBack(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    throw ref new Platform::NotImplementedException();
+}
+
+RingClientUWP::Views::IncomingVisibility::IncomingVisibility()
+{}
+
+
+Object ^ RingClientUWP::Views::OutGoingVisibility::Convert(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    auto state = static_cast<CallStatus>(value);
+
+    if (state == CallStatus::SEARCHING || state == CallStatus::OUTGOING_RINGING)
+        return  Windows::UI::Xaml::Visibility::Visible;
+    else
+        return  Windows::UI::Xaml::Visibility::Collapsed;
+}
+
+Object ^ RingClientUWP::Views::OutGoingVisibility::ConvertBack(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    throw ref new Platform::NotImplementedException();
+}
+
+RingClientUWP::Views::OutGoingVisibility::OutGoingVisibility()
+{}
+
+Object ^ RingClientUWP::Views::HasAnActiveCall::Convert(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    auto state = static_cast<CallStatus>(value);
+
+    if (state == CallStatus::NONE || state == CallStatus::ENDED)
+        return Windows::UI::Xaml::Visibility::Collapsed;
+    else
+        return Windows::UI::Xaml::Visibility::Visible;
+}
+
+Object ^ RingClientUWP::Views::HasAnActiveCall::ConvertBack(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    throw ref new Platform::NotImplementedException();
+
+}
+
+RingClientUWP::Views::HasAnActiveCall::HasAnActiveCall()
+{}
+
+Object ^ RingClientUWP::Views::NewMessageBubleNotification::Convert(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    auto unreadMessages = static_cast<uint32>(value);
+
+    if (unreadMessages > 0)
+        return Windows::UI::Xaml::Visibility::Visible;
+
+    return Windows::UI::Xaml::Visibility::Collapsed;
+}
+
+Object ^ RingClientUWP::Views::NewMessageBubleNotification::ConvertBack(Object ^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object ^ parameter, String ^ language)
+{
+    throw ref new Platform::NotImplementedException();
+}
+
+RingClientUWP::Views::NewMessageBubleNotification::NewMessageBubleNotification()
+{}
diff --git a/SmartPanel.xaml.h b/SmartPanel.xaml.h
index 58c9f05..c017617 100644
--- a/SmartPanel.xaml.h
+++ b/SmartPanel.xaml.h
@@ -22,11 +22,41 @@ namespace RingClientUWP
 {
 
 delegate void ToggleSmartPan();
-delegate void SumonMessageTextPage();
-delegate void SumonVideoPage();
+delegate void SummonMessageTextPage();
+delegate void SummonVideoPage();
+delegate void SummonWelcomePage();
 
 namespace Views
 {
+
+public ref class IncomingVisibility sealed : IValueConverter {
+public:
+    virtual Object^ Convert(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object^ parameter, String^ language);
+    virtual Object^ ConvertBack(Object^ value, Windows::UI::Xaml::Interop::TypeName  targetType, Object^ parameter, String^ language);
+    IncomingVisibility();
+};
+
+public ref class OutGoingVisibility sealed : IValueConverter {
+public:
+    virtual Object^ Convert(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object^ parameter, String^ language);
+    virtual Object^ ConvertBack(Object^ value, Windows::UI::Xaml::Interop::TypeName  targetType, Object^ parameter, String^ language);
+    OutGoingVisibility();
+};
+
+public ref class HasAnActiveCall sealed : IValueConverter {
+public:
+    virtual Object^ Convert(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object^ parameter, String^ language);
+    virtual Object^ ConvertBack(Object^ value, Windows::UI::Xaml::Interop::TypeName  targetType, Object^ parameter, String^ language);
+    HasAnActiveCall();
+};
+
+public ref class NewMessageBubleNotification sealed : IValueConverter {
+public:
+    virtual Object^ Convert(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object^ parameter, String^ language);
+    virtual Object^ ConvertBack(Object^ value, Windows::UI::Xaml::Interop::TypeName  targetType, Object^ parameter, String^ language);
+    NewMessageBubleNotification();
+};
+
 public ref class SmartPanel sealed
 {
 public:
@@ -36,8 +66,9 @@ public:
 internal:
     enum class Mode { Minimized, Normal };
     event ToggleSmartPan^ toggleSmartPan;
-    event SumonMessageTextPage^ sumonMessageTextPage;
-    event SumonVideoPage^ sumonVideoPage;
+    event SummonMessageTextPage^ summonMessageTextPage;
+    event SummonVideoPage^ summonVideoPage;
+    event SummonWelcomePage^ summonWelcomePage;
     void setMode(RingClientUWP::Views::SmartPanel::Mode mode);
 
 private:
diff --git a/SmartPanelItem.cpp b/SmartPanelItem.cpp
index ab986a6..d93b454 100644
--- a/SmartPanelItem.cpp
+++ b/SmartPanelItem.cpp
@@ -30,7 +30,10 @@ using namespace RingClientUWP::Controls;
 using namespace ViewModel;
 
 SmartPanelItem::SmartPanelItem()
-{}
+{
+    /* create an empty call to avoid the call bar */
+    _call = ref new Call("", "", "");
+}
 
 void
 SmartPanelItem::NotifyPropertyChanged(String^ propertyName)
diff --git a/SmartPanelItem.h b/SmartPanelItem.h
index aa5484b..0803fb1 100644
--- a/SmartPanelItem.h
+++ b/SmartPanelItem.h
@@ -32,52 +32,28 @@ public:
 
     virtual event PropertyChangedEventHandler^ PropertyChanged;
     property Contact^ _contact;
-    property Visibility _IncomingCallBar
-    {
-        Visibility get()
-        {
-            return incomingCallBar_;
-        }
-        void set(Visibility value)
-        {
-            incomingCallBar_ = value;
-            PropertyChanged(this, ref new PropertyChangedEventArgs("_IncomingCallBar"));
-        }
-    }
-    property Visibility _OutGoingCallBar
+    property Call^ _call
     {
-        Visibility get()
+        Call^ get()
         {
-            return outGoingCallBar_;
+            return call_;
         }
-        void set(Visibility value)
+        void set(Call^ value)
         {
-            outGoingCallBar_ = value;
-            PropertyChanged(this, ref new PropertyChangedEventArgs("_OutGoingCallBar"));
+            call_ = value;
+            PropertyChanged(this, ref new PropertyChangedEventArgs("_call"));
         }
     }
-    property Visibility _callBar
+    property Visibility _hovered
     {
         Visibility get()
         {
-            return callBar_;
+            return hovered_;
         }
         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"));
+            hovered_ = value;
+            PropertyChanged(this, ref new PropertyChangedEventArgs("_hovered"));
         }
     }
 
@@ -85,10 +61,9 @@ protected:
     void NotifyPropertyChanged(String^ propertyName);
 
 private:
-    Visibility incomingCallBar_ = Visibility::Collapsed;
-    Visibility outGoingCallBar_ = Visibility::Collapsed;
-    Visibility callBar_ = Visibility::Collapsed;
     Call^ call_;
+    Visibility hovered_ = Visibility::Collapsed;
+
 };
 }
 }
diff --git a/SmartPanelItemsViewModel.h b/SmartPanelItemsViewModel.h
index 52e1c86..7bcdfe7 100644
--- a/SmartPanelItemsViewModel.h
+++ b/SmartPanelItemsViewModel.h
@@ -26,7 +26,6 @@ using namespace RingClientUWP::Controls;
 
 namespace RingClientUWP
 {
-
 namespace ViewModel {
 public ref class SmartPanelItemsViewModel sealed
 {
@@ -55,7 +54,18 @@ internal:
         }
     }
 
-    /* events */
+    property SmartPanelItem^ _selectedItem
+    {
+        SmartPanelItem^ get()
+        {
+            return currentItem_;
+        }
+        void set(SmartPanelItem^ value)
+        {
+            oldItem_ = currentItem_;
+            currentItem_ = value;
+        }
+    }
 
 private:
     SmartPanelItemsViewModel(); // singleton
diff --git a/Styles.xaml b/Styles.xaml
index d010259..3f5854a 100644
--- a/Styles.xaml
+++ b/Styles.xaml
@@ -290,5 +290,20 @@
             </Setter.Value>
         </Setter>
     </Style>
+    <!-- rounded button for call -->
+    <Style x:Key ="roundButtonTemplate" TargetType ="Button">
+        <Setter Property ="Foreground" Value ="Black"/>
+        <Setter Property ="FontWeight" Value ="Bold"/>
+        <Setter Property ="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType ="Button">
+                    <Grid>
+                        <Ellipse Name ="OuterRing" Width ="30" Height ="30" Fill ="LightBlue"/>
+                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
 
 </ResourceDictionary>
diff --git a/VideoPage.xaml.cpp b/VideoPage.xaml.cpp
index 70eed4a..112741c 100644
--- a/VideoPage.xaml.cpp
+++ b/VideoPage.xaml.cpp
@@ -21,6 +21,7 @@
 #include "VideoPage.xaml.h"
 
 using namespace RingClientUWP::Views;
+using namespace ViewModel;
 
 using namespace Concurrency;
 using namespace Platform;
@@ -56,10 +57,9 @@ RingClientUWP::Views::VideoPage::OnNavigatedTo(Windows::UI::Xaml::Navigation::Na
 
 void RingClientUWP::Views::VideoPage::updatePageContent()
 {
-    auto selectedContact = ViewModel::ContactsViewModel::instance->selectedContact;
-    Contact^ contact = selectedContact?
-        ViewModel::SmartPanelItemsViewModel::instance->findItem(selectedContact)->_contact:
-        nullptr;
+    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
+    auto contact = (item) ? item->_contact : nullptr;
+
     if (!contact)
         return;
 
@@ -93,7 +93,9 @@ RingClientUWP::Views::VideoPage::_messageTextBox__KeyDown(Platform::Object^ send
 void
 RingClientUWP::Views::VideoPage::sendMessage()
 {
-    auto contact = ViewModel::ContactsViewModel::instance->selectedContact;
+    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
+    auto contact = item->_contact;
+
     auto txt = _messageTextBox_->Text;
 
     /* empty the textbox */
@@ -118,10 +120,9 @@ void RingClientUWP::Views::VideoPage::_btnCancel__Click(Platform::Object^ sender
 
 void RingClientUWP::Views::VideoPage::_btnHangUp__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
 {
-    Contact^ selectedContact = ViewModel::ContactsViewModel::instance->selectedContact;
-    Call^ call = selectedContact?
-        ViewModel::SmartPanelItemsViewModel::instance->findItem(selectedContact)->_call:
-        nullptr;
+    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
+    auto call = item->_call;
+
     if (call)
         RingD::instance->hangUpCall(call);
     pressHangUpCall();
-- 
GitLab