RingWindowController.mm 24.4 KB
Newer Older
1
/*
2
 *  Copyright (C) 2015-2016 Savoir-faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *  Author: Alexandre Lision <alexandre.lision@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, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */
19
#import "RingWindowController.h"
20
#import <QuartzCore/QuartzCore.h>
21
#include <qrencode.h>
22
#include <memory>
23 24 25 26

//Qt
#import <QItemSelectionModel>
#import <QItemSelection>
27

28
//LRC
29
#import <AvailableAccountModel.h>
30
#import <api/lrc.h>
31
#import <api/account.h>
32 33 34 35
#import <api/newaccountmodel.h>
#import <api/newcallmodel.h>
#import <api/behaviorcontroller.h>
#import <api/conversation.h>
36 37
#import <api/contactmodel.h>
#import <api/contact.h>
38
#import <api/datatransfermodel.h>
39
#import <media/recordingmodel.h>
40
#import <api/avmodel.h>
41

42
// Ring
43
#import "AppDelegate.h"
44
#import "Constants.h"
Alexandre Lision's avatar
Alexandre Lision committed
45
#import "CurrentCallVC.h"
46
#import "MigrateRingAccountsWC.h"
47
#import "ConversationVC.h"
48
#import "PreferencesWC.h"
49
#import "SmartViewVC.h"
50
#import "views/IconButton.h"
51
#import "views/NSColor+RingTheme.h"
52
#import "views/HoverButton.h"
53
#import "utils.h"
54
#import "RingWizardWC.h"
55
#import "AccountSettingsVC.h"
56 57 58 59 60 61 62
#import "views/CallLayer.h"

typedef NS_ENUM(NSInteger, ViewState) {
    SHOW_WELCOME_SCREEN = 0,
    SHOW_CONVERSATION_SCREEN,
    SHOW_CALL_SCREEN,
    SHOW_SETTINGS_SCREEN,
63
    LEAVE_MESSAGE,
64
};
65

Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
66
@interface RingWindowController () <MigrateRingAccountsDelegate>
67 68

@property (retain) MigrateRingAccountsWC* migrateWC;
69
@property RingWizardWC* wizard;
70 71 72

@end

73
@implementation RingWindowController {
74

75 76
    __unsafe_unretained IBOutlet NSLayoutConstraint* centerYQRCodeConstraint;
    __unsafe_unretained IBOutlet NSLayoutConstraint* centerYWelcomeContainerConstraint;
77
    IBOutlet NSLayoutConstraint* ringLabelTrailingConstraint;
78
    __unsafe_unretained IBOutlet NSView* welcomeContainer;
79 80
    __unsafe_unretained IBOutlet NSView* callView;
    __unsafe_unretained IBOutlet NSTextField* ringIDLabel;
81
    __unsafe_unretained IBOutlet NSTextField* explanationLabel;
82
    __unsafe_unretained IBOutlet NSButton* shareButton;
83
    __unsafe_unretained IBOutlet NSImageView* qrcodeView;
Alexandre Lision's avatar
Alexandre Lision committed
84

85
    PreferencesWC* preferencesWC;
86
    IBOutlet SmartViewVC* smartViewVC;
87

88
    CurrentCallVC* currentCallVC;
89
    ConversationVC* conversationVC;
90
    AccountSettingsVC* settingsVC;
91

Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
92
    IBOutlet ChooseAccountVC* chooseAccountVC;
93
}
Alexandre Lision's avatar
Alexandre Lision committed
94

95
@synthesize dataTransferModel, accountModel, behaviorController, avModel;
96
@synthesize wizard;
97

98
-(id) initWithWindowNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountModel:( lrc::api::NewAccountModel*)accountModel dataTransferModel:( lrc::api::DataTransferModel*)dataTransferModel behaviourController:( lrc::api::BehaviorController*) behaviorController avModel: (lrc::api::AVModel*)avModel
99 100 101 102 103 104
{
    if (self =  [self initWithWindowNibName:nibNameOrNil])
    {
        self.accountModel = accountModel;
        self.dataTransferModel = dataTransferModel;
        self.behaviorController = behaviorController;
105
        self.avModel = avModel;
106 107
        self.avModel->useAVFrame(YES);
        avModel->deactivateOldVideoModels();
108 109 110 111
    }
    return self;
}

Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
112 113 114 115 116 117 118
- (NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions
{
    return (NSApplicationPresentationFullScreen |
            NSApplicationPresentationAutoHideMenuBar |
            NSApplicationPresentationAutoHideToolbar);
}

119 120 121 122 123 124
-(void)changeViewTo:(ViewState) state  {
    switch (state) {
        case SHOW_WELCOME_SCREEN:
            [self accountSettingsShouldOpen: NO];
            [conversationVC hideWithAnimation:false];
            [currentCallVC hideWithAnimation:false];
Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
125
            [currentCallVC cleanUp];
126 127 128 129 130 131 132 133 134
            [currentCallVC.view removeFromSuperview];
            [welcomeContainer setHidden: NO];
            [smartViewVC.view setHidden: NO];
            [settingsVC hide];
            break;
        case SHOW_CONVERSATION_SCREEN:
            [self accountSettingsShouldOpen: NO];
            [conversationVC showWithAnimation:false];
            [currentCallVC hideWithAnimation:false];
Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
135
            [currentCallVC cleanUp];
136 137 138 139 140 141
            [currentCallVC.view removeFromSuperview];
            [welcomeContainer setHidden: YES];
            [smartViewVC.view setHidden: NO];
            [settingsVC hide];
            break;
        case SHOW_CALL_SCREEN:
142
            self.avModel->useAVFrame(YES);
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
            [self accountSettingsShouldOpen: NO];
            if (![currentCallVC.view superview]) {
            [callView addSubview:[currentCallVC view] positioned:NSWindowAbove relativeTo:nil];
            [currentCallVC initFrame];
            [currentCallVC showWithAnimation:false];
            [conversationVC hideWithAnimation:false];
            [welcomeContainer setHidden: YES];
            [smartViewVC.view setHidden: NO];
            [settingsVC hide];
            }
            [currentCallVC showWithAnimation:false];
            break;
        case SHOW_SETTINGS_SCREEN:
            @try {
                [self accountSettingsShouldOpen: YES];
            }
            @catch (NSException *ex) {
                return;
            }
            [welcomeContainer setHidden: YES];
            [currentCallVC hideWithAnimation:false];
            [currentCallVC.view removeFromSuperview];
            [conversationVC hideWithAnimation:false];
            [smartViewVC.view setHidden: YES];
            [settingsVC show];
            break;
169 170 171 172
        case LEAVE_MESSAGE:
            [conversationVC showWithAnimation: false];
            [currentCallVC hideWithAnimation: false];
            [conversationVC presentLeaveMessageView];
173 174 175 176 177
        default:
            break;
    }
}

178 179
- (void)windowDidLoad {
    [super windowDidLoad];
180
    [self.window setMovableByWindowBackground:YES];
Alexandre Lision's avatar
Alexandre Lision committed
181

182
    self.window.titleVisibility = NSWindowTitleHidden;
183

184
    currentCallVC = [[CurrentCallVC alloc] initWithNibName:@"CurrentCall" bundle:nil];
185
    currentCallVC.delegate = self;
186
    conversationVC = [[ConversationVC alloc] initWithNibName:@"Conversation" bundle:nil delegate:self aVModel:self.avModel];
Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
187
    [chooseAccountVC updateWithDelegate: self andModel:self.accountModel];
188
    settingsVC = [[AccountSettingsVC alloc] initWithNibName:@"AccountSettings" bundle:nil accountmodel:self.accountModel];
Alexandre Lision's avatar
Alexandre Lision committed
189
    [callView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
190
    [[currentCallVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
191
    [[conversationVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
192
    [[settingsVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
Alexandre Lision's avatar
Alexandre Lision committed
193

194
    [callView addSubview:[conversationVC view] positioned:NSWindowAbove relativeTo:nil];
195
    [self.window.contentView addSubview:[settingsVC view] positioned:NSWindowAbove relativeTo:nil];
Alexandre Lision's avatar
Alexandre Lision committed
196

197
    [conversationVC initFrame];
198
    [settingsVC initFrame];
199 200 201 202 203 204
    @try {
        [smartViewVC setConversationModel: [chooseAccountVC selectedAccount].conversationModel.get()];
    }
    @catch (NSException *ex) {
        NSLog(@"Caught exception %@: %@", [ex name], [ex reason]);
    }
205

206 207 208
    // Fresh run, we need to make sure RingID appears
    [shareButton sendActionOn:NSLeftMouseDownMask];

209
    [self connect];
210
    [self updateRingID];
211
    // set download folder (default - 'Documents')
212 213
    NSString* path = [[NSUserDefaults standardUserDefaults] stringForKey:Preferences::DownloadFolder];
    if (!path || path.length == 0) {
214 215
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        path = [[paths objectAtIndex:0] stringByAppendingString:@"/"];
216
    }
217
    self.dataTransferModel->downloadDirectory = std::string([path UTF8String]);
218 219
    if(appSandboxed()) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
220
        media::RecordingModel::instance().setRecordPath(QString::fromNSString([paths objectAtIndex:0]));
221
    }
Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
222 223
    NSToolbar *tb = [[self window] toolbar];
    [tb setAllowsUserCustomization:NO];
224 225 226 227 228

    //add messages view controller to responders chain
    NSResponder * viewNextResponder = [self nextResponder];
    [self setNextResponder: [conversationVC getMessagesView]];
    [[conversationVC getMessagesView] setNextResponder: viewNextResponder];
229 230 231 232
}

- (void) connect
{
233
    QObject::connect(self.behaviorController,
234 235 236
                     &lrc::api::BehaviorController::showCallView,
                     [self](const std::string accountId,
                            const lrc::api::conversation::Info convInfo){
237
                         auto* accInfo = &self.accountModel->getAccountInfo(accountId);
238 239 240 241 242
                         if (accInfo->contactModel->getContact(convInfo.participants[0]).profileInfo.type == lrc::api::profile::Type::PENDING)
                             [smartViewVC selectPendingList];
                         else
                             [smartViewVC selectConversationList];

243 244
                         [currentCallVC setCurrentCall:convInfo.callId
                                          conversation:convInfo.uid
245 246
                                               account:accInfo
                                               avModel: avModel];
247 248
                         [self changeViewTo:SHOW_CALL_SCREEN];

249
                     });
250

251
    QObject::connect(self.behaviorController,
252 253 254
                     &lrc::api::BehaviorController::showIncomingCallView,
                     [self](const std::string accountId,
                            const lrc::api::conversation::Info convInfo){
255
                         auto* accInfo = &self.accountModel->getAccountInfo(accountId);
256 257 258 259 260
                         if (accInfo->contactModel->getContact(convInfo.participants[0]).profileInfo.type == lrc::api::profile::Type::PENDING)
                             [smartViewVC selectPendingList];
                         else
                             [smartViewVC selectConversationList];

261 262
                         [currentCallVC setCurrentCall:convInfo.callId
                                          conversation:convInfo.uid
263 264
                                               account:accInfo
                                               avModel: avModel];
265
                         [smartViewVC selectConversation: convInfo model:accInfo->conversationModel.get()];
266
                         [self changeViewTo:SHOW_CALL_SCREEN];
267
                     });
268

269
    QObject::connect(self.behaviorController,
270 271 272
                     &lrc::api::BehaviorController::showChatView,
                     [self](const std::string& accountId,
                            const lrc::api::conversation::Info& convInfo){
273
                         auto& accInfo = self.accountModel->getAccountInfo(accountId);
274
                         [conversationVC setConversationUid:convInfo.uid model:accInfo.conversationModel.get()];
275
                         [smartViewVC selectConversation: convInfo model:accInfo.conversationModel.get()];
276
                         [self changeViewTo:SHOW_CONVERSATION_SCREEN];
277
                     });
278 279 280 281 282 283 284 285 286
    QObject::connect(self.behaviorController,
                     &lrc::api::BehaviorController::showLeaveMessageView,
                     [self](const std::string& accountId,
                            const lrc::api::conversation::Info& convInfo){
                         auto& accInfo = self.accountModel->getAccountInfo(accountId);
                         [conversationVC setConversationUid:convInfo.uid model:accInfo.conversationModel.get()];
                         [smartViewVC selectConversation: convInfo model:accInfo.conversationModel.get()];
                         [self changeViewTo:LEAVE_MESSAGE];
                     });
287 288 289 290 291 292 293 294
}

/**
 * Implement the necessary logic to choose which Ring ID to display.
 * This tries to choose the "best" ID to show
 */
- (void) updateRingID
{
295 296 297 298 299 300
    @try {
        auto& account = [chooseAccountVC selectedAccount];

        [ringIDLabel setStringValue:@""];

        if(account.profileInfo.type != lrc::api::profile::Type::RING) {
301 302
            self.notRingAccount = YES;
            self.isSIPAccount = YES;
303 304
            return;
        }
305 306 307
        self.isSIPAccount = NO;
        self.notRingAccount = NO;
        [ringLabelTrailingConstraint setActive:YES];
308 309 310 311 312
        auto& registeredName = account.registeredName;
        auto& ringID = account.profileInfo.uri;
        NSString* uriToDisplay = nullptr;
        if (!registeredName.empty()) {
            uriToDisplay = @(registeredName.c_str());
313
            [explanationLabel setStringValue: NSLocalizedString(@"This is your Jami username. \nCopy and share it with your friends!", @"Explanation label when user have Jami username")];
314 315
        } else {
            uriToDisplay = @(ringID.c_str());
316
            [explanationLabel setStringValue: NSLocalizedString(@"This is your ID. \nCopy and share it with your friends!", @"Explanation label when user have just ID")];
317 318 319
        }
        [ringIDLabel setStringValue:uriToDisplay];
        [self drawQRCode:@(ringID.c_str())];
320
    }
321 322
    @catch (NSException *ex) {
        NSLog(@"Caught exception %@: %@", [ex name], [ex reason]);
323 324 325
        self.notRingAccount = YES;
        self.isSIPAccount = NO;
        [ringLabelTrailingConstraint setActive:NO];
326
        [ringIDLabel setStringValue:NSLocalizedString(@"No account available", @"Displayed as RingID when no accounts are available for selection")];
327
    }
328 329
}

330 331
- (IBAction)shareRingID:(id)sender {
    NSSharingServicePicker* sharingServicePicker = [[NSSharingServicePicker alloc] initWithItems:[NSArray arrayWithObject:[ringIDLabel stringValue]]];
332
    [sharingServicePicker setDelegate:self];
333 334 335 336 337
    [sharingServicePicker showRelativeToRect:[sender bounds]
                                      ofView:sender
                               preferredEdge:NSMinYEdge];
}

338 339
- (IBAction)toggleQRCode:(id)sender {
    // Toggle pressed state of QRCode button
340 341 342
  //  [sender setPressed:![sender isPressed]];
    bool show = qrcodeView.animator.alphaValue == 0.0f ? YES: NO;
    [self showQRCode: show];
343 344 345 346 347
}

/**
 * Draw the QRCode in the qrCodeView
 */
348
- (void)drawQRCode:(NSString*) uriToDraw
349
{
350
    auto qrCode = QRcode_encodeString(uriToDraw.UTF8String,
351 352 353 354 355 356 357 358
                                      0,
                                      QR_ECLEVEL_L, // Lowest level of error correction
                                      QR_MODE_8, // 8-bit data mode
                                      1);
    if (!qrCode) {
        return;
    }

359 360 361 362 363 364
    unsigned char *data = 0;
    int width;
    data = qrCode->data;
    width = qrCode->width;
    int qr_margin = 3;

365 366 367 368 369 370 371 372 373 374
    CGFloat size = qrcodeView.frame.size.width;

    // create context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(0, size, size, 8, size * 4, colorSpace, kCGImageAlphaPremultipliedLast);

    CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(0, -size);
    CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1, -1);
    CGContextConcatCTM(ctx, CGAffineTransformConcat(translateTransform, scaleTransform));

375
    float zoom = ceil((double)size / (qrCode->width + 2.0 * qr_margin));
376 377 378 379 380 381
    CGRect rectDraw = CGRectMake(0, 0, zoom, zoom);

    int ran;
    for(int i = 0; i < width; ++i) {
        for(int j = 0; j < width; ++j) {
            if(*data & 1) {
382
                CGContextSetFillColorWithColor(ctx, [NSColor labelColor].CGColor);
383 384 385 386 387 388 389 390 391 392 393 394
                rectDraw.origin = CGPointMake((j + qr_margin) * zoom,(i + qr_margin) * zoom);
                CGContextAddRect(ctx, rectDraw);
                CGContextFillPath(ctx);
            } else {
                CGContextSetFillColorWithColor(ctx, [NSColor windowBackgroundColor].CGColor);
                rectDraw.origin = CGPointMake((j + qr_margin) * zoom,(i + qr_margin) * zoom);
                CGContextAddRect(ctx, rectDraw);
                CGContextFillPath(ctx);
            }
            ++data;
        }
    }
395 396 397 398 399 400 401 402 403 404 405 406

    // get image
    auto qrCGImage = CGBitmapContextCreateImage(ctx);
    auto qrImage = [[NSImage alloc] initWithCGImage:qrCGImage size:qrcodeView.frame.size];

    // some releases
    CGContextRelease(ctx);
    CGImageRelease(qrCGImage);
    CGColorSpaceRelease(colorSpace);
    QRcode_free(qrCode);

    [qrcodeView setImage:qrImage];
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
}

/**
 * Start the in/out animation displaying the QRCode
 * @param show should the QRCode be animated in or out
 */
- (void) showQRCode:(BOOL) show
{
    static const NSInteger offset = 110;
    [NSAnimationContext beginGrouping];
    NSAnimationContext.currentContext.duration = 0.5;
    [[NSAnimationContext currentContext] setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
    qrcodeView.animator.alphaValue = show ? 1.0 : 0.0;
    [centerYQRCodeConstraint.animator setConstant: show ? offset : 0];
    [centerYWelcomeContainerConstraint.animator setConstant:show ? -offset : 0];
    [NSAnimationContext endGrouping];
}

425 426
- (IBAction)openPreferences:(id)sender
{
427 428 429 430
    if (preferencesWC) {
        [preferencesWC.window orderFront:preferencesWC.window];
        return;
    }
431

432
    preferencesWC = [[PreferencesWC alloc] initWithWindowNibName: @"PreferencesWindow" bundle: nil accountModel:self.accountModel dataTransferModel:self.dataTransferModel behaviourController:self.behaviorController avModel: self.avModel];
433
    [preferencesWC.window makeKeyAndOrderFront:preferencesWC.window];
434
}
435

436 437 438 439 440 441 442 443 444 445 446 447
- (IBAction)callClickedAtRow:(id)sender
{
    NSTabViewItem *selectedTab = [smartViewVC.tabbar selectedTabViewItem];
    int index = [smartViewVC.tabbar indexOfTabViewItem:selectedTab];
    switch (index) {
        case 0:
            [smartViewVC startCallForRow:sender];
            break;
        default:
            break;
    }
}
448

449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
#pragma mark - Ring account migration

- (void) migrateRingAccount:(Account*) acc
{
    self.migrateWC = [[MigrateRingAccountsWC alloc] initWithDelegate:self actionCode:1];
    self.migrateWC.account = acc;
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_9
    [self.window beginSheet:self.migrateWC.window completionHandler:nil];
#else
    [NSApp beginSheet: self.migrateWC.window
       modalForWindow: self.window
        modalDelegate: self
       didEndSelector: nil
          contextInfo: nil];
#endif
}

466
// TODO: Reimplement as a blocking loop when new LRC models handle migration
467 468 469 470 471 472 473 474 475 476 477
- (void)checkAccountsToMigrate
{
    auto ringList = AccountModel::instance().accountsToMigrate();
    if (ringList.length() > 0){
        Account* acc = ringList.value(0);
        [self migrateRingAccount:acc];
    } else {
        // Fresh run, we need to make sure RingID appears
        [shareButton sendActionOn:NSLeftMouseDownMask];

        [self connect];
478
        [self updateRingID];
479 480 481 482 483 484 485 486 487 488 489 490 491
    }
}

- (void)migrationDidComplete
{
    [self checkAccountsToMigrate];
}

- (void)migrationDidCompleteWithError
{
    [self checkAccountsToMigrate];
}

492
- (void) selectAccount:(const lrc::api::account::Info&)accInfo currentRemoved:(BOOL) removed
493 494
{
    // If the selected account has been changed, we close any open panel
495
    [smartViewVC setConversationModel:accInfo.conversationModel.get()];
496 497
    // Welcome view informations are also updated
    [self updateRingID];
498
    [settingsVC setSelectedAccount:accInfo.id];
499
    [self changeViewTo: ([settingsVC.view isHidden] || removed)  ?  SHOW_WELCOME_SCREEN : SHOW_SETTINGS_SCREEN];
500 501
}

502 503 504
-(void)allAccountsDeleted
{
    [smartViewVC clearConversationModel];
505
    [self changeViewTo:SHOW_WELCOME_SCREEN];
506
    [self updateRingID];
507 508 509 510 511 512
    qrcodeView.animator.alphaValue = 0.0;
    [centerYQRCodeConstraint.animator setConstant: 0];
    [centerYWelcomeContainerConstraint.animator setConstant: 0];
    [self close];
    AppDelegate* delegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
    [delegate showWizard];
513 514
}

515 516 517
-(void)rightPanelClosed
{
    [smartViewVC deselect];
518
    [welcomeContainer setHidden:NO];
519 520
}

521 522 523 524 525
-(void)currentConversationTrusted
{
    [smartViewVC selectConversationList];
}

526
-(void) listTypeChanged {
527
    [self changeViewTo:SHOW_WELCOME_SCREEN];
528 529
}

530 531
- (IBAction)openAccountSettings:(NSButton *)sender
{
532
    [self changeViewTo: [settingsVC.view isHidden] ?  SHOW_SETTINGS_SCREEN : SHOW_WELCOME_SCREEN];
533 534
}

535
- (void) createNewAccount {
536
    [self changeViewTo:SHOW_WELCOME_SCREEN];
537 538 539
    wizard = [[RingWizardWC alloc] initWithNibName:@"RingWizard" bundle: nil accountmodel: self.accountModel];
    [wizard showChooseWithCancelButton: YES andAdvanced: YES];
    [self.window beginSheet:wizard.window completionHandler:nil];
540 541
}

Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
542 543 544 545 546 547 548 549
- (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet
       usingRect:(NSRect)rect
{
    float titleBarHeight = self.window.frame.size.height - [NSWindow contentRectForFrameRect:self.window.frame styleMask:self.window.styleMask].size.height;
    rect.origin.y = self.window.frame.size.height;
    return rect;
}

550 551
-(void) accountSettingsShouldOpen: (BOOL) open {
    if (open) {
552
        [settingsVC setSelectedAccount: [chooseAccountVC selectedAccount].id];
553
    }
554 555
}

556 557 558 559 560 561
#pragma mark - CallViewControllerDelegate

-(void) conversationInfoUpdatedFor:(const std::string&) conversationID {
    [smartViewVC reloadConversationWithUid:@(conversationID.c_str())];
}

Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
-(void) showConversation:(NSString* )conversationId forAccount:(NSString*)accountId {
    auto& accInfo = self.accountModel->getAccountInfo([accountId UTF8String]);
    [chooseAccountVC selectAccount: accountId];
    [settingsVC setSelectedAccount: [accountId UTF8String]];
    [smartViewVC setConversationModel:accInfo.conversationModel.get()];
    [smartViewVC selectConversationList];
    [self updateRingID];
    auto convInfo = getConversationFromUid([conversationId UTF8String], *accInfo.conversationModel.get());
    auto convQueue = accInfo.conversationModel.get()->allFilteredConversations();
    if (convInfo != convQueue.end()) {
        [conversationVC setConversationUid:convInfo->uid model:accInfo.conversationModel.get()];
        [smartViewVC selectConversation: *convInfo model:accInfo.conversationModel.get()];
        accInfo.conversationModel.get()->clearUnreadInteractions([conversationId UTF8String]);
    }
    [self changeViewTo:SHOW_CONVERSATION_SCREEN];
}

-(void) showCall:(NSString* )callId forAccount:(NSString*)accountId forConversation:(NSString*)conversationId {
    auto& accInfo = self.accountModel->getAccountInfo([accountId UTF8String]);
    [chooseAccountVC selectAccount: accountId];
    [settingsVC setSelectedAccount:accInfo.id];
    [smartViewVC setConversationModel:accInfo.conversationModel.get()];
    [self updateRingID];
    auto convInfo = getConversationFromUid([conversationId UTF8String], *accInfo.conversationModel.get());
    auto convQueue = accInfo.conversationModel.get()->allFilteredConversations();
    if (convInfo != convQueue.end()) {
        if (accInfo.contactModel->getContact(convInfo->participants[0]).profileInfo.type == lrc::api::profile::Type::PENDING)
            [smartViewVC selectPendingList];
        else
            [smartViewVC selectConversationList];
        [smartViewVC selectConversation: *convInfo model:accInfo.conversationModel.get()];
    }
    [currentCallVC setCurrentCall:[callId UTF8String]
                     conversation:[conversationId UTF8String]
596 597
                          account:&accInfo
                          avModel:avModel];
Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
    [self changeViewTo:SHOW_CALL_SCREEN];
}

-(void) showContactRequestFor:(NSString* )accountId contactUri:(NSString*)uri {
    auto& accInfo = self.accountModel->getAccountInfo([accountId UTF8String]);
    [chooseAccountVC selectAccount: accountId];
    [settingsVC setSelectedAccount:accInfo.id];
    [smartViewVC setConversationModel:accInfo.conversationModel.get()];
    [self updateRingID];
    [smartViewVC selectPendingList];
    auto convInfo = getConversationFromURI([uri UTF8String], *accInfo.conversationModel.get());
    auto convQueue = accInfo.conversationModel.get()->allFilteredConversations();
    if (convInfo != convQueue.end()) {
        [conversationVC setConversationUid:convInfo->uid model:accInfo.conversationModel.get()];
        [smartViewVC selectConversation: *convInfo model:accInfo.conversationModel.get()];
    }
    [self changeViewTo:SHOW_CONVERSATION_SCREEN];
}
616 617 618 619 620

- (BOOL)windowShouldClose:(id)sender {
    [NSApp hide:nil];
    return NO;
}
621
@end