blob: 9e85fbc6e9d5a338caa6e46329f312aa36a8a2c3 [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 Kostiuk1f8c1252018-07-30 18:18:57 -040066 self.password = @"";
67 self.registeredName = @"";
Alexandre Lision34079c22016-10-31 16:14:02 -040068}
69
70#pragma mark - Username validation delegate methods
71
72- (BOOL)userNameAvailable
73{
74 return (self.registeredName.length > 0 && self.isUserNameAvailable);
75}
76
77- (void)showLookUpAvailable:(BOOL)available andText:(NSString *)message
78{
79 [ivLookupResult setImage:[NSImage imageNamed:(available?@"ic_action_accept":@"ic_action_cancel")]] ;
80 [ivLookupResult setHidden:NO];
81 [ivLookupResult setToolTip:message];
82}
83
84- (void)onUsernameAvailabilityChangedWithNewAvailability:(BOOL)newAvailability
85{
86 self.isUserNameAvailable = newAvailability;
87}
88
89- (void)hideLookupSpinner
90{
91 [indicatorLookupResult setHidden:YES];
92}
93
94- (void)showLookupSpinner
95{
96 [ivLookupResult setHidden:YES];
97 [indicatorLookupResult setHidden:NO];
98 [indicatorLookupResult startAnimation:nil];
99}
100
101- (BOOL)lookupUserName
102{
103 [self showLookupSpinner];
104 QObject::disconnect(registeredNameFound);
105 registeredNameFound = QObject::connect(
106 &NameDirectory::instance(),
107 &NameDirectory::registeredNameFound,
108 [=] ( const Account* account, NameDirectory::LookupStatus status, const QString& address, const QString& name) {
109 NSLog(@"Name lookup ended");
110 lookupQueued = NO;
111 //If this is the username we are waiting for, we can disconnect.
112 if (name.compare(QString::fromNSString(usernameWaitingForLookupResult)) == 0) {
113 QObject::disconnect(registeredNameFound);
114 } else {
115 //Keep waiting...
116 return;
117 }
118
119 //We may now stop the spinner
120 [self hideLookupSpinner];
121
122 BOOL isAvailable = NO;
123 NSString* message;
124 switch(status)
125 {
126 case NameDirectory::LookupStatus::SUCCESS:
127 {
128 message = NSLocalizedString(@"The entered username is not available",
129 @"Text shown to user when his username is already registered");
130 isAvailable = NO;
131 break;
132 }
133 case NameDirectory::LookupStatus::NOT_FOUND:
134 {
135 message = NSLocalizedString(@"The entered username is available",
136 @"Text shown to user when his username is available to be registered");
137 isAvailable = YES;
138 break;
139 }
140 case NameDirectory::LookupStatus::INVALID_NAME:
141 {
Alexandre Lision5dc5d312016-11-10 10:41:37 -0500142 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 -0400143 @"Text shown to user when his username is invalid to be registered");
144 isAvailable = NO;
145 break;
146 }
147 case NameDirectory::LookupStatus::ERROR:
148 default:
149 {
150 message = NSLocalizedString(@"Failed to perform lookup",
151 @"Text shown to user when an error occur at registration");
152 isAvailable = NO;
153 break;
154 }
155 }
156 [self showLookUpAvailable:isAvailable andText: message];
157 [self onUsernameAvailabilityChangedWithNewAvailability:isAvailable];
Alexandre Lision34079c22016-10-31 16:14:02 -0400158 }
159 );
160
161 //Start the lookup in a second so that the UI dosen't seem to freeze
162 BOOL result = NameDirectory::instance().lookupName(nullptr, QString(), QString::fromNSString(usernameWaitingForLookupResult));
Alexandre Lision34079c22016-10-31 16:14:02 -0400163}
164
165- (void)controlTextDidChange:(NSNotification *)notif
166{
167 NSTextField* textField = [notif object];
168 if (textField.tag != BLOCKCHAIN_NAME_TAG) {
169 return;
170 }
171 NSString* alias = textField.stringValue;
172
173 [self showLookupSpinner];
174 [self onUsernameAvailabilityChangedWithNewAvailability:NO];
175 [NSObject cancelPreviousPerformRequestsWithTarget:self];
176 [self performSelector:@selector(lookUp:) withObject:alias afterDelay:0.5];
177}
178
179- (void) lookUp:(NSString*) name
180{
181 if (!lookupQueued) {
182 usernameWaitingForLookupResult = name;
183 lookupQueued = YES;
184 [self lookupUserName];
185 }
186}
187
188#pragma mark - Registration process
189
190- (IBAction)registerUsername:(id)sender
191{
192 [registrationProgress startAnimation:nil];
193 [self showLoading];
194 [self setCallback];
195
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400196 self.isUserNameAvailable = self.accountModel->registerName(self.selectedAccountID, [self.password UTF8String], [self.registeredName UTF8String]);
Alexandre Lision34079c22016-10-31 16:14:02 -0400197 if (!self.isUserNameAvailable) {
198 NSLog(@"Could not initialize registerName operation");
199 QObject::disconnect(registrationEnded);
200 }
201}
202
203- (void)setCallback
204{
205 QObject::disconnect(registrationEnded);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400206 registrationEnded = QObject::connect(self.accountModel,
207 &lrc::api::NewAccountModel::nameRegistrationEnded,
208 [self] (const std::string& accountId, lrc::api::account::RegisterNameStatus status, const std::string& name) {
209 if(accountId.compare(self.selectedAccountID) != 0) {
210 return;
211 }
212 switch(status)
213 {
214 case lrc::api::account::RegisterNameStatus::SUCCESS: {
215 [self.delegate didRegisterName: self.registeredName withSuccess: YES];
216 break;
217 }
218 case lrc::api::account::RegisterNameStatus::INVALID_NAME:
219 case lrc::api::account::RegisterNameStatus::WRONG_PASSWORD:
220 case lrc::api::account::RegisterNameStatus::NETWORK_ERROR:
221 case lrc::api::account::RegisterNameStatus::ALREADY_TAKEN: {
Alexandre Lision34079c22016-10-31 16:14:02 -0400222 [self showError];
223 break;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400224 }
Alexandre Lision34079c22016-10-31 16:14:02 -0400225 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400226 QObject::disconnect(registrationEnded);
Alexandre Lision34079c22016-10-31 16:14:02 -0400227 });
228}
229
230
231+ (NSSet *)keyPathsForValuesAffectingUserNameAvailableORNotBlockchain
232{
233 return [NSSet setWithObjects: NSStringFromSelector(@selector(isUserNameAvailable)), nil];
234}
235
Alexandre Lision34079c22016-10-31 16:14:02 -0400236
237@end