blob: 752fd691e8db4c7e58e2d3a188f2de6c6a92f955 [file] [log] [blame]
Alexandre Lision34079c22016-10-31 16:14:02 -04001/*
2 * Copyright (C) 2016 Savoir-faire Linux Inc.
3 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040020#import <Cocoa/Cocoa.h>
21
Alexandre Lision34079c22016-10-31 16:14:02 -040022#import "RegisterNameWC.h"
Alexandre Lision34079c22016-10-31 16:14:02 -040023#import "AppDelegate.h"
24
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040025//LRC
26#import <api/lrc.h>
27#import <api/newaccountmodel.h>
28#import <account.h>
Alexandre Lision34079c22016-10-31 16:14:02 -040029
30@implementation RegisterNameWC
31{
32 __unsafe_unretained IBOutlet NSTextField* registeredNameField;
33 __unsafe_unretained IBOutlet NSSecureTextField* passwordField;
34 __unsafe_unretained IBOutlet NSImageView* ivLookupResult;
35 __unsafe_unretained IBOutlet NSProgressIndicator* indicatorLookupResult;
36
37 __unsafe_unretained IBOutlet NSProgressIndicator *registrationProgress;
38
39 QMetaObject::Connection registrationEnded;
40 QMetaObject::Connection registeredNameFound;
41
42 BOOL lookupQueued;
43 NSString* usernameWaitingForLookupResult;
44}
45
46NSInteger const BLOCKCHAIN_NAME_TAG = 2;
47
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040048@synthesize accountModel;
Alexandre Lision34079c22016-10-31 16:14:02 -040049
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040050-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
Alexandre Lision34079c22016-10-31 16:14:02 -040051{
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040052 if (self = [self initWithWindowNibName:nibNameOrNil])
53 {
54 self.accountModel= accountModel;
55 }
56 return self;
Alexandre Lision34079c22016-10-31 16:14:02 -040057}
58
59- (void)windowDidLoad
60{
61 [super windowDidLoad];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040062 auto accounts = self.accountModel->getAccountList();
Alexandre Lision34079c22016-10-31 16:14:02 -040063 [registeredNameField setTag:BLOCKCHAIN_NAME_TAG];
Alexandre Lision34079c22016-10-31 16:14:02 -040064 [ivLookupResult setHidden:YES];
65 [indicatorLookupResult setHidden:YES];
Kateryna Kostiukbdaa2742018-09-04 15:49:30 -040066 // self.password = @"";
67 //self.registeredName = @"";
68 // [registeredNameField setPlaceholderString:@"Username..."];
69 // [passwordField setPlaceholderString:@"Password..."];
Alexandre Lision34079c22016-10-31 16:14:02 -040070}
71
72#pragma mark - Username validation delegate methods
73
74- (BOOL)userNameAvailable
75{
Kateryna Kostiukbdaa2742018-09-04 15:49:30 -040076 return (registeredNameField.stringValue.length > 0 && self.isUserNameAvailable);
Alexandre Lision34079c22016-10-31 16:14:02 -040077}
78
79- (void)showLookUpAvailable:(BOOL)available andText:(NSString *)message
80{
81 [ivLookupResult setImage:[NSImage imageNamed:(available?@"ic_action_accept":@"ic_action_cancel")]] ;
82 [ivLookupResult setHidden:NO];
83 [ivLookupResult setToolTip:message];
84}
85
86- (void)onUsernameAvailabilityChangedWithNewAvailability:(BOOL)newAvailability
87{
88 self.isUserNameAvailable = newAvailability;
89}
90
91- (void)hideLookupSpinner
92{
93 [indicatorLookupResult setHidden:YES];
94}
95
96- (void)showLookupSpinner
97{
98 [ivLookupResult setHidden:YES];
99 [indicatorLookupResult setHidden:NO];
100 [indicatorLookupResult startAnimation:nil];
101}
102
103- (BOOL)lookupUserName
104{
105 [self showLookupSpinner];
106 QObject::disconnect(registeredNameFound);
107 registeredNameFound = QObject::connect(
108 &NameDirectory::instance(),
109 &NameDirectory::registeredNameFound,
110 [=] ( const Account* account, NameDirectory::LookupStatus status, const QString& address, const QString& name) {
111 NSLog(@"Name lookup ended");
112 lookupQueued = NO;
113 //If this is the username we are waiting for, we can disconnect.
114 if (name.compare(QString::fromNSString(usernameWaitingForLookupResult)) == 0) {
115 QObject::disconnect(registeredNameFound);
116 } else {
117 //Keep waiting...
118 return;
119 }
120
121 //We may now stop the spinner
122 [self hideLookupSpinner];
123
124 BOOL isAvailable = NO;
125 NSString* message;
126 switch(status)
127 {
128 case NameDirectory::LookupStatus::SUCCESS:
129 {
130 message = NSLocalizedString(@"The entered username is not available",
131 @"Text shown to user when his username is already registered");
132 isAvailable = NO;
133 break;
134 }
135 case NameDirectory::LookupStatus::NOT_FOUND:
136 {
137 message = NSLocalizedString(@"The entered username is available",
138 @"Text shown to user when his username is available to be registered");
139 isAvailable = YES;
140 break;
141 }
142 case NameDirectory::LookupStatus::INVALID_NAME:
143 {
Alexandre Lision5dc5d312016-11-10 10:41:37 -0500144 message = NSLocalizedString(@"The entered username is invalid. It must have at least 3 characters and contain only lowercase alphanumeric characters.",
Alexandre Lision34079c22016-10-31 16:14:02 -0400145 @"Text shown to user when his username is invalid to be registered");
146 isAvailable = NO;
147 break;
148 }
149 case NameDirectory::LookupStatus::ERROR:
150 default:
151 {
152 message = NSLocalizedString(@"Failed to perform lookup",
153 @"Text shown to user when an error occur at registration");
154 isAvailable = NO;
155 break;
156 }
157 }
158 [self showLookUpAvailable:isAvailable andText: message];
159 [self onUsernameAvailabilityChangedWithNewAvailability:isAvailable];
Alexandre Lision34079c22016-10-31 16:14:02 -0400160 }
161 );
162
163 //Start the lookup in a second so that the UI dosen't seem to freeze
164 BOOL result = NameDirectory::instance().lookupName(nullptr, QString(), QString::fromNSString(usernameWaitingForLookupResult));
Alexandre Lision34079c22016-10-31 16:14:02 -0400165}
166
167- (void)controlTextDidChange:(NSNotification *)notif
168{
169 NSTextField* textField = [notif object];
170 if (textField.tag != BLOCKCHAIN_NAME_TAG) {
171 return;
172 }
173 NSString* alias = textField.stringValue;
174
175 [self showLookupSpinner];
176 [self onUsernameAvailabilityChangedWithNewAvailability:NO];
177 [NSObject cancelPreviousPerformRequestsWithTarget:self];
178 [self performSelector:@selector(lookUp:) withObject:alias afterDelay:0.5];
179}
180
181- (void) lookUp:(NSString*) name
182{
183 if (!lookupQueued) {
184 usernameWaitingForLookupResult = name;
185 lookupQueued = YES;
186 [self lookupUserName];
187 }
188}
189
190#pragma mark - Registration process
191
192- (IBAction)registerUsername:(id)sender
193{
194 [registrationProgress startAnimation:nil];
195 [self showLoading];
196 [self setCallback];
197
Kateryna Kostiukbdaa2742018-09-04 15:49:30 -0400198 self.isUserNameAvailable = self.accountModel->registerName(self.selectedAccountID, [passwordField.stringValue UTF8String], [registeredNameField.stringValue UTF8String]);
Alexandre Lision34079c22016-10-31 16:14:02 -0400199 if (!self.isUserNameAvailable) {
200 NSLog(@"Could not initialize registerName operation");
201 QObject::disconnect(registrationEnded);
202 }
203}
204
205- (void)setCallback
206{
207 QObject::disconnect(registrationEnded);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400208 registrationEnded = QObject::connect(self.accountModel,
209 &lrc::api::NewAccountModel::nameRegistrationEnded,
210 [self] (const std::string& accountId, lrc::api::account::RegisterNameStatus status, const std::string& name) {
211 if(accountId.compare(self.selectedAccountID) != 0) {
212 return;
213 }
214 switch(status)
215 {
216 case lrc::api::account::RegisterNameStatus::SUCCESS: {
Kateryna Kostiukbdaa2742018-09-04 15:49:30 -0400217 [self.delegate didRegisterName: registeredNameField.stringValue withSuccess: YES];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400218 break;
219 }
220 case lrc::api::account::RegisterNameStatus::INVALID_NAME:
221 case lrc::api::account::RegisterNameStatus::WRONG_PASSWORD:
222 case lrc::api::account::RegisterNameStatus::NETWORK_ERROR:
223 case lrc::api::account::RegisterNameStatus::ALREADY_TAKEN: {
Alexandre Lision34079c22016-10-31 16:14:02 -0400224 [self showError];
225 break;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400226 }
Alexandre Lision34079c22016-10-31 16:14:02 -0400227 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400228 QObject::disconnect(registrationEnded);
Alexandre Lision34079c22016-10-31 16:14:02 -0400229 });
230}
231
232
233+ (NSSet *)keyPathsForValuesAffectingUserNameAvailableORNotBlockchain
234{
235 return [NSSet setWithObjects: NSStringFromSelector(@selector(isUserNameAvailable)), nil];
236}
237
Alexandre Lision34079c22016-10-31 16:14:02 -0400238
239@end