Commit 34079c26 authored by Alexandre Lision's avatar Alexandre Lision

blockchain: register name in account settings

- Show field of blockchain server. No edition possible yet since this
feature has not been tested well enough
- Display register name window

Change-Id: I2b19ce83e40de9a6cda0e0ec601516b75c01702b
Tuleap: #1158
parent 882289b5
......@@ -156,6 +156,8 @@ SET(ringclient_CONTROLLERS
src/RingWizardNewAccountVC.h
src/DialpadWC.mm
src/DialpadWC.h
src/RegisterNameWC.mm
src/RegisterNameWC.h
)
SET(ringclient_BACKENDS
......@@ -223,6 +225,7 @@ SET(ringclient_XIBS
RingWizardNewAccount
RingWizardChoose
Dialpad
RegisterNameWindow
)
# Icons
......
......@@ -21,26 +21,34 @@
#import <accountmodel.h>
#import <qitemselectionmodel.h>
@interface AccRingVC ()
#import "RegisterNameWC.h"
@property (assign) IBOutlet NSTextField *aliasTextField;
@property (assign) IBOutlet NSTextField *bootstrapField;
@property (assign) IBOutlet NSTextField *hashField;
@interface AccRingVC () <RegisterNameDelegate>
@property (assign) IBOutlet NSButton *upnpButton;
@property (assign) IBOutlet NSButton *autoAnswerButton;
@property (assign) IBOutlet NSButton *userAgentButton;
@property (assign) IBOutlet NSTextField *userAgentTextField;
@property (unsafe_unretained) IBOutlet NSTextField *aliasTextField;
@property (unsafe_unretained) IBOutlet NSTextField *bootstrapField;
@property (unsafe_unretained) IBOutlet NSTextField *blockchainField;
@property (unsafe_unretained) IBOutlet NSTextField *ringIDField;
@property (unsafe_unretained) IBOutlet NSButton *registerBlockchainNameButton;
@property (unsafe_unretained) IBOutlet NSTextField *registeredNameField;
@property (unsafe_unretained) IBOutlet NSButton *upnpButton;
@property (unsafe_unretained) IBOutlet NSButton *autoAnswerButton;
@property (unsafe_unretained) IBOutlet NSButton *userAgentButton;
@property (unsafe_unretained) IBOutlet NSTextField *userAgentTextField;
@property (unsafe_unretained) IBOutlet NSButton *allowUnknown;
@property (unsafe_unretained) IBOutlet NSButton *allowHistory;
@property (unsafe_unretained) IBOutlet NSButton *allowContacts;
@property AbstractLoadingWC* accountModal;
@end
@implementation AccRingVC
@synthesize bootstrapField;
@synthesize hashField;
@synthesize ringIDField;
@synthesize aliasTextField;
@synthesize blockchainField;
@synthesize upnpButton;
@synthesize autoAnswerButton;
@synthesize userAgentButton;
......@@ -51,6 +59,7 @@ typedef NS_ENUM(NSInteger, TagViews) {
ALIAS = 0,
HOSTNAME,
USERAGENT,
BLOCKCHAIN,
};
- (void)awakeFromNib
......@@ -59,6 +68,7 @@ typedef NS_ENUM(NSInteger, TagViews) {
[aliasTextField setTag:TagViews::ALIAS];
[userAgentTextField setTag:TagViews::USERAGENT];
[bootstrapField setTag:TagViews::HOSTNAME];
[blockchainField setTag:TagViews::BLOCKCHAIN];
QObject::connect(AccountModel::instance().selectionModel(),
&QItemSelectionModel::currentChanged,
......@@ -90,13 +100,37 @@ typedef NS_ENUM(NSInteger, TagViews) {
[userAgentTextField setStringValue:account->userAgent().toNSString()];
[bootstrapField setStringValue:account->hostname().toNSString()];
[blockchainField setStringValue:account->nameServiceURL().toNSString()];
if([account->username().toNSString() isEqualToString:@""])
[hashField setStringValue:NSLocalizedString(@"Reopen account to see your hash",
if([account->username().toNSString() isEqualToString:@""]) {
[ringIDField setStringValue:NSLocalizedString(@"Reopen account to see your hash",
@"Show advice to user")];
else
[hashField setStringValue:account->username().toNSString()];
} else {
[ringIDField setStringValue:account->username().toNSString()];
}
[self refreshRegisteredName:account];
}
- (void) refreshRegisteredName:(Account*) account
{
[self.registerBlockchainNameButton setHidden:!account->registeredName().isEmpty()];
[self.registeredNameField setStringValue:account->registeredName().toNSString()];
}
- (IBAction)startNameRegistration:(id)sender
{
auto registerWC = [[RegisterNameWC alloc] initWithDelegate:self];
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_9
[self.view.window beginSheet:registerWC.window completionHandler:nil];
#else
[NSApp beginSheet: registerWC.window
modalForWindow: self.view.window
modalDelegate: self
didEndSelector: nil
contextInfo: nil];
#endif
self.accountModal = registerWC;
}
- (IBAction)toggleUpnp:(NSButton *)sender {
......@@ -146,9 +180,18 @@ typedef NS_ENUM(NSInteger, TagViews) {
case TagViews::USERAGENT:
AccountModel::instance().selectedAccount()->setUserAgent([[textField stringValue] UTF8String]);
break;
case TagViews::BLOCKCHAIN:
AccountModel::instance().selectedAccount()->setNameServiceURL([[textField stringValue] UTF8String]);
break;
default:
break;
}
}
- (void) didRegisterNameWithSuccess
{
[self.accountModal close];
[self refreshRegisteredName:AccountModel::instance().selectedAccount()];
}
@end
/*
* 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 "AbstractLoadingWC.h"
#import "LoadingWCDelegate.h"
@protocol RegisterNameDelegate <LoadingWCDelegate>
@optional
- (void) didRegisterNameWithSuccess;
@end
@interface RegisterNameWC : AbstractLoadingWC
- (id)initWithDelegate:(id <LoadingWCDelegate>) del;
@property (nonatomic, weak) NSWindowController <RegisterNameDelegate>* delegate;
/**
* KVO with the registeredNameField
*/
@property (nonatomic, weak)NSString* registeredName;
/**
* KVO with the passwordField
*/
@property (nonatomic, weak)NSString* password;
/**
* KVO validators for the UI
*/
@property (readonly)BOOL isPasswordValid;
@property (assign)BOOL isUserNameAvailable;
@end
/*
* 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 "RegisterNameWC.h"
//Cocoa
#import <AddressBook/AddressBook.h>
//LRC
#import <accountmodel.h>
#import <QItemSelectionModel>
#import <account.h>
#import "AppDelegate.h"
@interface RegisterNameWC ()
@end
@implementation RegisterNameWC
{
__unsafe_unretained IBOutlet NSTextField* registeredNameField;
__unsafe_unretained IBOutlet NSSecureTextField* passwordField;
__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;
- (id)initWithDelegate:(id <LoadingWCDelegate>) del
{
return [self initWithDelegate:del actionCode:0];
}
- (id)initWithDelegate:(id <RegisterNameDelegate>) del actionCode:(NSInteger) code
{
return [super initWithWindowNibName:@"RegisterNameWindow" delegate:del actionCode:code];
}
- (void)windowDidLoad
{
[super windowDidLoad];
[registeredNameField setTag:BLOCKCHAIN_NAME_TAG];
self.registeredName = @"";
[ivLookupResult setHidden:YES];
[indicatorLookupResult setHidden:YES];
}
#pragma mark - Input validation
- (BOOL)isPasswordValid
{
return self.password.length >= 6;
}
#pragma mark - Username validation delegate methods
- (BOOL)userNameAvailable
{
return (self.registeredName.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 leat 3 characters and contains 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 = AccountModel::instance().selectedAccount()->registerName(QString::fromNSString(self.password),
QString::fromNSString(self.registeredName));
if (!self.isUserNameAvailable) {
NSLog(@"Could not initialize registerName operation");
QObject::disconnect(registrationEnded);
}
}
- (void)setCallback
{
QObject::disconnect(registrationEnded);
registrationEnded = QObject::connect(AccountModel::instance().selectedAccount(),
&Account::nameRegistrationEnded,
[=] (NameDirectory::RegisterNameStatus status, const QString& name)
{
QObject::disconnect(registrationEnded);
switch(status) {
case NameDirectory::RegisterNameStatus::WRONG_PASSWORD:
case NameDirectory::RegisterNameStatus::ALREADY_TAKEN:
case NameDirectory::RegisterNameStatus::NETWORK_ERROR:
[self showError];
break;
case NameDirectory::RegisterNameStatus::SUCCESS:
[self.delegate didRegisterNameWithSuccess];
break;
}
});
}
+ (NSSet *)keyPathsForValuesAffectingUserNameAvailableORNotBlockchain
{
return [NSSet setWithObjects: NSStringFromSelector(@selector(isUserNameAvailable)), nil];
}
+ (NSSet *)keyPathsForValuesAffectingIsPasswordValid
{
return [NSSet setWithObjects:@"password", nil];
}
@end
This diff is collapsed.
/* Class = "NSSecureTextFieldCell"; placeholderString = "Confirm..."; ObjectID = "5Qf-em-tN4"; */
"5Qf-em-tN4.placeholderString" = "Confirm...";
/* Class = "CocoaBindingsConnection"; ibShadowedIsNilPlaceholder = "Password..."; ObjectID = "5cX-yS-4Sl"; */
"5cX-yS-4Sl.ibShadowedIsNilPlaceholder" = "Password...";
/* Class = "CocoaBindingsConnection"; ibShadowedMultipleValuesPlaceholder = "Password..."; ObjectID = "5cX-yS-4Sl"; */
"5cX-yS-4Sl.ibShadowedMultipleValuesPlaceholder" = "Password...";
/* Class = "CocoaBindingsConnection"; ibShadowedNoSelectionPlaceholder = "Password..."; ObjectID = "5cX-yS-4Sl"; */
"5cX-yS-4Sl.ibShadowedNoSelectionPlaceholder" = "Password...";
/* Class = "CocoaBindingsConnection"; ibShadowedNotApplicablePlaceholder = "Password..."; ObjectID = "5cX-yS-4Sl"; */
"5cX-yS-4Sl.ibShadowedNotApplicablePlaceholder" = "Password...";
/* Class = "NSTextFieldCell"; title = "Where"; ObjectID = "9h8-GU-av4"; */
"9h8-GU-av4.title" = "Where";
/* Class = "NSTextFieldCell"; title = "Choose where to backup your account. It needs to be password protected."; ObjectID = "KYZ-TW-44Y"; */
"KYZ-TW-44Y.title" = "Choose where to backup your account. It needs to be password protected.";
/* Class = "NSWindow"; title = "Window"; ObjectID = "QvC-M9-y7g"; */
"QvC-M9-y7g.title" = "Window";
/* Class = "NSButtonCell"; title = "OK"; ObjectID = "VN1-A3-RIh"; */
"VN1-A3-RIh.title" = "OK";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "cSU-aD-OwX"; */
"cSU-aD-OwX.title" = "Cancel";
/* Class = "CocoaBindingsConnection"; ibShadowedIsNilPlaceholder = "Password..."; ObjectID = "ccf-Bx-Qq8"; */
"ccf-Bx-Qq8.ibShadowedIsNilPlaceholder" = "Password...";
/* Class = "CocoaBindingsConnection"; ibShadowedMultipleValuesPlaceholder = "Password..."; ObjectID = "ccf-Bx-Qq8"; */
"ccf-Bx-Qq8.ibShadowedMultipleValuesPlaceholder" = "Password...";
/* Class = "CocoaBindingsConnection"; ibShadowedNoSelectionPlaceholder = "Password..."; ObjectID = "ccf-Bx-Qq8"; */
"ccf-Bx-Qq8.ibShadowedNoSelectionPlaceholder" = "Password...";
/* Class = "CocoaBindingsConnection"; ibShadowedNotApplicablePlaceholder = "Password..."; ObjectID = "ccf-Bx-Qq8"; */
"ccf-Bx-Qq8.ibShadowedNotApplicablePlaceholder" = "Password...";
/* Class = "NSTextFieldCell"; title = "An error occured during the backup"; ObjectID = "e7n-Ev-bK7"; */
"e7n-Ev-bK7.title" = "An error occured during the backup";
/* Class = "NSButtonCell"; title = "OK"; ObjectID = "rW5-Il-5YD"; */
"rW5-Il-5YD.title" = "OK";
/* Class = "NSTextFieldCell"; title = "Password"; ObjectID = "vwh-K9-3O9"; */
"vwh-K9-3O9.title" = "Password";
/* Class = "NSSecureTextFieldCell"; placeholderString = "Password..."; ObjectID = "xqz-Uz-hqU"; */
"xqz-Uz-hqU.placeholderString" = "Password...";
/* Class = "NSButtonCell"; title = "7"; ObjectID = "4Dd-Ba-oRg"; */
"4Dd-Ba-oRg.title" = "7";
/* Class = "NSButtonCell"; title = "*"; ObjectID = "6ZB-c1-gR6"; */
"6ZB-c1-gR6.title" = "*";
/* Class = "NSButtonCell"; title = "8"; ObjectID = "CTZ-Rn-5oT"; */
"CTZ-Rn-5oT.title" = "8";
/* Class = "NSButtonCell"; title = "6"; ObjectID = "ENK-x9-8ps"; */
"ENK-x9-8ps.title" = "6";
/* Class = "NSButtonCell"; title = "4"; ObjectID = "GvJ-yA-EDa"; */
"GvJ-yA-EDa.title" = "4";
/* Class = "NSButtonCell"; title = "#"; ObjectID = "H5T-k1-cjZ"; */
"H5T-k1-cjZ.title" = "#";
/* Class = "NSButtonCell"; title = "3"; ObjectID = "Hd9-Py-oob"; */
"Hd9-Py-oob.title" = "3";
/* Class = "NSButtonCell"; title = "1"; ObjectID = "Mda-73-3kM"; */
"Mda-73-3kM.title" = "1";
/* Class = "NSButtonCell"; title = "9"; ObjectID = "TYj-va-kS8"; */
"TYj-va-kS8.title" = "9";
/* Class = "NSButtonCell"; title = "2"; ObjectID = "anB-0b-8qb"; */
"anB-0b-8qb.title" = "2";
/* Class = "NSButtonCell"; title = "5"; ObjectID = "cXL-QF-edl"; */
"cXL-QF-edl.title" = "5";
/* Class = "NSButtonCell"; title = "0"; ObjectID = "u3Z-SY-MgY"; */
"u3Z-SY-MgY.title" = "0";
/* Class = "NSWindow"; title = "Dial Pad"; ObjectID = "vrA-VP-2Md"; */
"vrA-VP-2Md.title" = "Dial Pad";
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment