blob: f7a5d099dd9825e66519b1fdb7eefb03f869c1cd [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;
Alexandre Lision882289b2016-10-31 16:10:39 -040055 __unsafe_unretained IBOutlet NSTextField* displayNameField;
56 __unsafe_unretained IBOutlet NSTextField* registeredNameField;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -040057 __unsafe_unretained IBOutlet NSTextField* registeredNameError;
58 __unsafe_unretained IBOutlet NSTextField* passwordError;
Loïc Siretfcb4ca62016-09-21 17:12:09 -040059 __unsafe_unretained IBOutlet NSSecureTextField* passwordField;
Loïc Siret3652cfb2016-10-27 10:12:07 -040060 __unsafe_unretained IBOutlet NSSecureTextField* passwordRepeatField;
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -040061 __unsafe_unretained IBOutlet NSImageView* addProfilePhotoImage;
Loïc Siret3652cfb2016-10-27 10:12:07 -040062
63 __unsafe_unretained IBOutlet NSProgressIndicator* progressBar;
Alexandre Lision882289b2016-10-31 16:10:39 -040064
Alexandre Lision882289b2016-10-31 16:10:39 -040065 __unsafe_unretained IBOutlet NSProgressIndicator* indicatorLookupResult;
66
67 __unsafe_unretained IBOutlet NSPopover* helpBlockchainContainer;
68 __unsafe_unretained IBOutlet NSPopover* helpPasswordContainer;
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -050069 __unsafe_unretained IBOutlet NSLayoutConstraint* buttonTopConstraint;
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -050070 __unsafe_unretained IBOutlet NSButton* passwordButton;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -040071 __unsafe_unretained IBOutlet NSStackView* repeatPasswordView;
Alexandre Lision882289b2016-10-31 16:10:39 -040072
Alexandre Lision882289b2016-10-31 16:10:39 -040073 QMetaObject::Connection registeredNameFound;
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040074 QMetaObject::Connection accountCreated;
75 QMetaObject::Connection accountRemoved;
Alexandre Lision882289b2016-10-31 16:10:39 -040076
77 BOOL lookupQueued;
78 NSString* usernameWaitingForLookupResult;
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040079 std::string accountToCreate;
Loïc Siretfcb4ca62016-09-21 17:12:09 -040080}
81
Alexandre Lision882289b2016-10-31 16:10:39 -040082NSInteger const DISPLAY_NAME_TAG = 1;
83NSInteger const BLOCKCHAIN_NAME_TAG = 2;
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -040084NSInteger const PASSWORD_TAG = 3;
85NSInteger const REPEAT_PASSWORD_TAG = 4;
Loïc Siretfcb4ca62016-09-21 17:12:09 -040086
Loïc Siret3652cfb2016-10-27 10:12:07 -040087//ERROR CODE for textfields validations
88NSInteger const ERROR_PASSWORD_TOO_SHORT = -1;
89NSInteger const ERROR_REPEAT_MISMATCH = -2;
90
Kateryna Kostiukecaa3952018-07-13 16:00:34 -040091@synthesize accountModel;
92
93-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel {
94 if (self = [self initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
95 {
96 self.accountModel = accountModel;
97 }
98 return self;
99}
100
Loïc Siret3652cfb2016-10-27 10:12:07 -0400101- (BOOL)produceError:(NSError**)error withCode:(NSInteger)code andMessage:(NSString*)message
102{
103 if (error != NULL){
104 NSDictionary *errorDetail = @{NSLocalizedDescriptionKey: message};
105 *error = [NSError errorWithDomain:@"Input" code:code userInfo:errorDetail];
106 }
107 return NO;
108}
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400109
Alexandre Lision882289b2016-10-31 16:10:39 -0400110- (IBAction)showBlockchainHelp:(id)sender
111{
112 [helpBlockchainContainer showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxYEdge];
113}
114
115- (IBAction)showPasswordHelp:(id)sender
116{
117 [helpPasswordContainer showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxYEdge];
118}
119
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400120- (void)prepareViewToShow {
121 [self.view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
122 [creationView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400123 [loadingView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400124 [passwordField setHidden: YES];
125 [repeatPasswordView setHidden: YES];
126 buttonTopConstraint.constant = 35;
127}
128
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400129- (void)show
130{
Alexandre Lision882289b2016-10-31 16:10:39 -0400131 [displayNameField setTag:DISPLAY_NAME_TAG];
132 [registeredNameField setTag:BLOCKCHAIN_NAME_TAG];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400133 [photoView setWantsLayer: YES];
134 photoView.layer.cornerRadius = photoView.frame.size.width / 2;
135 photoView.layer.masksToBounds = YES;
Alexandre Lisionc2ad6392016-11-08 11:20:34 -0500136 self.signUpBlockchainState = YES;
137 [self toggleSignupRing:nil];
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -0400138 [addProfilePhotoImage setWantsLayer: YES];
139 [photoView setBordered:YES];
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500140 [passwordButton setState: NSControlStateValueOff];
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500141 self.registeredName = @"";
142 self.password = @"";
143 self.repeatPassword = @"";
Loïc Siret3652cfb2016-10-27 10:12:07 -0400144 [self display:creationView];
145}
146
Loïc Siret3652cfb2016-10-27 10:12:07 -0400147- (void)display:(NSView *)view
148{
149 [self.delegate showView:view];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400150}
151
152- (IBAction)editPhoto:(id)sender
153{
Loïc Siret3652cfb2016-10-27 10:12:07 -0400154 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400155#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400156 if (@available(macOS 10.14, *)) {
157 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
158 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
159 {
160 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
161 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400162
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400163 if(authStatus == AVAuthorizationStatusNotDetermined)
164 {
165 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
166 if(!granted){
167 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
168 }
169 }];
170 }
171 }
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400172#endif
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400173 [pictureTaker beginPictureTakerSheetForWindow:[self.delegate window]
174 withDelegate:self
175 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
176 contextInfo:nil];
177
178}
179
180- (void)pictureTakerDidEnd:(IKPictureTaker *) picker
Alexandre Lision882289b2016-10-31 16:10:39 -0400181 returnCode:(NSInteger) code
182 contextInfo:(void*) contextInfo
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400183{
Kateryna Kostiuk256814e2018-09-04 14:47:33 -0400184 //do nothing when editing canceled
185 if (code == 0) {
186 return;
187 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400188 if (auto outputImage = [picker outputImage]) {
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -0400189 [photoView setBordered:NO];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400190 auto image = [picker inputImage];
Kateryna Kostiuk2f2ef952019-05-07 11:04:41 -0400191 CGFloat newSize = MIN(MIN(image.size.height, image.size.width), MAX_IMAGE_SIZE);
192 outputImage = [outputImage imageResizeInsideMax: newSize];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400193 [photoView setImage:outputImage];
Kateryna Kostiuk87ae2bf2018-05-04 13:46:17 -0400194 [addProfilePhotoImage setHidden:YES];
195 } else if(!photoView.image) {
196 [photoView setBordered:YES];
197 [addProfilePhotoImage setHidden:NO];
Alexandre Lisionc2ad6392016-11-08 11:20:34 -0500198 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400199}
200
Loïc Siret3652cfb2016-10-27 10:12:07 -0400201#pragma mark - Input validation
Alexandre Lision882289b2016-10-31 16:10:39 -0400202
Loïc Siret3652cfb2016-10-27 10:12:07 -0400203- (BOOL)isPasswordValid
204{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400205 return self.password.length >= 6 || self.password.length == 0;
Loïc Siret3652cfb2016-10-27 10:12:07 -0400206}
207
208- (BOOL)isRepeatPasswordValid
209{
Anthony Léonard24110e82017-09-15 16:29:11 -0400210 return [self.password isEqualToString:self.repeatPassword] || ([self.password length] == 0 && [self.repeatPassword length] == 0);
Loïc Siret3652cfb2016-10-27 10:12:07 -0400211}
212
213- (BOOL)validateRepeatPassword:(NSError **)error
214{
215 if (!self.isRepeatPasswordValid){
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400216 passwordError.stringValue = NSLocalizedString(@"Passwords don't match",
217 @"Indication for user");
Loïc Siret3652cfb2016-10-27 10:12:07 -0400218 return [self produceError:error
219 withCode:ERROR_REPEAT_MISMATCH
220 andMessage:NSLocalizedString(@"Passwords don't match",
Alexandre Lision882289b2016-10-31 16:10:39 -0400221 @"Indication for user")];
Loïc Siret3652cfb2016-10-27 10:12:07 -0400222 }
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400223 passwordError.stringValue = @"";
Loïc Siret3652cfb2016-10-27 10:12:07 -0400224 return YES;
225}
226
227- (BOOL)validatePassword:(NSError **)error
228{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400229 if (!self.isPasswordValid){
230 passwordError.stringValue = NSLocalizedString(@"Password is too short",
231 @"Indication for user");
Loïc Siret3652cfb2016-10-27 10:12:07 -0400232 return [self produceError:error
233 withCode:ERROR_PASSWORD_TOO_SHORT
234 andMessage:NSLocalizedString(@"Password is too short",
Alexandre Lision882289b2016-10-31 16:10:39 -0400235 @"Indication for user")];
Loïc Siret3652cfb2016-10-27 10:12:07 -0400236 }
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400237 passwordError.stringValue = @"";
Loïc Siret3652cfb2016-10-27 10:12:07 -0400238 return YES;
239}
240
241- (BOOL)validateUserInputPassword:(NSError **)error
242{
243 return [self validatePassword:error] && [self validateRepeatPassword:error];
244}
245
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400246- (IBAction)createRingAccount:(id)sender
247{
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400248 QObject::disconnect(accountCreated);
249 QObject::disconnect(accountRemoved);
250 accountCreated = QObject::connect(self.accountModel,
251 &lrc::api::NewAccountModel::accountAdded,
252 [self] (const std::string& accountID) {
253 if(accountID.compare(accountToCreate) != 0) {
254 return;
255 }
256 QObject::disconnect(accountCreated);
257 QObject::disconnect(accountRemoved);
258 //set account avatar
259 if([photoView image]) {
260 NSImage *avatarImage = [photoView image];
261 auto imageToBytes = QByteArray::fromNSData([avatarImage TIFFRepresentation]).toBase64();
262 std::string imageToString = std::string(imageToBytes.constData(), imageToBytes.length());
263 self.accountModel->setAvatar(accountID, imageToString);
264 }
265 //register username
266 if (self.registeredName && ![self.registeredName isEqualToString:@""]) {
267 NSString *passwordString = self.password ? self.password: @"";
268 NSString *usernameString = self.registeredName;
269 self.accountModel->registerName(accountID, [passwordString UTF8String], [usernameString UTF8String]);
270 }
Kateryna Kostiuk0c0801e2019-07-18 20:10:51 -0400271 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(accountID);
272 accountProperties.Ringtone.ringtonePath = [defaultRingtonePath() UTF8String];
273 self.accountModel->setAccountConfig(accountID, accountProperties);
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400274 [self registerDefaultPreferences];
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400275 [self.delegate didCreateAccountWithSuccess:YES accountId: accountToCreate];
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400276 });
277 //if account creation failed remove loading view
278 accountRemoved = QObject::connect(self.accountModel,
279 &lrc::api::NewAccountModel::accountRemoved,
280 [self] (const std::string& accountID) {
281 if(accountID.compare(accountToCreate) != 0) {
282 return;
283 }
284 QObject::disconnect(accountCreated);
285 QObject::disconnect(accountRemoved);
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400286 [self.delegate didCreateAccountWithSuccess:NO accountId: accountToCreate];
Kateryna Kostiukecaa3952018-07-13 16:00:34 -0400287 });
Loïc Siret3652cfb2016-10-27 10:12:07 -0400288 [self display:loadingView];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400289 [progressBar startAnimation:nil];
Loïc Siret3652cfb2016-10-27 10:12:07 -0400290
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400291 accountToCreate = self.accountModel->createNewAccount(lrc::api::profile::Type::RING, [displayNameField.stringValue UTF8String],"",[passwordField.stringValue UTF8String], "");
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400292}
293
294/**
295 * Set default values for preferences
296 */
297- (void)registerDefaultPreferences
298{
Andreas Traczyk92c101e2018-07-03 14:43:53 -0400299 if (!appSandboxed()) {
300 // enable AutoStartup
301 LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
302 if (loginItemsRef == nil) return;
303 CFURLRef appUrl = (__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
304 LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItemsRef, kLSSharedFileListItemLast, NULL, NULL, appUrl, NULL, NULL);
305 if (itemRef) CFRelease(itemRef);
306 }
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400307
308 // enable Notifications
Kateryna Kostiuke3503842018-12-12 16:39:45 -0500309 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:Preferences::CallNotifications];
310 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:Preferences::MessagesNotifications];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400311}
312
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400313- (IBAction)cancel:(id)sender
314{
Kateryna Kostiuk61d41162019-10-25 16:51:44 -0400315 [self.delegate didCreateAccountWithSuccess:NO accountId: accountToCreate];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400316}
317
Alexandre Lision882289b2016-10-31 16:10:39 -0400318#pragma mark - UserNameRegistration delegate methods
319
320- (IBAction)toggleSignupRing:(id)sender
321{
322 if (self.withBlockchain) {
323 [self lookupUserName];
324 }
325}
326
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500327- (IBAction)togglePasswordButton:(NSButton *)sender
328{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400329 [passwordField setHidden: !passwordField.hidden];
330 [repeatPasswordView setHidden: !repeatPasswordView.hidden];
331 buttonTopConstraint.constant = repeatPasswordView.hidden ? 35 : 25;
332 [self display:creationView];
Kateryna Kostiuk23222fe2018-11-16 14:28:02 -0500333}
334
Alexandre Lision882289b2016-10-31 16:10:39 -0400335- (BOOL)withBlockchain
336{
337 return self.signUpBlockchainState == NSOnState;
338}
339
340- (BOOL)userNameAvailableORNotBlockchain
341{
342 return !self.withBlockchain || (self.registeredName.length > 0 && self.isUserNameAvailable);
343}
344
345- (void)showLookUpAvailable:(BOOL)available andText:(NSString *)message
346{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400347 if (registeredNameField.stringValue.length > 0) {
348 registeredNameError.stringValue = message;
349 }
350 [indicatorLookupResult setHidden:YES];
351 [indicatorLookupResult stopAnimation:nil];
Alexandre Lision882289b2016-10-31 16:10:39 -0400352}
353
354- (void)onUsernameAvailabilityChangedWithNewAvailability:(BOOL)newAvailability
355{
356 self.isUserNameAvailable = newAvailability;
357}
358
359- (void)hideLookupSpinner
360{
361 [indicatorLookupResult setHidden:YES];
362}
363
364- (void)showLookupSpinner
365{
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400366 registeredNameError.stringValue = @"";
367 if (registeredNameField.stringValue.length > 0) {
368 [indicatorLookupResult setHidden:NO];
369 [indicatorLookupResult startAnimation:nil];
370 }
Alexandre Lision882289b2016-10-31 16:10:39 -0400371}
372
373- (BOOL)lookupUserName
374{
375 [self showLookupSpinner];
376 QObject::disconnect(registeredNameFound);
377 registeredNameFound = QObject::connect(
378 &NameDirectory::instance(),
379 &NameDirectory::registeredNameFound,
Kateryna Kostiukbe7e2e42019-07-26 17:44:12 -0400380 [=] (NameDirectory::LookupStatus status,
381 const QString& address, const QString& name) {
Alexandre Lision882289b2016-10-31 16:10:39 -0400382 NSLog(@"Name lookup ended");
383 lookupQueued = NO;
384 //If this is the username we are waiting for, we can disconnect.
385 if (name.compare(QString::fromNSString(usernameWaitingForLookupResult)) == 0) {
386 QObject::disconnect(registeredNameFound);
387 } else {
388 //Keep waiting...
389 return;
390 }
391
392 //We may now stop the spinner
393 [self hideLookupSpinner];
394
395 BOOL isAvailable = NO;
396 NSString* message;
397 switch(status)
398 {
399 case NameDirectory::LookupStatus::SUCCESS:
400 {
401 message = NSLocalizedString(@"The entered username is not available",
402 @"Text shown to user when his username is already registered");
403 isAvailable = NO;
404 break;
405 }
406 case NameDirectory::LookupStatus::NOT_FOUND:
407 {
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400408 message = @"";
Alexandre Lision882289b2016-10-31 16:10:39 -0400409 isAvailable = YES;
410 break;
411 }
412 case NameDirectory::LookupStatus::INVALID_NAME:
413 {
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400414 message = NSLocalizedString(@"Invalid username.",
Alexandre Lision882289b2016-10-31 16:10:39 -0400415 @"Text shown to user when his username is invalid to be registered");
416 isAvailable = NO;
417 break;
418 }
419 case NameDirectory::LookupStatus::ERROR:
420 default:
421 {
422 message = NSLocalizedString(@"Failed to perform lookup",
423 @"Text shown to user when an error occur at registration");
424 isAvailable = NO;
425 break;
426 }
427 }
428 [self showLookUpAvailable:isAvailable andText: message];
429 [self onUsernameAvailabilityChangedWithNewAvailability:isAvailable];
430
431 });
432
433 //Start the lookup in a second so that the UI dosen't seem to freeze
Kateryna Kostiukbe7e2e42019-07-26 17:44:12 -0400434 BOOL result = NameDirectory::instance().lookupName(QString(), QString::fromNSString(usernameWaitingForLookupResult));
Alexandre Lision882289b2016-10-31 16:10:39 -0400435
436}
437
Alexandre Lision5dc5d312016-11-10 10:41:37 -0500438#pragma mark - NSTextFieldDelegate delegate methods
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400439
Alexandre Lision882289b2016-10-31 16:10:39 -0400440- (void)controlTextDidChange:(NSNotification *)notif
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400441{
442 NSTextField* textField = [notif object];
Kateryna Kostiukc7e68f32019-10-09 16:15:45 -0400443 if (textField.tag == PASSWORD_TAG) {
444 NSError *error = nil;
445 [self validatePassword: &error];
446 return;
447 }
448 if (textField.tag == REPEAT_PASSWORD_TAG) {
449 NSError *error = nil;
450 [self validateRepeatPassword: &error];
451 return;
452 }
Alexandre Lision882289b2016-10-31 16:10:39 -0400453 if (textField.tag != BLOCKCHAIN_NAME_TAG) {
454 return;
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400455 }
Alexandre Lision882289b2016-10-31 16:10:39 -0400456 NSString* alias = textField.stringValue;
Alexandre Lision882289b2016-10-31 16:10:39 -0400457 [self showLookupSpinner];
458 [self onUsernameAvailabilityChangedWithNewAvailability:NO];
459 [NSObject cancelPreviousPerformRequestsWithTarget:self];
460 [self performSelector:@selector(lookUp:) withObject:alias afterDelay:0.5];
461}
462
463- (void) lookUp:(NSString*) name
464{
465 if (self.withBlockchain && !lookupQueued) {
466 usernameWaitingForLookupResult = name;
467 lookupQueued = YES;
468 [self lookupUserName];
469 }
470}
471
472
473+ (NSSet *)keyPathsForValuesAffectingUserNameAvailableORNotBlockchain
474{
475 return [NSSet setWithObjects: NSStringFromSelector(@selector(signUpBlockchainState)),
476 NSStringFromSelector(@selector(isUserNameAvailable)),
477 nil];
478}
479
480+ (NSSet *)keyPathsForValuesAffectingWithBlockchain
481{
482 return [NSSet setWithObjects: NSStringFromSelector(@selector(signUpBlockchainState)),
483 nil];
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400484}
485
Loïc Siret3652cfb2016-10-27 10:12:07 -0400486+ (NSSet *)keyPathsForValuesAffectingIsPasswordValid
487{
488 return [NSSet setWithObjects:@"password", nil];
489}
490
491+ (NSSet *)keyPathsForValuesAffectingIsRepeatPasswordValid
492{
493 return [NSSet setWithObjects:@"password", @"repeatPassword", nil];
494}
Loïc Siretfcb4ca62016-09-21 17:12:09 -0400495@end