blob: 974d03255197d4d71be4511b996ccd58f2ba75b5 [file] [log] [blame]
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04001/*
Sébastien Blin029ffa82019-01-02 17:43:48 -05002 * Copyright (C) 2015-2019 Savoir-faire Linux Inc.
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20#import "AccRingGeneralVC.h"
21
22//cocoa
23#import <Quartz/Quartz.h>
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -040024#import <AVFoundation/AVFoundation.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040025
26
27//Qt
28#import <QSize>
29#import <QtMacExtras/qmacfunctions.h>
30#import <QPixmap>
31
32//LRC
33#import <api/lrc.h>
34#import <api/newaccountmodel.h>
35#import <api/newdevicemodel.h>
36#import <interfaces/pixmapmanipulatori.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040037
38#import "RegisterNameWC.h"
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040039#import "BackupAccountWC.h"
40#import "views/NSColor+RingTheme.h"
41#import "views/NSImage+Extensions.h"
42#import "views/HoverTableRowView.h"
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -050043#import "views/RoundedTextField.h"
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040044#import "ExportPasswordWC.h"
45#import "utils.h"
46
47@interface AccRingGeneralVC ()
48
49@property (unsafe_unretained) IBOutlet NSTextField *displayNameField;
50@property (unsafe_unretained) IBOutlet NSTextField *ringIDField;
51@property (unsafe_unretained) IBOutlet NSTextField *registeredNameField;
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -050052@property (unsafe_unretained) IBOutlet RoundedTextField *accountStatus;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040053@property (unsafe_unretained) IBOutlet NSButton *registerNameButton;
54@property (unsafe_unretained) IBOutlet NSButton* photoView;
55@property (unsafe_unretained) IBOutlet NSButton* passwordButton;
56@property (unsafe_unretained) IBOutlet NSButton* removeAccountButton;
57@property (unsafe_unretained) IBOutlet NSImageView* addProfilePhotoImage;
58@property (unsafe_unretained) IBOutlet NSTableView* devicesTableView;
59@property (unsafe_unretained) IBOutlet NSTableView* blockedContactsTableView;
60@property (assign) IBOutlet NSLayoutConstraint* buttonRegisterWidthConstraint;
61@property (assign) IBOutlet NSLayoutConstraint* bannedContactHeightConstraint;
62@property (assign) IBOutlet NSLayoutConstraint* advancedButtonMarginConstraint;
63
64
65@property AbstractLoadingWC* accountModal;
66@property PasswordChangeWC* passwordModal;
67@property std::string selectedAccountID;
68
69@end
70
71@implementation AccRingGeneralVC
72
73QMetaObject::Connection deviceAddedSignal;
74QMetaObject::Connection deviceRevokedSignal;
75QMetaObject::Connection deviceUpdatedSignal;
76QMetaObject::Connection contactBlockedSignal;
77QMetaObject::Connection bannedContactsChangedSignal;
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -050078QMetaObject::Connection accountStateChangedSignal;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040079
80
81@synthesize displayNameField;
82@synthesize ringIDField;
83@synthesize registeredNameField;
84@synthesize photoView;
85@synthesize addProfilePhotoImage;
86@synthesize accountModel;
87@synthesize registerNameButton, passwordButton, removeAccountButton;
88@synthesize buttonRegisterWidthConstraint;
89@synthesize accountModal;
90@synthesize delegate;
91@synthesize devicesTableView;
92@synthesize blockedContactsTableView;
93
94
95typedef NS_ENUM(NSInteger, TagViews) {
96 DISPLAYNAME = 100,
97 DEVICE_NAME_TAG = 200,
98 DEVICE_ID_TAG = 300,
99 DEVICE_EDIT_TAG = 400,
100 DEVICE_REVOKE_TAG = 500,
101 BANNED_CONTACT_NAME_TAG = 600,
102 BANNED_CONTACT_ID_TAG = 700,
103 UNBLOCK_CONTACT_TAG = 800
104};
105
106-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
107{
108 if (self = [self initWithNibName: nibNameOrNil bundle:nibBundleOrNil])
109 {
110 self.accountModel= accountModel;
111 }
112 return self;
113}
114
115- (void)awakeFromNib
116{
117 [super awakeFromNib];
Kateryna Kostiuk39ce23d2018-10-02 14:33:37 -0400118 [photoView setBordered:YES];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400119 [addProfilePhotoImage setWantsLayer: YES];
120 devicesTableView.delegate = self;
121 devicesTableView.dataSource = self;
122 blockedContactsTableView.delegate = self;
123 blockedContactsTableView.dataSource= self;
Kateryna Kostiuka8525942018-10-17 14:33:39 -0400124 [[self view] setAutoresizingMask: NSViewMinXMargin | NSViewMaxXMargin];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400125}
126
127- (void)viewDidLoad {
128 [super viewDidLoad];
129 [self updateView];
130}
131
132- (void) setSelectedAccount:(std::string) account {
133 self.selectedAccountID = account;
134 [self connectSignals];
135 [self updateView];
136 [self hideBannedContacts];
137}
138
139-(void) updateView {
140 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400141
Kateryna Kostiuk43a79232018-10-18 15:45:18 -0400142 NSData *imageData = [[NSData alloc] initWithBase64EncodedString:@(account.profileInfo.avatar.c_str()) options:NSDataBase64DecodingIgnoreUnknownCharacters];
143 NSImage *image = [[NSImage alloc] initWithData:imageData];
144 if(image) {
Kateryna Kostiuk39ce23d2018-10-02 14:33:37 -0400145 [photoView setBordered:NO];
Kateryna Kostiuk43a79232018-10-18 15:45:18 -0400146 [photoView setImage: [image roundCorners: 350]];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400147 [addProfilePhotoImage setHidden:YES];
148 } else {
149 [photoView setImage:nil];
Kateryna Kostiuk39ce23d2018-10-02 14:33:37 -0400150 [photoView setBordered:YES];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400151 [addProfilePhotoImage setHidden:NO];
152 }
153 NSString* displayName = @(account.profileInfo.alias.c_str());
154 [displayNameField setStringValue:displayName];
155 [ringIDField setStringValue:@(account.profileInfo.uri.c_str())];
156 if(account.registeredName.empty()) {
157 [registerNameButton setHidden:NO];
158 buttonRegisterWidthConstraint.constant = 260.0;
159 } else {
160 buttonRegisterWidthConstraint.constant = 0.0;
161 [registerNameButton setHidden:YES];
162 }
163
164 [registeredNameField setStringValue:@(account.registeredName.c_str())];
165
166 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
167 [passwordButton setTitle:accountProperties.archiveHasPassword ? @"Change password" : @"Create password"];
168 self.accountEnabled = account.enabled;
169
170 NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[removeAccountButton attributedTitle]];
171 NSRange titleRange = NSMakeRange(0, [colorTitle length]);
172 [colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor errorColor] range:titleRange];
173 [removeAccountButton setAttributedTitle:colorTitle];
174 [devicesTableView reloadData];
175 [blockedContactsTableView reloadData];
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -0500176 self.accountStatus.bgColor = colorForAccountStatus(accountModel->getAccountInfo(self.selectedAccountID).status);
177 [self.accountStatus setNeedsDisplay:YES];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400178}
179
180-(void) connectSignals {
181 QObject::disconnect(deviceAddedSignal);
182 QObject::disconnect(deviceRevokedSignal);
183 QObject::disconnect(deviceUpdatedSignal);
184 QObject::disconnect(bannedContactsChangedSignal);
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -0500185 QObject::disconnect(accountStateChangedSignal);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400186 deviceAddedSignal = QObject::connect(&*(self.accountModel->getAccountInfo(self.selectedAccountID)).deviceModel,
187 &lrc::api::NewDeviceModel::deviceAdded,
188 [self] (const std::string &id) {
189 [devicesTableView reloadData];
190 });
191 deviceRevokedSignal = QObject::connect(&*(self.accountModel->getAccountInfo(self.selectedAccountID)).deviceModel,
192 &lrc::api::NewDeviceModel::deviceRevoked,
193 [self] (const std::string &id, const lrc::api::NewDeviceModel::Status status) {
194 switch (status) {
195 case lrc::api::NewDeviceModel::Status::SUCCESS:
196 [devicesTableView reloadData];
197 break;
198 case lrc::api::NewDeviceModel::Status::WRONG_PASSWORD:
199 [self showAlertWithTitle: @"" andText: @"Device revocation failed with error: Wrong password"];
200 break;
201 case lrc::api::NewDeviceModel::Status::UNKNOWN_DEVICE:
202 [self showAlertWithTitle: @"" andText: @"Device revocation failed with error: Unknown device"];
203 break;
204 }
205 });
206 deviceUpdatedSignal = QObject::connect(&*(self.accountModel->getAccountInfo(self.selectedAccountID)).deviceModel,
207 &lrc::api::NewDeviceModel::deviceUpdated,
208 [self] (const std::string &id) {
209 [devicesTableView reloadData];
210 });
211 bannedContactsChangedSignal = QObject::connect(&*(self.accountModel->getAccountInfo(self.selectedAccountID)).contactModel,
212 &lrc::api::ContactModel::bannedStatusChanged,
213 [self] (const std::string &contactUri, bool banned) {
214 [blockedContactsTableView reloadData];
215 });
Kateryna Kostiuk9fca5422018-11-19 16:27:46 -0500216 accountStateChangedSignal = QObject::connect(self.accountModel,
217 &lrc::api::NewAccountModel::accountStatusChanged,
218 [self] (const std::string& accountID) {
219 if(accountID != self.selectedAccountID) {
220 return;
221 }
222 self.accountStatus.bgColor = colorForAccountStatus(accountModel->getAccountInfo(accountID).status);
223 [self.accountStatus setNeedsDisplay:YES];
224 });
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400225}
226
227-(void) showAlertWithTitle: (NSString *) title andText: (NSString *)text {
228 NSAlert *alert = [[NSAlert alloc] init];
229 [alert addButtonWithTitle:@"OK"];
230 [alert setMessageText:title];
231 [alert setInformativeText:text];
232 [alert runModal];
233}
234
235- (void)pictureTakerDidEnd:(IKPictureTaker *) picker
236 returnCode:(NSInteger) code
237 contextInfo:(void*) contextInfo
238{
Kateryna Kostiuk256814e2018-09-04 14:47:33 -0400239 //do nothing when editing canceled
240 if (code == 0) {
241 return;
242 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400243 if (auto outputImage = [picker outputImage]) {
244 auto image = [picker inputImage];
245 CGFloat newSize = MIN(image.size.height, image.size.width);
246 outputImage = [outputImage cropImageToSize:CGSizeMake(newSize, newSize)];
247 [photoView setImage: [outputImage roundCorners: outputImage.size.height * 0.5]];
Kateryna Kostiuk39ce23d2018-10-02 14:33:37 -0400248 [photoView setBordered:NO];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400249 [addProfilePhotoImage setHidden:YES];
250 auto imageToBytes = QByteArray::fromNSData([outputImage TIFFRepresentation]).toBase64();
251 std::string imageToString = std::string(imageToBytes.constData(), imageToBytes.length());
252 self.accountModel->setAvatar(self.selectedAccountID, imageToString);
253 } else if(!photoView.image) {
Kateryna Kostiuk39ce23d2018-10-02 14:33:37 -0400254 [photoView setBordered:YES];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400255 [addProfilePhotoImage setHidden:NO];
256 }
257}
258
259#pragma mark - RegisterNameDelegate methods
260
261- (void) didRegisterName:(NSString *) name withSuccess:(BOOL) success
262{
263 [self.accountModal close];
264 if(!success) {
265 return;
266 }
267
268 if(name.length == 0) {
269 return;
270 }
271 buttonRegisterWidthConstraint.constant = 0.0;
272 [registerNameButton setHidden:YES];
273 [registeredNameField setStringValue:name];
Kateryna Kostiukdf680762018-10-29 13:53:52 -0400274 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
275 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400276}
277
278#pragma mark - NSTextFieldDelegate delegate methods
279
280- (void)controlTextDidChange:(NSNotification *)notif
281{
282 NSTextField* textField = [notif object];
283 if (textField.tag != DISPLAYNAME) {
284 return;
285 }
286 NSString* displayName = textField.stringValue;
287
288 [NSObject cancelPreviousPerformRequestsWithTarget:self];
289 self.accountModel->setAlias(self.selectedAccountID, [displayName UTF8String]);
290 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
291 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
292}
293
294#pragma mark - NSTableViewDataSource methods
295
296- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
297 if(tableView == devicesTableView) {
298 return self.accountModel->getAccountInfo(self.selectedAccountID).deviceModel->getAllDevices().size();
299 } else if (tableView == blockedContactsTableView){
300 return self.accountModel->getAccountInfo(self.selectedAccountID).contactModel->getBannedContacts().size();
301 }
302 return 0;
303}
304
305#pragma mark - NSTableViewDelegate methods
306- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
307{
308 if(tableView == devicesTableView) {
309 NSTableCellView* deviceView = [tableView makeViewWithIdentifier:@"TableCellDeviceItem" owner:self];
310 NSTextField* nameLabel = [deviceView viewWithTag: DEVICE_NAME_TAG];
311 NSTextField* idLabel = [deviceView viewWithTag: DEVICE_ID_TAG];
312 NSButton* revokeButton = [deviceView viewWithTag: DEVICE_REVOKE_TAG];
313 NSButton* editButton = [deviceView viewWithTag: DEVICE_EDIT_TAG];
314 [editButton setAction:@selector(editDevice:)];
315 [editButton setTarget:self];
316 [revokeButton setAction:@selector(startDeviceRevocation:)];
317 [revokeButton setTarget:self];
318 auto devices = self.accountModel->getAccountInfo(self.selectedAccountID).deviceModel->getAllDevices();
319 auto device = devices.begin();
320
321 std::advance(device, row);
322
323 auto name = device->name;
324 auto deviceID = device->id;
325
326 [nameLabel setStringValue: @(name.c_str())];
327 [idLabel setStringValue: @(deviceID.c_str())];
328 [revokeButton setHidden: device->isCurrent];
329 [editButton setHidden: !device->isCurrent];
330 return deviceView;
331 } else if (tableView == blockedContactsTableView) {
332 NSTableCellView* contactView = [tableView makeViewWithIdentifier:@"TableCellBannedContactItem" owner:self];
333 NSTextField* nameLabel = [contactView viewWithTag: BANNED_CONTACT_NAME_TAG];
334 NSTextField* idLabel = [contactView viewWithTag: BANNED_CONTACT_ID_TAG];
335 NSButton* revokeButton = [contactView viewWithTag: UNBLOCK_CONTACT_TAG];
336 auto contacts = self.accountModel->getAccountInfo(self.selectedAccountID).contactModel->getBannedContacts();
337 auto contactID = contacts.begin();
338 std::advance(contactID, row);
339 [idLabel setStringValue: @(contactID->c_str())];
340 auto contact = self.accountModel->getAccountInfo(self.selectedAccountID).contactModel->getContact([@(contactID->c_str()) UTF8String]);
341 [nameLabel setStringValue: bestNameForContact(contact)];
342 [revokeButton setAction:@selector(unblockContact:)];
343 [revokeButton setTarget:self];
344 return contactView;
345 }
346}
347
348- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
349{
350 if(tableView == devicesTableView) {
351 return tableView.rowHeight;
352 } else if (tableView == blockedContactsTableView) {
353 CGFloat height = self.bannedContactHeightConstraint.constant;
354 if(height == 150) {
355 return 52;
356 } else {
357 return 1;
358 }
359 }
360}
361
362- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
363{
364 return [tableView makeViewWithIdentifier:@"HoverRowView" owner:nil];
365}
366
367#pragma mark - Actions
368
369- (IBAction)editPhoto:(id)sender
370{
371 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400372 if (@available(macOS 10.14, *)) {
373 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
374 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
375 {
376 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
377 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400378
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400379 if(authStatus == AVAuthorizationStatusNotDetermined)
380 {
381 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
382 if(!granted){
383 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
384 }
385 }];
386 }
387 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400388 [pictureTaker beginPictureTakerSheetForWindow:[self.view window]
389 withDelegate:self
390 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
391 contextInfo:nil];
392
393}
394
395- (IBAction)startExportOnRing:(id)sender
396{
397 ExportPasswordWC *passwordWC = [[ExportPasswordWC alloc] initWithNibName:@"ExportPasswordWindow" bundle: nil accountmodel: self.accountModel];
398 passwordWC.selectedAccountID = self.selectedAccountID;
399 accountModal = passwordWC;
400 [self.view.window beginSheet: passwordWC.window completionHandler:nil];
401}
402- (IBAction)triggerAdwancedSettings: (NSButton *)sender {
403 [self.delegate triggerAdvancedOptions];
404}
405
406- (IBAction)enableAccount: (NSButton *)sender {
407 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
408 self.accountModel->enableAccount(self.selectedAccountID, !account.enabled);
409 self.accountEnabled = account.enabled;
410 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
411 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
412}
413
414- (IBAction)removeAccount:(id)sender
415{
416 NSAlert *alert = [[NSAlert alloc] init];
417 [alert addButtonWithTitle:@"OK"];
418 [alert addButtonWithTitle:@"Cancel"];
419 [alert setMessageText: NSLocalizedString(@"Remove account",
420 @"Remove account alert title")];
421 [alert setInformativeText:NSLocalizedString(@"By clicking \"OK\" you will remove this account on this device! This action can not be undone. Also, your registered name can be lost.",
422 @"Remove account alert message")];
423
424 if ([alert runModal] == NSAlertFirstButtonReturn) {
425 self.accountModel->removeAccount(self.selectedAccountID);
426 }
427}
428
429- (IBAction)exportAccount:(id)sender
430{
431 BackupAccountWC* passwordWC = [[BackupAccountWC alloc] initWithNibName:@"BackupAccountWindow" bundle: nil accountmodel: self.accountModel];
432 passwordWC.delegate = self;
433 [passwordWC setAllowFileSelection:NO];
Kateryna Kostiuk14366812018-08-24 16:30:20 -0400434 passwordWC.selectedAccountID = self.selectedAccountID;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400435 accountModal = passwordWC;
436 [self.view.window beginSheet:passwordWC.window completionHandler:nil];
437}
438
439- (IBAction)startNameRegistration:(id)sender
440{
441 RegisterNameWC* registerWC = [[RegisterNameWC alloc] initWithNibName:@"RegisterNameWindow" bundle: nil accountmodel: self.accountModel];
442 registerWC.delegate = self;
443 registerWC.selectedAccountID = self.selectedAccountID;
444 self.accountModal = registerWC;
445 [self.view.window beginSheet:registerWC.window completionHandler:nil];
446}
447- (IBAction)changePassword:(id)sender
448{
449 PasswordChangeWC* passwordWC = [[PasswordChangeWC alloc] initWithNibName:@"PasswordChange" bundle: nil accountmodel: self.accountModel];
450 passwordWC.selectedAccountID = self.selectedAccountID;
451 passwordWC.delegate = self;
452 [self.view.window beginSheet:passwordWC.window completionHandler:nil];
453 self.passwordModal = passwordWC;
454}
455
456- (IBAction)showBanned: (NSButton *)sender {
457 CGFloat height = self.bannedContactHeightConstraint.constant;
458 NSRect frame = self.view.frame;
459 if(height == 150) {
460 frame.size.height = frame.size.height - 150 - 10;
461 } else {
462 frame.size.height = frame.size.height + 150 + 10;
463 }
464 self.view.frame = frame;
465 [self.delegate updateFrame];
466 CGFloat advancedHeight = self.advancedButtonMarginConstraint.constant;
467 self.advancedButtonMarginConstraint.constant = (height== 2) ? 40 : 30;
468 self.bannedContactHeightConstraint.constant = (height== 2) ? 150 : 2;
Kateryna Kostiuk394f74c2018-10-05 15:45:26 -0400469 [[[[self.blockedContactsTableView superview] superview] superview] setHidden:![[[[self.blockedContactsTableView superview] superview] superview] isHidden]];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400470 [blockedContactsTableView reloadData];
471}
472
473-(void) hideBannedContacts {
474 CGFloat height = self.bannedContactHeightConstraint.constant;
475 NSRect frame = self.view.frame;
476 if(height == 150) {
477 [self showBanned:nil];
478 }
479}
480
481- (IBAction)startDeviceRevocation:(NSView*)sender
482{
483 NSInteger row = [devicesTableView rowForView:sender];
484 if(row < 0) {
485 return;
486 }
487 auto devices = self.accountModel->getAccountInfo(self.selectedAccountID).deviceModel->getAllDevices();
488 auto device = devices.begin();
489 std::advance(device, row);
490 if(device == devices.end()) {
491 return;
492 }
493 [self proceedDeviceRevokationAlert:device->id];
494}
495
496- (IBAction)unblockContact:(NSView*)sender
497{
498 NSInteger row = [blockedContactsTableView rowForView:sender];
499 if(row < 0) {
500 return;
501 }
502 auto contacts = self.accountModel->getAccountInfo(self.selectedAccountID).contactModel->getBannedContacts();
503 auto contactID = contacts.begin();
504 std::advance(contactID, row);
505 if(contactID == contacts.end()) {
506 return;
507 }
508 auto contact = self.accountModel->getAccountInfo(self.selectedAccountID).contactModel->getContact([@(contactID->c_str()) UTF8String]);
509 if(!contact.isBanned) {
510 return;
511 }
512 self.accountModel->getAccountInfo(self.selectedAccountID).contactModel->addContact(contact);
513}
514
515- (IBAction)editDevice:(NSView*)sender
516{
517 NSInteger row = [devicesTableView rowForView:sender];
518 if(row < 0) {
519 return;
520 }
521
522 NSTableCellView* deviceView = [devicesTableView viewAtColumn:0 row:row makeIfNecessary:NO];
523 if(!deviceView || ![deviceView isKindOfClass:[NSTableCellView class]]) {
524 return;
525 }
526
527 NSTextField* nameLabel = [deviceView viewWithTag: DEVICE_NAME_TAG];
528 NSButton* editButton = [deviceView viewWithTag: DEVICE_EDIT_TAG];
529 if ([nameLabel isEditable]) {
530 self.accountModel->getAccountInfo(self.selectedAccountID).deviceModel->setCurrentDeviceName([nameLabel.stringValue UTF8String]);
531 [nameLabel setEditable:NO];
532 [self.view.window makeFirstResponder:nil];
533 editButton.image = [NSImage imageNamed:NSImageNameTouchBarComposeTemplate];
534 return;
535 }
536 [nameLabel setEditable:YES];
537 [nameLabel becomeFirstResponder];
538 editButton.image = [NSImage imageNamed:NSImageNameTouchBarDownloadTemplate];
539}
540
541-(void) revokeDeviceWithID: (std::string) deviceID password:(NSString *) password {
542 self.accountModel->getAccountInfo(self.selectedAccountID).deviceModel->revokeDevice(deviceID, [password UTF8String]);
543}
544
545-(void) proceedDeviceRevokationAlert: (std::string) deviceID {
546 NSAlert *alert = [[NSAlert alloc] init];
547 [alert addButtonWithTitle:@"OK"];
548 [alert addButtonWithTitle:@"Cancel"];
549 [alert setMessageText:@"Revoke Device"];
550 [alert setInformativeText:@"Attention! This action could not be undone!"];
551 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
552 if(accountProperties.archiveHasPassword) {
553 NSSecureTextField *passwordText = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
554 [passwordText setPlaceholderString:@"Enter password"];
555 [alert setAccessoryView:passwordText];
556 if ([alert runModal] == NSAlertFirstButtonReturn) {
557 [self revokeDeviceWithID:deviceID password:[passwordText stringValue]];
558 }
559 } else {
560 if ([alert runModal] == NSAlertFirstButtonReturn) {
561 [self revokeDeviceWithID:deviceID password:@""];
562 }
563 }
564}
565
566#pragma mark - BackupAccountDelegate methods
567
568-(void) didCompleteExportWithPath:(NSURL*) fileUrl
569{
570 [[NSWorkspace sharedWorkspace] selectFile:fileUrl.path inFileViewerRootedAtPath:@""];
571}
572
573#pragma mark - PasswordChangeDelegate
574
575-(void) paswordCreatedWithSuccess:(BOOL) success
576{
577 [passwordButton setTitle: success ? @"Change password" : @"Create password"];
578}
579
580@end