diff --git a/www/css/style.css b/www/css/style.css index 7f2849e0d067a90860edf4ebd584a636c36f13dc..40649fb597ccb92db55d74ff5ef109bde61be289 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -271,3 +271,11 @@ .dropzone.hover { background: lawngreen; } + +/********** + List of wallet +**********/ + +.list .item.item-wallet .badge{ + top: 28px !important; +} diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index a35a28af47ec94e723487b0c68e05e28610556ab..886b2b00c6d40eed0fc60fb35fd49e4156917de7 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -522,6 +522,15 @@ "TITLE": "Sélection de l'identité", "HELP": "Plusieurs <b>identités différentes</b> ont été envoyées, pour la clé publique <span class=\"gray\"><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</span>.<br/>Veuillez sélectionner le dossier à utiliser :" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Sélection du compte" + }, + "WALLET_LIST": { + "TITLE": "Comptes secondaires", + "BTN_NEW": "Ajouter un compte", + "NO_WALLET": "Aucun compte secondaire", + "BTN_DELETE": "Retirer un compte secondaire..." + }, "SECURITY": { "ADD_QUESTION": "Ajouter une question personnalisée ", "BTN_CLEAN": "Vider", @@ -708,7 +717,12 @@ "EXISTING_ACCOUNT_REQUEST": "Veuillez modifier vos identifiants afin qu'ils correspondent à un compte non utilisé.", "GET_LICENSE_FILE_FAILED": "Récupérer du fichier de licence impossible", "CHECK_NETWORK_CONNECTION": "Aucun nœud ne semble accessible.<br/><br/>Veuillez <b>vérifier votre connection Internet</b>.", - "ISSUE_524_TX_FAILED": "Echec du virement.<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>." + "ISSUE_524_TX_FAILED": "Echec du virement.<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Echec de l'ajout du portefeuille seconcdaire", + "UPDATE_WALLET_LIST_FAILED": "Echec du rafraichissement des portefeuilles secondaires", + "LOAD_WALLET_LIST_FAILED": "Echec du chargement des portefeuilles secondaires", + "COULD_NOT_ADD_MAIN_WALLET": "Le portefeuille à ajouter <b>doit être différent du compte principal</b> avec lequel vous êtes connecté.", + "UNKNOWN_WALLET_ID": "Portefeuille secondaire inconnu." }, "INFO": { "POPUP_TITLE": "Information", diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index 324281a831187a59e66f181c20c057d8a64e9009..17d1f849bfe11cbdaa3322f1f4df3083520530fb 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -82,8 +82,10 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ .then(UIUtils.loading.hide); }; + // removeIf(no-device) //////////////////////////////////////// - // Device Methods + // Device only methods + // (code removed when NO device) //////////////////////////////////////// function parseWIF_or_EWIF(data, options) { @@ -120,6 +122,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }); } + $scope.scanQrCodeAndGo = function() { if (!Device.barcode.enable) return; @@ -149,6 +152,27 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ .then(function(keypair) { if (!keypair || !keypair.signPk || !keypair.signSk) throw err; // rethrow the first error (e.g. Bad URI) + // User already logged + if (csWallet.isLogin()) { + // Open a temporary wallet + var wallet = csWallet.instance('WIF'); + csWallet.children.add(wallet); + return wallet.login({ + forceAuth: true, + minData: false, + authData: { + pubkey: CryptoUtils.base58.encode(keypair.signPk), + keypair: keypair + } + }) + .then(function () { + // Transfer all wallet + return $state.go('app.new_transfer', { + all: true, + wallet: wallet.id + }); + }); + } // TODO: Use a temporary wallet ? // var wallet = csWallet.instance('WIF'); // return wallet.login(...) @@ -174,6 +198,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ .catch(UIUtils.onError('ERROR.SCAN_FAILED')); }; + //////////////////////////////////////// + // End of device only methods + //////////////////////////////////////// + // endRemoveIf(no-device) + //////////////////////////////////////// // Show Help tour //////////////////////////////////////// @@ -241,7 +270,9 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ // Load wallet data (after login) $scope.loadWalletData = function(options) { - return csWallet.loadData(options) + options = options || {}; + var wallet = options.wallet || csWallet; + return wallet.loadData(options) .then(function(walletData) { if (walletData) { @@ -266,9 +297,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ options = options || {}; + var wallet = options.wallet || csWallet; + // If need auth - if (options.auth && !csWallet.isAuth()) { - return csWallet.auth(options) + if (options.auth && !wallet.isAuth()) { + return wallet.auth(options) .then(function (walletData) { if (walletData) return walletData; // failed to auth @@ -277,8 +310,8 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } // If need login - else if (!csWallet.isLogin()) { - return csWallet.login(options) + else if (!wallet.isLogin()) { + return wallet.login(options) .then(function (walletData) { if (walletData) return walletData; // failed to login @@ -287,11 +320,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } // Already login or auth - else if (!csWallet.isDataLoaded(options)) { + else if (!wallet.isDataLoaded(options)) { return $scope.loadWalletData(options); } else { - return $q.when(csWallet.data); + return $q.when(wallet.data); } }; diff --git a/www/js/controllers/login-controllers.js b/www/js/controllers/login-controllers.js index 21d383648ee4da7387170dc2739b943a264e5aa5..1ac630b0711a589fdfd10a7c3b6c52671559795c 100644 --- a/www/js/controllers/login-controllers.js +++ b/www/js/controllers/login-controllers.js @@ -22,7 +22,9 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, $scope.pubkeyPattern = '^(:?{0}|{1})$'.format(BMA.constants.regexp.PUBKEY, BMA.constants.regexp.PUBKEY_WITH_CHECKSUM); $scope.isAuth = parameters.auth; + $scope.title = parameters.title || ($scope.isAuth ? 'AUTH.TITLE' : 'LOGIN.TITLE'); $scope.showMethods = angular.isDefined(parameters.showMethods) ? parameters.showMethods : true; + $scope.showNewAccountLink = angular.isDefined(parameters.showNewAccountLink) ? parameters.showNewAccountLink : true; $scope.expectedPubkey = parameters.expectedPubkey; $scope.scryptParamsValues = _.keys(CryptoUtils.constants.SCRYPT_PARAMS) @@ -54,7 +56,6 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, // modal enter $scope.enter = function() { - console.log("Will enter !", arguments); UIUtils.loading.hide(); // Ink effect UIUtils.ink({selector: '.modal-login .ink'}); @@ -63,7 +64,6 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, // modal leave $scope.leave = function() { - console.log("Will hide !", arguments); $scope.formData = {}; $scope.computing = false; $scope.pubkey = null; @@ -148,27 +148,39 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, // Pubkey else if (method === 'PUBKEY') { - if (!$scope.formData.pubkey) return; - var matches = BMA.regexp.PUBKEY_WITH_CHECKSUM.exec($scope.formData.pubkey); - // Check checksum + var pubkey = $scope.formData.pubkey && $scope.formData.pubkey.trim(); + if (!pubkey) return; + var matches = BMA.regexp.PUBKEY.exec(pubkey); + // valid pubkey: use it if (matches) { - var pubkey = matches[1]; - var checksum = matches[2]; - var expectedChecksum = CryptoUtils.pkChecksum(pubkey); - if (checksum != expectedChecksum) { - $scope.form.pubkey.$error = {checksum: true}; + promise = $q.when({ + pubkey: pubkey + }); + } + + // Check checksum + else { + + matches = BMA.regexp.PUBKEY_WITH_CHECKSUM.exec(pubkey); + if (matches) { + + pubkey = matches[1]; + var checksum = matches[2]; + var expectedChecksum = CryptoUtils.pkChecksum(pubkey); + if (checksum != expectedChecksum) { + $scope.form.pubkey.$error = {checksum: true}; + } + else { + promise = $q.when({ + pubkey: pubkey + }); + } } + // Not a pubkey: launch search on else { - promise = $q.when({ - pubkey: pubkey - }); + return $scope.showWotLookupModal(pubkey) } } - else { - promise = $q.when({ - pubkey: $scope.formData.pubkey.trim() - }); - } } if (!promise) { @@ -204,7 +216,6 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, } // Return result then close - console.log("Will close login modal !!", res); return $scope.closeModal(res); }); }; @@ -436,6 +447,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, .then(function(res){ if (res && res.pubkey) { $scope.formData.pubkey = res.pubkey; + return $timeout($scope.doLogin, 300); } }); }; diff --git a/www/js/controllers/transfer-controllers.js b/www/js/controllers/transfer-controllers.js index 4e74bf516819099f4f16ae7ce87550d2381afb07..9d2978c40b580c7b2c2e1ec949628d0c10ebd52d 100644 --- a/www/js/controllers/transfer-controllers.js +++ b/www/js/controllers/transfer-controllers.js @@ -44,7 +44,7 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.curren .controller('TransferModalCtrl', TransferModalController) ; -function TransferController($scope, $controller, UIUtils, csWot, csWallet) { +function TransferController($scope, $controller, UIUtils) { 'ngInject'; // Initialize the super class and extend it. @@ -52,7 +52,7 @@ function TransferController($scope, $controller, UIUtils, csWot, csWallet) { $scope.enter = function(e, state) { - // Compute parameters + // Compute parameters from state var parameters = {}; if (state && state.stateParams) { if (state.stateParams.pubkey) { @@ -72,36 +72,19 @@ function TransferController($scope, $controller, UIUtils, csWot, csWallet) { if (state.stateParams.restPub) { parameters.restPub = state.stateParams.restPub; } - else if (state.stateParams.all) { + if (state.stateParams.all) { parameters.all = state.stateParams.all; $scope.formData.all = state.stateParams.all; } + if (state.stateParams.wallet) { + parameters.wallet = state.stateParams.wallet; + } } + // Apply parameters + $scope.setParameters(parameters); - // Make sure wallet is loaded - csWallet.login({sources: true}) - - // If pubkey, get the uid (+ name, avatar) - .then(function(data) { - $scope.walletData = data; - if (!parameters.pubkey) return; - return csWot.extend({pubkey: parameters.pubkey}) - .then(function(dest) { - if (dest && dest.uid) { - parameters.uid = dest.name || dest.uid; - } - }); - }) - - // Apply parameters, then recompute relative amount - .then(function() { - $scope.setParameters(parameters); - $scope.onUseRelativeChanged(); - $scope.onAmountChanged(); - UIUtils.loading.hide(); - $scope.loading = false; - UIUtils.ink({selector: '.modal-transfer .ink'}); - }); + return $scope.load() + .then(UIUtils.loading.hide); }; $scope.$on('$ionicView.enter', $scope.enter); @@ -129,7 +112,8 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc useComment: false, all: false, restPub: null, - restAmount: null + restAmount: null, + walletId: null }; $scope.udAmount = null; $scope.minAmount = minQuantitativeAmount; @@ -137,6 +121,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.currency = csCurrency.data.name; $scope.loading = true; $scope.commentInputId = 'transferComment-' + $scope.$id; + $scope.enableSelectWallet = true; // Define keyboard settings, to bind with model (If small screen AND mobile devices) $scope.smallscreen = angular.isDefined($scope.smallscreen) ? $scope.smallscreen : UIUtils.screen.isSmall(); @@ -188,26 +173,54 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc else { $scope.formData.all = false; } + if (!parameters.wallet || parameters.wallet === "default") { + $scope.formData.walletId = csWallet.id; + } + else { + $scope.formData.walletId = parameters.wallet; + } }; // Read default parameters $scope.setParameters(parameters); - $scope.enter = function() { + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + var wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + if (wallet.id !== "default") { + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + } // Make to sure to load full wallet data (balance) - return csWallet.login({sources: true, silent: true}) + return wallet.login({sources: true, silent: true}) .then(function(data) { - $scope.walletData = data; - $scope.onUseRelativeChanged(); - $scope.onAmountChanged(); + $scope.wallet = wallet; + $scope.walletData = data; + $scope.formData.walletId = wallet.id; + $scope.onUseRelativeChanged(); + $scope.onAmountChanged(); + UIUtils.ink({selector: '.modal-transfer .ink'}); + + if (!$scope.destPub || $scope.destUid) { $scope.loading = false; - UIUtils.ink({selector: '.modal-transfer .ink'}); - }) - .catch(function(err){ - if (err == 'CANCELLED') return $scope.cancel(); // close the modal - UIUtils.onError('ERROR.LOGIN_FAILED')(err); - }); + } + else { + // Fill the uid from the pubkey + return csWot.extend({pubkey: $scope.destPub}) + .then(function(res) { + $scope.destUid = res && (res.name || res.uid); + if ($scope.destUid) { + $scope.destPub = ''; + } + $scope.loading = false; + }); + } + }) + .catch(function(err){ + if (err == 'CANCELLED') return $scope.cancel(); // close the modal + UIUtils.onError('ERROR.LOGIN_FAILED')(err); + }); }; - $scope.$on('modal.shown', $scope.enter); + $scope.$on('modal.shown', $scope.load); $scope.cancel = function() { $scope.closeModal(); @@ -217,10 +230,10 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.onUseRelativeChanged = function() { $scope.currency = csCurrency.data.name; if ($scope.formData.useRelative) { - $scope.convertedBalance = csWallet.data.balance / csCurrency.data.currentUD; + $scope.convertedBalance = $scope.walletData.balance / csCurrency.data.currentUD; $scope.minAmount = minQuantitativeAmount / (csCurrency.data.currentUD / 100); } else { - $scope.convertedBalance = csWallet.data.balance / 100; + $scope.convertedBalance = $scope.walletData.balance / 100; $scope.minAmount = minQuantitativeAmount; } if ($scope.form) { @@ -240,12 +253,12 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc amount = parseFloat(amount.replace(new RegExp('[.,]'), '.')); } if ($scope.formData.useRelative) { - $scope.formData.restAmount = csWallet.data.balance - amount * csCurrency.data.currentUD; + $scope.formData.restAmount = $scope.walletData.balance - amount * csCurrency.data.currentUD; if ($scope.formData.restAmount < minQuantitativeAmount) { $scope.formData.restAmount = 0; } } else { - $scope.formData.restAmount = csWallet.data.balance - amount * 100; + $scope.formData.restAmount = $scope.walletData.balance - amount * 100; } }; @@ -280,7 +293,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc var currentUD; return $q.all([ // Make sure user is auth - csWallet.auth({silent: true}), + $scope.wallet.auth({silent: true}), // Get current UD csCurrency.currentUD() @@ -315,10 +328,10 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc } var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; if (hasRest) { - return csWallet.transferAll($scope.formData.destPub, amount, comment, $scope.formData.useRelative, $scope.formData.restPub); + return $scope.wallet.transferAll($scope.formData.destPub, amount, comment, $scope.formData.useRelative, $scope.formData.restPub); } else { - return csWallet.transfer($scope.formData.destPub, amount, comment, $scope.formData.useRelative); + return $scope.wallet.transfer($scope.formData.destPub, amount, comment, $scope.formData.useRelative); } }) .then(function() { @@ -344,7 +357,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc .then(function(translations) { var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; return $translate(hasRest ? 'CONFIRM.TRANSFER_ALL' : 'CONFIRM.TRANSFER', { - from: csWallet.data.isMember ? csWallet.data.uid : $filter('formatPubkey')(csWallet.data.pubkey), + from: $scope.walletData.isMember ? $scope.walletData.uid : $filter('formatPubkey')($scope.walletData.pubkey), to: $scope.destUid || $scope.destPub, amount: $scope.formData.amount, unit: $scope.formData.useRelative ? translations['COMMON.UD'] : $filter('abbreviate')($scope.currency), @@ -391,6 +404,22 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc }); }; + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet({ + useRelative: $scope.formData.useRelative + }) + .then(function(wallet) { + if (!wallet || $scope.formData.walletId === wallet.id) return; + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + $scope.wallet = wallet; + $scope.walletData = wallet.data; + $scope.formData.walletId = wallet.id; + $scope.onAmountChanged(); + }); + }; + /* -- popover -- */ $scope.showUnitPopover = function($event) { @@ -425,7 +454,6 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc return $q.when(); }; - $scope.hideDigitKeyboard = function(timeout) { if (!$scope.digitKeyboardVisible) return $q.when(); $scope.digitKeyboardVisible = false; diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index a2bd0e330cd64e8f5f7f16175929d71ef952b51d..0e1e448cf10ca814a4ac50b33ec18b71ad34a02a 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -14,7 +14,8 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency } }, data: { - login: true + login: true, + silentLocationChange: true } }) @@ -44,6 +45,47 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency login: true } }) + + .state('app.view_wallets', { + url: "/wallet/list", + views: { + 'menuContent': { + templateUrl: "templates/wallet/list/view_wallets.html", + controller: 'WalletListCtrl' + } + }, + data: { + login: true + } + }) + + .state('app.view_wallet_by_id', { + url: "/wallet/list/:id?refresh", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet.html", + controller: 'WalletCtrl' + } + }, + data: { + login: true, + silentLocationChange: true + } + }) + + .state('app.view_wallet_tx_by_id', { + url: "/history/:id?refresh", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet_tx.html", + controller: 'WalletTxCtrl' + } + }, + data: { + login: true, + silentLocationChange: true + } + }) ; }) @@ -55,6 +97,10 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency .controller('WalletTxErrorCtrl', WalletTxErrorController) .controller('WalletSecurityModalCtrl', WalletSecurityModalController) + + .controller('WalletListCtrl', WalletListController) + + .controller('WalletSelectModalCtrl', WalletSelectModalController) ; function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $translate, $ionicPopover, @@ -65,9 +111,19 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.settings = csSettings.data; $scope.qrcodeId = 'qrcode-wallet-' + $scope.$id; - $scope.$on('$ionicView.enter', function(e, state) { + var wallet; + + $scope.enter = function(e, state) { $scope.loading = $scope.loading || (state.stateParams && state.stateParams.refresh); if ($scope.loading) { // load once + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; return $scope.load(); } else { @@ -75,16 +131,22 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, UIUtils.loading.hide(); $timeout($scope.updateView, 300); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function() { - return $scope.loadWallet() + if (!wallet) return; + + return $scope.loadWallet({ + wallet: wallet + }) .then(function(walletData) { $scope.formData = walletData; $scope.loading=false; // very important, to avoid TX to be display before wallet.currentUd is loaded $scope.updateView(); $scope.showQRCode(); $scope.showHelpTip(); + $scope.addListeners(); UIUtils.loading.hide(); // loading could have be open (e.g. new account) }) .catch(function(err){ @@ -98,11 +160,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.motion.show({selector: '#wallet .item'}); $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind }; - // Listen new events (can appears from security wizard also) - $scope.$watchCollection('formData.events', function(newEvents, oldEvents) { - if (!oldEvents || $scope.loading || angular.equals(newEvents, oldEvents)) return; - $scope.updateView(); - }); + $scope.setRegisterForm = function(registerForm) { $scope.registerForm = registerForm; @@ -111,11 +169,32 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, // Clean controller data when logout $scope.onWalletLogout = function() { // clean QRcode - $scope.hideQRCode('qrcode'); + $scope.hideQRCode(); + $scope.removeListeners(); delete $scope.formData; + wallet = null; $scope.loading = true; }; - csWallet.api.data.on.logout($scope, $scope.onWalletLogout); + + $scope.addListeners = function() { + $scope.listeners = [ + // Reset the view on logout + wallet.api.data.on.logout($scope, $scope.onWalletLogout), + + // Listen new events (can appears from security wizard also) + $scope.$watchCollection('formData.events', function(newEvents, oldEvents) { + if (!oldEvents || $scope.loading || angular.equals(newEvents, oldEvents)) return; + $scope.updateView(); + }) + ]; + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; // Ask uid $scope.showUidPopup = function() { @@ -167,7 +246,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, .then(function(uid) { UIUtils.loading.show(); - return csWallet.self(uid) + return wallet.self(uid) .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -182,7 +261,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }; $scope.doMembershipIn = function(retryCount) { - return csWallet.membership.inside() + return wallet.membership.inside() .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -204,7 +283,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.membershipIn = function(keepSelf) { $scope.hideActionsPopover(); - if (csWallet.isMember()) { + if (wallet.isMember()) { return UIUtils.alert.info("INFO.NOT_NEED_MEMBERSHIP"); } @@ -231,7 +310,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.formData.blockUid = null; $scope.formData.uid = uid; - return csWallet.self(uid, false/*do NOT load membership here*/); + return wallet.self(uid, false/*do NOT load membership here*/); } }) @@ -239,7 +318,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, .then($scope.doMembershipIn) .catch(function(err) { if (err == 'CANCELLED') return; - if (!csWallet.data.uid) { + if (!wallet.data.uid) { UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')(err); } else { @@ -276,7 +355,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } UIUtils.loading.show(); - return csWallet.membership.out() + return wallet.membership.out() .then(function() { UIUtils.loading.hide(); UIUtils.toast.show('INFO.MEMBERSHIP_OUT_SENT'); @@ -288,9 +367,9 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.doUpdate = function(silent) { console.debug('[wallet] Refreshing data...'); return (silent ? - csWallet.refreshData() : + wallet.refreshData() : UIUtils.loading.show() - .then(csWallet.refreshData) + .then(wallet.refreshData) .then(UIUtils.loading.hide) ) .then($scope.updateView) @@ -315,7 +394,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }); } - return csWallet.auth({minData: true}) // Ask user to auth, before confirmation - fix #508 + return wallet.auth({minData: true}) // Ask user to auth, before confirmation - fix #508 .then(function() { UIUtils.loading.hide(); return UIUtils.alert.confirm("CONFIRM.RENEW_MEMBERSHIP"); @@ -341,7 +420,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, if (!$scope.formData.uid) return; return $q.all([ - csWallet.auth(), + wallet.auth(), $translate('CONFIRM.FIX_IDENTITY', {uid: $scope.formData.uid}) ]) .then(function(res) { @@ -354,7 +433,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.formData.blockUid = null; // Reset membership data $scope.formData.sigDate = null; - return csWallet.self($scope.formData.uid); + return wallet.self($scope.formData.uid); }) .then($scope.doMembershipIn) .catch(function(err){ @@ -370,11 +449,11 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.fixMembership = function() { if (!$scope.formData.uid) return; - if (csWallet.isMember()) { + if (wallet.isMember()) { return UIUtils.alert.info("INFO.NOT_NEED_MEMBERSHIP"); } - return csWallet.auth() + return wallet.auth() .then(function() { UIUtils.alert.confirm("CONFIRM.FIX_MEMBERSHIP"); }) @@ -385,7 +464,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.formData.blockUid = null; // Reset membership data $scope.formData.sigDate = null; - return csWallet.self($scope.formData.uid, false/*do NOT load membership here*/); + return wallet.self($scope.formData.uid, false/*do NOT load membership here*/); }) .then($scope.doMembershipIn) .catch(function(err){ @@ -419,7 +498,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, // Transfer $scope.showTransferModal = function() { var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); - if (!hasCredit) { + if (!hasCredit && !wallet.children.count()) { UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); return; } @@ -461,7 +540,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } }; - $scope.hideQRCode = function(id) { + $scope.hideQRCode = function() { if ($scope.qrcode) { $scope.qrcode.clear(); UIUtils.motion.toggleOff({selector: '#'+$scope.qrcodeId}); @@ -559,7 +638,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.loading = true; // Set self (= uid + blockUid) - return csWallet.setSelf(idty.uid, idty.blockUid) + return wallet.setSelf(idty.uid, idty.blockUid) .then(function() { $scope.loading=false; $scope.updateView(); @@ -579,38 +658,21 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, $scope.settings = csSettings.data; $scope.listeners = []; - $scope.addListeners = function() { - if ($scope.settings.walletHistoryAutoRefresh) { + var wallet; - $scope.listeners = [ - // Update on new block - csCurrency.api.data.on.newBlock($scope, function(block) { - if ($scope.loading) return; - console.debug("[wallet] Received new block. Will reload history."); - $timeout(function() { - $scope.doUpdate(true); - }, 300/*waiting for node cache propagation*/); - }) - ]; - } - else { - $scope.listeners = []; - } - }; - - $scope.removeListeners = function() { - _.forEach($scope.listeners, function(remove){ - remove(); - }); - $scope.listeners = []; - }; - - $scope.$on('$ionicView.enter', function(e, state) { + $scope.enter = function(e, state) { $scope.loading = $scope.loading || (state.stateParams && state.stateParams.refresh); if ($scope.loading) { - $scope.loadWallet() - .then(function (res) { - $scope.formData = res; + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.loadWallet({wallet: wallet}) + .then(function (walletData) { + $scope.formData = walletData; $scope.loading = false; // very important, to avoid TX to be display before wallet.currentUd is loaded $scope.updateView(); $scope.showFab('fab-transfer'); @@ -620,7 +682,11 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, // remove the stateParams if (state.stateParams && state.stateParams.refresh) { - $location.search({}).replace(); + $timeout(function() { + var stateParams = angular.copy(state.stateParams); + delete stateParams.refresh; + $location.search(stateParams).replace(); + }, 300); } }) .catch(function (err) { @@ -630,11 +696,17 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, }); } else { + $scope.addListeners(); // Make sure to display new pending (e.g. sending using another screen button) $timeout($scope.updateView, 300); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); + $scope.leave = function() { + $scope.removeListeners(); + }; + $scope.$on('$ionicView.leave', $scope.leave); // Update view $scope.updateView = function() { @@ -654,12 +726,21 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, // Updating wallet data $scope.doUpdate = function(silent) { console.debug('[wallet] TX history reloading...'); + var options = { + sources: true, + tx: { + enable: true + }, + api: false + }; return (silent ? // If silent: just refresh - csWallet.refreshData() : + wallet.refreshData(options) : // If not silent: show/hide loading indicator UIUtils.loading.show() - .then(csWallet.refreshData) + .then(function() { + return wallet.refreshData(options); + }) .then(UIUtils.loading.hide) ) .then($scope.updateView) @@ -668,20 +749,45 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, /* -- add listeners -- */ - csWallet.api.data.on.balanceChanged($scope, $scope.updateView); - $scope.$watch('settings.useRelative', $scope.updateView); - $scope.$watch('settings.showUDHistory', function() { - // Reload if show UD changed - if (!$scope.formData || $scope.loading) return; - $scope.doUpdate(); - }, true); + $scope.addListeners = function() { + $scope.listeners = [ + wallet.api.data.on.balanceChanged($scope, $scope.updateView), + $scope.$watch('settings.useRelative', $scope.updateView, true), + $scope.$watch('settings.showUDHistory', function(newVal, oldVal) { + // Reload if show UD changed + if (!$scope.formData || $scope.loading || (newVal == oldVal)) return; + console.log(arguments); + $scope.doUpdate(); + }, true) + ]; + + // Update on new block + if ($scope.settings.walletHistoryAutoRefresh) { + $scope.listeners.push( + csCurrency.api.data.on.newBlock($scope, function(block) { + if ($scope.loading) return; + console.debug("[wallet] Received new block. Will reload history."); + $timeout(function() { + $scope.doUpdate(true); + }, 300/*waiting for node cache propagation*/); + }) + ); + } + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; /* -- popup / UI -- */ // Transfer $scope.showTransferModal = function() { var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); - if (!hasCredit) { + if (!hasCredit && !csWallet.children.count()) { UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); return; } @@ -1266,7 +1372,257 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ }) ; }; +} + +function WalletListController($scope, $controller, $state, $timeout, $ionicPopover, UIUtils, Modals, + csCurrency, csSettings, csWallet){ + 'ngInject'; + + $scope.settings = csSettings.data; + $scope.listeners = []; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletSelectModalCtrl', {$scope: $scope, parameters: {}})); + // Override defaults + $scope.formData.displayDefault = false; + $scope.motion = UIUtils.motion.default; + + $scope.enter = function(e, state) { + // First enter + if ($scope.loading) { + $scope.setParameters({}); + + return $scope.load() + .then(function() { + $scope.addListeners(); + $scope.showFab('fab-add-wallet'); + }); + } + else { + $scope.addListeners(); + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.leave = function() { + $scope.removeListeners(); + }; + $scope.$on('$ionicView.leave', $scope.leave); + + $scope.cancel = function() { + $scope.showHome(); + }; + + $scope.select = function(wallet) { + $state.go('app.view_wallet_by_id', {id: wallet.id}); + }; + + /* -- modals -- */ + + $scope.showNewWalletModal = function() { + + var wallet = csWallet.instance('secondary-' + (csWallet.children.count() + 1)); + return wallet.login({ + showNewAccountLink: false, + title: 'ACCOUNT.WALLET_LIST.BTN_NEW', + // Load data options : + minData: true, + sources: true, + api: false, + success: UIUtils.loading.show + }) + .then(function(walletData) { + if (!walletData) return; + + // Avoid to add main wallet again + if (walletData.pubkey === csWallet.data.pubkey) { + UIUtils.loading.hide(); + UIUtils.alert.error('ERROR.COULD_NOT_ADD_MAIN_WALLET'); + return; + } + + return csWallet.api.data.raisePromise.load(wallet.data) + // continue, when plugins extension failed (just log in console) + .catch(console.error) + .then(function() { + csWallet.children.add(wallet); + UIUtils.loading.hide(); + $scope.motion.show({selector: '.list .item.item-wallet', ink: true}); + }); + }) + .catch(function(err) { + if (err === 'CANCELLED') return; + UIUtils.onError('ERROR.ADD_SECONDARY_WALLET_FAILED')(err); + }); + }; + + $scope.selectAndRemoveWallet = function() { + $scope.hideActionsPopover(); + return Modals.showSelectWallet({ + wallets: $scope.wallets, + displayDefault: false + }) + .then(function(wallet) { + if (!wallet || !wallet.id) return; + csWallet.children.remove(wallet.id); + }); + }; + + /* -- popovers -- */ + + $scope.showActionsPopover = function(event) { + if (!$scope.actionsPopover) { + $ionicPopover.fromTemplateUrl('templates/wallet/list/popover_actions.html', { + scope: $scope + }).then(function(popover) { + $scope.actionsPopover = popover; + //Cleanup the popover when we're done with it! + $scope.$on('$destroy', function() { + $scope.actionsPopover.remove(); + }); + $scope.actionsPopover.show(event); + }); + } + else { + $scope.actionsPopover.show(event); + } + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + } + }; + + /* -- listeners -- */ + + $scope.addListeners = function() { + if (csSettings.data.walletHistoryAutoRefresh) { + + $scope.listeners = [ + // Update on new block + csCurrency.api.data.on.newBlock($scope, function(block) { + if ($scope.loading) return; + console.debug("[wallet-list] Received new block. Will reload list."); + $timeout(function() { + $scope.doUpdate(true); + }, 300/*waiting for node cache propagation*/); + }) + ]; + } + else { + $scope.listeners = []; + } + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; } +function WalletSelectModalController($scope, $q, UIUtils, filterTranslations, csSettings, csCurrency, csWallet, parameters){ + 'ngInject'; + + $scope.loading = true; + $scope.formData = { + useRelative: csSettings.data.useRelative, + displayDefault: true + }; + $scope.motion = {}; // no animation + + $scope.setParameters = function(parameters) { + parameters = parameters || {}; + + $scope.formData.useRelative = angular.isDefined(parameters.useRelative) ? parameters.useRelative : $scope.formData.useRelative; + + $scope.formData.displayDefault = angular.isDefined(parameters.displayDefault) ? parameters.displayDefault : $scope.formData.displayDefault; + }; + + $scope.load = function() { + $scope.loading = true; + $scope.wallets = $scope.wallets || $scope.formData.displayDefault ? [csWallet].concat(csWallet.children.all()) : csWallet.children.all(); + + // Load currency, and filter translations (need by 'formatAmount' filter) + var jobs = [ + csCurrency.get() + .then(function(currency) { + if (!currency) { + return $timeout(function() { + return csCurrency.get(); + }, 500); + } + return currency; + }), + filterTranslations.start() + ]; + + var loadOptions = { + silent: true, + minData: true, + sources: true, + api: true + }; + return $q.all( + $scope.wallets.reduce(function(res, wallet){ + return wallet.isDataLoaded(loadOptions) ? + res : res.concat(wallet.loadData(loadOptions)); + }, jobs) + ) + .then(function(res) { + var currency = res[0]; + // Init scope var + $scope.currency = currency.name; + $scope.loading = false; + UIUtils.loading.hide(); + if ($scope.motion.show && $scope.wallets.length > 0) { + $scope.motion.show({selector: '.list .item.item-wallet', ink: true}); + } + }) + .catch(function(err) { + $scope.loading = false; + UIUtils.onError('ERROR.LOAD_WALLET_LIST_FAILED')(err); + }); + }; + $scope.$on('modal.shown', $scope.load); + $scope.cancel = function() { + $scope.closeModal(); + }; + + $scope.select = function(wallet) { + $scope.closeModal(wallet); + }; + + $scope.doUpdate = function(silent) { + if ($scope.loading || !$scope.wallets || !$scope.wallets.length) return $q.when(); + + $scope.loading = !silent; + + return $q.all($scope.wallets.reduce(function(res, wallet) { + return res.concat(wallet.refreshData({ + silent: true, + sources: true, + requirements: wallet.requirements && (wallet.requirements.isMember || wallet.requirements.wasMember || wallet.requirements.pendingMembership), + api: true + })); + }, [])) + .then(function() { + $scope.loading = false; + if ($scope.motion.show) { + $scope.motion.show({selector: '.list .item.item-wallet', ink: true}); + } + }) + .catch(function(err) { + $scope.loading = false; + UIUtils.onError('ERROR.UPDATE_WALLET_LIST_FAILED')(err); + }); + }; + + // Default actions + $scope.setParameters(parameters); + +} diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js index 5d6b2ec797b9c77f69fbb21adab2c19007fd1003..ab796fb8ac56a736d80c4973e3034a3726f3214c 100644 --- a/www/js/controllers/wot-controllers.js +++ b/www/js/controllers/wot-controllers.js @@ -64,19 +64,6 @@ angular.module('cesium.wot.controllers', ['cesium.services']) .state('app.wot_identity_tx_uid', { url: "/wot/tx/:pubkey/:uid?action", - views: { - 'menuContent': { - templateUrl: "templates/wot/view_identity_tx.html", - controller: 'WotIdentityTxViewCtrl' - }, - data: { - large: 'app.wot_identity_tx_uid_lg' - } - } - }) - - .state('app.wot_identity_tx_uid_lg', { - url: "/wot/tx/lg/:pubkey/:uid?action", views: { 'menuContent': { templateUrl: "templates/wot/view_identity_tx.html", diff --git a/www/js/services/currency-services.js b/www/js/services/currency-services.js index 130939fae635718dcf4c10ef99789d817908b3cd..960553fcb7fe6b837ca2e57b13f5550424a1a463 100644 --- a/www/js/services/currency-services.js +++ b/www/js/services/currency-services.js @@ -244,7 +244,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) if (cache) { if (currentBlock && (now - currentBlock.receivedAt) < 60/*1min*/) { - console.debug('[currency] Use current block #'+ currentBlock.number +' from cache (age='+ (now - currentBlock.receivedAt) + 's)'); + //console.debug('[currency] Use current block #'+ currentBlock.number +' from cache (age='+ (now - currentBlock.receivedAt) + 's)'); return currentBlock; } diff --git a/www/js/services/modal-services.js b/www/js/services/modal-services.js index 35b7ef593e62fa2d9b7159b1bf9b6d0ddd108dbf..d01eb749419a14882bc7c2a4f846933771d2a857 100644 --- a/www/js/services/modal-services.js +++ b/www/js/services/modal-services.js @@ -218,6 +218,11 @@ angular.module('cesium.modal.services', []) parameters); } + function showSelectWallet(parameters) { + return ModalUtils.show('templates/wallet/list/modal_wallets.html','WalletSelectModalCtrl', + parameters); + } + function showPassword(options) { options = options || {}; options.title = options.title || 'COMMON.SET_PASSWORD_TITLE'; @@ -258,7 +263,6 @@ angular.module('cesium.modal.services', []) } - return { showTransfer: showTransfer, showLogin: showLogin, @@ -272,6 +276,7 @@ angular.module('cesium.modal.services', []) showAccountSecurity: showAccountSecurity, showLicense: showLicense, showSelectPubkeyIdentity: showSelectPubkeyIdentity, + showSelectWallet: showSelectWallet, showPassword: showPassword }; diff --git a/www/js/services/settings-services.js b/www/js/services/settings-services.js index d6571c64004b5014bd7dab23397facbcdd59aba6..96508773f892dad93e4efb62a31ed20ad85984ec 100644 --- a/www/js/services/settings-services.js +++ b/www/js/services/settings-services.js @@ -48,7 +48,8 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) var constants = { - STORAGE_KEY: 'CESIUM_SETTINGS', + OLD_STORAGE_KEY: 'CESIUM_SETTINGS', + STORAGE_KEY: 'settings', KEEP_AUTH_IDLE_SESSION: 9999 }, defaultSettings = angular.merge({ @@ -212,8 +213,15 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) restore = function() { var now = new Date().getTime(); - return localStorage.getObject(constants.STORAGE_KEY) - .then(function(storedData) { + + return $q.all([ + localStorage.getObject(constants.OLD_STORAGE_KEY), + localStorage.getObject(constants.STORAGE_KEY) + ]) + .then(function(res) { + // Clean old storage + localStorage.put(constants.OLD_STORAGE_KEY, null); + var storedData = res[1] || res[0]; // No settings stored if (!storedData) { console.debug("[settings] No settings in local storage. Using defaults."); @@ -222,11 +230,6 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) return; } - // Workaround, to turn on 'rememberMe', but only once (at version 0.13.2) - if (!storedData.rememberMe && (!storedData.login || !storedData.login.method)) { - storedData.rememberMe = true; - } - // Apply stored data applyData(storedData); @@ -241,7 +244,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) (csConfig.license[locale] ? csConfig.license[locale] : csConfig.license[csConfig.defaultLanguage || 'en'] || csConfig.license) : undefined; }, - // Detect locale sucessuf changes, then apply to vendor libs + // Detect locale successful changes, then apply to vendor libs onLocaleChange = function() { var locale = $translate.use(); console.debug('[settings] Locale ['+locale+']'); diff --git a/www/js/services/storage-services.js b/www/js/services/storage-services.js index 1830fc0cd0ee59fd40d0a37fee1626484c0faae3..3f6645931cfe407180fbfff5bc620056b92aec23 100644 --- a/www/js/services/storage-services.js +++ b/www/js/services/storage-services.js @@ -55,7 +55,12 @@ angular.module('cesium.storage.services', [ 'cesium.config']) /* -- Use standard browser implementation -- */ exports.standard.put = function(key, value) { - exports.standard.storage[key] = value; + if (angular.isDefined(value) && value != null) { + exports.standard.storage[key] = value; + } + else { + exports.standard.storage.removeItem(key); + } return $q.when(); }; diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index f297709a628651bed169108ed2e5ba97368da30e..694bce2934235d8dbec2dee82ac5984b1b8eca15 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -9,6 +9,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se 'ngInject'; var defaultBMA = BMA; + var service; function factory(id, BMA) { @@ -19,6 +20,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se OLD_STORAGE_KEY: 'CESIUM_DATA', STORAGE_PUBKEY: 'pubkey', STORAGE_UID: 'uid', + STORAGE_CHILDREN_WALLET: 'wallets', STORAGE_SECKEY: 'seckey', /* Need for compat with old currencies (test_net and sou) */ TX_VERSION: csConfig.compatProtocol_0_80 ? 3 : BMA.constants.PROTOCOL_VERSION, @@ -47,8 +49,10 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se data.requirements = {}; data.blockUid = null; data.sigDate = null; + data.sigStock = null; data.isMember = false; data.events = []; + data.children = []; // children's wallets resetKeypair(); resetTxAndSources(); @@ -292,7 +296,12 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, isDataLoaded = function(options) { - if (options && options.minData) return data.loaded; + if (options) { + if (options.minData) return data.loaded; + if (options.requirements && !data.requirements) return false; + if (options.tx && options.tx.enable && !data.tx.fromTime) return false; + if (options.sigStock && !data.sigStock) return false; + } return data.loaded && data.sources; }, @@ -348,8 +357,19 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se jobs.push(localStorage.put(constants.STORAGE_UID, null)); } - // Clean old storage - jobs.push(localStorage.put(constants.OLD_STORAGE_KEY, null)); + // Use local storage for uid - fix #625 + if (data.children && data.children.length) { + var childrenPubkeys = data.children.reduce(function(res, wallet) { + return wallet.isLogin() ? res.concat({ + pubkey: wallet.data.pubkey, + name: wallet.data.name + }) : res; + }, []); + jobs.push(localStorage.put(constants.STORAGE_CHILDREN_WALLET, JSON.stringify(childrenPubkeys))); + } + else { + jobs.push(localStorage.put(constants.STORAGE_CHILDREN_WALLET, null)); + } return $q.all(jobs).then(function() { console.debug('[wallet] Saved locally'); @@ -360,8 +380,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se sessionStorage.put(constants.STORAGE_SECKEY, null), localStorage.put(constants.STORAGE_PUBKEY, null), localStorage.put(constants.STORAGE_UID, null), - // Clean old storage - localStorage.put(constants.OLD_STORAGE_KEY, null) + localStorage.put(constants.STORAGE_CHILDREN_WALLET, null) ]); } } @@ -370,25 +389,34 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se sessionStorage.put(constants.STORAGE_SECKEY, null), localStorage.put(constants.STORAGE_PUBKEY, null), localStorage.put(constants.STORAGE_UID, null), - // Clean old storage - localStorage.put(constants.OLD_STORAGE_KEY, null) + localStorage.put(constants.STORAGE_CHILDREN_WALLET, null) ]); - } + }, restore = function() { + // Clean old storage + localStorage.get(constants.OLD_STORAGE_KEY) + .then(function() { + localStorage.put(constants.OLD_STORAGE_KEY, null); + }); + return $q.all([ sessionStorage.get(constants.STORAGE_SECKEY), localStorage.get(constants.STORAGE_PUBKEY), - localStorage.get(constants.STORAGE_UID) + localStorage.get(constants.STORAGE_UID), + localStorage.get(constants.STORAGE_CHILDREN_WALLET) ]) .then(function(res) { var seckey = res[0]; var pubkey = res[1]; var uid = res[2]; + var childrenStr = res[3]; if (!pubkey || pubkey == 'null') return; + console.debug('[wallet] Restore {'+pubkey.substring(0,8)+'} from local storage'); + var keypair; if (seckey && seckey.length && seckey != 'null') { try { @@ -403,14 +431,27 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se } } + // Children's wallet + var children = childrenStr && JSON.parse(childrenStr); + var jobs = []; + if (children) { + _.forEach(children, function(child, index) { + console.debug('[wallet] - {'+child.pubkey.substring(0,8)+'} sub wallet'); + var wallet = service.instance('secondary-' + (index+1)); + wallet.data.pubkey = child.pubkey; + wallet.data.name = child.name; + jobs.push(addChildWallet(wallet, {store: false/*skip store*/})); + }); + } + data.pubkey = pubkey; data.uid = uid && uid != 'null' ? uid : undefined; data.keypair = keypair || {signPk: undefined, signSk: undefined}; - console.debug('[wallet] Restore \'{0}\' from local storage.'.format(pubkey.substring(0,8))); - // Call extend api - return api.data.raisePromise.login(data); + jobs.push(api.data.raisePromise.login(data)) + + return $q.all(jobs); }) .then(function(){ return data; @@ -690,13 +731,16 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se if (options.sigStock) jobs.push(loadSigStock()); return (jobs.length ? $q.all(jobs) : $q.when()) - .then(function(){ - // API extension (after all other jobs) - return api.data.raisePromise.load(data); - }) - .then(function(){ - return data; - }); + .then(function(){ + // Skip api + if (angular.isDefined(options.api) && !options.api) return data; + + // API extension (after all other jobs) + return api.data.raisePromise.load(data) + .then(function(){ + return data; + }) + }); }, setSelf = function(uid, blockUid){ @@ -1593,6 +1637,67 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se },[]); }, + addChildWallet = function(wallet, options) { + + // Add data loading listeners + wallet.api.data.on.load($rootScope, function(data, deferred) { + deferred = deferred || $q.defer(); + api.data.raisePromise.load(data) + .then(deferred.resolve) + .catch(deferred.reject); + return deferred.promise; + }, this); + + // Unauth when main wallet unauth + api.data.on.unauth($rootScope, function(data, deferred) { + deferred = deferred || $q.defer(); + if (wallet.isAuth()) { + wallet.unauth() + .then(deferred.resolve) + .catch(deferred.reject); + } + else { + deferred.resolve(); + } + return deferred.promise; + }, this); + + data.children = data.children || []; + data.children.push(wallet); + + // Store (store children locally) + var finishFn = (!options || angular.isUndefined(options.store) || options.store) ? store : $q.when; + + // if already login + if (wallet.isLogin()) { + // Raise login event + return api.data.raisePromise.login(wallet.data) + .then(finishFn); + } + else { + return finishFn(); + } + }, + + removeChildWalletById = function(id) { + data.children = data.children || []; + var childIndex = _.findIndex(data.children, function(child) {return child.id == id;}); + if (childIndex === -1) { + console.warn('Unable to remove child wallet {'+id+'} (not found)'); + return; + } + // Remove the wallet, and return it + return data.children.splice(childIndex, 1)[0]; + }, + + getChildWalletById = function(id) { + return _.find(data.children|| [], function(child) {return child.id == id;}); + }, + + getAllChildrenWallet = function() { + return data.children; + }, + /** * De-serialize from JSON string */ @@ -1794,6 +1899,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return data.isMember; }, isDataLoaded : isDataLoaded, + isDefault: function() {return id === "default"}, isNeverUsed: isNeverUsed, isNew: isNew, isUserPubkey: isUserPubkey, @@ -1820,11 +1926,20 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se add: addEvent, cleanByContext: cleanEventsByContext }, + children: { + add: addChildWallet, + remove: removeChildWalletById, + get: getChildWalletById, + all: getAllChildrenWallet, + count: function() { + return data.children && data.children.length || 0; + } + }, api: api }; } - var service = factory('default', BMA); + service = factory('default', BMA); service.instance = factory; return service; diff --git a/www/plugins/es/js/controllers/app-controllers.js b/www/plugins/es/js/controllers/app-controllers.js index b593797c990e9706b40abbdb75bfc167f46a23a9..f61d182158dc974cdd1e8459b14e165049e86b5e 100644 --- a/www/plugins/es/js/controllers/app-controllers.js +++ b/www/plugins/es/js/controllers/app-controllers.js @@ -53,16 +53,18 @@ function ESExtensionController($scope, esSettings, PluginService) { $scope.enable = esSettings.isEnable(); esSettings.api.state.on.changed($scope, function(enable) { $scope.enable = enable; + $scope.$broadcast('$$rebind::state'); }); } /** * Control menu extension */ -function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUtils, csWallet) { +function ESMenuExtendController($scope, $state, $controller, UIUtils, csWallet) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); + + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showRegistryLookupView = function() { $state.go(UIUtils.screen.isSmall() ? 'app.registry_lookup': 'app.registry_lookup_lg'); @@ -113,12 +115,6 @@ function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUti } }); }; - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); - - } /** @@ -133,7 +129,7 @@ function ESProfilePopoverExtendController($scope, $q, $state, esSettings, csWall $scope.showEditUserProfile = function() { $scope.closeProfilePopover(); - $state.go('app.user_edit_profile'); + $state.go('app.edit_profile'); }; esSettings.api.state.on.changed($scope, $scope.updateView); diff --git a/www/plugins/es/js/controllers/network-controllers.js b/www/plugins/es/js/controllers/network-controllers.js index e329488e6b2fa03a9aa073fdcff14b8a81162bf3..cbf2346249dfb63197ca2bf71d1968068ec6677f 100644 --- a/www/plugins/es/js/controllers/network-controllers.js +++ b/www/plugins/es/js/controllers/network-controllers.js @@ -10,25 +10,11 @@ angular.module('cesium.es.network.controllers', ['cesium.es.services']) points: { 'buttons': { templateUrl: "plugins/es/templates/network/view_network_extend.html", - controller: 'ESNetworkViewExtendCtrl' + controller: 'ESExtensionCtrl' } } }) ; } - }) - - .controller('ESNetworkViewExtendCtrl', ESNetworkViewExtendController) -; - - -function ESNetworkViewExtendController($scope, PluginService, esSettings) { - 'ngInject'; - - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; }); -} + diff --git a/www/plugins/es/js/controllers/notification-controllers.js b/www/plugins/es/js/controllers/notification-controllers.js index f18fcfe5e61678dd291a26cf0befbc15acc57137..468eb4422c9e6e5aa586287211c91693ceab92fa 100644 --- a/www/plugins/es/js/controllers/notification-controllers.js +++ b/www/plugins/es/js/controllers/notification-controllers.js @@ -118,9 +118,9 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim UIUtils.loading.show() .then(function() { - $rootScope.walletData.notifications.unreadCount = 0; + csWallet.data.notifications.unreadCount = 0; var lastNotification = $scope.search.results[0]; - $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0; + csWallet.data.notifications.readTime = lastNotification ? lastNotification.time : 0; _.forEach($scope.search.results, function (item) { if (item.markAsRead && typeof item.markAsRead == 'function') item.markAsRead(); }); diff --git a/www/plugins/es/js/controllers/profile-controllers.js b/www/plugins/es/js/controllers/profile-controllers.js index 7580eb47e24db494c29bec1e0b30014edce59097..ba5137ff2ce0b20d6ed4da2ddae6d518f5070998 100644 --- a/www/plugins/es/js/controllers/profile-controllers.js +++ b/www/plugins/es/js/controllers/profile-controllers.js @@ -2,19 +2,34 @@ angular.module('cesium.es.profile.controllers', ['cesium.es.services']) .config(function($stateProvider) { - $stateProvider.state('app.user_edit_profile', { - url: "/wallet/profile/edit", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/user/edit_profile.html", - controller: 'ESViewEditProfileCtrl' + $stateProvider + .state('app.edit_profile', { + url: "/wallet/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + auth: true } - }, - cache: false, - data: { - auth: true - } - }); + }) + + .state('app.edit_profile_by_id', { + url: "/wallet/list/:id/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + login: true + } + }); }) @@ -23,7 +38,7 @@ angular.module('cesium.es.profile.controllers', ['cesium.es.services']) ; -function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $focus, $translate, $controller, +function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $translate, $controller, $ionicHistory, $ionicPopover, UIUtils, csWallet, esHttp, esProfile, ModalUtils, Device) { 'ngInject'; @@ -47,11 +62,22 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ }; $scope.socialReorder = true; - $scope.$on('$ionicView.enter', function(e) { - $scope.loadWallet() - .then(function(walletData) { - return $scope.load(walletData); - }) + var wallet; + + $scope.enter = function(e, state) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.loadWallet({ + wallet: wallet, + auth: true, + minData: true + }) + .then($scope.load) .catch(function(err){ if (err == 'CANCELLED') { return $scope.close() @@ -59,7 +85,8 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ } UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err); }); - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { if ($scope.dirty && !$scope.saving) { @@ -161,7 +188,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.$watch('formData', $scope.onFormDataChanged, true); $scope.save = function(silent, hasWaitDebounce) { - if($scope.form.$invalid || !$rootScope.walletData || ($scope.saving && !hasWaitDebounce)) { + if($scope.form.$invalid || !$scope.walletData || ($scope.saving && !hasWaitDebounce)) { return $q.reject(); } @@ -238,7 +265,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ } if (!$scope.existing) { - return esProfile.add(formData) + return esProfile.add(formData, {wallet: wallet}) .then(function() { console.info("[ES] [profile] Successfully created."); $scope.existing = true; @@ -251,7 +278,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ .catch(onError('PROFILE.ERROR.SAVE_PROFILE_FAILED')); } else { - return esProfile.update(formData, {id: $rootScope.walletData.pubkey}) + return esProfile.update(formData, {id: $scope.walletData.pubkey, wallet: wallet}) .then(function() { console.info("[ES] Profile successfully updated."); $scope.saving = false; @@ -295,7 +322,12 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ }; $scope.close = function() { - return $state.go('app.view_wallet', {refresh: true}); + if (wallet.isDefault()) { + return $state.go('app.view_wallet', {refresh: true}); + } + else { + return $state.go('app.view_wallet_by_id', {refresh: true, id: wallet.id}); + } }; $scope.showAvatarModal = function() { @@ -343,7 +375,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ // Hide popover if need $scope.hideActionsPopover(); - return $scope.existing && csWallet.auth({minData: true}) + return $scope.existing && wallet.auth({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); diff --git a/www/plugins/es/js/controllers/registry-controllers.js b/www/plugins/es/js/controllers/registry-controllers.js index d9e25ef22afdd748e9e2f36a2a6279ccac360f8a..cd04f36f33f5bdd76982dd8e74b8a1e12b11fd66 100644 --- a/www/plugins/es/js/controllers/registry-controllers.js +++ b/www/plugins/es/js/controllers/registry-controllers.js @@ -735,6 +735,7 @@ function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWalle $scope.search.issuer = walletData.pubkey; $scope.search.advanced = true; $timeout($scope.doSearch, 100); + $scope.showFab('fab-wallet-add-registry-record'); }); } else { diff --git a/www/plugins/es/js/controllers/settings-controllers.js b/www/plugins/es/js/controllers/settings-controllers.js index b6b981a8817aaedfa62ac18164632687ff651d3b..1e2687001defdb15d2595df6d7e33dcc597e1300 100644 --- a/www/plugins/es/js/controllers/settings-controllers.js +++ b/www/plugins/es/js/controllers/settings-controllers.js @@ -11,7 +11,7 @@ angular.module('cesium.es.settings.controllers', ['cesium.es.services']) points: { 'plugins': { templateUrl: "plugins/es/templates/settings/settings_extend.html", - controller: "ESExtendSettingsCtrl" + controller: "ESExtensionCtrl" } } }); diff --git a/www/plugins/es/js/controllers/subscription-controllers.js b/www/plugins/es/js/controllers/subscription-controllers.js index c9fde17b7daff3dce330a18ef98eff9de94402b6..fd084fc5c77cc6c64852621b09d9576fab6539dd 100644 --- a/www/plugins/es/js/controllers/subscription-controllers.js +++ b/www/plugins/es/js/controllers/subscription-controllers.js @@ -2,20 +2,36 @@ angular.module('cesium.es.subscription.controllers', ['cesium.es.services']) .config(function($stateProvider) { - $stateProvider.state('app.edit_subscriptions', { - cache: false, - url: "/wallet/subscriptions", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", - controller: 'ViewSubscriptionsCtrl' + $stateProvider + .state('app.edit_subscriptions', { + cache: false, + url: "/wallet/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + auth: true, + minData: true } - }, - data: { - auth: true, - minData: true - } - }); + }) + + .state('app.edit_subscriptions_by_id', { + cache: false, + url: "/wallet/list/:id/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + login: true, + minData: true + } + }); }) @@ -25,9 +41,10 @@ angular.module('cesium.es.subscription.controllers', ['cesium.es.services']) ; -function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, ModalUtils, esSubscription) { +function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, UIUtils, ModalUtils, esSubscription) { 'ngInject'; + $scope.loading = true; $scope.popupData = {}; // need for the node popup $scope.search = { results: [], @@ -38,25 +55,44 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod {id: "weekly", label: "weekly"} ]; - $scope.onEnter = function() { - $scope.loading = true; - $scope.loadWallet({minData: true}) - .then(function() { - UIUtils.loading.hide(); - return $scope.load(); + var wallet; + + $scope.enter = function(e, state) { + + // First load + if ($scope.loading) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.loadWallet({ + wallet: wallet, + auth: true, + minData: true }) - .catch(function(err){ - if (err == 'CANCELLED') { - return UIUtils.loading.hide(); - } - UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); - }); + .then(function() { + UIUtils.loading.hide(); + return $scope.load(); + }) + .catch(function(err){ + if (err == 'CANCELLED') { + UIUtils.loading.hide(10); + $ionicHistory.goBack(); + return + } + UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); + }); + } + }; - $scope.$on('$ionicView.enter', $scope.onEnter); + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function() { $scope.loading = true; // to avoid the call of doSave() - return esSubscription.record.load($rootScope.walletData.pubkey, $rootScope.walletData.keypair) + return esSubscription.record.load(wallet.data.pubkey, wallet.data.keypair) .then(function(results) { // Group by type var groups = _.groupBy((results || []), function (record) { @@ -74,10 +110,8 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(results) { return csWot.extendAll(results, 'recipient'); }) - .then(function(results) { - // Display result - $scope.updateView(results); - }) + // Display result + .then($scope.updateView) .catch(function(err){ UIUtils.loading.hide(10); if (err && err.ucode == 404) { @@ -118,11 +152,11 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(record) { if (!record) return; UIUtils.loading.show(); - esSubscription.record.add(record) + esSubscription.record.add(record, wallet) .then($scope.addToUI) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 0}; - $rootScope.walletData.subscriptions.count++; + $scope.wallet.data.subscriptions = $scope.wallet.data.subscriptions || {count: 0}; + $scope.wallet.data.subscriptions.count++; UIUtils.loading.hide(); $scope.updateView(); }) @@ -140,11 +174,11 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod } if (!promise) return; return promise - .then(function() { - if (!record) return; + .then(function(res) { + if (!res) return; UIUtils.loading.show(); record.id = oldRecord.id; - return esSubscription.record.update(record) + return esSubscription.record.update(record, wallet) .then(function() { // If recipient change, update in results if (oldRecord.type != record.type || @@ -174,8 +208,8 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod UIUtils.loading.show(); esSubscription.record.remove(record.id) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 1}; - $rootScope.walletData.subscriptions.count--; + $scope.wallet.data.subscriptions = $scope.wallet.data.subscriptions || {count: 1}; + $scope.wallet.data.subscriptions.count--; $scope.removeFromUI(record); UIUtils.loading.hide(); }) diff --git a/www/plugins/es/js/controllers/wallet-controllers.js b/www/plugins/es/js/controllers/wallet-controllers.js index 692eaeb1bd6fad4ba4a6a0a428e52851e1703b83..664b4f0ded763479065065cd73cb40e0b9f2d979 100644 --- a/www/plugins/es/js/controllers/wallet-controllers.js +++ b/www/plugins/es/js/controllers/wallet-controllers.js @@ -5,7 +5,8 @@ angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) var enable = csConfig.plugins && csConfig.plugins.es; if (enable) { - PluginServiceProvider.extendState('app.view_wallet', { + PluginServiceProvider + .extendStates(['app.view_wallet', 'app.view_wallet_by_id'], { points: { 'after-general': { templateUrl: "plugins/es/templates/wallet/view_wallet_extend.html", @@ -27,7 +28,7 @@ function ESWalletController($scope, $controller, esModals) { 'ngInject'; // Initialize the super class and extend it. - angular.extend(this, $controller('ESWotIdentityViewCtrl', {$scope: $scope})); + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showProfileHelp = false; diff --git a/www/plugins/es/js/controllers/wot-controllers.js b/www/plugins/es/js/controllers/wot-controllers.js index 420c9ecbdeadee49581580e38761fcfcaa96b415..d568d3c3376f77867b405a6d5d0317bbe545940e 100644 --- a/www/plugins/es/js/controllers/wot-controllers.js +++ b/www/plugins/es/js/controllers/wot-controllers.js @@ -82,15 +82,12 @@ function ESWotLookupExtendController($scope, $controller, $state) { }; } -function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, esSettings, PluginService, csWallet, +function ESWotIdentityViewController($scope, $ionicPopover, $q, $controller, UIUtils, Modals, csWallet, esModals, esHttp, esWallet, esInvitation) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); /* -- modals -- */ diff --git a/www/plugins/es/js/services/http-services.js b/www/plugins/es/js/services/http-services.js index 8f7c01fd5362d2e9468e157c4df1b1fff2364351..8e034d3fff542d109a186e215cb7d16eb0e4a720 100644 --- a/www/plugins/es/js/services/http-services.js +++ b/www/plugins/es/js/services/http-services.js @@ -441,7 +441,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic options = options || {}; var postRequest = that.post(path); return function(record, params) { - return csWallet.auth() + + var wallet = (params && params.wallet || csWallet); + delete params.wallet; + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) .then(function(walletData) { if (options.creationTime && !record.creationTime) { record.creationTime = that.date.now(); @@ -485,8 +488,11 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic } function removeRecord(index, type) { - return function(id) { - return (csWallet.isAuth() ? $q.when(csWallet.data) : csWallet.auth({silent: true, minData: true})) + return function(id, options) { + options = options || {}; + var wallet = (options && options.wallet || csWallet); + delete options.wallet; + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) .then(function(walletData) { var obj = { diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js index f492d36d8875dcd8d8d8e28cadffe838b58253f5..26bccd31c9c02e01d60bc470bfe6222e42343222 100644 --- a/www/plugins/es/js/services/message-services.js +++ b/www/plugins/es/js/services/message-services.js @@ -45,6 +45,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function onWalletLogin(data, deferred) { deferred = deferred || $q.defer(); + + console.log("MESSAGE login on ", data); if (!data || !data.pubkey) { deferred.resolve(); return deferred.promise; diff --git a/www/plugins/es/js/services/settings-services.js b/www/plugins/es/js/services/settings-services.js index 8999754db2685090575183c817b428f30d4699be..96d8f98061536cb16fb147a72176b6be843d2fa8 100644 --- a/www/plugins/es/js/services/settings-services.js +++ b/www/plugins/es/js/services/settings-services.js @@ -237,7 +237,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt } var time = esHttp.date.now(); // always update time - console.debug('[ES] [settings] Saving user settings... at time ' + time); + console.debug('[ES] [settings] Saving user settings remotely...'); return $q.all([ csWallet.getKeypair(), // same result as esWallet.box.getKeypair(), because box keypair computed on auth diff --git a/www/plugins/es/js/services/subscription-services.js b/www/plugins/es/js/services/subscription-services.js index b18115b36d7e6203a646d4276bab85021388e709..a8924bd6722f96da4614f4d4ddbc9235cbd08ed2 100644 --- a/www/plugins/es/js/services/subscription-services.js +++ b/www/plugins/es/js/services/subscription-services.js @@ -81,12 +81,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es }); } - function addRecord(record) { + function addRecord(record, wallet) { if (!record || !record.type || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.type' or 'record.content' or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + wallet = wallet || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); @@ -95,8 +96,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -105,7 +106,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.add(encryptedRecord) + return that.raw.add(encryptedRecord, {wallet: wallet}) .then(function(id) { record.id = id; return record; @@ -114,12 +115,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es ; } - function updateRecord(record) { + function updateRecord(record, wallet) { if (!record || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.content', or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + wallet = wallet || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); // Get a unique nonce @@ -127,8 +129,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -137,7 +139,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.update(encryptedRecord, {id:record.id}) + return that.raw.update(encryptedRecord, {id:record.id, wallet: wallet}) .then(function() { return record; // return original record }); diff --git a/www/plugins/es/js/services/wallet-services.js b/www/plugins/es/js/services/wallet-services.js index 2de5e31ad13af68cc7f32e244665b5ccc96be431..52fb01f96cef02e2fdcb223298b080f2b44816ea 100644 --- a/www/plugins/es/js/services/wallet-services.js +++ b/www/plugins/es/js/services/wallet-services.js @@ -24,8 +24,8 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c // Generate box keypair esCrypto.box.getKeypair(data.keypair) .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; + data.keypair.boxSk = res.boxSk; + data.keypair.boxPk = res.boxPk; console.debug("[ES] [wallet] Box keypair successfully computed"); deferred.resolve(); }); @@ -108,23 +108,23 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c return deferred.promise; } - function getBoxKeypair() { - if (!csWallet.isAuth()) { + function getBoxKeypair(keypair) { + if (!keypair && !csWallet.isAuth()) { throw new Error('Unable to get box keypair: user not authenticated !'); } - return csWallet.getKeypair({silent: true}) + return (keypair ? $q.when(keypair) : csWallet.getKeypair({silent: true})) .then(function(keypair) { if (keypair && keypair.boxPk && keypair.boxSk) { - return $q.when(csWallet.data.keypair); + return $q.when(keypair); } return esCrypto.box.getKeypair(keypair); }) .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; + keypair.boxSk = res.boxSk; + keypair.boxPk = res.boxPk; console.debug("[ES] [wallet] Box keypair successfully computed"); - return csWallet.data.keypair; + return keypair; }); } @@ -177,15 +177,15 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c getKeypair: getBoxKeypair, record: { pack: function(record, keypair, recipientFieldName, cypherFieldNames, nonce) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.pack(record, keypair, recipientFieldName, cypherFieldNames, nonce); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.pack(record, fullKeypair, recipientFieldName, cypherFieldNames, nonce); }); }, open: function(records, keypair, issuerFieldName, cypherFieldNames) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.open(records, keypair, issuerFieldName, cypherFieldNames); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.open(records, fullKeypair, issuerFieldName, cypherFieldNames); }); } } diff --git a/www/plugins/es/templates/common/popover_profile_extend.html b/www/plugins/es/templates/common/popover_profile_extend.html index 33d61e3d561ccceb1b642ac1449af578b3165c6c..21c1faff66b5a041180227b79963771d0d488fc7 100644 --- a/www/plugins/es/templates/common/popover_profile_extend.html +++ b/www/plugins/es/templates/common/popover_profile_extend.html @@ -1,5 +1,5 @@ <!-- profile --> - <button ng-if="enable && auth" + <button ng-if=":state:enable && auth" class="button button-positive button-small ink" ng-click="showEditUserProfile()"> {{'PROFILE.BTN_EDIT' | translate}} diff --git a/www/plugins/es/templates/currency/tab_blocks_extend.html b/www/plugins/es/templates/currency/tab_blocks_extend.html index 6524798fe761810741e780c218e56c67e60f6cfe..228d5d3f2edc77e0311737a693b7bce81b2b0977 100644 --- a/www/plugins/es/templates/currency/tab_blocks_extend.html +++ b/www/plugins/es/templates/currency/tab_blocks_extend.html @@ -1,6 +1,6 @@ <!-- Buttons section --> -<ng-if ng-if="enable && extensionPoint === 'nav-buttons'"> +<ng-if ng-if=":state:enable && extensionPoint === 'nav-buttons'"> <button class="button button-icon button-clear icon ion-android-search visible-xs visible-sm" ui-sref="app.blockchain_search"> diff --git a/www/plugins/es/templates/join/modal_join_extend.html b/www/plugins/es/templates/join/modal_join_extend.html index f107c52e1a3c62f977c320d1e0c60edd235bae83..c0aa9749cc76615726193914225576e6bacbc0e4 100644 --- a/www/plugins/es/templates/join/modal_join_extend.html +++ b/www/plugins/es/templates/join/modal_join_extend.html @@ -1,4 +1,4 @@ -<ng-if ng-if="enable && extensionPoint === 'select-account-type'"> +<ng-if ng-if=":state:enable && extensionPoint === 'select-account-type'"> <!-- ornigzation wallet --> <div class="item item-complex card stable-bg item-icon-left item-icon-right ink" @@ -15,7 +15,7 @@ </ng-if> <!-- Add a slide --> -<ng-if ng-if="enable && extensionPoint === 'last-slide'"> +<ng-if ng-if=":state:enable && extensionPoint === 'last-slide'"> <!-- STEP 6: organization type --> <ion-slide-page> diff --git a/www/plugins/es/templates/menu_extend.html b/www/plugins/es/templates/menu_extend.html index 7c255eee9d3fbeb3e1388bd2a069bad63ce39034..c931d80f3a77c3e23e499f93f070ffcbb9477ca8 100644 --- a/www/plugins/es/templates/menu_extend.html +++ b/www/plugins/es/templates/menu_extend.html @@ -1,7 +1,6 @@ <!-- Top header: Main section --> -<div - ng-if="enable && extensionPoint === 'nav-buttons-right'" class="hidden-xs hidden-sm"> +<div ng-if=":state:enable && extensionPoint === 'nav-buttons-right'" class="hidden-xs hidden-sm"> <!-- invitation event --> @@ -39,7 +38,7 @@ </div> <!-- Left menu: User section --> -<div ng-if="enable && extensionPoint === 'menu-user'" class="visible-xs visible-sm"> +<div ng-if=":state:enable && extensionPoint === 'menu-user'" class="visible-xs visible-sm"> <a menu-close class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/invitations" diff --git a/www/plugins/es/templates/network/view_network_extend.html b/www/plugins/es/templates/network/view_network_extend.html index 3b070a9d78b05404d7ee3843678d043410b47ce8..91d217861f80cf35c67fb216358326326302c73a 100644 --- a/www/plugins/es/templates/network/view_network_extend.html +++ b/www/plugins/es/templates/network/view_network_extend.html @@ -1,5 +1,5 @@ <!-- Buttons section --> -<ng-if ng-if="enable && extensionPoint === 'buttons'"> +<ng-if ng-if=":state:enable && extensionPoint === 'buttons'"> <a class="button button-text button-small ink" ui-sref="app.blockchain_search" > <i class="icon ion-android-search"></i> diff --git a/www/plugins/es/templates/registry/lookup_lg.html b/www/plugins/es/templates/registry/lookup_lg.html index 5ff7c9039ddc92eaee7074c8de4433470c8448b2..1c09a1b16aeef5f098677131a6ada30f28dc585a 100644 --- a/www/plugins/es/templates/registry/lookup_lg.html +++ b/www/plugins/es/templates/registry/lookup_lg.html @@ -5,7 +5,7 @@ <ion-content class="lookupForm padding no-padding-xs"> - <ng-include src="::'plugins/es/templates/wot/lookup_lg_extend.html'" ng-init="showNewPageButton=true;"></ng-include> + <ng-include src="::'plugins/es/templates/wot/lookup_lg_extend.html'" ng-init="enable= true; showNewPageButton=true;"></ng-include> <ng-include src="::'plugins/es/templates/registry/lookup_form.html'"></ng-include> diff --git a/www/plugins/es/templates/registry/lookup_list.html b/www/plugins/es/templates/registry/lookup_list.html index 36b63579392779921f9afbe25a0750b9152a7b2f..6497132477500ffad60b37bb2e263cc71d1af428 100644 --- a/www/plugins/es/templates/registry/lookup_list.html +++ b/www/plugins/es/templates/registry/lookup_list.html @@ -1,6 +1,6 @@ <ion-list class="{{::motion.ionListClass}}" - ng-if="!search.loading && search.results && search.results.length > 0"> + ng-if="!search.loading && search.results"> <ion-item ng-repeat="item in search.results" class="item item-border-large item-avatar item-icon-right ink" diff --git a/www/plugins/es/templates/registry/view_wallet_pages.html b/www/plugins/es/templates/registry/view_wallet_pages.html index 5d20cc44cd38614347ab45af5a3f7f0a62b738c4..275f1ffbcfc2f8e99723d1738b6d0e24ce985725 100644 --- a/www/plugins/es/templates/registry/view_wallet_pages.html +++ b/www/plugins/es/templates/registry/view_wallet_pages.html @@ -43,4 +43,9 @@ </ion-content> + <button id="fab-wallet-add-registry-record" + class="button button-fab button-fab-bottom-right button-assertive hidden-md hidden-lg drop" + ng-click="showNewPageModal()"> + <i class="icon ion-plus"></i> + </button> </ion-view> diff --git a/www/plugins/es/templates/wallet/view_wallet_extend.html b/www/plugins/es/templates/wallet/view_wallet_extend.html index 76787717f3c271db7fd6b67c863afc573be1b1d0..6514240e063236bc6bfa2d630d435ea916cf8c66 100644 --- a/www/plugins/es/templates/wallet/view_wallet_extend.html +++ b/www/plugins/es/templates/wallet/view_wallet_extend.html @@ -1,4 +1,4 @@ -<ng-if ng-if="enable"> +<ng-if ng-if=":state:enable"> <!-- profile --> <div class="item item-divider item-divider-top-border"> <span> @@ -8,8 +8,16 @@ class="icon positive ion-ios-help-outline" title="{{'PROFILE.PROFILE_DIVIDER_HELP' | translate}}"></i> </span> + <a class="badge button button-text button-small button-small-padding" + ng-if="isDefaultWallet" + ui-sref="app.edit_profile"> + <i class="icon ion-edit"></i> + <span ng-if="!formData.profile" translate>PROFILE.BTN_ADD</span> + <span ng-if="formData.profile" translate>PROFILE.BTN_EDIT</span> + </a> <a class="badge button button-text button-small button-small-padding " - ui-sref="app.user_edit_profile"> + ng-if="!isDefaultWallet" + ui-sref="app.edit_profile_by_id({id: walletId})"> <i class="icon ion-edit"></i> <span ng-if="!formData.profile" translate>PROFILE.BTN_ADD</span> <span ng-if="formData.profile" translate>PROFILE.BTN_EDIT</span> @@ -36,11 +44,17 @@ <span> <a class="badge button button-text button-small button-small-padding " - ng-if="!formData.subscriptions.count" + ng-if="!formData.subscriptions.count && isDefaultWallet" ui-sref="app.edit_subscriptions"> <i class="icon ion-edit"></i> <span translate>SUBSCRIPTION.BTN_ADD</span> </a> + <a class="badge button button-text button-small button-small-padding " + ng-if="!formData.subscriptions.count && !isDefaultWallet" + ui-sref="app.edit_subscriptions_by_id({id: walletId})"> + <i class="icon ion-edit"></i> + <span translate>SUBSCRIPTION.BTN_ADD</span> + </a> </div> <div class="item item-text-wrap positive item-small-height" ng-show="showSubscriptionHelp"> @@ -53,12 +67,21 @@ class="item gray" translate>SUBSCRIPTION.NO_SUBSCRIPTION</div> <a class="item item-icon-left item-text-wrap item-icon-right ink" - ng-if="formData.subscriptions.count" + ng-if="formData.subscriptions.count && isDefaultWallet" ui-sref="app.edit_subscriptions"> <i class="icon ion-gear-a"></i> <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> <span class="badge badge-calm">{{formData.subscriptions.count}}</span> + <i class="gray icon ion-ios-arrow-right"></i> + </a> + <a class="item item-icon-left item-text-wrap item-icon-right ink" + ng-if="formData.subscriptions.count && !isDefaultWallet" + ui-sref="app.edit_subscriptions_by_id({id: walletId})"> + <i class="icon ion-gear-a"></i> + <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> + <span class="badge badge-calm">{{formData.subscriptions.count}}</span> + <i class="gray icon ion-ios-arrow-right"></i> </a> </div> @@ -91,12 +114,21 @@ class="item gray" translate>REGISTRY.NO_PAGE</div> <a class="item item-icon-left item-text-wrap item-icon-right ink" - ng-if="formData.pages.count" + ng-if="formData.pages.count && isDefaultWallet" ui-sref="app.wallet_pages"> <i class="icon ion-social-buffer"></i> <span translate>REGISTRY.MY_PAGES</span> <span class="badge badge-calm">{{formData.pages.count}}</span> + <i class="gray icon ion-ios-arrow-right"></i> + </a> + <a class="item item-icon-left item-text-wrap item-icon-right ink" + ng-if="formData.pages.count && !isDefaultWallet" + ui-sref="app.wallet_pages_by_id({id: walletId})"> + <i class="icon ion-social-buffer"></i> + <span translate>REGISTRY.MY_PAGES</span> + <span class="badge badge-calm">{{formData.pages.count}}</span> + <i class="gray icon ion-ios-arrow-right"></i> </a> </div> diff --git a/www/plugins/es/templates/wot/lookup_extend.html b/www/plugins/es/templates/wot/lookup_extend.html index 0229cb9588973118734c3d569113aaba143aec03..a1fdf25927e8686d99ecd25989a9ab5f8e4c2280 100644 --- a/www/plugins/es/templates/wot/lookup_extend.html +++ b/www/plugins/es/templates/wot/lookup_extend.html @@ -1,4 +1,5 @@ -<ion-tab title="{{'MENU.REGISTRY'|translate}}" icon="ion-social-buffer" +<ion-tab ng-if=":state:enable" + title="{{'MENU.REGISTRY'|translate}}" icon="ion-social-buffer" ui-sref="app.wot_lookup.tab_registry"> <ion-nav-view name="tab_registry"></ion-nav-view> </ion-tab> diff --git a/www/plugins/es/templates/wot/lookup_lg_extend.html b/www/plugins/es/templates/wot/lookup_lg_extend.html index e2197e79229593b31870ea6bbd29581566cbf899..ced498410ec3c18a6b89c6df3b3f0b1592a34fe8 100644 --- a/www/plugins/es/templates/wot/lookup_lg_extend.html +++ b/www/plugins/es/templates/wot/lookup_lg_extend.html @@ -1,4 +1,4 @@ -<div class="buttons-tabs"> +<div class="buttons-tabs" ng-if=":state:enable"> <div class="pull-right"> <div class="button button-tab dark" diff --git a/www/plugins/es/templates/wot/view_certifications_extend.html b/www/plugins/es/templates/wot/view_certifications_extend.html index 98dd25c08d140f19d6972b5d4f8adb98b7577e72..46de8d5d0d64c507112e58f9d01c8f54f0f059c3 100644 --- a/www/plugins/es/templates/wot/view_certifications_extend.html +++ b/www/plugins/es/templates/wot/view_certifications_extend.html @@ -1,5 +1,5 @@ <!-- nav buttons section --> -<ng-if ng-if="enable && extensionPoint === 'nav-buttons'"> +<ng-if ng-if=":state:enable && extensionPoint === 'nav-buttons'"> <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showCertificationActionsPopover($event)"> </button> @@ -7,7 +7,7 @@ </ng-if> <!-- Buttons section --> -<ng-if ng-if="enable && extensionPoint === 'buttons'"> +<ng-if ng-if=":state:enable && extensionPoint === 'buttons'"> <button class="button button-stable button-small-padding icon ion-android-more-vertical" ng-click="showCertificationActionsPopover($event)" diff --git a/www/plugins/es/templates/wot/view_identity_extend.html b/www/plugins/es/templates/wot/view_identity_extend.html index acabb2485fbb96dfe207615e521feaa662caf91c..fec67385e1f10bae208cfd28c1e4fbecf4c8368c 100644 --- a/www/plugins/es/templates/wot/view_identity_extend.html +++ b/www/plugins/es/templates/wot/view_identity_extend.html @@ -1,5 +1,5 @@ <!-- Buttons section --> -<ng-if ng-if="enable && extensionPoint === 'buttons'"> +<ng-if ng-if=":state:enable && extensionPoint === 'buttons'"> <button class="button button-stable button-small-padding icon ion-compose" ng-click="showNewMessageModal()" title="{{'MESSAGE.BTN_WRITE' | translate}}"> @@ -7,7 +7,7 @@ </ng-if> <!-- General section --> -<ng-if ng-if="enable && extensionPoint === 'after-general'"> +<ng-if ng-if=":state:enable && extensionPoint === 'after-general'"> <span class="item item-divider item-divider-top-border"> <span> diff --git a/www/templates/login/form_login.html b/www/templates/login/form_login.html index 6c05dd7c25ae16d41753f0feb84f346c50d6064f..cb5c4d5e4de447ad9b8ab40d3ef0aac2d80077f9 100644 --- a/www/templates/login/form_login.html +++ b/www/templates/login/form_login.html @@ -56,7 +56,7 @@ </div> <!-- Register ? --> - <ng-if ng-if="!isAuth"> + <ng-if ng-if="!isAuth && showNewAccountLink"> <div class="text-center no-padding"> {{'LOGIN.NO_ACCOUNT_QUESTION'|translate}} <br class="visible-xs"/> diff --git a/www/templates/login/form_pubkey.html b/www/templates/login/form_pubkey.html index b9e75a2c88b59c40ef76fa08293a9b4e5054f548..876d27ff955cce692bcd9df9820744fcafbae0e6 100644 --- a/www/templates/login/form_pubkey.html +++ b/www/templates/login/form_pubkey.html @@ -9,7 +9,6 @@ <input name="pubkey" type="text" placeholder="{{'LOGIN.PUBKEY_HELP' | translate}}" ng-model="formData.pubkey" ng-model-options="{ debounce: 650 }" - ng-pattern="pubkeyPattern" required > <a class="button button-stable icon ion-android-search ink" ng-click="showWotLookupModal(form.pubkey.$viewValue)"> @@ -21,9 +20,6 @@ <div class="form-error" ng-message="required"> <span translate="ERROR.FIELD_REQUIRED"></span> </div> - <div class="form-error" ng-message="pattern"> - <span translate="ERROR.INVALID_PUBKEY"></span> - </div> <div class="form-error" ng-message="checksum"> <span translate="ERROR.INVALID_PUBKEY_CHECKSUM"></span> </div> diff --git a/www/templates/login/modal_login.html b/www/templates/login/modal_login.html index 20d59dd993450dde3a28c317383f3b602c7948a9..1004ddee34d0f566ed82bc8ed396a402bdf8e321 100644 --- a/www/templates/login/modal_login.html +++ b/www/templates/login/modal_login.html @@ -3,7 +3,7 @@ ng-class="{'bar-positive': !isAuth, 'bar-assertive': isAuth}"> <button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL </button> - <h1 class="title" ng-bind-html="isAuth ? 'AUTH.TITLE' : 'LOGIN.TITLE' | translate"> + <h1 class="title" ng-bind-html="title | translate"> </h1> <div class="buttons buttons-right"> <div class="secondary-buttons"> diff --git a/www/templates/wallet/list/modal_wallets.html b/www/templates/wallet/list/modal_wallets.html new file mode 100644 index 0000000000000000000000000000000000000000..8d6118c158795b57b1665df3161aedf8cff6e1c1 --- /dev/null +++ b/www/templates/wallet/list/modal_wallets.html @@ -0,0 +1,13 @@ +<ion-modal-view id="transfer" class="modal-full-height"> + <ion-header-bar class="bar-positive"> + <button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button> + <h1 class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</h1> + </ion-header-bar> + + <ion-content scroll="true"> + + <ng-include src="'templates/wallet/list/wallets.html'"></ng-include> + + </ion-content> + +</ion-modal-view> diff --git a/www/templates/wallet/list/popover_actions.html b/www/templates/wallet/list/popover_actions.html new file mode 100644 index 0000000000000000000000000000000000000000..5382fee0343aa280200982066f2dbbfe05b27530 --- /dev/null +++ b/www/templates/wallet/list/popover_actions.html @@ -0,0 +1,19 @@ +<ion-popover-view class="fit has-header"> + <ion-header-bar> + <h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1> + </ion-header-bar> + <ion-content scroll="false"> + <div class="list item-text-wrap"> + + <!-- delete some wallets --> + <button class="item item-icon-left ink" + ng-class="{'gray': loading || !wallets.length, 'assertive': !loading && wallets.length}" + ng-disabled="loading || !wallets.length" + ng-click="selectAndRemoveWallet()"> + <i class="icon ion-trash-a"></i> + {{'ACCOUNT.WALLET_LIST.BTN_DELETE' | translate}} + </button> + + </div> + </ion-content> +</ion-popover-view> diff --git a/www/templates/wallet/list/view_wallets.html b/www/templates/wallet/list/view_wallets.html new file mode 100644 index 0000000000000000000000000000000000000000..e70d513a2d69ae223fd01a309b3a2c8805857c4a --- /dev/null +++ b/www/templates/wallet/list/view_wallets.html @@ -0,0 +1,53 @@ +<ion-view left-buttons="leftButtons" + class="view-wallet-list"> + <ion-nav-title> + <!-- no title--> + </ion-nav-title> + + <ion-nav-buttons side="secondary"> + <cs-extension-point name="nav-buttons"></cs-extension-point> + + <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" + ng-click="showActionsPopover($event)"> + </button> + </ion-nav-buttons> + + <ion-content scroll="true" + bind-notifier="{ rebind:formData.useRelative, locale:settings.locale.id}"> + + <ion-refresher pulling-text="{{:locale:'COMMON.BTN_REFRESH' | translate}}" + on-refresh="doUpdate(true)"> + </ion-refresher> + + <!-- Buttons bar--> + <div class="hidden-xs hidden-sm padding text-center"> + + <button class="button button-stable button-small-padding icon ion-loop ink" + ng-click="doUpdate()" + title="{{:locale:'COMMON.BTN_REFRESH' | translate}}"> + </button> + + <cs-extension-point name="buttons"></cs-extension-point> + + <button class="button button-calm icon-left ink" + ng-click="showNewWalletModal()"> + {{:locale:'ACCOUNT.WALLET_LIST.BTN_NEW' | translate}} + </button> + + <button class="button button-stable button-small-padding icon ion-android-more-vertical ink" + ng-click="showActionsPopover($event)" + title="{{:locale:'COMMON.BTN_OPTIONS' | translate}}"> + </button> + + </div> + + <ng-include src="'templates/wallet/list/wallets.html'"></ng-include> + + </ion-content> + + <button id="fab-add-wallet" + class="button button-fab button-fab-bottom-right button-assertive hidden-md hidden-lg drop" + ng-click="showNewWalletModal()"> + <i class="icon ion-plus"></i> + </button> +</ion-view> diff --git a/www/templates/wallet/list/wallets.html b/www/templates/wallet/list/wallets.html new file mode 100644 index 0000000000000000000000000000000000000000..ead7cefe15ff559eb19b129c727ac9b6e6a9c3eb --- /dev/null +++ b/www/templates/wallet/list/wallets.html @@ -0,0 +1,42 @@ +<div class="center padding" ng-if="loading"> + <ion-spinner icon="android"></ion-spinner> +</div> + +<div class="center padding gray" ng-if="!loading && !wallets.length"> + {{:locale:'ACCOUNT.WALLET_LIST.NO_WALLET'|translate}} +</div> + +<ion-list ng-if="!loading" class="{{::motion.ionListClass}}"> + <ng-repeat ng-repeat="wallet in wallets track by wallet.id"> + <div class="item item-avatar item-icon-right item-border-large item-wallet" + ng-click="select(wallet)" + ng-init="walletData=wallet.data;"> + + <i ng-if="::!walletData.avatar" class="item-image icon" + ng-class=":rebind:{'ion-card': !walletData.isMember, 'ion-persion': walletData.isMember}"></i> + <i ng-if="::walletData.avatar" class="item-image avatar" style="background-image: url({{::walletData.avatar.src}})"></i> + + <h2> + <ng-if ng-if="::walletData.name||walletData.uid" ng-bind-html="::walletData.name||walletData.uid"></ng-if> + <ng-if ng-if="::!walletData.name && !walletData.uid">{{::walletData.pubkey|formatPubkey}}</ng-if> + </h2> + + <h4 class="gray"> + <span class="positive" ng-if="::walletData.name && walletData.uid"> + <i class="ion-person"></i> + {{::walletData.uid}} + </span> + <b class="ion-key"></b> + {{::walletData.pubkey | formatPubkey}} + <span ng-if="::!walletData.uid" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span> + </h4> + + <span class="badge" + ng-class="{'badge-assertive': (walletData.balance <= 0), 'badge-balanced': (walletData.balance > 0) }"> + <span ng-bind-html="walletData.balance|formatAmount:{useRelative: true, currency: currency}"></span> + </span> + + <i class="icon ion-ios-arrow-right "></i> + </div> + </ng-repeat> +</ion-list> diff --git a/www/templates/wallet/popover_actions.html b/www/templates/wallet/popover_actions.html index 9c0f9141f6e177df02bdbcadbd4e01a70dbdff42..bc1ce199326aa692565a275b9e04e1ed9bed0e49 100644 --- a/www/templates/wallet/popover_actions.html +++ b/www/templates/wallet/popover_actions.html @@ -55,6 +55,7 @@ <!-- help tour --> <a class="item item-icon-left ink hidden-sm hidden-xs" + ng-if="isDefaultWallet" ng-click="startWalletTour()"> <i class="icon ion-easel"></i> {{'COMMON.BTN_HELP_TOUR_SCREEN' | translate}} diff --git a/www/templates/wallet/transfer_form.html b/www/templates/wallet/transfer_form.html index fedf8ae7cd8457a17f41be85e95c441f2daf221e..a32257921bec6af1295776e386e0f31d3c0d03c7 100644 --- a/www/templates/wallet/transfer_form.html +++ b/www/templates/wallet/transfer_form.html @@ -4,7 +4,7 @@ <div class="list no-padding-xs" ng-init="setForm(transferForm)"> <!-- dest --> - <a class="item item-icon-right gray ink" + <ion-item class="item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.destPub}" ng-click="showWotLookupModal()"> <span class="gray" translate>TRANSFER.TO</span> @@ -15,7 +15,7 @@ <i class="ion-key"></i> {{formData.destPub | formatPubkey}} </span> <i class="gray icon ion-ios-arrow-right"></i> - </a> + </ion-item> <div class="form-errors" ng-if="form.$submitted && !formData.destPub"> <div class="form-error"> @@ -23,21 +23,25 @@ </div> </div> - <span class="item item-text-wrap"> - <span class="gray" translate>TRANSFER.FROM</span> - <span class="badge animate-fade-in animate-show-hide ng-hide" ng-show="!loading" - ng-class="{'badge-assertive': (convertedBalance <= 0 || (formData.amount && convertedBalance < formData.amount)), 'badge-balanced': (convertedBalance > 0 && (!formData.amount || convertedBalance >= formData.amount)) }"> - <ion-spinner icon="android" ng-show="!walletData.pubkey"></ion-spinner> - <span ng-if="walletData.pubkey && !walletData.isMember"> - <i class="ion-key"></i> {{walletData.pubkey| formatPubkey}} - </span> - <span ng-if="walletData.isMember"> - <i class="ion-person"></i> {{walletData.name||walletData.uid}} - </span> - <span ng-bind-html="walletData.balance|formatAmount:{useRelative: formData.useRelative, currency:currency}"></span> - </span> + <!-- from --> + <ion-item class="item-text-wrap ink" + ng-class="{'item-icon-right': enableSelectWallet}" + ng-click="showSelectWalletModal()"> + <span class="gray" translate>TRANSFER.FROM</span> + <span class="badge animate-fade-in animate-show-hide ng-hide" ng-show="!loading" + ng-class="{'badge-assertive': (convertedBalance <= 0 || (formData.amount && convertedBalance < formData.amount)), 'badge-balanced': (convertedBalance > 0 && (!formData.amount || convertedBalance >= formData.amount)) }"> + <ion-spinner icon="android" ng-show="!walletData.pubkey"></ion-spinner> + <span ng-if="walletData.pubkey && !walletData.isMember"> + <i class="ion-key"></i> {{walletData.pubkey| formatPubkey}} + </span> + <span ng-if="walletData.isMember"> + <i class="ion-person"></i> {{walletData.name||walletData.uid}} + </span> + <span ng-bind-html="walletData.balance|formatAmount:{useRelative: formData.useRelative, currency:currency}"></span> + </span> - </span> + <i class="gray icon ion-ios-arrow-right" ng-if="enableSelectWallet"></i> + </ion-item> <!-- Amount --> <ion-item class="item-input item-floating-label item-button-right" diff --git a/www/templates/wallet/view_wallet.html b/www/templates/wallet/view_wallet.html index e7f45a5c72a093ce5240329d0c46271f117e0692..0d9c134d90f85f2784749e3fe94823b03d8013c8 100644 --- a/www/templates/wallet/view_wallet.html +++ b/www/templates/wallet/view_wallet.html @@ -155,12 +155,19 @@ <!-- Account transaction --> <a class="item item-icon-left item-icon-right ink" - ng-if="!loading" + ng-if="isDefaultWallet" ui-sref="app.view_wallet_tx"> <i class="icon ion-card"></i> <span translate>WOT.ACCOUNT_OPERATIONS</span> <i class="gray icon ion-ios-arrow-right"></i> </a> + <a class="item item-icon-left item-icon-right ink" + ng-if="!isDefaultWallet" + ui-sref="app.view_wallet_tx_by_id({id: walletId})"> + <i class="icon ion-card"></i> + <span translate>WOT.ACCOUNT_OPERATIONS</span> + <i class="gray icon ion-ios-arrow-right"></i> + </a> <!-- Events --> <span class="item item-divider" ng-if="formData.events.length"> @@ -175,6 +182,15 @@ <span trust-as-html="event.message | translate:event.messageParams"></span> </div> + <!-- Other wallets --> + <a class="item item-icon-left item-icon-right ink" + ng-if="isDefaultWallet" + ui-sref="app.view_wallets"> + <i class="icon ion-android-list calm"></i> + <span translate>ACCOUNT.WALLET_LIST.TITLE</span> + <span class="badge badge-calm" ng-if="formData.children.length>0">{{:rebind:formData.children.length}}</span> + <i class="gray icon ion-ios-arrow-right"></i> + </a> <cs-extension-point name="general"></cs-extension-point> diff --git a/www/templates/wot/view_identity_tx.html b/www/templates/wot/view_identity_tx.html index 9b89d552953e4985f24d9871874dfc9947724766..a77ce86dd43cc5f9bd23b2e6c52a43ab28287563 100644 --- a/www/templates/wot/view_identity_tx.html +++ b/www/templates/wot/view_identity_tx.html @@ -43,7 +43,9 @@ <!-- the balance --> <div class="item item-tx item-divider"> {{'ACCOUNT.BALANCE_ACCOUNT'|translate}} - <div class="badge item-note badge-balanced" ng-bind-html=":balance:formData.balance|formatAmount:{currency: $root.currency.name}"> + <div class="badge item-note" + ng-class=":balance:{'badge-assertive': formData.balance <= 0, 'badge-balanced': formData.balance > 0 }" + ng-bind-html=":balance:formData.balance|formatAmount:{currency: $root.currency.name}"> </div> <div class="badge badge-secondary" ng-if="$root.settings.expertMode"> (<span ng-bind-html=":balance:formData.balance| formatAmount: {useRelative: !$root.settings.useRelative, currency: $root.currency.name} "></span>)