diff --git a/Call.cpp b/Call.cpp index 6b02ec7deec35c53e1e52724d8331e24bbe16406..b75603386a600cf98a636f0b3b66d10088fa787b 100644 --- a/Call.cpp +++ b/Call.cpp @@ -25,12 +25,16 @@ using namespace Windows::UI::Core; using namespace RingClientUWP; +// REFACTORING : for the whole Call class, change "from" to "peer" + Call::Call(String^ accountIdz, String^ callIdz, String^ fromz) { this->accountId = accountIdz; this->callId = callIdz; this->from = fromz; + isOutGoing = false; // by default, we consider the call incomming, REFACTO : add this to the constructor params... + this->state = "incoming call"; this->code = -1; } @@ -64,3 +68,8 @@ void RingClientUWP::Call::accept() { RingD::instance->acceptIncommingCall(this); } + +void RingClientUWP::Call::cancel() +{ + RingD::instance->cancelOutGoingCall(this); +} diff --git a/Call.h b/Call.h index c0d4fa129fa768b6d0ca1cb873f2aa89a8dd62ca..fb5be0b45f07188c544ea00ac6e662455c353724 100644 --- a/Call.h +++ b/Call.h @@ -35,6 +35,7 @@ public: property String^ callId; property String^ from; property String^ state; + property bool isOutGoing; property int code; /* events */ @@ -46,6 +47,7 @@ protected: internal: void refuse(); void accept(); + void cancel(); }; } diff --git a/CallsViewModel.cpp b/CallsViewModel.cpp index f5dd3d2fc57f25bb6a41028e70615fc74bb1a433..41dd4af1ab3375ada25267de45f83c797e51fd21 100644 --- a/CallsViewModel.cpp +++ b/CallsViewModel.cpp @@ -33,6 +33,7 @@ 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); }); @@ -56,9 +57,12 @@ CallsViewModel::CallsViewModel() } Call^ -RingClientUWP::ViewModel::CallsViewModel::addNewCall(String^ accountId, String^ callId, String^ from) +RingClientUWP::ViewModel::CallsViewModel::addNewCall(String^ accountId, String^ callId, String^ peer) { - auto call = ref new Call(accountId, callId, from); + if (accountId == "" | callId == "" | peer == "") { + WNG_("call can't be created"); + } + auto call = ref new Call(accountId, callId, peer); CallsList_->Append(call); return call; } diff --git a/RingD.cpp b/RingD.cpp index b52c2e2993a9816929908e643cb11266edcc4d85..fdf734723aa53ca946bfdb39a97e584387bdca6d 100644 --- a/RingD.cpp +++ b/RingD.cpp @@ -125,6 +125,41 @@ void RingClientUWP::RingD::acceptIncommingCall(Call^ call) tasksList_.push(ref new RingD::Task(Request::AcceptIncommingCall, call)); } +void RingClientUWP::RingD::placeCall(Contact^ contact) +{ + auto to = contact->ringID_; + auto accountId = AccountsViewModel::instance->selectedAccount->accountID_; + + auto to2 = Utils::toString(to); + auto accountId2 = Utils::toString(accountId); + + auto callId2 = DRing::placeCall(accountId2, to2); + + if (callId2 == "") { + WNG_("call not created, the daemon didn't return a call Id"); + return; + } + + auto callId = Utils::toPlatformString(callId2); + + auto call = CallsViewModel::instance->addNewCall(accountId, callId, to); + call->isOutGoing = true; + + if (call == nullptr) { + WNG_("call not created, nullptr reason"); + return; + } + + calling(call); + +} + +void +RingClientUWP::RingD::cancelOutGoingCall(Call^ call) +{ + tasksList_.push(ref new RingD::Task(Request::CancelOutGoingCall, call)); +} + void RingClientUWP::RingD::startDaemon() { @@ -221,7 +256,13 @@ RingClientUWP::RingD::startDaemon() ref new DispatchedHandler([=]() { reloadAccountList(); })); - }) + }), + /* to remove from daemon API, this callback is never used */ + //DRing::exportable_callback<DRing::CallSignal::NewCallCreated>([&]( + // const std::string& accountId, + // const std::string& callId, + // const std::string& to) + //{ /*...*/ }) }; registerCallHandlers(callHandlers); @@ -313,6 +354,13 @@ RingD::dequeueTasks() DRing::accept(callId2); } break; + case Request::CancelOutGoingCall: + { + auto callId = task->_call->callId; + auto callId2 = Utils::toString(callId); + DRing::hangUp(callId2); + } + break; default: break; } diff --git a/RingD.h b/RingD.h index ceff0446c73be74250e99b493798a42adf6e6e39..6305151f3b31dc1a4607eec9268e4340b257ce6d 100644 --- a/RingD.h +++ b/RingD.h @@ -26,6 +26,7 @@ namespace RingClientUWP delegate void IncomingCall(String^ accountId, String^ callId, String^ from); delegate void StateChange(String^ callId, String^ state, int code); delegate void IncomingAccountMessage(String^ accountId, String^ from, String^ payload); +delegate void Calling(Call^ call); public ref class RingD sealed @@ -60,6 +61,8 @@ internal: void createSIPAccount(String^ alias); void refuseIncommingCall(Call^ call); void acceptIncommingCall(Call^ call); + void placeCall(Contact^ contact); + void cancelOutGoingCall(Call^ call); /* TODO : move members */ bool hasConfig; @@ -69,6 +72,7 @@ internal: event IncomingCall^ incomingCall; event StateChange^ stateChange; event IncomingAccountMessage^ incomingAccountMessage; + event Calling^ calling; private: /* sub classes */ @@ -77,7 +81,8 @@ private: AddRingAccount, AddSIPAccount, RefuseIncommingCall, - AcceptIncommingCall + AcceptIncommingCall, + CancelOutGoingCall }; ref class Task { diff --git a/SmartPanel.xaml b/SmartPanel.xaml index 307c9c13416f913b7f12a6068f15d8d1b5385d3e..b291d37f3edf5d645baed88881bc37afe7217e17 100644 --- a/SmartPanel.xaml +++ b/SmartPanel.xaml @@ -77,8 +77,8 @@ Grid.Row="0" Text="{x:Bind name_}"> </TextBlock> - <!-- call status. --> - <StackPanel MaxWidth="240" + <!-- call status. REFACTO : REMOVE CODE BELOW --> + <!--<StackPanel MaxWidth="240" MinWidth="240" Grid.Row="1" HorizontalAlignment="Left"> @@ -88,12 +88,13 @@ Visibility="Visible" HorizontalAlignment="Center"> </TextBlock> - </StackPanel> + </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" + <!--<Grid Width="320" HorizontalAlignment="Left" Grid.Row="2" Background="DarkGray"> @@ -111,7 +112,7 @@ HorizontalAlignment="Center" Content="Reject"/> </StackPanel> - </Grid> + </Grid>--> </Grid> </DataTemplate> <!-- template for accounts. --> @@ -149,11 +150,10 @@ Text="{x:Bind ringID_}"/> </Grid> </DataTemplate> - <!-- template for calls. --> - <DataTemplate x:Key="CallTemplate" x:DataType="local:Call"> + <!-- template for incoming calls. --> + <DataTemplate x:Key="IncomingCallTemplate" x:DataType="local:Call"> <Grid Width="320" HorizontalAlignment="Left" - Background="DarkGray"> <Grid.RowDefinitions> <RowDefinition Height="30"/> @@ -182,10 +182,37 @@ </StackPanel> </Grid> </DataTemplate> + <!-- template for outgoing calls. --> + <DataTemplate x:Key="OutGoingCallTemplate" 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="_cancelCallBtn_" + Click="_cancelCallBtn__Click" + VerticalAlignment="Center" + HorizontalAlignment="Center" + Content="Cancel"/> + </StackPanel> + </Grid> + </DataTemplate> <!-- template for smartpanelitems. --> <DataTemplate x:Key="SmartPanelItemsTemplate" x:DataType="controls:SmartPanelItem"> - <Grid> + <Grid PointerEntered="Grid_PointerEntered" PointerExited="Grid_PointerExited"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> @@ -193,16 +220,33 @@ <ListBoxItem x:Name="_contactItem_" Padding="0" Margin="0" - IsHitTestVisible="False" Grid.Row="0" + PointerReleased="_contactItem__PointerReleased" ContentTemplate="{StaticResource ContactTemplate}" Content="{x:Bind _contact, Mode=OneWay}"/> - <ListBoxItem x:Name="_callItem_" - Grid.Row="1" - Visibility="{x:Bind _callBar, 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 CallTemplate}" + ContentTemplate="{StaticResource OutGoingCallTemplate}" Content="{x:Bind _call, Mode=OneWay}"/> </Grid> </DataTemplate> diff --git a/SmartPanel.xaml.cpp b/SmartPanel.xaml.cpp index 201a6388d192f6390b14a68dbc0f68a45d85a2d6..0557bd6f20e073c0c2601735be4abecfaa802292 100644 --- a/SmartPanel.xaml.cpp +++ b/SmartPanel.xaml.cpp @@ -93,13 +93,17 @@ SmartPanel::SmartPanel() } if (call->state == "incoming call") - item->_callBar = Windows::UI::Xaml::Visibility::Visible; + item->_IncomingCallBar = Windows::UI::Xaml::Visibility::Visible; - if (call->state == "CURRENT") - item->_callBar = Windows::UI::Xaml::Visibility::Collapsed; + if (call->state == "CURRENT") { + item->_IncomingCallBar = Windows::UI::Xaml::Visibility::Collapsed; + item->_OutGoingCallBar = Windows::UI::Xaml::Visibility::Collapsed; + } - if (call->state == "") - item->_callBar = Windows::UI::Xaml::Visibility::Collapsed; + if (call->state == "") { + item->_IncomingCallBar = Windows::UI::Xaml::Visibility::Collapsed; + item->_OutGoingCallBar = Windows::UI::Xaml::Visibility::Collapsed; + } }); @@ -109,6 +113,30 @@ SmartPanel::SmartPanel() smartPanelItemsList_->Append(smartPanelItem); }); + RingD::instance->calling += ref new RingClientUWP::Calling([&]( + Call^ call) { + auto from = call->from; + auto contact = ContactsViewModel::instance->findContactByName(from); + + if (contact == nullptr) { + WNG_("cannot call the peer, contact not found!"); + return; + } + + auto item = findItem(contact); + + if (item == nullptr) { + WNG_("cannot call the peer, smart panel item not found!"); + return; + } + + /* use underscore to differentiate states from UI, we need to think more about states management */ + call->state = "_calling_"; + + item->_OutGoingCallBar = Windows::UI::Xaml::Visibility::Visible; + item->_call = call; + }); + } void @@ -228,13 +256,10 @@ SmartPanel::_smartList__SelectionChanged(Platform::Object^ sender, Windows::UI:: { auto listbox = safe_cast<ListBox^>(sender); auto item = safe_cast<SmartPanelItem^>(listbox->SelectedItem); - if (item != nullptr) { - auto contact = safe_cast<Contact^>(item->_contact); - ContactsViewModel::instance->selectedContact = contact; - } - else { - ContactsViewModel::instance->selectedContact = nullptr; - } + + Contact^ contact = (item) ? safe_cast<Contact^>(item->_contact) : nullptr; + + ContactsViewModel::instance->selectedContact = contact; } void @@ -269,7 +294,7 @@ void RingClientUWP::Views::SmartPanel::_ringTxtBx__KeyDown(Platform::Object^ sen } } - +// REFACTO : change the name IncomingCall if used with OutGoingCall too. void RingClientUWP::Views::SmartPanel::_rejectIncomingCallBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { auto button = dynamic_cast<Button^>(e->OriginalSource); @@ -306,4 +331,56 @@ SmartPanel::findItem(Call^ call) return item; return nullptr; +} + +void +SmartPanel::_callContact__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) +{ + auto button = dynamic_cast<Button^>(e->OriginalSource); + auto item = dynamic_cast<SmartPanelItem^>(button->DataContext); + auto contact = item->_contact; + + RingD::instance->placeCall(contact); +} + + +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); + + call->cancel(); +} + + +void RingClientUWP::Views::SmartPanel::Grid_PointerEntered(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) +{ + auto grid = dynamic_cast<Grid^>(sender); + auto listBoxItem = dynamic_cast<ListBoxItem^>(sender); + auto item = dynamic_cast<SmartPanelItem^>(grid->DataContext); + + item->_callBar = Windows::UI::Xaml::Visibility::Visible; +} + + +void RingClientUWP::Views::SmartPanel::Grid_PointerExited(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) +{ + auto listBoxItem = dynamic_cast<ListBoxItem^>(sender); + auto grid = dynamic_cast<Grid^>(sender); + auto item = dynamic_cast<SmartPanelItem^>(grid->DataContext); + + item->_callBar = Windows::UI::Xaml::Visibility::Collapsed; +} + + +void RingClientUWP::Views::SmartPanel::_contactItem__PointerReleased(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e) +{ + auto listBoxItem = dynamic_cast<ListBoxItem^>(sender); + auto smartPanelItem = dynamic_cast<SmartPanelItem^>(listBoxItem->DataContext); + + if (_smartList_->SelectedItem != smartPanelItem) + _smartList_->SelectedItem = smartPanelItem; + else + _smartList_->SelectedItem = nullptr; + } \ No newline at end of file diff --git a/SmartPanel.xaml.h b/SmartPanel.xaml.h index 9128fe303695f3fb30ebce78d001038de717f3aa..2d71204ee319f4e54c64b8d591287ecb50f6a9b8 100644 --- a/SmartPanel.xaml.h +++ b/SmartPanel.xaml.h @@ -58,6 +58,11 @@ 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); + void _callContact__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void _cancelCallBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); + void Grid_PointerEntered(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e); + void Grid_PointerExited(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e); + void _contactItem__PointerReleased(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e); /* members */ Vector<Controls::SmartPanelItem^>^ smartPanelItemsList_; diff --git a/SmartPanelItem.cpp b/SmartPanelItem.cpp index 7d91b2abd6f8d6556e3a2519e85c7f83b695d2ce..ab986a6b2de7999781ac784ec2b6b20dd8e64fa7 100644 --- a/SmartPanelItem.cpp +++ b/SmartPanelItem.cpp @@ -42,5 +42,4 @@ SmartPanelItem::NotifyPropertyChanged(String^ propertyName) { PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName)); })); -} - +} \ No newline at end of file diff --git a/SmartPanelItem.h b/SmartPanelItem.h index a651d154073c6f944c2be10adf2df84e3c3d3158..aa5484b53e1db2ea7ab03cb14cac1fa7bb7f7255 100644 --- a/SmartPanelItem.h +++ b/SmartPanelItem.h @@ -31,8 +31,31 @@ public: SmartPanelItem(); 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 + { + Visibility get() + { + return outGoingCallBar_; + } + void set(Visibility value) + { + outGoingCallBar_ = value; + PropertyChanged(this, ref new PropertyChangedEventArgs("_OutGoingCallBar")); + } + } property Visibility _callBar { Visibility get() @@ -62,6 +85,8 @@ protected: void NotifyPropertyChanged(String^ propertyName); private: + Visibility incomingCallBar_ = Visibility::Collapsed; + Visibility outGoingCallBar_ = Visibility::Collapsed; Visibility callBar_ = Visibility::Collapsed; Call^ call_; };