diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss index 0aa2047138a4b169a0e721d6ea359e911bbcaab0..e8df662edcc3a57d9bc0e0fb3a644e751975f3a7 100644 --- a/scss/ionic.app.scss +++ b/scss/ionic.app.scss @@ -552,10 +552,13 @@ $screen-menu: 845px; } } -.popover-invitation { +.popover-invitation, +.popover-network, +.popover-peer-info{ width: 420px; } + /********** Unit popover **********/ diff --git a/www/css/ionic.app.css b/www/css/ionic.app.css index a703c76321964584e9c3ccf6b393b017bc927811..f8cf96da697977df2dcc10201210ce00e8a2881c 100644 --- a/www/css/ionic.app.css +++ b/www/css/ionic.app.css @@ -14077,7 +14077,9 @@ a { padding: 0px 5px !important; line-height: 30px; } -.popover-invitation { +.popover-invitation, +.popover-network, +.popover-peer-info { width: 420px; } /********** diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index 4355774aafe63e5ba34913ba373844f257e6c5bc..de8f0c7939d3611defd8272ece0b8e0bc71c9464 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -113,7 +113,8 @@ "BTN_HELP": "Aide en ligne", "REPORT_ISSUE": "anomalie", "NOT_YOUR_ACCOUNT_QUESTION" : "Vous n'êtes pas propriétaire du compte <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> ?", - "BTN_CHANGE_ACCOUNT": "Déconnecter ce compte" + "BTN_CHANGE_ACCOUNT": "Déconnecter ce compte", + "CONNECTION_ERROR": "Nœud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifez votre connection Internet, ou changer de nœud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>." }, "SETTINGS": { "TITLE": "Paramètres", diff --git a/www/js/app.js b/www/js/app.js index f9b47fedecc53cd6db04ec670f7586a8a0ce89c6..edb4129d82a1040882f81d296a9ec798f261f603 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -89,7 +89,8 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht 'ngInject'; return function(exception, cause) { - console.error(exception, cause); + if (cause) console.error(exception, cause); + else console.error(exception); }; }) diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index 15ab560523ab107bc56dc82c8975b042b5bd7880..4c8e26490119a6d145aef1e37915cc2f1e3f5bfd 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -26,7 +26,7 @@ angular.module('cesium.app.controllers', ['ngIdle', 'cesium.platform', 'cesium.s }) .state('app.home', { - url: "/home", + url: "/home?error", views: { 'menuContent': { templateUrl: "templates/home/home.html", @@ -87,7 +87,7 @@ function PluginExtensionPointController($scope, PluginService) { /** * Abstract controller (inherited by other controllers) */ -function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout, +function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout, $ionicPopover, $ionicHistory, $controller, $window, csPlatform, UIUtils, BMA, csWallet, csCurrency, Device, Modals, csSettings, csConfig ) { @@ -428,6 +428,21 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return Modals.showHelp(parameters); }; + //////////////////////////////////////// + // Change node (expert mode) + //////////////////////////////////////// + + $scope.showNodeListPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/network/popover_peer_info.html', + autoremove: true, + scope: $scope.$new(true) + }).then(function(res) { + console.log(res); + }); + }; + + //////////////////////////////////////// // Layout Methods //////////////////////////////////////// @@ -452,18 +467,60 @@ function AboutController($scope, csConfig) { } -function HomeController($scope, csPlatform) { +function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csCurrency) { 'ngInject'; $scope.loading = true; - $scope.$on('$ionicView.enter', function(e, state) { - csPlatform.ready() - .then(function() { - $scope.loading = false; + $scope.enter = function(e, state) { + if (state && state.stateParams && state.stateParams.error) { // Query parameter + $scope.error = state.stateParams.error; + $scope.node = csCurrency.data.node; + $scope.loading = false; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + disableBack: true, + historyRoot: true }); - }); + $state.go('app.home', {error: undefined}, { + reload: false, + inherit: true, + notify: false}); + } + else { + // Start platform + csPlatform.ready() + .then(function() { + $scope.loading = false; + }) + .catch(function(err) { + $scope.node = csCurrency.data.node; + $scope.loading = false; + $scope.error = err; + }); + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.reload = function() { + $scope.loading = true; + delete $scope.error; + $timeout($scope.enter, 200); + }; + + /** + * Catch click for quick fix + * @param event + */ + $scope.doQuickFix = function(event) { + if (event == 'settings') { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + $state.go('app.settings'); + } + }; } diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js index f2c90afe495921982e8f3ddc46e5b9c9d30d0a2f..cabcf73429d85a2904ab6fd37b5c9ecf1e5057c4 100644 --- a/www/js/controllers/network-controllers.js +++ b/www/js/controllers/network-controllers.js @@ -38,6 +38,10 @@ angular.module('cesium.network.controllers', ['cesium.services']) .controller('NetworkLookupModalCtrl', NetworkLookupModalController) +.controller('NetworkLookupPopoverCtrl', NetworkLookupPopoverController) + +.controller('PeerInfoPopoverCtrl', PeerInfoPopoverController) + ; function NetworkLookupController($scope, $state, $ionicHistory, $ionicPopover, $window, @@ -337,6 +341,61 @@ function NetworkLookupModalController($scope, $controller, parameters) { } +function NetworkLookupPopoverController($scope, $controller) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('NetworkLookupCtrl', {$scope: $scope})); + + // Read parameters + var parameters = parameters || {}; + $scope.enableFilter = angular.isDefined(parameters.enableFilter) ? parameters.enableFilter : true; + $scope.search.type = angular.isDefined(parameters.type) ? parameters.type : $scope.search.type; + $scope.search.endpointFilter = angular.isDefined(parameters.endpointFilter) ? parameters.endpointFilter : $scope.search.endpointFilter; + $scope.expertMode = angular.isDefined(parameters.expertMode) ? parameters.expertMode : $scope.expertMode; + $scope.ionItemClass = parameters.ionItemClass || 'item-border-large'; + + $scope.selectPeer = function(peer) { + $scope.closePopover(peer); + }; + + $scope.$on('popover.hidden', function(){ + $scope.leave(); + }); + + // Disable this unsed method - called by load() + $scope.showHelpTip = function() {}; + + // Enter the popover + $scope.enter(); +} + +function PeerInfoPopoverController($scope, csCurrency) { + 'ngInject'; + + $scope.loading = true; + $scope.formData = {}; + + $scope.enter = function() { + csCurrency.blockchain.current() + .then(function(block) { + $scope.formData = block; + }) + .then(function() { + $scope.loading = false; + }); + }; + + // Update UI on new block + csCurrency.api.data.on.newBlock($scope, function(block) { + $scope.formData = block; + console.debug("[peer info] Received a new block: ", block); + }); + + // Enter the popover + $scope.enter(); +} + function PeerViewController($scope, $q, UIUtils, csWot, BMA) { 'ngInject'; diff --git a/www/js/controllers/settings-controllers.js b/www/js/controllers/settings-controllers.js index 68b2ce3df95dde106bdd10c77083d7898f4f05b7..7e8cd04f94004671edae997e769950df92d51f85 100644 --- a/www/js/controllers/settings-controllers.js +++ b/www/js/controllers/settings-controllers.js @@ -21,7 +21,7 @@ angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.curren ; function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $translate, csHttp, - UIUtils, BMA, csSettings, $ionicPopover, Modals) { + UIUtils, BMA, csSettings, csPlatform, $ionicPopover, Modals) { 'ngInject'; $scope.formData = angular.copy(csSettings.data); @@ -87,6 +87,7 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t } $scope.pendingSaving = true; csSettings.reset() + .then(csPlatform.restart) .then(function() { // reload $scope.load(); @@ -126,6 +127,9 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t BMA.copy(nodeBMA); $scope.bma = BMA; + // Start platform is not already started + csPlatform.restart(); + // Reset history cache return $ionicHistory.clearCache(); }); diff --git a/www/js/platform.js b/www/js/platform.js index 5c7b07425aa587544423d65d8555ffe79125ed93..68956a18b2b24102b48fe5ea7b7a6c0e14e3d016 100644 --- a/www/js/platform.js +++ b/www/js/platform.js @@ -15,11 +15,16 @@ angular.module('cesium.platform', ['cesium.config', 'cesium.services']) function disableChangeState() { var remove = $rootScope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { - if (startPromise && next.name !== 'app.home') { + if (next.name !== 'app.home' && next.name !== 'app.settings') { event.preventDefault(); - startPromise.then(function() { - $state.go(next.name, nextParams); - }); + if (startPromise) { + startPromise.then(function() { + $state.go(next.name, nextParams); + }); + } + else { + UIUtils.loading.hide(); + } } }); @@ -41,13 +46,7 @@ angular.module('cesium.platform', ['cesium.config', 'cesium.services']) var fallbackNode = csSettings.data.fallbackNodes && fallbackNodeIndex < csSettings.data.fallbackNodes.length && csSettings.data.fallbackNodes[fallbackNodeIndex++]; if (!fallbackNode) { - return UIUtils.alert.error('ERROR.CHECK_NETWORK_CONNECTION') - .then(function() { - fallbackNodeIndex = 0; - // loop - return BMA.copy(defaultSettingsNode) - .then(checkBmaNodeAlive); - }); + throw 'ERROR.CHECK_NETWORK_CONNECTION'; } var newServer = fallbackNode.host + ((!fallbackNode.port && fallbackNode.port != 80 && fallbackNode.port != 443) ? (':' + fallbackNode.port) : ''); return $translate('CONFIRM.USE_FALLBACK_NODE', {old: BMA.server, new: newServer}) @@ -99,6 +98,8 @@ angular.module('cesium.platform', ['cesium.config', 'cesium.services']) } function start() { + enableChangeState(); + // Avoid change state disableChangeState(); @@ -129,6 +130,14 @@ angular.module('cesium.platform', ['cesium.config', 'cesium.services']) addListeners(); startPromise = null; started = true; + }) + .catch(function(err) { + startPromise = null; + started = false; + if($state.current.name !== 'app.home') { + $state.go('app.home', {error: 'peer'}); + } + throw err; }); return startPromise; @@ -157,6 +166,8 @@ angular.module('cesium.platform', ['cesium.config', 'cesium.services']) return { isStarted: isStarted, ready: ready, + restart: restart, + start: start, stop: stop }; }) diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js index 89ab42bc512a8f169b99f339f5a65f2c99b168b8..f4fe40952884f0c92529ce0c930d7b96c7d19984 100644 --- a/www/js/services/bma-services.js +++ b/www/js/services/bma-services.js @@ -785,9 +785,6 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. }; service.lightInstance = function(host, port, useSsl, timeout) { - if (host && host =='g1.duniter.tednet.fr') { - console.log('TORTUE Node [{0}:{1}] useSsl [{2}]'.format(host, port, useSsl ? 'true': 'false')); - } port = port || 80; useSsl = angular.isDefined(useSsl) ? useSsl : (port == 443); return { diff --git a/www/js/services/currency-services.js b/www/js/services/currency-services.js index 15a06d087a8aaaa59bd5b975b429cf4145ab9113..8a015255a74718b8d035760a196fc3bd6c6052ea 100644 --- a/www/js/services/currency-services.js +++ b/www/js/services/currency-services.js @@ -50,8 +50,8 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) return loadFirstBlock(parameters.currency); }), - // get current data (e.g. UD, members count) - loadCurrentData(), + // get current UD + loadCurrentUD(), // call extensions api.data.raisePromise.load(data) @@ -95,7 +95,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }); } - function loadCurrentData() { + function loadCurrentUD() { return BMA.blockchain.stats.ud() .then(function(res){ // Special case for currency init @@ -108,7 +108,6 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) return BMA.blockchain.block({ block: lastBlockWithUD }) .then(function(block){ data.currentUD = powBase(block.dividend, block.unitbase); - data.membersCount = block.membersCount; return data.currentUD; }) .catch(function(err) { @@ -146,10 +145,34 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }; } + function onBlock(json) { + var block = new Block(json); + block.cleanData(); // keep only count values + console.debug('[currency] Received new block', block); + + data.currentBlock = block; + + data.medianTime = block.medianTime; + data.membersCount = block.membersCount; + + // Update UD + if (block.dividend) { + data.currentUD = block.dividend; + } + + // Dispatch to extensions + api.data.raise.newBlock(block); + } + function addListeners() { + // open web socket on block + var wsBlock = BMA.websocket.block(); + wsBlock.on(onBlock); + listeners = [ // Listen if node changed - BMA.api.node.on.restart($rootScope, restart, this) + BMA.api.node.on.restart($rootScope, restart, this), + wsBlock.close ]; } @@ -210,6 +233,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) api.registerEvent('data', 'ready'); api.registerEvent('data', 'load'); api.registerEvent('data', 'reset'); + api.registerEvent('data', 'newBlock'); // init data resetData(); @@ -225,6 +249,9 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) get: getData, parameters: getDataField('parameters'), currentUD: getDataField('currentUD'), + blockchain: { + current: getDataField('currentBlock') + }, // api extension api: api, // deprecated methods diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index b9051f7a2ff486bf3fbf974a731ae674dda11d21..ce093de9c6c28c253229770faf62324ac9e7e943 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -546,7 +546,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se if (options.sources || (options.tx && options.tx.enable)) { // Get TX and sources - jobs.push(loadTxAndSources()); + jobs.push(loadTxAndSources(options.tx ? options.tx.fromTime: undefined)); } // Load sigStock diff --git a/www/templates/currency/charts/ud.html b/www/templates/currency/charts/ud.html deleted file mode 100644 index 90ce67e31a2fb63ad60b42753a880443909a2f18..0000000000000000000000000000000000000000 --- a/www/templates/currency/charts/ud.html +++ /dev/null @@ -1,13 +0,0 @@ -<ion-view left-buttons="leftButtons" class="pane"> - <ion-nav-title> - - </ion-nav-title> - - <ion-nav-buttons side="secondary"> - <button class="button button-icon button-clear icon ion-loop" ng-click="refresh()"> - </button> - </ion-nav-buttons> - - <ion-content class="has-header"> - </ion-content> -</ion-view> diff --git a/www/templates/home/home.html b/www/templates/home/home.html index 5b84fd06ba45b37f81481d4f1fba0f8db9712f8c..b8d68335b75a1043cfdd6f3964433dc297c84a4c 100644 --- a/www/templates/home/home.html +++ b/www/templates/home/home.html @@ -9,11 +9,25 @@ <h4 class="hidden-xs" translate>HOME.MESSAGE</h4> <h4 class="visible-xs" translate>HOME.MESSAGE_SHORT</h4> - <div class="center padding" ng-if="loading"> - <ion-spinner icon="android"></ion-spinner> + <div class="center padding" > + + <ion-spinner icon="android" ng-if="loading"></ion-spinner> + + <div class="animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error"> + <div class="card card-item padding"> + <p class="item-content item-text-wrap"> + <span class="dark" trust-as-html="'HOME.CONNECTION_ERROR'|translate:node"></span> + </p> + + <!-- Retry--> + <button type="button" + class="button button-positive icon icon-left ion-refresh ink" + ng-click="reload()">{{'COMMON.BTN_REFRESH'|translate}}</button> + </div> + </div> </div> - <div class="center animate-fade-in animate-show-hide ng-hide" ng-show="!loading"> + <div class="center animate-fade-in animate-show-hide ng-hide" ng-show="!loading && !error"> <!-- Help tour (NOT ready yet for small device) --> <button type="button" diff --git a/www/templates/menu.html b/www/templates/menu.html index 59d6121fd2c162f1a107a02dec1835bf9b7da716..97bfcdd5ff116eeb40a6fc55315b787ee21cd904 100644 --- a/www/templates/menu.html +++ b/www/templates/menu.html @@ -11,6 +11,16 @@ <button class="button button-icon button-clear icon ion-navicon visible-nomenu" menu-toggle="left" ></button> </ion-nav-buttons> <ion-nav-buttons side="right" > + + <!-- current node info --> + <button class="button button-clear hidden-xs hidden-sm gray" + ng-if="$root.settings.expertMode" + style="max-width: 450px !important;" + ng-click="showNodeListPopover($event)"> + {{$root.currency.node.server}} + <small class="ion-arrow-down-b"></small> + </button> + <!-- Allow extension here --> <cs-extension-point name="nav-buttons-right"></cs-extension-point> diff --git a/www/templates/network/items_peers.html b/www/templates/network/items_peers.html index cf350df38832ec47d30e43ed54f20be5a39660d6..59c2decddce40284ab569ed1406224cbd7e3c066 100644 --- a/www/templates/network/items_peers.html +++ b/www/templates/network/items_peers.html @@ -1,7 +1,7 @@ <bind-notifier bind-notifier="{ rebind:search.results}" ng-class="::motion.ionListClass"> - <div class="item item-text-wrap no-border done in gray" ng-if="isHttps && expertMode"> - <i class="icon ion-alert-circled"></i> {{'NETWORK.INFO.ONLY_SSL_PEERS'|translate}} + <div class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom" ng-if="isHttps && expertMode"> + <small><i class="icon ion-alert-circled"></i> {{'NETWORK.INFO.ONLY_SSL_PEERS'|translate}}</small> </div> <div class="item row row-header hidden-xs hidden-sm done in" ng-if="expertMode"> diff --git a/www/templates/network/popover_network.html b/www/templates/network/popover_network.html new file mode 100644 index 0000000000000000000000000000000000000000..c62df9e33a043ee1c5b91f0baa4e8d449d15c5ee --- /dev/null +++ b/www/templates/network/popover_network.html @@ -0,0 +1,38 @@ +<ion-popover-view class="fit hidden-xs hidden-sm popover-notification popover-network" + ng-controller="NetworkLookupPopoverCtrl"> + <ion-header-bar class="stable-bg block"> + <div class="title"> + {{'MENU.NETWORK'|translate}} + <ion-spinner class="ion-spinner-small" icon="android" ng-if="search.loading"></ion-spinner> + </div> + + <div class="pull-right"> + <a ng-class="{'positive': search.type=='member', 'dark': search.type!=='member'}" + ng-click="toggleSearchType('member')" + translate>PEER.MEMBERS</a> + </div> + </ion-header-bar> + <ion-content scroll="true"> + <div class="list no-padding"> + <ng-include src="'templates/network/items_peers.html'"></ng-include> + </div> + </ion-content> + + <ion-footer-bar class="stable-bg block"> + <!-- settings --> + <div class="pull-left"> + <a class="positive" + ui-sref="app.settings" + ng-click="closePopover()" + translate>COMMON.NOTIFICATIONS.SETTINGS</a> + </div> + + <!-- show all --> + <div class="pull-right"> + <a class="positive" + ui-sref="app.network" + ng-click="closePopover()" + translate>COMMON.NOTIFICATIONS.SHOW_ALL</a> + </div> + </ion-footer-bar> +</ion-popover-view> diff --git a/www/templates/network/popover_peer_info.html b/www/templates/network/popover_peer_info.html new file mode 100644 index 0000000000000000000000000000000000000000..031e11281336f83443aa7eec886f58fe39b35e58 --- /dev/null +++ b/www/templates/network/popover_peer_info.html @@ -0,0 +1,53 @@ +<ion-popover-view class="fit hidden-xs hidden-sm popover-notification popover-peer-info" + ng-controller="PeerInfoPopoverCtrl"> + <ion-header-bar class="stable-bg block"> + <div class="title"> + {{'MENU.NETWORK'|translate}} + </div> + </ion-header-bar> + <ion-content scroll="true"> + <div class="center" ng-if="loading"> + <ion-spinner icon="android"></ion-spinner> + </div> + + <div class="list no-padding"> + <div class="item"> + <i class="ion-clock"></i> + {{'CURRENCY.VIEW.MEDIAN_TIME'|translate}} + <div class="badge"> + {{formData.medianTime | formatDate}} + </div> + </div> + + <div class="item"> + <i class="ion-lock-combination"></i> + {{'CURRENCY.VIEW.POW_MIN'|translate}} + <div class="badge"> + {{formData.powMin | formatInteger}} + </div> + </div> + + <!-- Allow extension here --> + <cs-extension-point name="default"></cs-extension-point> + + </div> + </ion-content> + + <ion-footer-bar class="stable-bg block"> + <!-- settings --> + <div class="pull-left"> + <a class="positive" + ui-sref="app.settings" + ng-click="closePopover()" + translate>COMMON.NOTIFICATIONS.SETTINGS</a> + </div> + + <!-- show all --> + <div class="pull-right"> + <a class="positive" + ui-sref="app.network" + ng-click="closePopover()" + translate>COMMON.NOTIFICATIONS.SHOW_ALL</a> + </div> + </ion-footer-bar> +</ion-popover-view>