MainPage.xaml.cpp 18 KB
Newer Older
Nicolas Jager's avatar
Nicolas Jager committed
1 2 3
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux                                *
* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com>              *
atraczyk's avatar
atraczyk committed
4
* Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com>          *
Nicolas Jager's avatar
Nicolas Jager committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
*                                                                         *
* 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"

21
#include "ContactListModel.h"
22
#include "MessageTextPage.xaml.h"
Nicolas Jager's avatar
Nicolas Jager committed
23
#include "SmartPanel.xaml.h"
Nicolas Jager's avatar
Nicolas Jager committed
24
#include "VideoPage.xaml.h"
25
#include "PreviewPage.xaml.h"
Nicolas Jager's avatar
Nicolas Jager committed
26
#include "WelcomePage.xaml.h"
atraczyk's avatar
atraczyk committed
27
#include "AboutPage.xaml.h"
Nicolas Jager's avatar
Nicolas Jager committed
28 29 30 31 32

#include "MainPage.xaml.h"

using namespace RingClientUWP;
using namespace RingClientUWP::Views;
33
using namespace RingClientUWP::ViewModel;
Nicolas Jager's avatar
Nicolas Jager committed
34 35

using namespace Platform;
Nicolas Jager's avatar
Nicolas Jager committed
36
using namespace Windows::ApplicationModel::Core;
Nicolas Jager's avatar
Nicolas Jager committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50
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;
51
using namespace Concurrency;
atraczyk's avatar
atraczyk committed
52
using namespace Windows::System::Threading;
Nicolas Jager's avatar
Nicolas Jager committed
53 54 55 56 57

MainPage::MainPage()
{
    InitializeComponent();

58
    UserModel::instance->getUserData();
59

60 61
    Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &MainPage::OnResize);

Nicolas Jager's avatar
Nicolas Jager committed
62 63
    _welcomeFrame_->Navigate(TypeName(RingClientUWP::Views::WelcomePage::typeid));
    _smartPanel_->Navigate(TypeName(RingClientUWP::Views::SmartPanel::typeid));
Nicolas Jager's avatar
Nicolas Jager committed
64
    _videoFrame_->Navigate(TypeName(RingClientUWP::Views::VideoPage::typeid));
65
    _previewFrame_->Navigate(TypeName(RingClientUWP::Views::PreviewPage::typeid));
66 67
    _messageTextFrame_->Navigate(TypeName(RingClientUWP::Views::MessageTextPage::typeid));

68 69
    isSmartPanelOpen = true;

70
    /* connect to delegates */
Nicolas Jager's avatar
Nicolas Jager committed
71 72 73 74
    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);
75 76
    smartPanel->summonPreviewPage += ref new RingClientUWP::SummonPreviewPage(this, &RingClientUWP::MainPage::OnsummonPreviewPage);
    smartPanel->hidePreviewPage += ref new RingClientUWP::HidePreviewPage(this, &RingClientUWP::MainPage::OnhidePreviewPage);
Nicolas Jager's avatar
Nicolas Jager committed
77
    smartPanel->summonVideoPage += ref new RingClientUWP::SummonVideoPage(this, &RingClientUWP::MainPage::OnsummonVideoPage);
atraczyk's avatar
atraczyk committed
78

Nicolas Jager's avatar
Nicolas Jager committed
79 80
    auto videoPage = dynamic_cast<VideoPage^>(_videoFrame_->Content);
    videoPage->pressHangUpCall += ref new RingClientUWP::PressHangUpCall(this, &RingClientUWP::MainPage::OnpressHangUpCall);
81

82 83 84
    auto messageTextFrame = dynamic_cast<MessageTextPage^>(_messageTextFrame_->Content);
    messageTextFrame->closeMessageTextPage += ref new RingClientUWP::CloseMessageTextPage(this, &RingClientUWP::MainPage::OncloseMessageTextPage);

atraczyk's avatar
atraczyk committed
85
    dpiChangedtoken = (DisplayInformation::GetForCurrentView()->DpiChanged += ref new TypedEventHandler<DisplayInformation^,
86
                       Platform::Object^>(this, &MainPage::DisplayProperties_DpiChanged));
87 88

    visibilityChangedEventToken = Window::Current->VisibilityChanged +=
Nicolas Jager's avatar
Nicolas Jager committed
89
                                      ref new WindowVisibilityChangedEventHandler(this, &MainPage::Application_VisibilityChanged);
atraczyk's avatar
atraczyk committed
90 91

    applicationSuspendingEventToken = Application::Current->Suspending +=
92
                                          ref new SuspendingEventHandler(this, &MainPage::Application_Suspending);
atraczyk's avatar
atraczyk committed
93
    applicationResumingEventToken = Application::Current->Resuming +=
94
                                        ref new EventHandler<Object^>(this, &MainPage::Application_Resuming);
atraczyk's avatar
atraczyk committed
95

96 97
    RingD::instance->registrationStateErrorGeneric += ref new RingClientUWP::RegistrationStateErrorGeneric(this, &RingClientUWP::MainPage::OnregistrationStateErrorGeneric);
    RingD::instance->registrationStateRegistered += ref new RingClientUWP::RegistrationStateRegistered(this, &RingClientUWP::MainPage::OnregistrationStateRegistered);
98
    RingD::instance->registrationStateUnregistered += ref new RingClientUWP::RegistrationStateUnregistered(this, &RingClientUWP::MainPage::OnregistrationStateUnregistered);
99
    RingD::instance->callPlaced += ref new RingClientUWP::CallPlaced(this, &RingClientUWP::MainPage::OncallPlaced);
100

101
    RingD::instance->setOverlayStatusText += ref new SetOverlayStatusText(this, &MainPage::OnsetOverlayStatusText);
102

103
    RingD::instance->fullScreenToggled += ref new RingClientUWP::FullScreenToggled(this, &RingClientUWP::MainPage::OnFullScreenToggled);
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

    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);
Nicolas Jager's avatar
Nicolas Jager committed
142 143 144 145 146
}

void
MainPage::OnKeyDown(KeyRoutedEventArgs^ e)
{
147 148 149 150 151
    if (DEBUG_ON)
        if (e->Key == VirtualKey::F5) {
            _outerSplitView_->OpenPaneLength = Window::Current->Bounds.Width;
            _outerSplitView_->IsPaneOpen = !_outerSplitView_->IsPaneOpen;
        }
Nicolas Jager's avatar
Nicolas Jager committed
152 153
}

154 155
void
MainPage::_toggleSmartBoxButton__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
Nicolas Jager's avatar
Nicolas Jager committed
156
{
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
    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);
173
    }
Nicolas Jager's avatar
Nicolas Jager committed
174
}
175 176 177 178 179 180 181 182 183

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_) {
184
        _currentFrame = FrameOpen::WELCOME;
185 186
        _navGrid_->SetRow(_welcomeFrame_, 1);
    } else if (frame == _videoFrame_) {
187
        _currentFrame = FrameOpen::VIDEO;
188 189
        _navGrid_->SetRow(_videoFrame_, 1);
    } else if (frame == _messageTextFrame_) {
190
        _currentFrame = FrameOpen::MESSAGE;
191 192
        _navGrid_->SetRow(_messageTextFrame_, 1);
    }
193

194
}
195 196 197 198

void
RingClientUWP::MainPage::OnNavigatedTo(NavigationEventArgs ^ e)
{
atraczyk's avatar
atraczyk committed
199 200 201 202
    bool fromAboutPage = (e->Parameter != nullptr) ? safe_cast<bool>(e->Parameter) : false;
    if (!fromAboutPage) {
        RingD::instance->init();
        showLoadingOverlay(true, false);
atraczyk's avatar
atraczyk committed
203
    }
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
}

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;
221
            _loadingOverlay_->Opacity = 1.0;
222 223
        }
    }
224
    else if (!load && isLoading) {
225 226 227 228 229 230
        isLoading = false;
        _fadeOutStoryboard_->Begin();
    }
}

void
231
MainPage::OnResize(Platform::Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e)
232
{
233 234 235 236 237 238 239 240 241 242 243 244 245 246
    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);
        }
    }
247 248 249 250 251 252
}

void
RingClientUWP::MainPage::DisplayProperties_DpiChanged(DisplayInformation^ sender, Platform::Object^ args)
{
    OnResize(nullptr, nullptr);
253 254 255
    SmartPanelItemsViewModel::instance->update({ "" });
    ContactRequestItemsViewModel::instance->update({ "" });
    AccountListItemsViewModel::instance->update({ "" });
256 257 258 259 260 261
}

void
RingClientUWP::MainPage::hideLoadingOverlay()
{
    _loadingOverlay_->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
Nicolas Jager's avatar
Nicolas Jager committed
262 263
}

264 265
void
RingClientUWP::MainPage::OnsummonMessageTextPage()
Nicolas Jager's avatar
Nicolas Jager committed
266
{
267
    updateMessageTextPage(nullptr);
Nicolas Jager's avatar
Nicolas Jager committed
268 269 270
    showFrame(_messageTextFrame_);
}

271 272 273 274 275 276
void
RingClientUWP::MainPage::updateMessageTextPage(SmartPanelItem^ item)
{
    auto messageTextPage = dynamic_cast<MessageTextPage^>(_messageTextFrame_->Content);
    messageTextPage->updatePageContent(item);
}
Nicolas Jager's avatar
Nicolas Jager committed
277 278 279 280 281 282

void RingClientUWP::MainPage::OnsummonWelcomePage()
{
    showFrame(_welcomeFrame_);
}

283 284
void RingClientUWP::MainPage::OnsummonPreviewPage()
{
285
    MSG_("Show Settings Preview");
286 287 288 289 290
    _previewFrame_->Visibility = VIS::Visible;
}

void RingClientUWP::MainPage::OnhidePreviewPage()
{
291
    MSG_("Hide Settings Preview");
292 293
    _previewFrame_->Visibility = VIS::Collapsed;
}
Nicolas Jager's avatar
Nicolas Jager committed
294 295 296

void RingClientUWP::MainPage::OnsummonVideoPage()
{
297
    auto item = SmartPanelItemsViewModel::instance->_selectedItem;
298
    auto videoPage = dynamic_cast<VideoPage^>(_videoFrame_->Content);
299 300 301 302 303 304 305 306 307 308 309 310 311

    if (item) {
        switch (item->_callStatus) {
        case CallStatus::IN_PROGRESS:
            videoPage->screenVideo(true);
            break;
        case CallStatus::PEER_PAUSED:
        case CallStatus::PAUSED:
            videoPage->screenVideo(false);
            break;
        }
    }

Nicolas Jager's avatar
Nicolas Jager committed
312 313 314 315 316 317 318 319 320
    videoPage->updatePageContent();
    showFrame(_videoFrame_);
}


void RingClientUWP::MainPage::OnpressHangUpCall()
{
}

321 322
void
MainPage::OnstateChange(Platform::String ^callId, RingClientUWP::CallStatus state, int code)
Nicolas Jager's avatar
Nicolas Jager committed
323 324 325 326 327
{
    auto item = SmartPanelItemsViewModel::instance->_selectedItem;

    switch (state) {
    /* send the user to the peer's message text page */
328
    case CallStatus::ENDED:
Nicolas Jager's avatar
Nicolas Jager committed
329
    {
330 331 332 333 334 335 336 337 338
        auto selectedItem = SmartPanelItemsViewModel::instance->_selectedItem;

        if (!selectedItem) {
            return;
        }

        if (item &&
            selectedItem->_callId == callId &&
            _currentFrame == FrameOpen::VIDEO) {
Nicolas Jager's avatar
Nicolas Jager committed
339
            OnsummonMessageTextPage();
340 341
            //showFrame(_messageTextFrame_);
        }
Nicolas Jager's avatar
Nicolas Jager committed
342 343 344 345 346 347
        break;
    }
    default:
        break;
    }
}
348

atraczyk's avatar
atraczyk committed
349 350 351
void
MainPage::Application_Suspending(Object^, Windows::ApplicationModel::SuspendingEventArgs^ e)
{
352
    /*MSG_("Application_Suspending");
atraczyk's avatar
atraczyk committed
353
    auto deferral = e->SuspendingOperation->GetDeferral();
atraczyk's avatar
atraczyk committed
354
    Video::VideoManager::instance->captureManager()->CleanupCameraAsync();
atraczyk's avatar
atraczyk committed
355 356
    MSG_("Hang up calls...");
    RingD::instance->deinit();
357
    deferral->Complete();*/
atraczyk's avatar
atraczyk committed
358 359 360 361 362
}

void
MainPage::Application_VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
{
363
    auto vcm = Video::VideoManager::instance->captureManager();
364
    if (e->Visible) {
365
        MSG_("->Visible");
366
        RingD::instance->isInvisible = false;
367 368 369 370 371 372 373 374
        bool isInCall = false;
        for (auto item : SmartPanelItemsViewModel::instance->itemsList) {
            if (item->_callId && item->_callStatus == CallStatus::IN_PROGRESS) {
                isInCall = true;
                break;
            }
        }
        if (isInCall) {
375 376 377 378 379
            vcm->InitializeCameraAsync(false);
            vcm->videoFrameCopyInvoker->Start();
        }
        else if (vcm->isSettingsPreviewing) {
            vcm->CleanupCameraAsync()
Nicolas Jager's avatar
Nicolas Jager committed
380
            .then([=](task<void> cleanupCameraTask) {
381 382 383 384 385 386 387 388 389
                try {
                    cleanupCameraTask.get();
                    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
                        CoreDispatcherPriority::High, ref new DispatchedHandler([=]()
                    {
                        vcm->InitializeCameraAsync(true);
                    }));
                }
                catch (Exception^ e) {
390
                    EXC_(e);
391
                }
392
            });
393
        }
atraczyk's avatar
atraczyk committed
394
    }
395
    else {
396
        MSG_("->Invisible");
397
        RingD::instance->isInvisible = true;
398 399 400 401 402 403 404 405 406
        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) {
407 408 409 410 411
            if (vcm->isPreviewing) {
                vcm->StopPreviewAsync();
                if (vcm->captureTaskTokenSource)
                    vcm->captureTaskTokenSource->cancel();
                vcm->videoFrameCopyInvoker->Stop();
412 413
            }
        }
414 415 416
        else if (vcm->isSettingsPreviewing) {
            vcm->StopPreviewAsync();
        }
atraczyk's avatar
atraczyk committed
417
    }
418 419
}

420 421
void MainPage::Application_Resuming(Object^, Object^)
{
422
    MSG_("Application_Resuming");
423 424
}

425 426
void RingClientUWP::MainPage::OncloseMessageTextPage()
{
427 428
    SmartPanelItemsViewModel::instance->_selectedItem = nullptr;
    showFrame(_welcomeFrame_);
429
}
430 431 432 433 434 435


void RingClientUWP::MainPage::OnregistrationStateErrorGeneric(const std::string& accountId)
{
}

436
void RingClientUWP::MainPage::OnregistrationStateUnregistered(const std::string& accountId)
437
{
438 439
    RingD::instance->volatileDetailsChanged += ref new RingClientUWP::VolatileDetailsChanged(this, &MainPage::OnvolatileDetailsChanged);
}
Nicolas Jager's avatar
Nicolas Jager committed
440

441 442
void RingClientUWP::MainPage::OnregistrationStateRegistered(const std::string& accountId)
{
Nicolas Jager's avatar
Nicolas Jager committed
443 444
    /* do not connect those delegates before initial registration on dht is fine.
       Otherwise your going to mess with the wizard */
445
    RingD::instance->nameRegistered += ref new RingClientUWP::NameRegistered(this, &RingClientUWP::MainPage::OnnameRegistred);
446
    RingD::instance->volatileDetailsChanged += ref new RingClientUWP::VolatileDetailsChanged(this, &MainPage::OnvolatileDetailsChanged);
447
}
448 449 450 451

void RingClientUWP::MainPage::OncallPlaced(Platform::String ^callId)
{
}
Nicolas Jager's avatar
Nicolas Jager committed
452

453 454
void
MainPage::OnnameRegistred(bool status, String ^accountId)
Nicolas Jager's avatar
Nicolas Jager committed
455 456 457 458 459
{
    showLoadingOverlay(false, false);
}


460
void RingClientUWP::MainPage::OnvolatileDetailsChanged(const std::string &accountId, const std::map<std::string, std::string>& details)
Nicolas Jager's avatar
Nicolas Jager committed
461 462 463
{
    showLoadingOverlay(false, false);
}
464

465
void RingClientUWP::MainPage::OnFullScreenToggled(bool state)
466 467 468 469 470 471
{
    if (state == true) {
        _innerSplitView_->IsPaneOpen = false;
        _innerSplitView_->CompactPaneLength = 0;
    }
    else {
472
        _innerSplitView_->IsPaneOpen = isSmartPanelOpen;
473 474 475
        _innerSplitView_->CompactPaneLength = 60;
    }
}