blob: 312abab8fbdd25323628a536327f4e75f7cff63d [file] [log] [blame]
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import <Cocoa/Cocoa.h>
#import "RegisterNameWC.h"
#import "AppDelegate.h"
//LRC
#import <api/lrc.h>
#import <api/newaccountmodel.h>
#import <account.h>
@implementation RegisterNameWC
{
__unsafe_unretained IBOutlet NSTextField* registeredNameField;
__unsafe_unretained IBOutlet NSImageView* ivLookupResult;
__unsafe_unretained IBOutlet NSProgressIndicator* indicatorLookupResult;
__unsafe_unretained IBOutlet NSProgressIndicator *registrationProgress;
QMetaObject::Connection registrationEnded;
QMetaObject::Connection registeredNameFound;
BOOL lookupQueued;
NSString* usernameWaitingForLookupResult;
}
NSInteger const BLOCKCHAIN_NAME_TAG = 2;
@synthesize accountModel;
-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
{
if (self = [self initWithWindowNibName:nibNameOrNil])
{
self.accountModel= accountModel;
}
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
auto accounts = self.accountModel->getAccountList();
[registeredNameField setTag:BLOCKCHAIN_NAME_TAG];
[ivLookupResult setHidden:YES];
[indicatorLookupResult setHidden:YES];
}
#pragma mark - Username validation delegate methods
- (BOOL)userNameAvailable
{
return (registeredNameField.stringValue.length > 0 && self.isUserNameAvailable);
}
- (void)showLookUpAvailable:(BOOL)available andText:(NSString *)message
{
[ivLookupResult setImage:[NSImage imageNamed:(available?@"ic_action_accept":@"ic_action_cancel")]] ;
[ivLookupResult setHidden:NO];
[ivLookupResult setToolTip:message];
}
- (void)onUsernameAvailabilityChangedWithNewAvailability:(BOOL)newAvailability
{
self.isUserNameAvailable = newAvailability;
}
- (void)hideLookupSpinner
{
[indicatorLookupResult setHidden:YES];
}
- (void)showLookupSpinner
{
[ivLookupResult setHidden:YES];
[indicatorLookupResult setHidden:NO];
[indicatorLookupResult startAnimation:nil];
}
- (BOOL)lookupUserName
{
[self showLookupSpinner];
QObject::disconnect(registeredNameFound);
registeredNameFound = QObject::connect(
&NameDirectory::instance(),
&NameDirectory::registeredNameFound,
[=] ( const Account* account, NameDirectory::LookupStatus status, const QString& address, const QString& name) {
NSLog(@"Name lookup ended");
lookupQueued = NO;
//If this is the username we are waiting for, we can disconnect.
if (name.compare(QString::fromNSString(usernameWaitingForLookupResult)) == 0) {
QObject::disconnect(registeredNameFound);
} else {
//Keep waiting...
return;
}
//We may now stop the spinner
[self hideLookupSpinner];
BOOL isAvailable = NO;
NSString* message;
switch(status)
{
case NameDirectory::LookupStatus::SUCCESS:
{
message = NSLocalizedString(@"The entered username is not available",
@"Text shown to user when his username is already registered");
isAvailable = NO;
break;
}
case NameDirectory::LookupStatus::NOT_FOUND:
{
message = NSLocalizedString(@"The entered username is available",
@"Text shown to user when his username is available to be registered");
isAvailable = YES;
break;
}
case NameDirectory::LookupStatus::INVALID_NAME:
{
message = NSLocalizedString(@"The entered username is invalid. It must have at least 3 characters and contain only lowercase alphanumeric characters.",
@"Text shown to user when his username is invalid to be registered");
isAvailable = NO;
break;
}
case NameDirectory::LookupStatus::ERROR:
default:
{
message = NSLocalizedString(@"Failed to perform lookup",
@"Text shown to user when an error occur at registration");
isAvailable = NO;
break;
}
}
[self showLookUpAvailable:isAvailable andText: message];
[self onUsernameAvailabilityChangedWithNewAvailability:isAvailable];
}
);
//Start the lookup in a second so that the UI dosen't seem to freeze
BOOL result = NameDirectory::instance().lookupName(nullptr, QString(), QString::fromNSString(usernameWaitingForLookupResult));
}
- (void)controlTextDidChange:(NSNotification *)notif
{
NSTextField* textField = [notif object];
if (textField.tag != BLOCKCHAIN_NAME_TAG) {
return;
}
NSString* alias = textField.stringValue;
[self showLookupSpinner];
[self onUsernameAvailabilityChangedWithNewAvailability:NO];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self performSelector:@selector(lookUp:) withObject:alias afterDelay:0.5];
}
- (void) lookUp:(NSString*) name
{
if (!lookupQueued) {
usernameWaitingForLookupResult = name;
lookupQueued = YES;
[self lookupUserName];
}
}
#pragma mark - Registration process
- (IBAction)registerUsername:(id)sender
{
[registrationProgress startAnimation:nil];
[self showLoading];
[self setCallback];
self.isUserNameAvailable = self.accountModel->registerName(self.selectedAccountID, "", [registeredNameField.stringValue UTF8String]);
if (!self.isUserNameAvailable) {
NSLog(@"Could not initialize registerName operation");
QObject::disconnect(registrationEnded);
}
}
- (void)setCallback
{
QObject::disconnect(registrationEnded);
registrationEnded = QObject::connect(self.accountModel,
&lrc::api::NewAccountModel::nameRegistrationEnded,
[self] (const std::string& accountId, lrc::api::account::RegisterNameStatus status, const std::string& name) {
if(accountId.compare(self.selectedAccountID) != 0) {
return;
}
switch(status)
{
case lrc::api::account::RegisterNameStatus::SUCCESS: {
[self.delegate didRegisterName: registeredNameField.stringValue withSuccess: YES];
break;
}
case lrc::api::account::RegisterNameStatus::INVALID_NAME:
case lrc::api::account::RegisterNameStatus::WRONG_PASSWORD:
case lrc::api::account::RegisterNameStatus::NETWORK_ERROR:
case lrc::api::account::RegisterNameStatus::ALREADY_TAKEN: {
[self showError];
break;
}
}
QObject::disconnect(registrationEnded);
});
}
+ (NSSet *)keyPathsForValuesAffectingUserNameAvailableORNotBlockchain
{
return [NSSet setWithObjects: NSStringFromSelector(@selector(isUserNameAvailable)), nil];
}
@end