blob: 5943e40a8f5ed71621edde41034ebb57b8e8787e [file] [log] [blame]
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux *
* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
* Author: Traczyk Andreas <andreas.traczyk@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 "ContactListModel.h"
#include "MessageTextPage.xaml.h"
#include "SmartPanel.xaml.h"
#include "VideoPage.xaml.h"
#include "PreviewPage.xaml.h"
#include "WelcomePage.xaml.h"
#include "AboutPage.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;
using namespace Windows::System::Threading;
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));
_videoFrame_->Navigate(TypeName(RingClientUWP::Views::VideoPage::typeid));
_previewFrame_->Navigate(TypeName(RingClientUWP::Views::PreviewPage::typeid));
_messageTextFrame_->Navigate(TypeName(RingClientUWP::Views::MessageTextPage::typeid));
isSmartPanelOpen = true;
/* 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->summonPreviewPage += ref new RingClientUWP::SummonPreviewPage(this, &RingClientUWP::MainPage::OnsummonPreviewPage);
smartPanel->hidePreviewPage += ref new RingClientUWP::HidePreviewPage(this, &RingClientUWP::MainPage::OnhidePreviewPage);
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);
dpiChangedtoken = (DisplayInformation::GetForCurrentView()->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);
RingD::instance->registrationStateErrorGeneric += ref new RingClientUWP::RegistrationStateErrorGeneric(this, &RingClientUWP::MainPage::OnregistrationStateErrorGeneric);
RingD::instance->registrationStateRegistered += ref new RingClientUWP::RegistrationStateRegistered(this, &RingClientUWP::MainPage::OnregistrationStateRegistered);
RingD::instance->registrationStateUnregistered += ref new RingClientUWP::RegistrationStateUnregistered(this, &RingClientUWP::MainPage::OnregistrationStateUnregistered);
RingD::instance->callPlaced += ref new RingClientUWP::CallPlaced(this, &RingClientUWP::MainPage::OncallPlaced);
RingD::instance->setOverlayStatusText += ref new SetOverlayStatusText(this, &MainPage::OnsetOverlayStatusText);
RingD::instance->fullScreenToggled += ref new RingClientUWP::FullScreenToggled(this, &RingClientUWP::MainPage::OnFullScreenToggled);
Window::Current->CoreWindow->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(
[this](CoreWindow^ c, KeyEventArgs^ e)
{
auto ctrlState = CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::Control);
RingD::instance->isCtrlPressed = (ctrlState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
auto shiftState = CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::LeftShift);
RingD::instance->isShiftPressed = (shiftState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
//MSG_("KEYDOWN -- isCtrlDown: " + isCtrlPressed.ToString() + " isShiftDown: " + isShiftPressed.ToString());
});
Window::Current->CoreWindow->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(
[this](CoreWindow^ c, KeyEventArgs^ e)
{
auto ctrlState = CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::Control);
RingD::instance->isCtrlPressed = (ctrlState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
auto shiftState = CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::LeftShift);
RingD::instance->isShiftPressed = (shiftState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
//MSG_("KEYUP -- isCtrlDown: " + isCtrlPressed.ToString() + " isShiftDown: " + isShiftPressed.ToString());
});
}
void
MainPage::OnsetOverlayStatusText(String^ statusText, String^ color)
{
_loadingStatus_->Text = statusText;
auto col = Utils::ColorFromString(color);
auto brush = ref new Windows::UI::Xaml::Media::SolidColorBrush(col);
_loadingStatus_->Foreground = brush;
}
void
MainPage::focusOnMessagingTextbox()
{
auto messageTextPage = dynamic_cast<MessageTextPage^>(_messageTextFrame_->Content);
auto messageTextBox = dynamic_cast<TextBox^>(messageTextPage->FindName("_messageTextBox_"));
messageTextBox->Focus(Windows::UI::Xaml::FocusState::Programmatic);
}
void
MainPage::OnKeyDown(KeyRoutedEventArgs^ e)
{
if (DEBUG_ON)
if (e->Key == VirtualKey::F5) {
_outerSplitView_->OpenPaneLength = Window::Current->Bounds.Width;
_outerSplitView_->IsPaneOpen = !_outerSplitView_->IsPaneOpen;
}
}
void
MainPage::_toggleSmartBoxButton__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
if (Window::Current->Bounds.Width <= 638)
return;
isSmartPanelOpen = !isSmartPanelOpen;
setSmartPanelState(isSmartPanelOpen);
RingD::instance->raiseWindowResized(Window::Current->Bounds.Width, Window::Current->Bounds.Height);
}
void
MainPage::setSmartPanelState(bool open)
{
if (_innerSplitView_->IsPaneOpen != open) {
_innerSplitView_->IsPaneOpen = open;
auto newMode = open ? Views::SmartPanel::Mode::Normal : Views::SmartPanel::Mode::Minimized;
dynamic_cast<SmartPanel^>(_smartPanel_->Content)->setMode(newMode);
}
}
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_) {
_currentFrame = FrameOpen::WELCOME;
_navGrid_->SetRow(_welcomeFrame_, 1);
} else if (frame == _videoFrame_) {
_currentFrame = FrameOpen::VIDEO;
_navGrid_->SetRow(_videoFrame_, 1);
} else if (frame == _messageTextFrame_) {
_currentFrame = FrameOpen::MESSAGE;
_navGrid_->SetRow(_messageTextFrame_, 1);
}
}
void
RingClientUWP::MainPage::OnNavigatedTo(NavigationEventArgs ^ e)
{
bool fromAboutPage = (e->Parameter != nullptr) ? safe_cast<bool>(e->Parameter) : false;
if (!fromAboutPage) {
RingD::instance->init();
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;
_loadingOverlay_->Opacity = 1.0;
}
}
else if (!load && isLoading) {
isLoading = false;
_fadeOutStoryboard_->Begin();
}
}
void
MainPage::OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e)
{
if (e) {
auto windowWidth = e->Size.Width;
auto windowHeight = e->Size.Height;
RingD::instance->raiseWindowResized(windowWidth, windowHeight);
if (windowWidth <= 638) {
setSmartPanelState(false);
return;
}
if (isSmartPanelOpen && !RingD::instance->isFullScreen) {
setSmartPanelState(true);
}
}
}
void
RingClientUWP::MainPage::DisplayProperties_DpiChanged(DisplayInformation^ sender, Platform::Object^ args)
{
OnResize(nullptr, nullptr);
SmartPanelItemsViewModel::instance->update({ "" });
ContactRequestItemsViewModel::instance->update({ "" });
AccountListItemsViewModel::instance->update({ "" });
}
void
RingClientUWP::MainPage::hideLoadingOverlay()
{
_loadingOverlay_->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
}
void
RingClientUWP::MainPage::OnsummonMessageTextPage()
{
updateMessageTextPage(nullptr);
showFrame(_messageTextFrame_);
}
void
RingClientUWP::MainPage::updateMessageTextPage(SmartPanelItem^ item)
{
auto messageTextPage = dynamic_cast<MessageTextPage^>(_messageTextFrame_->Content);
messageTextPage->updatePageContent(item);
}
void RingClientUWP::MainPage::OnsummonWelcomePage()
{
showFrame(_welcomeFrame_);
}
void RingClientUWP::MainPage::OnsummonPreviewPage()
{
MSG_("Show Settings Preview");
_previewFrame_->Visibility = VIS::Visible;
}
void RingClientUWP::MainPage::OnhidePreviewPage()
{
MSG_("Hide Settings Preview");
_previewFrame_->Visibility = VIS::Collapsed;
}
void RingClientUWP::MainPage::OnsummonVideoPage()
{
auto item = SmartPanelItemsViewModel::instance->_selectedItem;
auto videoPage = dynamic_cast<VideoPage^>(_videoFrame_->Content);
if (item) {
switch (item->_callStatus) {
case CallStatus::IN_PROGRESS:
videoPage->screenVideo(true);
break;
case CallStatus::PEER_PAUSED:
case CallStatus::PAUSED:
videoPage->screenVideo(false);
break;
}
}
videoPage->updatePageContent();
showFrame(_videoFrame_);
}
void RingClientUWP::MainPage::OnpressHangUpCall()
{
}
void
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:
{
auto selectedItem = SmartPanelItemsViewModel::instance->_selectedItem;
if (!selectedItem) {
return;
}
if (item &&
selectedItem->_callId == callId &&
_currentFrame == FrameOpen::VIDEO) {
OnsummonMessageTextPage();
//showFrame(_messageTextFrame_);
}
break;
}
default:
break;
}
}
void
MainPage::Application_Suspending(Object^, Windows::ApplicationModel::SuspendingEventArgs^ e)
{
/*MSG_("Application_Suspending");
auto deferral = e->SuspendingOperation->GetDeferral();
Video::VideoManager::instance->captureManager()->CleanupCameraAsync();
MSG_("Hang up calls...");
RingD::instance->deinit();
deferral->Complete();*/
}
void
MainPage::Application_VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
{
auto vcm = Video::VideoManager::instance->captureManager();
if (e->Visible) {
MSG_("->Visible");
RingD::instance->isInvisible = false;
bool isInCall = false;
for (auto item : SmartPanelItemsViewModel::instance->itemsList) {
if (item->_callId && item->_callStatus == CallStatus::IN_PROGRESS) {
isInCall = true;
break;
}
}
if (isInCall) {
vcm->InitializeCameraAsync(false);
vcm->videoFrameCopyInvoker->Start();
}
else if (vcm->isSettingsPreviewing) {
vcm->CleanupCameraAsync()
.then([=](task<void> cleanupCameraTask) {
try {
cleanupCameraTask.get();
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
{
vcm->InitializeCameraAsync(true);
}));
}
catch (Exception^ e) {
EXC_(e);
}
});
}
}
else {
MSG_("->Invisible");
RingD::instance->isInvisible = true;
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 (vcm->isPreviewing) {
vcm->StopPreviewAsync();
if (vcm->captureTaskTokenSource)
vcm->captureTaskTokenSource->cancel();
vcm->videoFrameCopyInvoker->Stop();
}
}
else if (vcm->isSettingsPreviewing) {
vcm->StopPreviewAsync();
}
}
}
void MainPage::Application_Resuming(Object^, Object^)
{
MSG_("Application_Resuming");
}
void RingClientUWP::MainPage::OncloseMessageTextPage()
{
SmartPanelItemsViewModel::instance->_selectedItem = nullptr;
showFrame(_welcomeFrame_);
}
void RingClientUWP::MainPage::OnregistrationStateErrorGeneric(const std::string& accountId)
{
}
void RingClientUWP::MainPage::OnregistrationStateUnregistered(const std::string& accountId)
{
RingD::instance->volatileDetailsChanged += ref new RingClientUWP::VolatileDetailsChanged(this, &MainPage::OnvolatileDetailsChanged);
}
void RingClientUWP::MainPage::OnregistrationStateRegistered(const std::string& accountId)
{
/* do not connect those delegates before initial registration on dht is fine.
Otherwise your going to mess with the wizard */
RingD::instance->nameRegistered += ref new RingClientUWP::NameRegistered(this, &RingClientUWP::MainPage::OnnameRegistred);
RingD::instance->volatileDetailsChanged += ref new RingClientUWP::VolatileDetailsChanged(this, &MainPage::OnvolatileDetailsChanged);
}
void RingClientUWP::MainPage::OncallPlaced(Platform::String ^callId)
{
}
void
MainPage::OnnameRegistred(bool status, String ^accountId)
{
showLoadingOverlay(false, false);
}
void RingClientUWP::MainPage::OnvolatileDetailsChanged(const std::string &accountId, const std::map<std::string, std::string>& details)
{
showLoadingOverlay(false, false);
}
void RingClientUWP::MainPage::OnFullScreenToggled(bool state)
{
if (state == true) {
_innerSplitView_->IsPaneOpen = false;
_innerSplitView_->CompactPaneLength = 0;
}
else {
_innerSplitView_->IsPaneOpen = isSmartPanelOpen;
_innerSplitView_->CompactPaneLength = 60;
}
}