/************************************************************************** * Copyright (C) 2016 by Savoir-faire Linux * * Author: Jäger Nicolas <nicolas.jager@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 "ContactsViewModel.h" #include "MessageTextPage.xaml.h" #include "SmartPanel.xaml.h" #include "RingConsolePanel.xaml.h" #include "VideoPage.xaml.h" #include "WelcomePage.xaml.h" #include "MainPage.xaml.h" using namespace RingClientUWP; using namespace RingClientUWP::Views; using namespace RingClientUWP::ViewModel; using namespace Platform; using namespace Windows::ApplicationModel::Core; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::UI::ViewManagement; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls::Primitives; using namespace Windows::UI::Core; using namespace Windows::UI::Xaml::Data; using namespace Windows::UI::Xaml::Input; using namespace Windows::UI::Xaml::Interop; using namespace Windows::UI::Xaml::Navigation; using namespace Windows::ApplicationModel::Activation; using namespace Windows::Graphics::Display; using namespace Windows::System; using namespace Concurrency; MainPage::MainPage() { InitializeComponent(); UserModel::instance->getUserData(); Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &MainPage::OnResize); _welcomeFrame_->Navigate(TypeName(RingClientUWP::Views::WelcomePage::typeid)); _smartPanel_->Navigate(TypeName(RingClientUWP::Views::SmartPanel::typeid)); _consolePanel_->Navigate(TypeName(RingClientUWP::Views::RingConsolePanel::typeid)); _videoFrame_->Navigate(TypeName(RingClientUWP::Views::VideoPage::typeid)); _messageTextFrame_->Navigate(TypeName(RingClientUWP::Views::MessageTextPage::typeid)); /* connect to delegates */ 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); auto messageTextFrame = dynamic_cast<MessageTextPage^>(_messageTextFrame_->Content); messageTextFrame->closeMessageTextPage += ref new RingClientUWP::CloseMessageTextPage(this, &RingClientUWP::MainPage::OncloseMessageTextPage); DisplayInformation^ displayInformation = DisplayInformation::GetForCurrentView(); dpiChangedtoken = (displayInformation->DpiChanged += ref new TypedEventHandler<DisplayInformation^, Platform::Object^>(this, &MainPage::DisplayProperties_DpiChanged)); visibilityChangedEventToken = Window::Current->VisibilityChanged += ref new WindowVisibilityChangedEventHandler(this, &MainPage::Application_VisibilityChanged); applicationSuspendingEventToken = Application::Current->Suspending += ref new SuspendingEventHandler(this, &MainPage::Application_Suspending); applicationResumingEventToken = Application::Current->Resuming += ref new EventHandler<Object^>(this, &MainPage::Application_Resuming); } void MainPage::OnKeyDown(KeyRoutedEventArgs^ e) { if (e->Key == VirtualKey::F5) { _outerSplitView_->OpenPaneLength = Window::Current->Bounds.Width; _outerSplitView_->IsPaneOpen = !_outerSplitView_->IsPaneOpen; } } void RingClientUWP::MainPage::_toggleSmartBoxButton__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { _innerSplitView_->IsPaneOpen = !_innerSplitView_->IsPaneOpen; if (_innerSplitView_->IsPaneOpen) { dynamic_cast<SmartPanel^>(_smartPanel_->Content)->setMode(Views::SmartPanel::Mode::Normal); _hamburgerButtonBar_->Width = 320; } else { dynamic_cast<SmartPanel^>(_smartPanel_->Content)->setMode(Views::SmartPanel::Mode::Minimized); _hamburgerButtonBar_->Width = 60; } } void RingClientUWP::MainPage::showFrame(Windows::UI::Xaml::Controls::Frame^ frame) { _navGrid_->SetRow(_welcomeFrame_, 0); _navGrid_->SetRow(_messageTextFrame_, 0); _navGrid_->SetRow(_videoFrame_, 0); if (frame == _welcomeFrame_) { _navGrid_->SetRow(_welcomeFrame_, 1); } else if (frame == _videoFrame_) { _navGrid_->SetRow(_videoFrame_, 1); } else if (frame == _messageTextFrame_) { _navGrid_->SetRow(_messageTextFrame_, 1); } } void RingClientUWP::MainPage::OnNavigatedTo(NavigationEventArgs ^ e) { RingD::instance->startDaemon(); showLoadingOverlay(true, false); } void RingClientUWP::MainPage::showLoadingOverlay(bool load, bool modal) { if (!isLoading && load) { isLoading = true; _loadingOverlay_->Visibility = Windows::UI::Xaml::Visibility::Visible; if (modal) { _fadeInModalStoryboard_->Begin(); auto blackBrush = ref new Windows::UI::Xaml::Media::SolidColorBrush(Windows::UI::Colors::Black); _loadingOverlayRect_->Fill = blackBrush; } else { auto whiteBrush = ref new Windows::UI::Xaml::Media::SolidColorBrush(Windows::UI::Colors::White); _loadingOverlayRect_->Fill = whiteBrush; _loadingOverlayRect_->Opacity = 1.0; } OnResize(nullptr, nullptr); } else if (!load) { isLoading = false; _fadeOutStoryboard_->Begin(); } } void RingClientUWP::MainPage::PositionImage() { bounds = ApplicationView::GetForCurrentView()->VisibleBounds; auto img = ref new Image(); auto bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(); Windows::Foundation::Uri^ uri; if (bounds.Width < 1200) uri = ref new Windows::Foundation::Uri("ms-appx:///Assets/TESTS/logo-ring.scale-200.png"); else uri = ref new Windows::Foundation::Uri("ms-appx:///Assets/TESTS/logo-ring.scale-150.png"); bitmapImage->UriSource = uri; img->Source = bitmapImage; _loadingImage_->Source = img->Source; _loadingImage_->SetValue(Canvas::LeftProperty, bounds.Width * 0.5 - _loadingImage_->Width * 0.5); _loadingImage_->SetValue(Canvas::TopProperty, bounds.Height * 0.5 - _loadingImage_->Height * 0.5); } void RingClientUWP::MainPage::PositionRing() { double left; double top; if (bounds.Width < 1200) { _splashProgressRing_->Width = 118; _splashProgressRing_->Height = 118; left = bounds.Width * 0.5 - _loadingImage_->Width * 0.5 - 145; top = bounds.Height * 0.5 - _loadingImage_->Height * 0.5 - 60; } else { _splashProgressRing_->Width = 162; _splashProgressRing_->Height = 162; left = bounds.Width * 0.5 - _loadingImage_->Width * 0.5 - 195; top = bounds.Height * 0.5 - _loadingImage_->Height * 0.5 - 84; } _splashProgressRing_->SetValue(Canvas::LeftProperty, left + _loadingImage_->Width * 0.5); _splashProgressRing_->SetValue(Canvas::TopProperty, top + _loadingImage_->Height * 0.5); } void RingClientUWP::MainPage::OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e) { PositionImage(); PositionRing(); } void RingClientUWP::MainPage::DisplayProperties_DpiChanged(DisplayInformation^ sender, Platform::Object^ args) { OnResize(nullptr, nullptr); } void RingClientUWP::MainPage::hideLoadingOverlay() { _loadingOverlay_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; } 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::NONE: { if (item) OnsummonMessageTextPage(); break; } default: break; } } #include <dring.h> #include "callmanager_interface.h" void MainPage::Application_Suspending(Object^, Windows::ApplicationModel::SuspendingEventArgs^ e) { RingDebug::instance->WriteLine("Application_Suspending"); if (Frame->CurrentSourcePageType.Name == Interop::TypeName(MainPage::typeid).Name) { auto deferral = e->SuspendingOperation->GetDeferral(); BeginExtendedExecution() .then([=](task<void> previousTask) { try { previousTask.get(); } catch (Exception^ e) { RingDebug::instance->WriteLine("Exception: Extended Execution Begin"); } }) .then([this, deferral](task<void> previousTask) { try { previousTask.get(); RingDebug::instance->WriteLine("deferral->Complete()"); deferral->Complete(); } catch (Exception^ e) { RingDebug::instance->WriteLine("Exception: Extended Execution"); deferral->Complete(); } }); } } void MainPage::Application_VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e) { if (e->Visible) { RingDebug::instance->WriteLine("->Visible"); auto isPreviewing = Video::VideoManager::instance->captureManager()->isPreviewing; bool isInCall = false; for (auto item : SmartPanelItemsViewModel::instance->itemsList) { if (item->_callId && item->_callStatus == CallStatus::IN_PROGRESS) { isInCall = true; break; } } if (isInCall) { /*if (RingD::instance->currentCallId) RingD::instance->unPauseCall(RingD::instance->currentCallId);*/ Video::VideoManager::instance->captureManager()->InitializeCameraAsync(); Video::VideoManager::instance->captureManager()->videoFrameCopyInvoker->Start(); } } else { RingDebug::instance->WriteLine("->Invisible"); auto isPreviewing = Video::VideoManager::instance->captureManager()->isPreviewing; bool isInCall = false; for (auto item : SmartPanelItemsViewModel::instance->itemsList) { if (item->_callId && item->_callStatus == CallStatus::IN_PROGRESS) { isInCall = true; RingD::instance->currentCallId = item->_callId; break; } } if (isInCall) { /*if (RingD::instance->currentCallId) { WriteLine("Pausing call: " + RingD::instance->currentCallId); RingD::instance->pauseCall(RingD::instance->currentCallId); }*/ if (isPreviewing) { Video::VideoManager::instance->captureManager()->StopPreviewAsync(); if (Video::VideoManager::instance->captureManager()->captureTaskTokenSource) Video::VideoManager::instance->captureManager()->captureTaskTokenSource->cancel(); Video::VideoManager::instance->captureManager()->videoFrameCopyInvoker->Stop(); } } } } void MainPage::Application_Resuming(Object^, Object^) { RingDebug::instance->WriteLine("Application_Resuming"); } void MainPage::SessionRevoked(Object^ sender, ExtendedExecutionRevokedEventArgs^ args) { Dispatcher->RunAsync(CoreDispatcherPriority::High, ref new DispatchedHandler([=]() { ClearExtendedExecution(); })); } void MainPage::ClearExtendedExecution() { if (session != nullptr) { RingDebug::instance->WriteLine("End Extended Execution"); session->Revoked -= sessionRevokedToken; } } task<void> MainPage::BeginExtendedExecution() { ClearExtendedExecution(); auto newSession = ref new ExtendedExecutionSession(); newSession->Reason = ExtendedExecutionReason::SavingData; newSession->Description = "Extended Execution"; sessionRevokedToken = (newSession->Revoked += ref new TypedEventHandler<Object^, ExtendedExecutionRevokedEventArgs^>(this, &MainPage::SessionRevoked)); return create_task(newSession->RequestExtensionAsync()) .then([=](ExtendedExecutionResult result) { try { switch (result) { case ExtendedExecutionResult::Allowed: session = newSession; RingDebug::instance->WriteLine("Request Extended Execution Allowed"); RingDebug::instance->WriteLine("Clean up camera..."); Video::VideoManager::instance->captureManager()->CleanupCameraAsync() .then([]() { RingDebug::instance->WriteLine("Hang up calls..."); DRing::fini(); }); break; default: case ExtendedExecutionResult::Denied: RingDebug::instance->WriteLine("Request Extended Execution Denied"); break; } } catch (Exception^ e) { RingDebug::instance->WriteLine("Exception: Extended Execution Request"); } }); } void RingClientUWP::MainPage::OncloseMessageTextPage() { auto smartPanel = dynamic_cast<SmartPanel^>(_smartPanel_->Content); smartPanel->unselectContact(); }