blob: a63dc1b3ae3bef02190f2032297229ebcf8077d9 [file] [log] [blame]
Loïc Siretfcb4ca62016-09-21 17:12:09 -04001/*
2 * Copyright (C) 2015-2016 Savoir-faire Linux Inc.
3 * Author: Loïc Siret <loic.siret@savoirfairelinux.com>
Kateryna Kostiukecaa3952018-07-13 16:00:34 -04004 * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
Loïc Siretfcb4ca62016-09-21 17:12:09 -04005 *
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
21#import "RingWizardNewAccountVC.h"
22
23
24//Cocoa
Loïc Siretfcb4ca62016-09-21 17:12:09 -040025#import <Quartz/Quartz.h>
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -040026#import <AVFoundation/AVFoundation.h>
Loïc Siretfcb4ca62016-09-21 17:12:09 -040027
28//Qt
29#import <QUrl>
30#import <QPixmap>
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040031#import <QSize>
32#import <QtMacExtras/qmacfunctions.h>
Loïc Siretfcb4ca62016-09-21 17:12:09 -040033
34//LRC
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040035#import <api/lrc.h>
36#import <api/newaccountmodel.h>
Kateryna Kostiukbe7e2e42019-07-26 17:44:12 -040037#import <api/account.h>
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040038#import <interfaces/pixmapmanipulatori.h>
Kateryna Kostiukbe7e2e42019-07-26 17:44:12 -040039#import <namedirectory.h>
Loïc Siretfcb4ca62016-09-21 17:12:09 -040040
Loïc Siretfcb4ca62016-09-21 17:12:09 -040041#import "Constants.h"
42#import "views/NSImage+Extensions.h"
43#import "views/NSColor+RingTheme.h"
Andreas Traczyk92c101e2018-07-03 14:43:53 -040044#import "utils.h"
Loïc Siretfcb4ca62016-09-21 17:12:09 -040045
46@interface RingWizardNewAccountVC ()
47@end
48
49@implementation RingWizardNewAccountVC
50{
Loïc Siret3652cfb2016-10-27 10:12:07 -040051 __unsafe_unretained IBOutlet NSView* loadingView;
52 __unsafe_unretained IBOutlet NSView* creationView;
53
Loïc Siretfcb4ca62016-09-21 17:12:09 -040054 __unsafe_unretained IBOutlet NSButton* photoView;
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -040055 __unsafe_unretained IBOutlet NSButton* registerInfoButton;
56 __unsafe_unretained IBOutlet NSButton* enableUsername;
Alexandre Lision882289b2016-10-31 16:10:39 -040057 __unsafe_unretained IBOutlet NSTextField* displayNameField;
58 __unsafe_unretained IBOutlet NSTextField* registeredNameField;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -040059 __unsafe_unretained IBOutlet NSTextField* registeredNameError;
60 __unsafe_unretained IBOutlet NSTextField* passwordError;
Loïc Siretfcb4ca62016-09-21 17:12:09 -040061 __unsafe_unretained IBOutlet NSSecureTextField* passwordField;
Loïc Siret3652cfb2016-10-27 10:12:07 -040062 __unsafe_unretained IBOutlet NSSecureTextField* passwordRepeatField;
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -040063 __unsafe_unretained IBOutlet NSImageView* addProfilePhotoImage;
Loïc Siret3652cfb2016-10-27 10:12:07 -040064
65 __unsafe_unretained IBOutlet NSProgressIndicator* progressBar;
Alexandre Lision882289b2016-10-31 16:10:39 -040066
Alexandre Lision882289b2016-10-31 16:10:39 -040067 __unsafe_unretained IBOutlet NSProgressIndicator* indicatorLookupResult;
68
69 __unsafe_unretained IBOutlet NSPopover* helpBlockchainContainer;
70 __unsafe_unretained IBOutlet NSPopover* helpPasswordContainer;
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -050071 __unsafe_unretained IBOutlet NSLayoutConstraint* buttonTopConstraint;
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -050072 __unsafe_unretained IBOutlet NSButton* passwordButton;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -040073 __unsafe_unretained IBOutlet NSStackView* repeatPasswordView;
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -040074 __unsafe_unretained IBOutlet NSStackView* passwordButtonContainer;
Alexandre Lision882289b2016-10-31 16:10:39 -040075
Alexandre Lision882289b2016-10-31 16:10:39 -040076 QMetaObject::Connection registeredNameFound;
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040077 QMetaObject::Connection accountCreated;
78 QMetaObject::Connection accountRemoved;
Alexandre Lision882289b2016-10-31 16:10:39 -040079
80 BOOL lookupQueued;
81 NSString* usernameWaitingForLookupResult;
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040082 QString accountToCreate;
Loïc Siretfcb4ca62016-09-21 17:12:09 -040083}
84
Alexandre Lision882289b2016-10-31 16:10:39 -040085NSInteger const DISPLAY_NAME_TAG = 1;
86NSInteger const BLOCKCHAIN_NAME_TAG = 2;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -040087NSInteger const PASSWORD_TAG = 3;
88NSInteger const REPEAT_PASSWORD_TAG = 4;
Loïc Siretfcb4ca62016-09-21 17:12:09 -040089
Loïc Siret3652cfb2016-10-27 10:12:07 -040090//ERROR CODE for textfields validations
91NSInteger const ERROR_PASSWORD_TOO_SHORT = -1;
92NSInteger const ERROR_REPEAT_MISMATCH = -2;
93
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -040094BOOL isRendevous = false;
95
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040096@synthesize accountModel;
97
98-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel {
99 if (self = [self initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
100 {
101 self.accountModel = accountModel;
102 }
103 return self;
104}
105
Loïc Siret3652cfb2016-10-27 10:12:07 -0400106- (BOOL)produceError:(NSError**)error withCode:(NSInteger)code andMessage:(NSString*)message
107{
108 if (error != NULL){
109 NSDictionary *errorDetail = @{NSLocalizedDescriptionKey: message};
110 *error = [NSError errorWithDomain:@"Input" code:code userInfo:errorDetail];
111 }
112 return NO;
113}
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400114
Alexandre Lision882289b2016-10-31 16:10:39 -0400115- (IBAction)showBlockchainHelp:(id)sender
116{
117 [helpBlockchainContainer showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxYEdge];
118}
119
120- (IBAction)showPasswordHelp:(id)sender
121{
122 [helpPasswordContainer showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxYEdge];
123}
124
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -0400125- (void)prepareViewToShow:(BOOL)isRendevousAccount {
126 isRendevous = isRendevousAccount;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400127 [self.view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
128 [creationView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400129 [loadingView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400130 [passwordField setHidden: YES];
131 [repeatPasswordView setHidden: YES];
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -0400132 buttonTopConstraint.constant = isRendevous ? 15 : 25;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400133}
134
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -0400135- (void)show {
136 NSString *buttonTitle = isRendevous ?
Kateryna Kostiuk63d766d2020-10-02 14:20:28 -0400137 NSLocalizedString(@"Choose a name for your rendezvous point", @"Choose registered name for rendezvous") :
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -0400138 NSLocalizedString(@"Choose a username for your account", @"Choose registered name for account");
139 [enableUsername setTitle:buttonTitle];
140 [passwordButtonContainer setHidden: isRendevous];
141 [registerInfoButton setHidden: isRendevous];
Alexandre Lision882289b2016-10-31 16:10:39 -0400142 [displayNameField setTag:DISPLAY_NAME_TAG];
143 [registeredNameField setTag:BLOCKCHAIN_NAME_TAG];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400144 [photoView setWantsLayer: YES];
145 photoView.layer.cornerRadius = photoView.frame.size.width / 2;
146 photoView.layer.masksToBounds = YES;
Alexandre Lisionc2ad6392016-11-08 11:20:34 -0500147 self.signUpBlockchainState = YES;
148 [self toggleSignupRing:nil];
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -0400149 [addProfilePhotoImage setWantsLayer: YES];
150 [photoView setBordered:YES];
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500151 [passwordButton setState: NSControlStateValueOff];
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500152 self.registeredName = @"";
153 self.password = @"";
154 self.repeatPassword = @"";
Loïc Siret3652cfb2016-10-27 10:12:07 -0400155 [self display:creationView];
156}
157
Loïc Siret3652cfb2016-10-27 10:12:07 -0400158- (void)display:(NSView *)view
159{
160 [self.delegate showView:view];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400161}
162
163- (IBAction)editPhoto:(id)sender
164{
Loïc Siret3652cfb2016-10-27 10:12:07 -0400165 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400166#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400167 if (@available(macOS 10.14, *)) {
168 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
169 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
170 {
171 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
172 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400173
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400174 if(authStatus == AVAuthorizationStatusNotDetermined)
175 {
176 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
177 if(!granted){
178 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
179 }
180 }];
181 }
182 }
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400183#endif
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400184 [pictureTaker beginPictureTakerSheetForWindow:[self.delegate window]
185 withDelegate:self
186 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
187 contextInfo:nil];
188
189}
190
191- (void)pictureTakerDidEnd:(IKPictureTaker *) picker
Alexandre Lision882289b2016-10-31 16:10:39 -0400192 returnCode:(NSInteger) code
193 contextInfo:(void*) contextInfo
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400194{
Kateryna Kostiuk256814e2018-09-04 14:47:33 -0400195 //do nothing when editing canceled
196 if (code == 0) {
197 return;
198 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400199 if (auto outputImage = [picker outputImage]) {
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -0400200 [photoView setBordered:NO];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400201 [photoView setImage:outputImage];
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -0400202 [addProfilePhotoImage setHidden:YES];
203 } else if(!photoView.image) {
204 [photoView setBordered:YES];
205 [addProfilePhotoImage setHidden:NO];
Alexandre Lisionc2ad6392016-11-08 11:20:34 -0500206 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400207}
208
Loïc Siret3652cfb2016-10-27 10:12:07 -0400209#pragma mark - Input validation
Alexandre Lision882289b2016-10-31 16:10:39 -0400210
Loïc Siret3652cfb2016-10-27 10:12:07 -0400211- (BOOL)isPasswordValid
212{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400213 return self.password.length >= 6 || self.password.length == 0;
Loïc Siret3652cfb2016-10-27 10:12:07 -0400214}
215
216- (BOOL)isRepeatPasswordValid
217{
Anthony Léonard24110e82017-09-15 16:29:11 -0400218 return [self.password isEqualToString:self.repeatPassword] || ([self.password length] == 0 && [self.repeatPassword length] == 0);
Loïc Siret3652cfb2016-10-27 10:12:07 -0400219}
220
221- (BOOL)validateRepeatPassword:(NSError **)error
222{
223 if (!self.isRepeatPasswordValid){
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400224 passwordError.stringValue = NSLocalizedString(@"Passwords don't match",
225 @"Indication for user");
Loïc Siret3652cfb2016-10-27 10:12:07 -0400226 return [self produceError:error
227 withCode:ERROR_REPEAT_MISMATCH
228 andMessage:NSLocalizedString(@"Passwords don't match",
Alexandre Lision882289b2016-10-31 16:10:39 -0400229 @"Indication for user")];
Loïc Siret3652cfb2016-10-27 10:12:07 -0400230 }
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400231 passwordError.stringValue = @"";
Loïc Siret3652cfb2016-10-27 10:12:07 -0400232 return YES;
233}
234
235- (BOOL)validatePassword:(NSError **)error
236{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400237 if (!self.isPasswordValid){
238 passwordError.stringValue = NSLocalizedString(@"Password is too short",
239 @"Indication for user");
Loïc Siret3652cfb2016-10-27 10:12:07 -0400240 return [self produceError:error
241 withCode:ERROR_PASSWORD_TOO_SHORT
242 andMessage:NSLocalizedString(@"Password is too short",
Alexandre Lision882289b2016-10-31 16:10:39 -0400243 @"Indication for user")];
Loïc Siret3652cfb2016-10-27 10:12:07 -0400244 }
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400245 passwordError.stringValue = @"";
Loïc Siret3652cfb2016-10-27 10:12:07 -0400246 return YES;
247}
248
249- (BOOL)validateUserInputPassword:(NSError **)error
250{
251 return [self validatePassword:error] && [self validateRepeatPassword:error];
252}
253
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400254- (IBAction)createRingAccount:(id)sender
255{
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400256 QObject::disconnect(accountCreated);
257 QObject::disconnect(accountRemoved);
258 accountCreated = QObject::connect(self.accountModel,
259 &lrc::api::NewAccountModel::accountAdded,
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400260 [self] (const QString& accountID) {
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400261 if(accountID.compare(accountToCreate) != 0) {
262 return;
263 }
264 QObject::disconnect(accountCreated);
265 QObject::disconnect(accountRemoved);
266 //set account avatar
267 if([photoView image]) {
268 NSImage *avatarImage = [photoView image];
Kateryna Kostiuk14b8aa72020-11-11 10:40:15 -0500269 NSData* imageData = [avatarImage TIFFRepresentation];
270 NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData: imageData];
271 NSDictionary *properties = [[NSDictionary alloc] init];
272 imageData = [imageRep representationUsingType:NSPNGFileType properties: properties];
273 NSString * dataString = [imageData base64EncodedStringWithOptions:0];
274 self.accountModel->setAvatar(accountID, QString::fromNSString(dataString));
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400275 }
276 //register username
277 if (self.registeredName && ![self.registeredName isEqualToString:@""]) {
278 NSString *passwordString = self.password ? self.password: @"";
279 NSString *usernameString = self.registeredName;
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400280 self.accountModel->registerName(accountID,
281 QString::fromNSString(passwordString),
282 QString::fromNSString(usernameString));
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400283 }
Kateryna Kostiuk0c0801e2019-07-18 20:10:51 -0400284 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(accountID);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400285 accountProperties.Ringtone.ringtonePath = QString::fromNSString(defaultRingtonePath());
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -0400286 accountProperties.isRendezVous = isRendevous;
Kateryna Kostiuk0c0801e2019-07-18 20:10:51 -0400287 self.accountModel->setAccountConfig(accountID, accountProperties);
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400288 [self registerDefaultPreferences];
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400289 [self.delegate didCreateAccountWithSuccess:YES accountId: accountToCreate];
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400290 });
291 //if account creation failed remove loading view
292 accountRemoved = QObject::connect(self.accountModel,
293 &lrc::api::NewAccountModel::accountRemoved,
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400294 [self] (const QString& accountID) {
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400295 if(accountID.compare(accountToCreate) != 0) {
296 return;
297 }
298 QObject::disconnect(accountCreated);
299 QObject::disconnect(accountRemoved);
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400300 [self.delegate didCreateAccountWithSuccess:NO accountId: accountToCreate];
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400301 });
Loïc Siret3652cfb2016-10-27 10:12:07 -0400302 [self display:loadingView];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400303 [progressBar startAnimation:nil];
Loïc Siret3652cfb2016-10-27 10:12:07 -0400304
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400305 accountToCreate = self.accountModel->createNewAccount(lrc::api::profile::Type::RING, QString::fromNSString(displayNameField.stringValue),"",QString::fromNSString(passwordField.stringValue), "");
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400306}
307
308/**
309 * Set default values for preferences
310 */
311- (void)registerDefaultPreferences
312{
Andreas Traczyk92c101e2018-07-03 14:43:53 -0400313 if (!appSandboxed()) {
314 // enable AutoStartup
315 LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
316 if (loginItemsRef == nil) return;
317 CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
318 LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL);
319 if (itemRef) CFRelease(itemRef);
320 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400321
322 // enable Notifications
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500323 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:Preferences::CallNotifications];
324 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:Preferences::MessagesNotifications];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400325}
326
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400327- (IBAction)cancel:(id)sender
328{
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400329 [self.delegate didCreateAccountWithSuccess:NO accountId: accountToCreate];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400330}
331
Alexandre Lision882289b2016-10-31 16:10:39 -0400332#pragma mark - UserNameRegistration delegate methods
333
334- (IBAction)toggleSignupRing:(id)sender
335{
336 if (self.withBlockchain) {
337 [self lookupUserName];
338 }
339}
340
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500341- (IBAction)togglePasswordButton:(NSButton *)sender
342{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400343 [passwordField setHidden: !passwordField.hidden];
344 [repeatPasswordView setHidden: !repeatPasswordView.hidden];
Kateryna Kostiuk707c7ac2020-09-18 11:27:13 -0400345 buttonTopConstraint.constant = repeatPasswordView.hidden ? 25 : 15;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400346 [self display:creationView];
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500347}
348
Alexandre Lision882289b2016-10-31 16:10:39 -0400349- (BOOL)withBlockchain
350{
351 return self.signUpBlockchainState == NSOnState;
352}
353
354- (BOOL)userNameAvailableORNotBlockchain
355{
356 return !self.withBlockchain || (self.registeredName.length > 0 && self.isUserNameAvailable);
357}
358
359- (void)showLookUpAvailable:(BOOL)available andText:(NSString *)message
360{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400361 if (registeredNameField.stringValue.length > 0) {
362 registeredNameError.stringValue = message;
363 }
364 [indicatorLookupResult setHidden:YES];
365 [indicatorLookupResult stopAnimation:nil];
Alexandre Lision882289b2016-10-31 16:10:39 -0400366}
367
368- (void)onUsernameAvailabilityChangedWithNewAvailability:(BOOL)newAvailability
369{
370 self.isUserNameAvailable = newAvailability;
371}
372
373- (void)hideLookupSpinner
374{
375 [indicatorLookupResult setHidden:YES];
376}
377
378- (void)showLookupSpinner
379{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400380 registeredNameError.stringValue = @"";
381 if (registeredNameField.stringValue.length > 0) {
382 [indicatorLookupResult setHidden:NO];
383 [indicatorLookupResult startAnimation:nil];
384 }
Alexandre Lision882289b2016-10-31 16:10:39 -0400385}
386
387- (BOOL)lookupUserName
388{
389 [self showLookupSpinner];
390 QObject::disconnect(registeredNameFound);
391 registeredNameFound = QObject::connect(
392 &NameDirectory::instance(),
393 &NameDirectory::registeredNameFound,
Kateryna Kostiukbe7e2e42019-07-26 17:44:12 -0400394 [=] (NameDirectory::LookupStatus status,
395 const QString& address, const QString& name) {
Alexandre Lision882289b2016-10-31 16:10:39 -0400396 NSLog(@"Name lookup ended");
397 lookupQueued = NO;
398 //If this is the username we are waiting for, we can disconnect.
399 if (name.compare(QString::fromNSString(usernameWaitingForLookupResult)) == 0) {
400 QObject::disconnect(registeredNameFound);
401 } else {
402 //Keep waiting...
403 return;
404 }
405
406 //We may now stop the spinner
407 [self hideLookupSpinner];
408
409 BOOL isAvailable = NO;
410 NSString* message;
411 switch(status)
412 {
413 case NameDirectory::LookupStatus::SUCCESS:
414 {
415 message = NSLocalizedString(@"The entered username is not available",
416 @"Text shown to user when his username is already registered");
417 isAvailable = NO;
418 break;
419 }
420 case NameDirectory::LookupStatus::NOT_FOUND:
421 {
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400422 message = @"";
Alexandre Lision882289b2016-10-31 16:10:39 -0400423 isAvailable = YES;
424 break;
425 }
426 case NameDirectory::LookupStatus::INVALID_NAME:
427 {
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400428 message = NSLocalizedString(@"Invalid username.",
Alexandre Lision882289b2016-10-31 16:10:39 -0400429 @"Text shown to user when his username is invalid to be registered");
430 isAvailable = NO;
431 break;
432 }
433 case NameDirectory::LookupStatus::ERROR:
434 default:
435 {
436 message = NSLocalizedString(@"Failed to perform lookup",
437 @"Text shown to user when an error occur at registration");
438 isAvailable = NO;
439 break;
440 }
441 }
442 [self showLookUpAvailable:isAvailable andText: message];
443 [self onUsernameAvailabilityChangedWithNewAvailability:isAvailable];
444
445 });
446
447 //Start the lookup in a second so that the UI dosen't seem to freeze
Kateryna Kostiukbe7e2e42019-07-26 17:44:12 -0400448 BOOL result = NameDirectory::instance().lookupName(QString(), QString::fromNSString(usernameWaitingForLookupResult));
Alexandre Lision882289b2016-10-31 16:10:39 -0400449
450}
451
Alexandre Lision5dc5d312016-11-10 10:41:37 -0500452#pragma mark - NSTextFieldDelegate delegate methods
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400453
Alexandre Lision882289b2016-10-31 16:10:39 -0400454- (void)controlTextDidChange:(NSNotification *)notif
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400455{
456 NSTextField* textField = [notif object];
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400457 if (textField.tag == PASSWORD_TAG) {
458 NSError *error = nil;
459 [self validatePassword: &error];
460 return;
461 }
462 if (textField.tag == REPEAT_PASSWORD_TAG) {
463 NSError *error = nil;
464 [self validateRepeatPassword: &error];
465 return;
466 }
Alexandre Lision882289b2016-10-31 16:10:39 -0400467 if (textField.tag != BLOCKCHAIN_NAME_TAG) {
468 return;
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400469 }
Alexandre Lision882289b2016-10-31 16:10:39 -0400470 NSString* alias = textField.stringValue;
Alexandre Lision882289b2016-10-31 16:10:39 -0400471 [self showLookupSpinner];
472 [self onUsernameAvailabilityChangedWithNewAvailability:NO];
473 [NSObject cancelPreviousPerformRequestsWithTarget:self];
474 [self performSelector:@selector(lookUp:) withObject:alias afterDelay:0.5];
475}
476
477- (void) lookUp:(NSString*) name
478{
479 if (self.withBlockchain && !lookupQueued) {
480 usernameWaitingForLookupResult = name;
481 lookupQueued = YES;
482 [self lookupUserName];
483 }
484}
485
486
487+ (NSSet *)keyPathsForValuesAffectingUserNameAvailableORNotBlockchain
488{
489 return [NSSet setWithObjects: NSStringFromSelector(@selector(signUpBlockchainState)),
490 NSStringFromSelector(@selector(isUserNameAvailable)),
491 nil];
492}
493
494+ (NSSet *)keyPathsForValuesAffectingWithBlockchain
495{
496 return [NSSet setWithObjects: NSStringFromSelector(@selector(signUpBlockchainState)),
497 nil];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400498}
499
Loïc Siret3652cfb2016-10-27 10:12:07 -0400500+ (NSSet *)keyPathsForValuesAffectingIsPasswordValid
501{
502 return [NSSet setWithObjects:@"password", nil];
503}
504
505+ (NSSet *)keyPathsForValuesAffectingIsRepeatPasswordValid
506{
507 return [NSSet setWithObjects:@"password", @"repeatPassword", nil];
508}
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400509@end