From 721c85f8b618485552b47165d211a314d3f49cad Mon Sep 17 00:00:00 2001 From: Benoit Lavenier <benoit.lavenier@e-is.pro> Date: Fri, 6 Mar 2020 12:22:33 +0100 Subject: [PATCH] [fix] Disable cache storage in local store, by default - see issue #885 [enh] Settings: add an option to enable/disable local storage of cache --- www/i18n/locale-en-GB.json | 2 + www/i18n/locale-en.json | 2 + www/i18n/locale-es-ES.json | 2 + www/i18n/locale-fr-FR.json | 6 +- www/js/platform.js | 14 +++- www/js/services/cache-services.js | 101 ++++++++++++++++++--------- www/js/services/http-services.js | 2 +- www/js/services/settings-services.js | 5 ++ www/js/services/wot-services.js | 8 +-- www/templates/settings/settings.html | 20 +++++- 10 files changed, 117 insertions(+), 45 deletions(-) diff --git a/www/i18n/locale-en-GB.json b/www/i18n/locale-en-GB.json index a9e6b89b..7b4f7c56 100644 --- a/www/i18n/locale-en-GB.json +++ b/www/i18n/locale-en-GB.json @@ -140,6 +140,8 @@ "PEER": "Duniter peer address", "PEER_SHORT": "Peer address", "PEER_CHANGED_TEMPORARY": "Address used temporarily", + "PERSIST_CACHE": "Keep navigation data (experimental)", + "PERSIST_CACHE_HELP": "Allows faster navigation, locally retaining the data received, for use from one session to another.", "USE_LOCAL_STORAGE": "Enable local storage", "USE_LOCAL_STORAGE_HELP": "Allows you to save your settings", "WALLETS_SETTINGS": "My wallets", diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json index bfca9588..101eb868 100644 --- a/www/i18n/locale-en.json +++ b/www/i18n/locale-en.json @@ -140,6 +140,8 @@ "PEER": "Duniter peer address", "PEER_SHORT": "Peer address", "PEER_CHANGED_TEMPORARY": "Address used temporarily", + "PERSIST_CACHE": "Keep navigation data (experimental)", + "PERSIST_CACHE_HELP": "Allows faster navigation, locally retaining the data received, for use from one session to another.", "USE_LOCAL_STORAGE": "Enable local storage", "USE_LOCAL_STORAGE_HELP": "Allows you to save your settings", "WALLETS_SETTINGS": "My wallets", diff --git a/www/i18n/locale-es-ES.json b/www/i18n/locale-es-ES.json index aa1c119b..f57fa6ae 100644 --- a/www/i18n/locale-es-ES.json +++ b/www/i18n/locale-es-ES.json @@ -134,6 +134,8 @@ "NETWORK_SETTINGS": "Red", "PEER": "Dirección del nodo Duniter", "PEER_CHANGED_TEMPORARY": "Dirección utilizada temporalmente", + "PERSIST_CACHE": "Mantener datos de navegación (experimental)", + "PERSIST_CACHE_HELP": "Permite una navegación más rápida, conservando localmente los datos recibidos, para usar de una sesión a otra.", "USE_LOCAL_STORAGE": "Activar el almacenamiento local", "USE_LOCAL_STORAGE_HELP": "Permitir el ahorro de almacenamiento local", "WALLETS_SETTINGS": "Mis monederos", diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index 1f472e58..3ed72166 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -137,9 +137,11 @@ "DISPLAY_DIVIDER": "Affichage", "STORAGE_DIVIDER": "Stockage", "NETWORK_SETTINGS": "Réseau", - "PEER": "Adresse du nœud Duniter", - "PEER_SHORT": "Adresse du nœud", + "PEER": "Nœud Duniter", + "PEER_SHORT": "Nœud Duniter", "PEER_CHANGED_TEMPORARY": "Adresse utilisée temporairement", + "PERSIST_CACHE": "Conserver les données de navigation (expérimental)", + "PERSIST_CACHE_HELP": "Permet une navigation plus rapide, en conservant localement les données reçues, pour les utiliser d'une session à l'autre.", "USE_LOCAL_STORAGE": "Activer le stockage local", "USE_LOCAL_STORAGE_HELP": "Permet de sauvegarder vos paramètres", "WALLETS_SETTINGS": "Mes portefeuilles", diff --git a/www/js/platform.js b/www/js/platform.js index 02c2de56..f2e30f8e 100644 --- a/www/js/platform.js +++ b/www/js/platform.js @@ -44,10 +44,20 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] $animateProvider.classNameFilter( /\banimate-/ ); }) - // Configure cache (used by HTTP requests) default max age + // Configure cache (used by HTTP requests) default options .config(function (CacheFactoryProvider, csConfig) { 'ngInject'; - angular.extend(CacheFactoryProvider.defaults, { maxAge: csConfig.cacheTimeMs || 60 * 1000 /*1min*/}); + + angular.extend(CacheFactoryProvider.defaults, { + // Fixed options: + recycleFreq: 60 * 1000, // Scan expired items every 1min + storagePrefix: 'caches.', // Override storage key prefix + capacity: 100, // Force to use a LRU cache, to avoid size exceed max + + // Options overwritten by the csCache service: + maxAge: csConfig.cacheTimeMs || 60 * 1000, // from config if exists, or 1min + storageMode: 'memory' // Do NOT use local Storage by default + }); }) // Configure screen size detection diff --git a/www/js/services/cache-services.js b/www/js/services/cache-services.js index a1e4f8aa..9650fdb2 100644 --- a/www/js/services/cache-services.js +++ b/www/js/services/cache-services.js @@ -1,6 +1,6 @@ angular.module('cesium.cache.services', ['angular-cache']) -.factory('csCache', function($http, $window, csSettings, CacheFactory) { +.factory('csCache', function($rootScope, $http, $window, csSettings, CacheFactory) { 'ngInject'; var @@ -10,54 +10,78 @@ angular.module('cesium.cache.services', ['angular-cache']) MEDIUM: 5 * 60 * 1000 /*5 min*/, SHORT: csSettings.defaultSettings.cacheTimeMs // around 1min }, + storageMode = getSettingsStorageMode(), cacheNames = [] ; - function getOrCreateCache(prefix, maxAge, onExpire){ - prefix = prefix || 'csCache-'; - maxAge = maxAge || constants.SHORT; - var cacheName = prefix + (maxAge / 1000); + function getSettingsStorageMode(settings) { + settings = settings || csSettings.data; + return settings && settings.useLocalStorage && settings.persistCache && $window.localStorage ? 'localStorage' : 'memory'; + } - // FIXME: enable this when cache is cleaning on rollback - var storageMode = csSettings.data.useLocalStorage && $window.localStorage ? 'localStorage' : 'memory'; + function fillStorageOptions(options) { + options = options || {}; + options.storageMode = getSettingsStorageMode(); + options.deleteOnExpire = (options.storageMode === 'localStorage' || options.onExpire) ? 'aggressive' : 'passive'; + options.cacheFlushInterval = options.deleteOnExpire === 'passive' ? + (60 * 60 * 1000) : // If passive mode, remove all items every hour + null; + return options; + } - if (!onExpire) { - if (!cacheNames[cacheName]) { - cacheNames[cacheName] = true; - console.debug("[cache] Creating cache {0}...".format(cacheName)); + function onSettingsChanged(settings) { + var newStorageMode = getSettingsStorageMode(settings) + var hasChanged = (newStorageMode !== storageMode); + if (hasChanged) { + storageMode = newStorageMode; + console.debug("[cache] Updating caches with {storageMode: {0}}".format(storageMode)); + if (storageMode === 'memory') { + clearAllCaches(); } - return CacheFactory.get(cacheName) || - CacheFactory.createCache(cacheName, { - maxAge: maxAge, - deleteOnExpire: 'passive', - //cacheFlushInterval: 60 * 60 * 1000, // clear itself every hour - recycleFreq: Math.max(maxAge - 1000, 5 * 60 * 1000 /*5min*/), - storageMode: storageMode - }); + _.forEach(_.keys(cacheNames), function(cacheName) { + var cache = CacheFactory.get(cacheName); + if (cache) { + cache.setOptions({storageMode: storageMode}); + } + }); } - else { + } + + function getOrCreateCache(prefix, maxAge, onExpire){ + prefix = prefix || ''; + maxAge = maxAge || constants.SHORT; + var cacheName = prefix + ((maxAge / 1000) + 's'); + + // If onExpire fn, generate a new cache key + var cache; + if (onExpire && typeof onExpire == 'function') { var counter = 1; - while(CacheFactory.get(cacheName + counter)) { + while (CacheFactory.get(cacheName + counter)) { counter++; } cacheName = cacheName + counter; - if (!cacheNames[cacheName]) { - cacheNames[cacheName] = true; - } - console.debug("[cache] Creating cache {0} with 'onExpire' option...".format(cacheName)); - return CacheFactory.createCache(cacheName, { - maxAge: maxAge, - deleteOnExpire: 'aggressive', - //cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour - recycleFreq: maxAge, - onExpire: onExpire, - storageMode: storageMode - }); } + else { + cache = CacheFactory.get(cacheName); + } + + // Add to cache names map + if (!cacheNames[cacheName]) cacheNames[cacheName] = true; + + // Already exists: use it + if (cache) return cache; + + // Not exists yet: create a new cache + var options = fillStorageOptions({ + maxAge: maxAge, + onExpire: onExpire || null + }); + console.debug("[cache] Creating cache {{0}} with {storageMode: {1}}...".format(cacheName, options.storageMode)); + return CacheFactory.createCache(cacheName, options); } function clearAllCaches() { - console.debug("[cache] cleaning all caches"); + console.debug("[cache] Cleaning all caches..."); _.forEach(_.keys(cacheNames), function(cacheName) { var cache = CacheFactory.get(cacheName); if (cache) { @@ -77,6 +101,15 @@ angular.module('cesium.cache.services', ['angular-cache']) }); } + function addListeners() { + listeners = [ + // Listen if node changed + csSettings.api.data.on.changed($rootScope, onSettingsChanged, this) + ]; + } + + addListeners(); + return { get: getOrCreateCache, clear: clearFromPrefix, diff --git a/www/js/services/http-services.js b/www/js/services/http-services.js index b332d635..32030a16 100644 --- a/www/js/services/http-services.js +++ b/www/js/services/http-services.js @@ -102,7 +102,7 @@ angular.module('cesium.http.services', ['cesium.cache.services']) }; if (autoRefresh) { // redo the request if need config.cache = csCache.get(cachePrefix, maxAge, function (key, value, done) { - console.debug('[http] Refreshing cache for ['+key+'] '); + console.debug('[http] Refreshing cache for {{0}} '.format(key)); $http.get(key, config) .success(function (data) { config.cache.put(key, data); diff --git a/www/js/services/settings-services.js b/www/js/services/settings-services.js index d279f379..c7cf9ad9 100644 --- a/www/js/services/settings-services.js +++ b/www/js/services/settings-services.js @@ -69,6 +69,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) useRelative: false, useLocalStorage: !!$window.localStorage, // override to false if no device useLocalStorageEncryption: false, + persistCache: false, // disable by default (waiting resolution of issue #885) walletHistoryTimeSecond: 30 * 24 * 60 * 60 /*30 days*/, walletHistorySliceSecond: 5 * 24 * 60 * 60 /*download using 5 days slice*/, walletHistoryAutoRefresh: true, // override to false if device @@ -300,6 +301,9 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) api.locale.raise.changed(locale); }, + isStarted = function() { + return started; + }, ready = function() { if (started) return $q.when(); @@ -341,6 +345,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) //start(); return { + isStarted: isStarted, ready: ready, start: start, data: data, diff --git a/www/js/services/wot-services.js b/www/js/services/wot-services.js index 94b656df..87faa4c2 100644 --- a/www/js/services/wot-services.js +++ b/www/js/services/wot-services.js @@ -2,7 +2,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services', 'cesium.settings.services']) -.factory('csWot', function($rootScope, $q, $timeout, BMA, Api, CacheFactory, csConfig, csCurrency, csSettings, csCache) { +.factory('csWot', function($rootScope, $q, $timeout, BMA, Api, CacheFactory, UIUtils, csConfig, csCurrency, csSettings, csCache) { 'ngInject'; @@ -681,17 +681,17 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c if (pubkey) { data = (options.cache !== false) ? identityCache.get(pubkey) : null; if (data && (!uid || data.uid === uid) && (!options.blockUid || data.blockUid === options.blockUid)) { - console.debug("[wot] Identity " + pubkey.substring(0, 8) + " found in cache"); + console.debug("[wot] Identity {{0}} found in cache".format(pubkey.substring(0, 8))); return $q.when(data); } - console.debug("[wot] Loading identity " + pubkey.substring(0, 8) + "..."); + console.debug("[wot] Loading identity {{0}}...".format(pubkey.substring(0, 8))); data = { pubkey: pubkey, uid: uid }; } else { - console.debug("[wot] Loading identity from uid " + uid); + console.debug("[wot] Loading identity from uid {{0}}...".format(uid)); data = { uid: uid }; diff --git a/www/templates/settings/settings.html b/www/templates/settings/settings.html index b5e93a0a..9c11718c 100644 --- a/www/templates/settings/settings.html +++ b/www/templates/settings/settings.html @@ -90,6 +90,20 @@ </label> </div> + <!-- Persist cache ? --> + <div class="item item-text-wrap item-toggle dark hidden-xs hidden-sm"> + <div class="input-label" ng-class="{'gray': !formData.useLocalStorage}" + ng-bind-html="'SETTINGS.PERSIST_CACHE' | translate"></div> + <h4 class="gray" ng-bind-html="'SETTINGS.PERSIST_CACHE_HELP' | translate"></h4> + <label class="toggle toggle-royal"> + <input type="checkbox" ng-model="formData.persistCache" ng-if="formData.useLocalStorage"> + <input type="checkbox" ng-model="formData.useLocalStorage" ng-if="!formData.useLocalStorage" disabled> + <div class="track"> + <div class="handle"></div> + </div> + </label> + </div> + <!-- Allow extension here --> <cs-extension-point name="common"></cs-extension-point> @@ -104,7 +118,8 @@ <h4 class="gray text-wrap" ng-bind-html="'SETTINGS.REMEMBER_ME_HELP' | translate"></h4> <label class="toggle toggle-royal"> - <input type="checkbox" ng-model="formData.rememberMe" ng-disabled="!formData.useLocalStorage"> + <input type="checkbox" ng-model="formData.rememberMe" ng-if="formData.useLocalStorage"> + <input type="checkbox" ng-model="formData.useLocalStorage" ng-if="!formData.useLocalStorage" disabled> <div class="track"> <div class="handle"></div> </div> @@ -145,7 +160,8 @@ <h4 class="gray text-wrap" ng-bind-html="'SETTINGS.USE_WALLETS_ENCRYPTION_HELP' | translate"> </h4> <label class="toggle toggle-royal"> - <input type="checkbox" ng-model="formData.useLocalStorageEncryption" ng-disabled="!formData.useLocalStorage"> + <input type="checkbox" ng-model="formData.useLocalStorageEncryption" ng-if="formData.useLocalStorage"> + <input type="checkbox" ng-model="formData.useLocalStorage" ng-if="!formData.useLocalStorage" disabled> <div class="track"> <div class="handle"></div> </div> -- GitLab