From 49cb29183666195f81144c1b8f7ea65d6748f094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anthony=20L=C3=A9onard?= Date: Mon, 13 Nov 2017 16:15:39 -0500 Subject: [PATCH] reimplement ChooseAccountVC with new account model This controller is in charge of the account selector shown at the top right of the client. It now uses the new account model in LRC to display account available on the machine. As the account selection is now to be managed on client instead of LRC, a lot has changed in the AccountSelectionManager too. Finally, RingWindowController gives a reference of the account model to the ChooseAccountVC has we don't use singleton that are accessible from anywhere anymore. Change-Id: I5c320923cd561dc44f600d388793a338af89adfd Reviewed-by: Guillaume Roguez --- src/AccountSelectionManager.h | 17 ++- src/AccountSelectionManager.mm | 82 ++++++--------- src/ChooseAccountVC.h | 15 +++ src/ChooseAccountVC.mm | 143 +++++++++++++------------- src/RingWindowController.mm | 33 ++++-- ui/Base.lproj/AccountMenuItemView.xib | 14 +-- 6 files changed, 163 insertions(+), 141 deletions(-) diff --git a/src/AccountSelectionManager.h b/src/AccountSelectionManager.h index 43861a31..8a5da223 100644 --- a/src/AccountSelectionManager.h +++ b/src/AccountSelectionManager.h @@ -1,6 +1,8 @@ /* * Copyright (C) 2015-2017 Savoir-faire Linux Inc. * Author: Kateryna Kostiuk + * Author: Olivier Soldano + * Author: Anthony Léonard * * 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 @@ -19,9 +21,20 @@ #import +namespace lrc { + namespace api { + class NewAccountModel; + + namespace account { + struct Info; + } + } +} + @interface AccountSelectionManager : NSObject -- (void) saveAccountWithIndex:(QModelIndex )index; -- (void) selectChosenAccount; +@property const lrc::api::account::Info& savedAccount; + +- (id) initWithAccountModel:(const lrc::api::NewAccountModel*) accMdl; @end diff --git a/src/AccountSelectionManager.mm b/src/AccountSelectionManager.mm index 335db25c..f3e4a961 100644 --- a/src/AccountSelectionManager.mm +++ b/src/AccountSelectionManager.mm @@ -1,6 +1,8 @@ /* * Copyright (C) 2015-2017 Savoir-faire Linux Inc. * Author: Kateryna Kostiuk + * Author: Olivier Soldano + * Author: Anthony Léonard * * 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 @@ -18,67 +20,45 @@ */ // LRC -#import -#import -#import -#import +#import +#import #import "AccountSelectionManager.h" -@implementation AccountSelectionManager +@implementation AccountSelectionManager { + + const lrc::api::NewAccountModel* accMdl_; + +} NSString* const savedUserAccountKey = @"savedUserSelectedAccountKey"; -- (void) saveAccountWithIndex:(QModelIndex )index { - if(!index.isValid()) { - return; - } - QByteArray accountID = index.data(static_cast(Account::Role::Id)).toByteArray(); - if (accountID.isEmpty()) { - return; - } - NSString* accountToNSString = QString::QString(accountID).toNSString(); - [[NSUserDefaults standardUserDefaults] setObject:accountToNSString forKey:savedUserAccountKey]; +- (id) initWithAccountModel:(const lrc::api::NewAccountModel*) accMdl { + accMdl_ = accMdl; + return [self init]; } +- (void) saveAccountWithId:(NSString*)accId +{ + [[NSUserDefaults standardUserDefaults] setObject:accId forKey:savedUserAccountKey]; +} -- (void) selectChosenAccount { - NSString* savedAccount = [[NSUserDefaults standardUserDefaults] stringForKey:savedUserAccountKey]; - if(!savedAccount || savedAccount.length <= 0) { - return; - } - const char* secondName = [savedAccount UTF8String]; - QByteArray assountToarray = QByteArray::QByteArray(secondName); - if (strlen(assountToarray) <= 0) { - return; - } - if (!(AccountModel::instance().getById(assountToarray))) { - return; - } - auto account = AccountModel::instance().getById(assountToarray); - QModelIndex savedIndex = QModelIndex::QModelIndex(); - // first try to get saved account - savedIndex = AvailableAccountModel::instance().mapFromSource(account->index()); - if (savedIndex.isValid()) { - AvailableAccountModel::instance().selectionModel()->setCurrentIndex(savedIndex, QItemSelectionModel::ClearAndSelect); - return; - } - // if account is not saved, try to select RING account - if (auto account = AvailableAccountModel::instance().currentDefaultAccount(URI::SchemeType::RING)) { - savedIndex = AvailableAccountModel::instance().mapFromSource(account->index()); - } - if (savedIndex.isValid()) { - AvailableAccountModel::instance().selectionModel()->setCurrentIndex(savedIndex, QItemSelectionModel::ClearAndSelect); - return; - } - // if no RING account try to select SIP - if (auto account = AvailableAccountModel::instance().currentDefaultAccount(URI::SchemeType::SIP)) { - savedIndex = AvailableAccountModel::instance().mapFromSource(account->index()); +- (NSString*) getSavedAccountId +{ + return [[NSUserDefaults standardUserDefaults] stringForKey:savedUserAccountKey]; +} - } - if (savedIndex.isValid()) { - AvailableAccountModel::instance().selectionModel()->setCurrentIndex(savedIndex, QItemSelectionModel::ClearAndSelect); - } +- (const lrc::api::account::Info&) savedAccount +{ + return accMdl_->getAccountInfo(std::string([[self getSavedAccountId] UTF8String])); +} + +- (void) setSavedAccount:(const lrc::api::account::Info&) acc +{ + if (acc.profileInfo.type == lrc::api::profile::Type::INVALID) + return; + else + saveAccountWithId:@(acc.id.c_str()); } @end diff --git a/src/ChooseAccountVC.h b/src/ChooseAccountVC.h index a0384e91..b6a66cbe 100644 --- a/src/ChooseAccountVC.h +++ b/src/ChooseAccountVC.h @@ -1,6 +1,8 @@ /* * Copyright (C) 2015-2017 Savoir-faire Linux Inc. * Author: Kateryna Kostiuk + * Author: Olivier Soldano + * Author: Anthony Léonard * * 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 @@ -19,9 +21,22 @@ #import +namespace lrc { + namespace api { + class NewAccountModel; + + namespace account { + struct Info; + } + } +} + @interface ChooseAccountVC : NSViewController +@property (readonly) const lrc::api::account::Info& selectedAccount; + -(void) enable; -(void) disable; +-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil model:(const lrc::api::NewAccountModel*) accMdl; @end diff --git a/src/ChooseAccountVC.mm b/src/ChooseAccountVC.mm index 450e69bb..bc7df0e8 100644 --- a/src/ChooseAccountVC.mm +++ b/src/ChooseAccountVC.mm @@ -1,6 +1,8 @@ /* * Copyright (C) 2015-2017 Savoir-faire Linux Inc. * Author: Kateryna Kostiuk + * Author: Olivier Soldano + * Author: Anthony Léonard * * 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 @@ -25,15 +27,11 @@ #import //LRC -#import -#import -#import #import -#import -#import #import #import -#import +#import +#import //RING #import "views/AccountMenuItemView.h" @@ -47,73 +45,73 @@ __unsafe_unretained IBOutlet NSImageView* profileImage; __unsafe_unretained IBOutlet NSPopUpButton* accountSelectionButton; + const lrc::api::NewAccountModel* accMdl_; + AccountSelectionManager* accountSelectionManager_; } Boolean menuIsOpen; Boolean menuNeedsUpdate; NSMenu* accountsMenu; NSMenuItem* selectedMenuItem; -QMetaObject::Connection accountUpdate; -QMetaObject::Connection personUpdate; -AccountSelectionManager* accountManager; + +-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil model:(const lrc::api::NewAccountModel*) accMdl +{ + accMdl_ = accMdl; + accountSelectionManager_ = [[AccountSelectionManager alloc] initWithAccountModel:accMdl_]; + return [self initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; +} - (void)awakeFromNib { [profileImage setWantsLayer: YES]; profileImage.layer.cornerRadius = profileImage.frame.size.width / 2; profileImage.layer.masksToBounds = YES; - accountManager = [[AccountSelectionManager alloc] init]; - - if (ProfileModel::instance().selectedProfile() && ProfileModel::instance().selectedProfile()->person()) { - Person* person = ProfileModel::instance().selectedProfile()->person(); - auto photo = GlobalInstances::pixmapManipulator().contactPhoto(person, {140,140}); - [profileImage setImage:QtMac::toNSImage(qvariant_cast(photo))]; - QObject::disconnect(personUpdate); - personUpdate = QObject::connect(person, - &Person::changed, - [=] { - //give time to cach to be updated and then change image - dispatch_time_t updateTime = dispatch_time(DISPATCH_TIME_NOW, 1); - dispatch_after(updateTime, dispatch_get_main_queue(), ^(void){ - auto photo = GlobalInstances::pixmapManipulator().contactPhoto(person, {140,140}); - [profileImage setImage:QtMac::toNSImage(qvariant_cast(photo))]; - }); - }); - } accountsMenu = [[NSMenu alloc] initWithTitle:@""]; [accountsMenu setDelegate:self]; accountSelectionButton.menu = accountsMenu; [self update]; - QObject::disconnect(accountUpdate); - accountUpdate = QObject::connect(&AccountModel::instance(), - &AccountModel::dataChanged, - [=] { + QObject::connect(accMdl_, + &lrc::api::NewAccountModel::accountAdded, + [self]{ [self update]; }); - QObject::connect(AvailableAccountModel::instance().selectionModel(), - &QItemSelectionModel::currentChanged, - [self](const QModelIndex& idx){ - if(!idx.isValid()) { - return; - } - [accountManager saveAccountWithIndex:idx]; + QObject::connect(accMdl_, + &lrc::api::NewAccountModel::accountRemoved, + [self]{ [self update]; }); - QObject::connect(&AvailableAccountModel::instance(), - &QAbstractItemModel::rowsRemoved, + QObject::connect(accMdl_, + &lrc::api::NewAccountModel::profileUpdated, [self]{ [self update]; }); } +-(const lrc::api::account::Info&) selectedAccount +{ + const auto& account = [accountSelectionManager_ savedAccount]; + if(account.profileInfo.type == lrc::api::profile::Type::INVALID){ + try { + auto accountId = accMdl_->getAccountList().at(0); + const auto& fallbackAccount = accMdl_->getAccountInfo(accMdl_->getAccountList().at(0)); + return fallbackAccount; + } catch (std::out_of_range& e) { // Is thrown if account model has no account. We then return an invalid account + return account; + } + } + return account; +} + -(void) updateMenu { [accountsMenu removeAllItems]; - for (int i = 0; i < AvailableAccountModel::instance().rowCount(); i++) { - QModelIndex index = AvailableAccountModel::instance().selectionModel()->model()->index(i, 0); - Account* account = index.data(static_cast(Account::Role::Object)).value(); + auto accList = accMdl_->getAccountList(); + + for (std::string accId : accList) { + auto& account = accMdl_->getAccountInfo(accId); + NSMenuItem* menuBarItem = [[NSMenuItem alloc] initWithTitle:[self itemTitleForAccount:account] action:NULL @@ -121,40 +119,45 @@ AccountSelectionManager* accountManager; menuBarItem.attributedTitle = [self attributedItemTitleForAccount:account]; AccountMenuItemView *itemView = [[AccountMenuItemView alloc] initWithFrame:CGRectZero]; - [itemView.accountLabel setStringValue:account->alias().toNSString()]; + [itemView.accountLabel setStringValue:@(account.profileInfo.alias.c_str())]; NSString* userNameString = [self nameForAccount: account]; [itemView.userNameLabel setStringValue:userNameString]; - switch (account->protocol()) { - case Account::Protocol::SIP: + switch (account.profileInfo.type) { + case lrc::api::profile::Type::SIP: [itemView.accountTypeLabel setStringValue:@"SIP"]; break; - case Account::Protocol::RING: + case lrc::api::profile::Type::RING: [itemView.accountTypeLabel setStringValue:@"RING"]; break; default: break; } - auto humanState = account->toHumanStateName(); - [itemView.accountStatus setStringValue:humanState.toNSString()]; + [menuBarItem setView:itemView]; [accountsMenu addItem:menuBarItem]; [accountsMenu addItem:[NSMenuItem separatorItem]]; } } --(NSString*) nameForAccount:(Account*) account { - auto name = account->registeredName(); - NSString* userNameString = nullptr; - if (!name.isNull() && !name.isEmpty()) { - userNameString = name.toNSString(); - } else { - userNameString = account->username().toNSString(); - } - return userNameString; +-(void) updatePhoto +{ + auto& account = [self selectedAccount]; + if(account.profileInfo.type == lrc::api::profile::Type::INVALID) + return; + + QByteArray ba = QByteArray::fromStdString(account.profileInfo.avatar); + + QVariant photo = GlobalInstances::pixmapManipulator().personPhoto(ba); + [profileImage setImage:QtMac::toNSImage(qvariant_cast(photo))]; +} + +-(NSString*) nameForAccount:(const lrc::api::account::Info&) account { + auto name = account.registeredName; + return @(name.c_str()); } --(NSString*) itemTitleForAccount:(Account*) account { - NSString* alias = account->alias().toNSString(); +-(NSString*) itemTitleForAccount:(const lrc::api::account::Info&) account { + NSString* alias = @(account.profileInfo.alias.c_str()); NSString* userNameString = [self nameForAccount: account]; if([userNameString length] > 0) { alias = [NSString stringWithFormat: @"%@\n", alias]; @@ -162,8 +165,8 @@ AccountSelectionManager* accountManager; return [alias stringByAppendingString:userNameString]; } -- (NSAttributedString*) attributedItemTitleForAccount:(Account*) account { - NSString* alias = account->alias().toNSString(); +- (NSAttributedString*) attributedItemTitleForAccount:(const lrc::api::account::Info&) account { + NSString* alias = @(account.profileInfo.alias.c_str()); NSString* userNameString = [self nameForAccount: account]; if([userNameString length] > 0){ alias = [NSString stringWithFormat: @"%@\n", alias]; @@ -193,6 +196,7 @@ AccountSelectionManager* accountManager; return; } [self updateMenu]; + [self updatePhoto]; [self setPopUpButtonSelection]; } @@ -202,9 +206,8 @@ AccountSelectionManager* accountManager; return; } [self.view setHidden:NO]; - QModelIndex index = AvailableAccountModel::instance().selectionModel()->currentIndex(); - Account* account = index.data(static_cast(Account::Role::Object)).value(); - if(account == nil){ + auto& account = [self selectedAccount]; + if(account.profileInfo.type == lrc::api::profile::Type::INVALID){ return; } [accountSelectionButton selectItemWithTitle:[self itemTitleForAccount:account]]; @@ -214,12 +217,12 @@ AccountSelectionManager* accountManager; - (IBAction)itemChanged:(id)sender { NSInteger row = [(NSPopUpButton *)sender indexOfSelectedItem] / 2; - QModelIndex index = AvailableAccountModel::instance().selectionModel()->model()->index(row, 0); - if(!index.isValid()) { + auto accList = accMdl_->getAccountList(); + if (row >= accList.size()) return; - } - AvailableAccountModel::instance().selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); - [accountManager saveAccountWithIndex:index]; + + auto& account = accMdl_->getAccountInfo(accList[row]); + [accountSelectionManager_ setSavedAccount:account]; } #pragma mark - NSMenuDelegate diff --git a/src/RingWindowController.mm b/src/RingWindowController.mm index b1948a74..0febf3f0 100644 --- a/src/RingWindowController.mm +++ b/src/RingWindowController.mm @@ -33,6 +33,7 @@ #import #import #import +#import // Ring #import "AppDelegate.h" @@ -94,7 +95,7 @@ NSString* const kTrustRequestMenuItemIdentifier = @"TrustRequestMenuItemIde currentCallVC = [[CurrentCallVC alloc] initWithNibName:@"CurrentCall" bundle:nil]; offlineVC = [[ConversationVC alloc] initWithNibName:@"Conversation" bundle:nil]; // toolbar items - chooseAccountVC = [[ChooseAccountVC alloc] initWithNibName:@"ChooseAccount" bundle:nil]; + chooseAccountVC = [[ChooseAccountVC alloc] initWithNibName:@"ChooseAccount" bundle:nil model:&(lrc_->getAccountModel())]; contactRequestVC = [[ContactRequestVC alloc] initWithNibName:@"ContactRequest" bundle:nil]; [callView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [[currentCallVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; @@ -106,9 +107,18 @@ NSString* const kTrustRequestMenuItemIdentifier = @"TrustRequestMenuItemIde [currentCallVC initFrame]; [offlineVC initFrame]; - [self checkAccountsToMigrate]; + // Fresh run, we need to make sure RingID appears + [shareButton sendActionOn:NSLeftMouseDownMask]; + + [self updateRingID]; + // display accounts to select + NSToolbar *toolbar = self.window.toolbar; + toolbar.delegate = self; + [toolbar insertItemWithItemIdentifier:kChangeAccountToolBarItemIdentifier atIndex:1]; + [toolbar insertItemWithItemIdentifier:kTrustRequestMenuItemIdentifier atIndex:2]; } +// TODO: Reimplement with new LRC signals - (void) connect { // Update Ring ID label based on account model changes @@ -167,25 +177,25 @@ NSString* const kTrustRequestMenuItemIdentifier = @"TrustRequestMenuItemIde */ - (void) updateRingID { - Account* finalChoice = nullptr; + auto& account = [chooseAccountVC selectedAccount]; [ringIDLabel setStringValue:@""]; - QModelIndex index = AvailableAccountModel::instance().selectionModel()->currentIndex(); - finalChoice = index.data(static_cast(Account::Role::Object)).value(); - if(finalChoice == nil || (finalChoice->protocol() != Account::Protocol::RING)) { + + if(account.profileInfo.type != lrc::api::profile::Type::RING) { self.hideRingID = YES; return; } self.hideRingID = NO; - auto name = finalChoice->registeredName(); + auto& registeredName = account.registeredName; + auto& ringID = account.profileInfo.uri; NSString* uriToDisplay = nullptr; - if (!name.isNull() && !name.isEmpty()) { - uriToDisplay = name.toNSString(); + if (!registeredName.empty()) { + uriToDisplay = @(registeredName.c_str()); } else { - uriToDisplay = finalChoice->username().toNSString(); + uriToDisplay = @(ringID.c_str()); } [ringIDLabel setStringValue:uriToDisplay]; - [self drawQRCode:finalChoice->username().toNSString()]; + [self drawQRCode:@(ringID.c_str())]; } - (IBAction)shareRingID:(id)sender { @@ -320,6 +330,7 @@ NSString* const kTrustRequestMenuItemIdentifier = @"TrustRequestMenuItemIde #endif } +// TODO: Reimplement as a blocking loop when new LRC models handle migration - (void)checkAccountsToMigrate { auto ringList = AccountModel::instance().accountsToMigrate(); diff --git a/ui/Base.lproj/AccountMenuItemView.xib b/ui/Base.lproj/AccountMenuItemView.xib index d6c3ddcd..c5a39089 100644 --- a/ui/Base.lproj/AccountMenuItemView.xib +++ b/ui/Base.lproj/AccountMenuItemView.xib @@ -1,8 +1,8 @@ - + - - + + @@ -20,7 +20,7 @@ - + @@ -31,7 +31,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -53,7 +53,7 @@ - +