diff --git a/www/css/style.css b/www/css/style.css index a4487ccab..db2f99190 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -677,56 +677,7 @@ background-image: none !important; } margin: 1rem; position: relative; } -/* Dark theme */ -/* -.tab-nav{ - background-color: #212121 !important; background-size: 0 !important; -} -ion-header-bar { - background-color: #212121 !important; -} -.ion-view-background{ - background-color: #303030 !important; -} -.tabs-custom-dark > .tabs, -.tabs.tabs-custom-dark { - border-color: #5D3A23; - background-color: #5D3A23; - background-image: linear-gradient(0deg, #0c60ee, #0c60ee 50%, transparent 30%); - color: #33e0bb; } - .tabs-custom-dark > .tabs .tab-item .badge, - .tabs.tabs-custom-dark .tab-item .badge { - background-color: #33e0bb; - color: #387ef5; } -.tabs-striped.tabs-custom-dark .tabs { - background-color: #5D3A23; } - -.tabs-striped.tabs-custom-dark .tab-item { - color: rgba(255, 255, 255, 0.3); - opacity: 1; } - .tabs-striped.tabs-custom-dark .tab-item .badge { - opacity: 0.3; } - .tabs-striped.tabs-custom-dark .tab-item.tab-item-active, .tabs-striped.tabs-custom-dark .tab-item.active, .tabs-striped.tabs-positive .tab-item.activated { - margin-top: -2px; - color: #fff; - border-style: solid; - border-width: 2px 0 0 0; - border-color: #fff; } - -.title.title-center.header-item { - color: white; -} -.date-picker-button-dark { - color: #33e0bb !important; padding: 0 15px; border-color: transparent; margin-top: 4px; box-shadow: 0 1px 2px rgba(0,0,0,0.16), 0 2px 2px rgba(0,0,0,0.23); - border-style: solid; border-color: white; border-width: 0px; border-radius: 5px; -} -.date-picker-arrow-dark { - color: rgba(51,224,187, 0.7) !important; margin-top: 4px; background-color: transparent !important; -} - -*/ -/* Dark theme ends */ /* Light theme */ .control-icon-button{ text-align: center; @@ -776,9 +727,6 @@ ion-header-bar { .ion-view-background{ background-color: #ededed !important; } -.ion-view-background-dark { - background-color: #303030 !important; -} .tabs-custom > .tabs, .tabs.tabs-custom { border-color: #5D3A23; @@ -817,12 +765,6 @@ ion-header-bar { /* Light theme ends */ -.earlier-later-expand-dark { - color: white; - margin: 16px 16px 0 6px; - font-size: 0.8em; - opacity: 0.7; -} .earlier-later-expand { color: #303030; margin: 16px 16px 0 6px; @@ -839,35 +781,9 @@ ion-header-bar { margin-top: 0 !important; margin-bottom: 0!important; } -.list-location-dark { - color: white; - background-color: transparent; - font-size: 0.8em; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 30px; - margin-top: 0 !important; - margin-bottom: 0 !important; -} -.list-location-dark { - color: white; - background-color: transparent; - font-size: 0.8em; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 30px; - margin-top: 0; - margin-bottom: 0; -} -p.list-text-dark { - color: white; -} p.list-text { color: #303030; } -a.list-text-dark { - color: white; -} a.list-text { color: #303030; } @@ -940,9 +856,6 @@ button.button.back-button.buttons.button-clear.header-item { .list-card { margin: 16px 0; box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); } -.bg-dark { - background-color: #424242; -} .bg-light { background-color: #ffffff; } @@ -961,21 +874,12 @@ button.button.back-button.buttons.button-clear.header-item { .list-col-left-margin { text-align: center; padding: 0.7em 0.8em 0.4em 0.8em; border-right-width: 0.5px; border-right-color: #ccc; border-right-style: solid; border-bottom-color: #ccc; border-bottom-width: 0.5px; border-bottom-style: solid; } -.list-col-left-dark-margin { - text-align: center; padding: 0.7em 0.8em 0.4em 0.8em; border-right-width: 0.5px; border-right-color: white; border-right-style: solid; border-bottom-color: white; border-bottom-width: 0.5px; border-bottom-style: solid; -} .list-col-left { text-align: center; padding: 1.1em 0.8em 0.6em 0.8em; border-right-width: 0.5px; border-right-color: #ccc; border-right-style: solid; border-bottom-color: #ccc; border-bottom-width: 0.5px; border-bottom-style: solid; } -.list-col-left-dark { - text-align: center; padding: 1.1em 0.8em 0.6em 0.8em; border-right-width: 0.5px; border-right-color: white; border-right-style: solid; border-bottom-color: white; border-bottom-width: 0.5px; border-bottom-style: solid; -} .list-col-right { text-align: center; padding: 0.25em 0.8em; border-bottom-color: #ccc; border-bottom-width: 0.5px; border-bottom-style: solid; } -.list-col-right-dark { - text-align: center; padding: 0.25em 0.8em; border-bottom-color: white; border-bottom-width: 0.5px; border-bottom-style: solid; -} .start-time-tag { box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); text-align: center; diff --git a/www/index.html b/www/index.html index 7aad8d326..af568513f 100644 --- a/www/index.html +++ b/www/index.html @@ -98,6 +98,7 @@ + diff --git a/www/js/common/services.js b/www/js/common/services.js index 0f7fbb244..dd406fd21 100644 --- a/www/js/common/services.js +++ b/www/js/common/services.js @@ -7,7 +7,6 @@ angular.module('emission.main.common.services', []) commonGraph.data = {}; commonGraph.UPDATE_DONE = "COMMON_GRAPH_UPDATE_DONE"; - var db = window.cordova.plugins.BEMUserCache; var selKey = "common-trips"; commonGraph.createEmpty = function() { @@ -18,6 +17,7 @@ angular.module('emission.main.common.services', []) }; commonGraph.updateCurrent = function() { + var db = window.cordova.plugins.BEMUserCache; db.getDocument(selKey, false).then(function(entryList) { try{ var cmGraph = entryList; diff --git a/www/js/control/general-settings.js b/www/js/control/general-settings.js index 58ed383fb..0d9032185 100644 --- a/www/js/control/general-settings.js +++ b/www/js/control/general-settings.js @@ -10,12 +10,13 @@ angular.module('emission.main.control',['emission.services', 'emission.splash.updatecheck', 'emission.main.metrics.factory', 'emission.stats.clientstats', - 'angularLocalStorage', + 'emission.plugin.kvstore', 'emission.plugin.logger']) .controller('ControlCtrl', function($scope, $window, $ionicScrollDelegate, + $ionicPlatform, $state, $ionicPopup, $ionicActionSheet, $ionicPopover, - $rootScope, storage, ionicDatePicker, + $rootScope, KVStore, ionicDatePicker, StartPrefs, ControlHelper, ControlCollectionHelper, ControlSyncHelper, ControlTransitionNotifyHelper, @@ -48,30 +49,37 @@ angular.module('emission.main.control',['emission.services', }; $scope.emailLog = ControlHelper.emailLog; - $scope.dark_theme = $rootScope.dark_theme; $scope.userData = [] $scope.getUserData = function() { - var userDataFromStorage = CalorieCal.get(); - $scope.userData = [] - var height = userDataFromStorage.height.toString(); - var weight = userDataFromStorage.weight.toString(); - var temp = { - age: userDataFromStorage.age, - height: height + (userDataFromStorage.heightUnit == 1? ' cm' : ' ft'), - weight: weight + (userDataFromStorage.weightUnit == 1? ' kg' : ' lb'), - gender: userDataFromStorage.gender == 1? 'Male' : 'Female' - } - for (var i in temp) { - $scope.userData.push({key: i, value: temp[i]}); + return CalorieCal.get().then(function(userDataFromStorage) { + $scope.rawUserData = userDataFromStorage; + if ($scope.userDataSaved()) { + $scope.userData = [] + var height = userDataFromStorage.height.toString(); + var weight = userDataFromStorage.weight.toString(); + var temp = { + age: userDataFromStorage.age, + height: height + (userDataFromStorage.heightUnit == 1? ' cm' : ' ft'), + weight: weight + (userDataFromStorage.weightUnit == 1? ' kg' : ' lb'), + gender: userDataFromStorage.gender == 1? 'Male' : 'Female' + } + for (var i in temp) { + $scope.userData.push({key: i, value: temp[i]}); + } } + }); } $scope.userDataSaved = function() { - return CalorieCal.get().userDataSaved == true; - } - if ($scope.userDataSaved()) { - $scope.getUserData(); + if (angular.isDefined($scope.rawUserData) && $scope.rawUserData != null) { + return $scope.rawUserData.userDataSaved; + } else { + return false; + } } + $ionicPlatform.ready().then(function() { + $scope.refreshScreen(); + }); $scope.getLowAccuracy = function() { // return true: toggle on; return false: toggle off. var isMediumAccuracy = ControlCollectionHelper.isMediumAccuracy(); @@ -86,25 +94,6 @@ angular.module('emission.main.control',['emission.services', } } $scope.toggleLowAccuracy = ControlCollectionHelper.toggleLowAccuracy; - $scope.ionViewBackgroundClass = function() { - return ($scope.dark_theme)? "ion-view-background-dark" : "ion-view-background"; - } - $scope.getDarkTheme = function() { - return $scope.dark_theme; - } - $scope.toggleDarkTheme = function() { - if ($scope.dark_theme) { - $rootScope.dark_theme = false; - $scope.dark_theme = false; - StartPrefs.setDefaultTheme(null); - $state.reload(); - } else { - $rootScope.dark_theme = true; - $scope.dark_theme = true; - StartPrefs.setDefaultTheme('dark_theme'); - $state.reload(); - } - } $scope.getConnectURL = function() { ControlHelper.getSettings().then(function(response) { @@ -165,12 +154,12 @@ angular.module('emission.main.control',['emission.services', $state.go("root.main.map"); } $scope.getState = function() { - ControlCollectionHelper.getState().then(function(response) { + return ControlCollectionHelper.getState().then(function(response) { $scope.$apply(function() { $scope.settings.collect.state = response; }); }, function(error) { - $ionicPopup.alert("while getting email, "+error); + $ionicPopup.alert("while reading FSM state, "+error); }); }; @@ -192,18 +181,13 @@ angular.module('emission.main.control',['emission.services', }); } - var clearBoth = function() { - storage.clearAll(); - clearUsercache(); - } - $scope.nukeUserCache = function() { var nukeChoiceActions = [{text: "UI state only", - action: storage.clearAll}, + action: KVStore.clearOnlyLocal}, {text: 'Native cache only', - action: clearUsercache}, + action: KVStore.clearOnlyNative}, {text: 'Everything', - action: clearBoth}]; + action: KVStore.clearAll}]; $ionicActionSheet.show({ titleText: "Clear data", @@ -229,7 +213,9 @@ angular.module('emission.main.control',['emission.services', } $scope.$on('$ionicView.afterEnter', function() { + $ionicPlatform.ready().then(function() { $scope.refreshScreen(); + }); }) // Execute action on hidden popover @@ -249,15 +235,24 @@ angular.module('emission.main.control',['emission.services', $scope.settings.auth = {}; $scope.settings.connect = {}; $scope.settings.channel = function(newName) { - return arguments.length ? (UpdateCheck.setChannel(newName)) : UpdateCheck.getChannel(); + return arguments.length ? (UpdateCheck.setChannel(newName)) : $scope.settings.storedChannel; }; - + UpdateCheck.getChannel().then(function(retVal) { + $scope.$apply(function() { + $scope.settings.storedChannel = retVal; + }); + }); $scope.getConnectURL(); $scope.getCollectionSettings(); $scope.getSyncSettings(); $scope.getTNotifySettings(); $scope.getEmail(); - $scope.getState(); + $scope.getState().then($scope.isTrackingOn).then(function(isTracking) { + $scope.$apply(function() { + $scope.settings.collect.trackingOn = isTracking; + }); + }); + $scope.getUserData(); }; $scope.returnToIntro = function() { @@ -336,18 +331,19 @@ angular.module('emission.main.control',['emission.services', return ionic.Platform.isIOS(); } - $scope.refreshScreen(); $ionicPopover.fromTemplateUrl('templates/control/main-sync-settings.html', { scope: $scope }).then(function(popover) { $scope.syncSettingsPopup = popover; }); - $scope.trackingOn = function() { + $scope.isTrackingOn = function() { + return $ionicPlatform.ready().then(function() { if($scope.isAndroid()){ return $scope.settings.collect.state != "local.state.tracking_stopped"; } else if ($scope.isIOS()) { return $scope.settings.collect.state != "STATE_TRACKING_STOPPED"; } + }); }; $scope.userStartStopTracking = function() { if ($scope.startStopBtnToggle){ @@ -358,7 +354,7 @@ angular.module('emission.main.control',['emission.services', $scope.startStopBtnToggle = true; } } - $scope.startStopBtnToggle = $scope.trackingOn(); + $scope.startStopBtnToggle = $scope.trackingOn; $scope.getExpandButtonClass = function() { return ($scope.expanded)? "icon ion-ios-arrow-up" : "icon ion-ios-arrow-down"; } @@ -366,9 +362,9 @@ angular.module('emission.main.control',['emission.services', return ($scope.dataExpanded)? "icon ion-ios-arrow-up" : "icon ion-ios-arrow-down"; } $scope.eraseUserData = function() { - CalorieCal.delete(); + CalorieCal.delete().then(function() { $ionicPopup.alert({template: 'User data erased.'}); - + }); } $scope.parseState = function(state) { if (state) { diff --git a/www/js/diary/current.js b/www/js/diary/current.js index f32b5a547..477ebefe5 100644 --- a/www/js/diary/current.js +++ b/www/js/diary/current.js @@ -4,17 +4,19 @@ 'ionic', 'emission.incident.posttrip.manual', 'rzModule', - 'angularLocalStorage', + 'emission.plugin.kvstore', 'emission.plugin.logger']) .controller('CurrMapCtrl', function($scope, Config, $state, $timeout, $ionicActionSheet,leafletData, - Logger, $window, PostTripManualMarker, CommHelper, $http, storage, $ionicPlatform) { + Logger, $window, PostTripManualMarker, CommHelper, $http, KVStore, $ionicPlatform) { - Logger.log("controller CurrMapCtrl called from current.js"); + console.log("controller CurrMapCtrl called from current.js"); var _map; var _localIncidentMarkers = []; var _serverIncidentMarkers = []; - var db = window.cordova.plugins.BEMUserCache; + var db = function() { + return window.cordova.plugins.BEMUserCache; + } MANUAL_INCIDENT = "manual/incident"; BACKGROUND_LOCATION = "background/location"; INCIDENT_CONFIG = 'incident_config'; @@ -32,7 +34,7 @@ }); angular.extend($scope.mapCtrl.defaults, Config.getMapTiles()); - Logger.log("mapCtrl", $scope.mapCtrl); + console.log("mapCtrl", $scope.mapCtrl); $scope.verticalSlider = { options: { @@ -53,18 +55,26 @@ } }; - var incident_value = storage.get(INCIDENT_CONFIG); - if(incident_value != null) { - $scope.verticalSlider.value = incident_value; - } else { - $scope.verticalSlider.value = 1; + var loadSliderValue = function() { + KVStore.get(INCIDENT_CONFIG).then(function(incident_value) { + Logger.log("in current screen, read incident_value = "+incident_value); + if(incident_value != null) { + $scope.verticalSlider.value = incident_value; + } else { + $scope.verticalSlider.value = 1; + } + }); } var fromIncidentDate = moment().subtract($scope.verticalSlider.value, 'd'); $scope.$watch('verticalSlider.value', function(newVal, oldVal){ - storage.set(INCIDENT_CONFIG, newVal); + $ionicPlatform.ready().then(function() { + if (angular.isDefined(newVal) && !isNaN(newVal)) { + KVStore.set(INCIDENT_CONFIG, newVal); + } + }); incidentServerCalldata.start_time = CommHelper.moment2Timestamp(moment().subtract(newVal, 'd')); }, true); @@ -106,7 +116,7 @@ }); var refreshTrip = function() { - db.getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) { + db().getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) { $scope.$apply(function() { Logger.log("current location data" + JSON.stringify(result[0].data)); var coordinates = result.map(function(locWrapper, index, locList) { @@ -175,8 +185,10 @@ }; $scope.$on('leafletDirectiveMap.current.resize', function(event, data) { - Logger.log("current/map received resize event, invalidating map size"); - data.leafletObject.invalidateSize(); + $ionicPlatform.ready().then(function() { + Logger.log("current/map received resize event, invalidating map size"); + data.leafletObject.invalidateSize(); + }); }); var addIncidentLayer = function(stress, marker, map) { @@ -217,7 +229,7 @@ var getLocalIncidents = function() { // No metadata, to make it consistent with the server incidents - db.getAllMessages(MANUAL_INCIDENT, false).then(function(incidents) { + db().getAllMessages(MANUAL_INCIDENT, false).then(function(incidents) { Logger.log("Incidents stored locally" + JSON.stringify(incidents)); if(incidents.length > 0) { addIncidents(incidents, _map, _localIncidentMarkers); @@ -238,13 +250,13 @@ } }, function(error){ Logger.log("Error when getting incidents"); - Logger.log(error); + Logger.log(JSON.stringify(error)); }); }; var marker; $scope.showIncidentSheet = function() { - db.getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) { + db().getAllSensorData(BACKGROUND_LOCATION, true).then(function(result) { both = [result[0].data.latitude, result[0].data.longitude]; var ts = result[0].data.ts; var latlng = L.latLng(both); @@ -281,9 +293,12 @@ }; $scope.$on('$ionicView.enter', function() { - Logger.log("entered current screen, starting incident refresh"); - refreshTripLoop(); - getIncidentsLoop(); + $ionicPlatform.ready().then(function() { + Logger.log("entered current screen, starting incident refresh"); + loadSliderValue(); + refreshTripLoop(); + getIncidentsLoop(); + }); }); $scope.$on('$ionicView.leave', function() { @@ -303,6 +318,9 @@ clearTimeout(mapRunning); clearTimeout(gettingIncidents); }); - getLocalIncidents(); + $ionicPlatform.ready().then(function() { + Logger.log("ionicPlatform.ready in current screen, getting local incidents"); + getLocalIncidents(); + }); }); diff --git a/www/js/diary/detail.js b/www/js/diary/detail.js index 49f530f8c..eebcada4c 100644 --- a/www/js/diary/detail.js +++ b/www/js/diary/detail.js @@ -1,11 +1,11 @@ 'use strict'; angular.module('emission.main.diary.detail',['ui-leaflet', 'ng-walkthrough', - 'nvd3', 'angularLocalStorage', + 'nvd3', 'emission.plugin.kvstore', 'emission.services', 'emission.plugin.logger', 'emission.incident.posttrip.manual']) .controller("DiaryDetailCtrl", function($scope, $rootScope, $window, $stateParams, $ionicActionSheet, - leafletData, leafletMapEvents, nzTour, storage, + leafletData, leafletMapEvents, nzTour, KVStore, Logger, Timeline, DiaryHelper, Config, CommHelper, PostTripManualMarker) { console.log("controller DiaryDetailCtrl called with params = "+ @@ -67,7 +67,7 @@ angular.module('emission.main.diary.detail',['ui-leaflet', 'ng-walkthrough', $scope.tripgj = DiaryHelper.directiveForTrip($scope.trip); $scope.getTripBackground = function() { - var ret_val = DiaryHelper.getTripBackground($rootScope.dark_theme, $scope.tripgj); + var ret_val = DiaryHelper.getTripBackground($scope.tripgj); return ret_val; } @@ -148,10 +148,10 @@ angular.module('emission.main.diary.detail',['ui-leaflet', 'ng-walkthrough', var checkDetailTutorialDone = function () { var DETAIL_DONE_KEY = 'detail_tutorial_done'; - var detailTutorialDone = storage.get(DETAIL_DONE_KEY); + var detailTutorialDone = KVStore.getDirect(DETAIL_DONE_KEY); if (!detailTutorialDone) { startWalkthrough(); - storage.set(DETAIL_DONE_KEY, true); + KVStore.set(DETAIL_DONE_KEY, true); } }; diff --git a/www/js/diary/list.js b/www/js/diary/list.js index b04882686..022e8a260 100644 --- a/www/js/diary/list.js +++ b/www/js/diary/list.js @@ -5,7 +5,7 @@ angular.module('emission.main.diary.list',['ui-leaflet', 'emission.main.common.services', 'emission.incident.posttrip.manual', 'emission.services', - 'ng-walkthrough', 'nzTour', 'angularLocalStorage', + 'ng-walkthrough', 'nzTour', 'emission.plugin.kvstore', 'emission.plugin.logger']) .controller("DiaryListCtrl", function($window, $scope, $rootScope, $ionicPlatform, $state, @@ -14,11 +14,9 @@ angular.module('emission.main.diary.list',['ui-leaflet', $ionicActionSheet, ionicDatePicker, leafletData, Timeline, CommonGraph, DiaryHelper, - Config, PostTripManualMarker, nzTour, storage, Logger) { + Config, PostTripManualMarker, nzTour, KVStore, Logger) { console.log("controller DiaryListCtrl called"); // Add option - // StatusBar.styleBlackOpaque() - $scope.dark_theme = $rootScope.dark_theme; $scope.$on('leafletDirectiveMap.resize', function(event, data) { console.log("diary/list received resize event, invalidating map size"); @@ -90,21 +88,18 @@ angular.module('emission.main.diary.list',['ui-leaflet', * +date and -date operations. */ $scope.listExpandClass = function () { - return ($scope.dark_theme)? "earlier-later-expand-dark" : "earlier-later-expand"; + return "earlier-later-expand"; } $scope.listLocationClass = function() { - return ($scope.dark_theme)? "item item-icon-left list-location-dark" : "item item-icon-left list-location"; + return "item item-icon-left list-location"; } $scope.listTextClass = function() { - return ($scope.dark_theme)? "list-text-dark" : "list-text"; - } - $scope.ionViewBackgroundClass = function() { - return ($scope.dark_theme)? "ion-view-background-dark" : "ion-view-background"; + return "list-text"; } $scope.datePickerClass = function() { } $scope.listCardClass = function(tripgj) { - var background = DiaryHelper.getTripBackground($scope.dark_theme, tripgj); + var background = DiaryHelper.getTripBackground(tripgj); if ($window.screen.width <= 320) { return "list card list-card "+ background +" list-card-sm"; } else if ($window.screen.width <= 375) { @@ -116,13 +111,13 @@ angular.module('emission.main.diary.list',['ui-leaflet', } $scope.listColLeftClass = function(margin) { if (margin == 0) { - return ($scope.dark_theme)? "col-50 list-col-left-dark" : "col-50 list-col-left"; + return "col-50 list-col-left"; } else { - return ($scope.dark_theme)? "col-50 list-col-left-margin-dark" : "col-50 list-col-left-margin"; + return "col-50 list-col-left-margin"; } } $scope.listColRightClass = function() { - return ($scope.dark_theme)? "col-50 list-col-right-dark" : "col-50 list-col-right"; + return "col-50 list-col-right"; } $scope.differentCommon = function(tripgj) { return ($scope.isCommon(tripgj.id))? ((DiaryHelper.getEarlierOrLater(tripgj.data.properties.start_ts, tripgj.data.id) == '')? false : true) : false; @@ -346,10 +341,10 @@ angular.module('emission.main.diary.list',['ui-leaflet', */ var checkDiaryTutorialDone = function () { var DIARY_DONE_KEY = 'diary_tutorial_done'; - var diaryTutorialDone = storage.get(DIARY_DONE_KEY); + var diaryTutorialDone = KVStore.getDirect(DIARY_DONE_KEY); if (!diaryTutorialDone) { startWalkthrough(); - storage.set(DIARY_DONE_KEY, true); + KVStore.set(DIARY_DONE_KEY, true); } }; diff --git a/www/js/diary/services.js b/www/js/diary/services.js index ac074217e..f62266cfa 100644 --- a/www/js/diary/services.js +++ b/www/js/diary/services.js @@ -111,11 +111,8 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', } } - dh.getTripBackground = function(dark_theme, tripgj) { + dh.getTripBackground = function(tripgj) { var background = "bg-light"; - if (dark_theme) { - background = "bg-dark"; - } if (dh.isDraft(tripgj)) { background = "bg-unprocessed"; } diff --git a/www/js/goals.js b/www/js/goals.js index 973edaae1..9c5945dfc 100644 --- a/www/js/goals.js +++ b/www/js/goals.js @@ -1,13 +1,14 @@ 'use strict'; angular.module('emission.main.goals',['emission.services', 'emission.plugin.logger', + 'emission.plugin.kvstore', 'emission.survey.launch', 'ngSanitize', 'ngAnimate', - 'emission.splash.referral', 'angularLocalStorage', + 'emission.splash.referral', 'ng-walkthrough', 'nzTour']) -.controller('GoalsCtrl', function(CommHelper, $state, $ionicLoading, $scope, $rootScope, $ionicModal, nzTour, - $window, $http, $ionicPopup, $timeout, storage, ReferralHandler, ReferHelper, Logger, $cordovaInAppBrowser, SurveyLaunch) { +.controller('GoalsCtrl', function(CommHelper, $state, $ionicLoading, $ionicPlatform, $scope, $rootScope, $ionicModal, nzTour, + $window, $http, $ionicPopup, $timeout, KVStore, ReferralHandler, ReferHelper, Logger, $cordovaInAppBrowser, SurveyLaunch) { $scope.goals = []; $scope.goal = {}; $scope.challenges=[]; @@ -122,7 +123,8 @@ angular.module('emission.main.goals',['emission.services', 'emission.plugin.logg */ var handlePendingRefer = function() { Logger.log("About to handle pending referral"); - if (storage.get(HABITICA_REGISTERED_KEY) == true) { + KVStore.get(HABITICA_REGISTERED_KEY).then(function(stored_val) { + if (stored_val == true) { Logger.log("Registered with habitica - checking pending registration"); if (ReferralHandler.hasPendingRegistration() == true) { Logger.log("Registration is pending, calling joinGroup"); @@ -140,6 +142,7 @@ angular.module('emission.main.goals',['emission.services', 'emission.plugin.logg showNeedRegister(); } } + }); } //var element = angular.element(document.querySelector('#todo')); @@ -240,9 +243,10 @@ angular.module('emission.main.goals',['emission.services', 'emission.plugin.logg CommHelper.habiticaRegister(regConfig).then(function(response) { console.log("Success!"); console.log(response); - storage.set('party_id',response.habitica_group_id); - storage.set(HABITICA_REGISTERED_KEY, true); - refreshInfo(); + Promise.all([KVStore.set('party_id',response.habitica_group_id), + KVStore.set(HABITICA_REGISTERED_KEY, true)]).then(function() { + refreshInfo(); + }); }, function(error) { $ionicLoading.hide(); $ionicPopup.alert({title: "

Username is Required

", @@ -279,7 +283,9 @@ angular.module('emission.main.goals',['emission.services', 'emission.plugin.logg Math.floor($scope.profile.stats.gp))*100); if(!('_id' in $scope.profile.party)){ $scope.hasParty = false; - partyId = storage.get('party_id'); + KVStore.get('party_id').then(function(ret_val) { + partyId = ret_val; + }); } else{ $scope.hasParty = true; partyId = $scope.profile.party._id; @@ -845,22 +851,21 @@ angular.module('emission.main.goals',['emission.services', 'emission.plugin.logg var refreshInfo = function(){ console.log("Refreshing information"); - console.log("Party ID = " + storage.get('party_id')); refresh = true; - if (storage.get(HABITICA_REGISTERED_KEY) == true) { + Promise.all([KVStore.get('party_id'), + KVStore.get(HABITICA_REGISTERED_KEY)]).then(function(party_id, is_registered) { + console.log("Party ID = " + party_id); + if (is_registered == true) { getUserInfo(); getUserTask(); } else { $ionicLoading.hide(); } + // TODO: Does this need to be within refreshInfo? handlePendingRefer(); + }); }; - //if (storage.get(HABITICA_REGISTERED_KEY) == true) { - // getChallenges(); - //} - refreshInfo(); - $scope.refreshPage = function() { console.log("Refreshing page"); refreshInfo(); @@ -927,23 +932,7 @@ angular.module('emission.main.goals',['emission.services', 'emission.plugin.logg startWalkthrough(); } - /* - * Checks if it is the first time the user has loaded the goals tab. If it is then - * show a walkthrough and store the info that the user has seen the tutorial. - */ - /*var checkGoalsTutorialDone = function () { - var GOALS_DONE_KEY = 'goals_tutorial_done'; - var goalsTutorialDone = storage.get(GOALS_DONE_KEY); - if (!goalsTutorialDone) { - startWalkthrough(); - storage.set(GOALS_DONE_KEY, true); - } - };*/ - - /* - * Just to clean everything up. - * TODO: Remove after a few releases. - */ - var SURVEY_DONE_KEY = 'survey_done'; - storage.remove(SURVEY_DONE_KEY); + $ionicPlatform.ready().then(function() { + refreshInfo(); + }); }); diff --git a/www/js/heatmap.js b/www/js/heatmap.js index b3b2cc1cd..bf6af215b 100644 --- a/www/js/heatmap.js +++ b/www/js/heatmap.js @@ -2,11 +2,11 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', 'emission.plugin.logger', 'emission.incident.posttrip.manual', - 'ng-walkthrough', 'nzTour', 'angularLocalStorage']) + 'ng-walkthrough', 'nzTour', 'emission.plugin.kvstore']) .controller('HeatmapCtrl', function($scope, $ionicLoading, $ionicActionSheet, $http, leafletData, Logger, Config, PostTripManualMarker, - $window, nzTour, storage) { + $window, nzTour, KVStore) { $scope.mapCtrl = {}; angular.extend($scope.mapCtrl, { @@ -371,10 +371,10 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', */ var checkHeatmapTutorialDone = function () { var HEATMAP_DONE_KEY = 'heatmap_tutorial_done'; - var heatmapTutorialDone = storage.get(HEATMAP_DONE_KEY); + var heatmapTutorialDone = KVStore.getDirect(HEATMAP_DONE_KEY); if (!heatmapTutorialDone) { startWalkthrough(); - storage.set(HEATMAP_DONE_KEY, true); + KVStore.set(HEATMAP_DONE_KEY, true); } }; diff --git a/www/js/incident/post-trip-map-display.js b/www/js/incident/post-trip-map-display.js index df56e654e..aff514b1e 100644 --- a/www/js/incident/post-trip-map-display.js +++ b/www/js/incident/post-trip-map-display.js @@ -1,13 +1,13 @@ 'use strict'; angular.module('emission.incident.posttrip.map',['ui-leaflet', 'ng-walkthrough', - 'angularLocalStorage', + 'emission.plugin.kvstore', 'emission.services', 'emission.plugin.logger', 'emission.main.diary.services', 'emission.incident.posttrip.manual']) .controller("PostTripMapCtrl", function($scope, $window, $state, $stateParams, $ionicLoading, - leafletData, leafletMapEvents, nzTour, storage, + leafletData, leafletMapEvents, nzTour, KVStore, Logger, Timeline, DiaryHelper, Config, UnifiedDataLoader, PostTripManualMarker) { Logger.log("controller PostTripMapDisplay called with params = "+ @@ -183,10 +183,10 @@ angular.module('emission.incident.posttrip.map',['ui-leaflet', 'ng-walkthrough', var checkIncidentTutorialDone = function () { var INCIDENT_DONE_KEY = 'incident_tutorial_done'; - var incidentTutorialDone = storage.get(INCIDENT_DONE_KEY); + var incidentTutorialDone = KVStore.getDirect(INCIDENT_DONE_KEY); if (!incidentTutorialDone) { startWalkthrough(); - storage.set(INCIDENT_DONE_KEY, true); + KVStore.set(INCIDENT_DONE_KEY, true); } }; diff --git a/www/js/main.js b/www/js/main.js index a01594a92..c62785966 100644 --- a/www/js/main.js +++ b/www/js/main.js @@ -136,8 +136,7 @@ angular.module('emission.main', ['emission.main.recent', // Currently this is blank since it is basically a placeholder for the // three screens. But we can totally add hooks here if we want. It is the // controller for all the screens because none of them do anything for now. - $scope.dark_theme = $rootScope.dark_theme; $scope.tabsCustomClass = function() { - return ($scope.dark_theme)? "tabs-icon-top tabs-custom-dark" : "tabs-icon-top tabs-custom"; + return "tabs-icon-top tabs-custom"; } }); diff --git a/www/js/metrics-factory.js b/www/js/metrics-factory.js index 8c806e133..8d9116eff 100644 --- a/www/js/metrics-factory.js +++ b/www/js/metrics-factory.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('emission.main.metrics.factory', ['angularLocalStorage']) +angular.module('emission.main.metrics.factory', ['emission.plugin.kvstore']) .factory('FootprintHelper', function() { var fh = {}; @@ -33,34 +33,19 @@ angular.module('emission.main.metrics.factory', ['angularLocalStorage']) return fh; }) -.factory('CalorieCal', function(storage){ +.factory('CalorieCal', function(KVStore){ var cc = {}; + var USER_DATA_KEY = "user-data"; + cc.set = function(info) { - for(var key in info){ - storage.set(key, info[key]) - } + return KVStore.set(USER_DATA_KEY, info); }; cc.get = function() { - var userData = { - 'gender': storage.get('gender'), - 'heightUnit': storage.get('heightUnit'), - 'height': storage.get('height'), - 'weightUnit': storage.get('weightUnit'), - 'weight': storage.get('weight'), - 'age': storage.get('age'), - 'userDataSaved': storage.get('userDataSaved') - } - return userData; + return KVStore.get(USER_DATA_KEY); }; cc.delete = function() { - storage.remove('gender'); - storage.remove('height'); - storage.remove('heightUnit'); - storage.remove('weight'); - storage.remove('weightUnit'); - storage.remove('age'); - storage.remove('userDataSaved'); + return KVStore.remove(USER_DATA_KEY); }; Number.prototype.between = function (min, max) { return this >= min && this <= max; @@ -184,4 +169,4 @@ angular.module('emission.main.metrics.factory', ['angularLocalStorage']) } return cc; -}); \ No newline at end of file +}); diff --git a/www/js/metrics.js b/www/js/metrics.js index 1c8db2150..d80e81d75 100644 --- a/www/js/metrics.js +++ b/www/js/metrics.js @@ -1,11 +1,11 @@ 'use strict'; -angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-datepicker', 'emission.main.metrics.factory', 'angularLocalStorage', 'emission.plugin.logger']) +angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-datepicker', 'emission.main.metrics.factory', 'emission.plugin.kvstore', 'emission.plugin.logger']) .controller('MetricsCtrl', function($scope, $ionicActionSheet, $ionicLoading, CommHelper, $window, $ionicPopup, ionicDatePicker, $ionicPlatform, - FootprintHelper, CalorieCal, $ionicModal, $timeout, storage, + FootprintHelper, CalorieCal, $ionicModal, $timeout, KVStore, $rootScope, $location, $state, ReferHelper, $http, Logger) { var lastTwoWeeksQuery = true; var first = true; @@ -52,22 +52,25 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date }); } + // TODO: Move this out into its own service + var FOOD_COMPARE_KEY = 'foodCompare'; $scope.setCookie = function(){ $scope.foodCompare = 'cookie'; - storage.set('foodCompare', 'cookie'); + return KVStore.set(FOOD_COMPARE_KEY, 'cookie'); } $scope.setIceCream = function(){ $scope.foodCompare = 'iceCream'; - storage.set('foodCompare', 'iceCream'); + return KVStore.set(FOOD_COMPARE_KEY, 'iceCream'); } $scope.setBanana = function(){ $scope.foodCompare = 'banana'; - storage.set('foodCompare', 'banana'); + return KVStore.set(FOOD_COMPARE_KEY, 'banana'); } - if(storage.get('foodCompare') == null){ + $scope.handleChosenFood = function(retVal) { + if (retVal == null){ $scope.setCookie(); } else { - var choosenFood = storage.get('foodCompare') + var choosenFood = retVal; if(choosenFood == 'cookie') $scope.setCookie(); else if (choosenFood == 'iceCream') @@ -75,6 +78,7 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date else $scope.setBanana(); } + } $ionicModal.fromTemplateUrl('templates/metrics/metrics-control.html', { scope: $scope, animation: 'slide-in-up' @@ -226,14 +230,31 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date 'weight': $scope.userData.weight, 'age': $scope.userData.age, 'userDataSaved': true}; - CalorieCal.set(info); + CalorieCal.set(info).then(function() { + $scope.savedUserData = info; + }); + } + + $scope.loadUserData = function() { + if(angular.isDefined($scope.savedUserData)) { + // loaded or set + return Promise.resolve(); + } else { + return CalorieCal.get().then(function(userDataFromStorage) { + $scope.savedUserData = userDataFromStorage; + }); + } } $scope.userDataSaved = function() { - var saved_user_data = CalorieCal.get(); - // console.log("saved vals = "+JSON.stringify(saved_user_data)); - return saved_user_data.userDataSaved == true; + // console.log("saved vals = "+JSON.stringify($scope.savedUserData)); + if (angular.isDefined($scope.savedUserData) && $scope.savedUserData != null) { + return $scope.savedUserData.userDataSaved == true; + } else { + return false; + }; } + $scope.options = { chart: { type: 'multiBarChart', @@ -306,6 +327,10 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date var getData = function(){ $scope.getMetricsHelper(); + $scope.loadUserData(); + KVStore.get(FOOD_COMPARE_KEY).then(function(retVal) { + $scope.handleChosenFood(retVal); + }); } $scope.getMetricsHelper = function() { @@ -655,7 +680,9 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.getCorrectedMetFromUserData = function(currDurationData, currSpeedData) { if ($scope.userDataSaved()) { - var userDataFromStorage = CalorieCal.get(); + // this is safe because userDataSaved will never be set unless there + // is stored user data that we have loaded + var userDataFromStorage = $scope.storedUserData; var met = CalorieCal.getMet(currDurationData.key, currSpeedData.values); var gender = userDataFromStorage.gender; var heightUnit = userDataFromStorage.heightUnit; diff --git a/www/js/plugin/storage.js b/www/js/plugin/storage.js new file mode 100644 index 000000000..89fb2239a --- /dev/null +++ b/www/js/plugin/storage.js @@ -0,0 +1,134 @@ +angular.module('emission.plugin.kvstore', ['emission.plugin.logger', + 'angularLocalStorage']) + +.factory('KVStore', function($window, Logger, storage, $ionicPopup) { + var logger = Logger; + var kvstoreJs = {} + /* + * Sets in both localstorage and native storage + * If the message is not a JSON object, wrap it in an object with the key + * "value" before storing it. + */ + var getNativePlugin = function() { + return $window.cordova.plugins.BEMUserCache; + } + + kvstoreJs.set = function(key, value) { + // add checks for data type + var store_val = value; + if (typeof value != "object") { + // Should this be {"value": value} or {key: value}? + store_val = {}; + store_val[key] = value; + } + /* + * How should we deal with consistency here? Have the threads be + * independent so that there is greater chance that one will succeed, + * or the local only succeed if native succeeds. I think parallel is + * better for greater robustness. + */ + storage.set(key, store_val); + return getNativePlugin().putLocalStorage(key, store_val); + } + + var getUnifiedValue = function(key) { + var ls_stored_val = storage.get(key, undefined); + return getNativePlugin().getLocalStorage(key, false).then(function(uc_stored_val) { + logger.log("uc_stored_val = "+JSON.stringify(uc_stored_val)+" ls_stored_val = "+JSON.stringify(ls_stored_val)); + if (angular.equals(ls_stored_val, uc_stored_val)) { + logger.log("local and native values match, already synced"); + return uc_stored_val; + } else { + // the values are different + if (ls_stored_val == null) { + console.assert(uc_stored_val != null, "uc_stored_val should be non-null"); + logger.log("uc_stored_val = "+JSON.stringify(uc_stored_val)+ + " ls_stored_val = "+JSON.stringify(ls_stored_val)+ + " copying native "+key+" to local..."); + storage.set(key, uc_stored_val); + return uc_stored_val; + } else if (uc_stored_val == null) { + console.assert(ls_stored_val != null); + $ionicPopup.alert({template: "Local "+key+" found, native " + +key+" missing, writing "+key+" to native"}) + logger.log("uc_stored_val = "+JSON.stringify(uc_stored_val)+ + " ls_stored_val = "+JSON.stringify(ls_stored_val)+ + " copying local "+key+" to native..."); + return getNativePlugin().putLocalStorage(key, ls_stored_val).then(function() { + // we only return the value after we have finished writing + return ls_stored_val; + }); + } + console.assert(ls_stored_val != null && uc_stored_val != null, + "ls_stored_val ="+JSON.stringify(ls_stored_val)+ + "uc_stored_val ="+JSON.stringify(uc_stored_val)); + $ionicPopup.alert({template: "Local "+key+" found, native " + +key+" found, but different, writing "+key+" to local"}) + logger.log("uc_stored_val = "+JSON.stringify(uc_stored_val)+ + " ls_stored_val = "+JSON.stringify(ls_stored_val)+ + " copying native "+key+" to local..."); + storage.set(key, uc_stored_val); + return uc_stored_val; + } + }); + } + + var unmungeValue = function(key, retData) { + if((retData != null) && (angular.isDefined(retData[key]))) { + // it must have been a simple data type that we munged upfront + return retData[key]; + } else { + // it must have been an object + return retData; + } + } + + kvstoreJs.get = function(key) { + return getUnifiedValue(key).then(function(retData) { + return unmungeValue(key, retData); + }); + } + + /* + * TODO: Temporary fix for data that: + - we want to return inline instead of in a promise + - is not catastrophic if it is cleared out (e.g. walkthrough code), OR + - is used primarily for session storage so will not be cleared out + (e.g. referral code) + We can replace this with promises in a future PR if needed + + The code does copy the native value to local storage in the background, + so even if this is stripped out, it will work on retry. + */ + kvstoreJs.getDirect = function(key) { + // will run in background, we won't wait for the results + getUnifiedValue(key); + return unmungeValue(key, storage.get(key)); + } + + kvstoreJs.remove = function(key) { + storage.remove(key); + return getNativePlugin().removeLocalStorage(key); + } + + kvstoreJs.clearAll = function() { + storage.clearAll(key); + return getNativePlugin().clearAll(); + } + + /* + * TODO: remove these two functions after we have confirmed that native + * storage is never deleted weirdly, and returned to only native storage. + * In that case, there will be only one clear - of native storage - which + * will be covered using clearAll. + */ + kvstoreJs.clearOnlyLocal = function() { + return storage.clearAll(); + } + + kvstoreJs.clearOnlyNative = function() { + return getNativePlugin().clearAll(); + } + + return kvstoreJs; +}); diff --git a/www/js/splash/localnotify.js b/www/js/splash/localnotify.js index 2bb0a5f76..dde7012bc 100644 --- a/www/js/splash/localnotify.js +++ b/www/js/splash/localnotify.js @@ -6,11 +6,9 @@ */ angular.module('emission.splash.localnotify', ['emission.plugin.logger', - 'emission.splash.startprefs', - 'angularLocalStorage']) + 'emission.splash.startprefs']) .factory('LocalNotify', function($window, $ionicPlatform, $ionicPopup, - $state, $rootScope, storage, - Logger) { + $state, $rootScope, Logger) { var localNotify = {}; /* diff --git a/www/js/splash/pushnotify.js b/www/js/splash/pushnotify.js index 6502a7839..16c4a2db6 100644 --- a/www/js/splash/pushnotify.js +++ b/www/js/splash/pushnotify.js @@ -1,9 +1,8 @@ angular.module('emission.splash.pushnotify', ['emission.plugin.logger', 'emission.services', - 'emission.splash.startprefs', - 'angularLocalStorage']) + 'emission.splash.startprefs']) .factory('PushNotify', function($window, $state, $rootScope, $ionicPlatform, - $ionicPopup, storage, Logger, CommHelper, StartPrefs) { + $ionicPopup, Logger, CommHelper, StartPrefs) { var pushnotify = {}; var push = null; diff --git a/www/js/splash/referral.js b/www/js/splash/referral.js index 284ff98ca..acafb59ef 100644 --- a/www/js/splash/referral.js +++ b/www/js/splash/referral.js @@ -1,6 +1,6 @@ -angular.module('emission.splash.referral', ['angularLocalStorage']) +angular.module('emission.splash.referral', ['emission.plugin.kvstore']) -.factory('ReferralHandler', function($window, $state, $interval, $rootScope, storage) { +.factory('ReferralHandler', function($window, KVStore) { var referralHandler = {}; var REFERRAL_NAVIGATION_KEY = 'referral_navigation'; @@ -9,32 +9,32 @@ angular.module('emission.splash.referral', ['angularLocalStorage']) var REFERRED_USER_ID = 'referred_user_id'; referralHandler.getReferralNavigation = function() { - toReturn = storage.get(REFERRAL_NAVIGATION_KEY); - storage.remove(REFERRAL_NAVIGATION_KEY); + toReturn = KVStore.getDirect(REFERRAL_NAVIGATION_KEY); + KVStore.remove(REFERRAL_NAVIGATION_KEY); return toReturn; } referralHandler.setupGroupReferral = function(kvList) { - storage.set(REFERRED_KEY, true); - storage.set(REFERRED_GROUP_ID, kvList['groupid']); - storage.set(REFERRED_USER_ID, kvList['userid']); - storage.set(REFERRAL_NAVIGATION_KEY, 'goals'); + KVStore.set(REFERRED_KEY, true); + KVStore.set(REFERRED_GROUP_ID, kvList['groupid']); + KVStore.set(REFERRED_USER_ID, kvList['userid']); + KVStore.set(REFERRAL_NAVIGATION_KEY, 'goals'); }; referralHandler.clearGroupReferral = function(kvList) { - storage.remove(REFERRED_KEY); - storage.remove(REFERRED_GROUP_ID); - storage.remove(REFERRED_USER_ID); - storage.remove(REFERRAL_NAVIGATION_KEY); + KVStore.remove(REFERRED_KEY); + KVStore.remove(REFERRED_GROUP_ID); + KVStore.remove(REFERRED_USER_ID); + KVStore.remove(REFERRAL_NAVIGATION_KEY); }; referralHandler.getReferralParams = function(kvList) { - return [storage.get(REFERRED_GROUP_ID), - storage.get(REFERRED_USER_ID)]; + return [KVStore.getDirect(REFERRED_GROUP_ID), + KVStore.getDirect(REFERRED_USER_ID)]; } referralHandler.hasPendingRegistration = function() { - return storage.get(REFERRED_KEY) + return KVStore.getDirect(REFERRED_KEY) }; return referralHandler; diff --git a/www/js/splash/startprefs.js b/www/js/splash/startprefs.js index 62b89c4ee..afa41765d 100644 --- a/www/js/splash/startprefs.js +++ b/www/js/splash/startprefs.js @@ -1,9 +1,9 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', 'emission.splash.referral', - 'angularLocalStorage']) + 'emission.plugin.kvstore']) .factory('StartPrefs', function($window, $state, $interval, $rootScope, $ionicPlatform, - $ionicPopup, storage, $http, Logger, ReferralHandler) { + $ionicPopup, KVStore, storage, $http, Logger, ReferralHandler) { var logger = Logger; var nTimesCalled = 0; var startprefs = {}; @@ -28,30 +28,17 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', return storage.get(DEFAULT_THEME_KEY); } - startprefs.loadDefaultTheme = function() { - logger.log("About to set theme from preference"); - var curr_theme = startprefs.getDefaultTheme(); - logger.log("preferred theme = "+curr_theme); - - if (curr_theme == 'dark_theme') { - $rootScope.dark_theme = true; - } else { - $rootScope.dark_theme = false; - } - logger.log("set dark_theme = "+$rootScope.dark_theme); - }; - var writeConsentToNative = function() { return $window.cordova.plugins.BEMDataCollection.markConsented($rootScope.req_consent); }; startprefs.markConsented = function() { logger.log("changing consent from "+ - $rootScope.curr_consented+" -> "+$rootScope.req_consent); + $rootScope.curr_consented+" -> "+JSON.stringify($rootScope.req_consent)); // mark in native storage return startprefs.readConsentState().then(writeConsentToNative).then(function(response) { // mark in local storage - storage.set(DATA_COLLECTION_CONSENTED_PROTOCOL, + KVStore.set(DATA_COLLECTION_CONSENTED_PROTOCOL, $rootScope.req_consent); // mark in local variable as well $rootScope.curr_consented = angular.copy($rootScope.req_consent); @@ -60,72 +47,57 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', }; startprefs.markIntroDone = function() { - storage.set(INTRO_DONE_KEY, true); - // Need to initialize this first because if we try to - // create it inlike with {key: value}, the key becomes the - // word "INTRO_DONE_KEY" and the stored object is - // {"INTRO_DONE_KEY":"2018-01-31T06:26:02+00:00"} - var to_store = {}; - to_store[INTRO_DONE_KEY] = moment().format(); - $window.cordova.plugins.BEMUserCache.putLocalStorage(INTRO_DONE_KEY, to_store); - $rootScope.$emit(startprefs.INTRO_DONE_EVENT, $rootScope.req_consent); + var currTime = moment().format(); + KVStore.set(INTRO_DONE_KEY, currTime); + $rootScope.$emit(startprefs.INTRO_DONE_EVENT, currTime); } // returns boolean + startprefs.readIntroDone = function() { + return KVStore.get(INTRO_DONE_KEY).then(function(read_val) { + logger.log("in readIntroDone, read_val = "+JSON.stringify(read_val)); + $rootScope.intro_done = read_val; + }); + } + startprefs.isIntroDone = function() { - var read_val = storage.get(INTRO_DONE_KEY); - logger.log("in isIntroDone, read_val = "+read_val); - if (read_val == null || read_val == "") { + if ($rootScope.intro_done == null || $rootScope.intro_done == "") { logger.log("in isIntroDone, returning false"); + $rootScope.is_intro_done = false; return false; } else { - logger.log("in isIntroDone, returning "+read_val); - return read_val; + logger.log("in isIntroDone, returning true"); + $rootScope.is_intro_done = true; + return true; } } startprefs.isConsented = function() { - logger.log("curr_consented = "+$rootScope.curr_consented+ - "isIntroDone = " + startprefs.isIntroDone()); - if (startprefs.isIntroDone() && - ($rootScope.curr_consented == null || $rootScope.curr_consented == "")) { - alert("intro is done, but consent not found, re-consenting..."); - } if ($rootScope.curr_consented == null || $rootScope.curr_consented == "" || $rootScope.curr_consented.approval_date != $rootScope.req_consent.approval_date) { console.log("Not consented in local storage, need to show consent"); + $rootScope.is_consented = false; return false; } else { console.log("Consented in local storage, no need to show consent"); + $rootScope.is_consented = true; return true; } } startprefs.readConsentState = function() { - /* - * Read from local storage and move on so that we don't depend on native code. - * Native code will be checked once the plugins are ready - */ - if (angular.isDefined($rootScope.req_consent) && - angular.isDefined($rootScope.curr_consented) && - $rootScope.curr_consented != null) { - // consent state is all populated - logger.log("req_consent = "+$rootScope.req_consent - +" curr_consented = " + $rootScope.curr_consented); - return new Promise(function(resolve, reject) { - logger.log("resolving with empty information"); - resolve(); - }); - } else { - // read consent state from the file and populate it - return $http.get("json/startupConfig.json") - .then(function(startupConfigResult) { - $rootScope.req_consent = startupConfigResult.data.emSensorDataCollectionProtocol; - logger.log("required consent version = " + JSON.stringify($rootScope.req_consent)); - $rootScope.curr_consented = storage.get( - DATA_COLLECTION_CONSENTED_PROTOCOL); + // read consent state from the file and populate it + return $http.get("json/startupConfig.json") + .then(function(startupConfigResult) { + $rootScope.req_consent = startupConfigResult.data.emSensorDataCollectionProtocol; + logger.log("required consent version = " + JSON.stringify($rootScope.req_consent)); + return KVStore.get(DATA_COLLECTION_CONSENTED_PROTOCOL); + }).then(function(kv_store_consent) { + $rootScope.curr_consented = kv_store_consent; + console.assert(angular.isDefined($rootScope.req_consent), "in readConsentState $rootScope.req_consent", JSON.stringify($rootScope.req_consent)); + // we can just launch this, we don't need to wait for it + startprefs.checkNativeConsent(); }); - } } /* @@ -135,26 +107,33 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', */ startprefs.getPendingOnboardingState = function() { - if (!startprefs.isIntroDone()) { - // Since we must return a promise when the intro is done, - // we create and return one here even though we don't need it - return new Promise(function(resolve, reject) { - resolve('root.intro'); - }); - } else { - // intro is done. Now, let's read and check the current version - // of the startup config - return $http.get("json/startupConfig.json") - .then(startprefs.readConsentState) - .then(startprefs.isConsented) - .then(function(result) { - if (result) { - return null; + return startprefs.readStartupState().then(function([is_intro_done, is_consented]) { + if (!is_intro_done) { + console.assert(!$rootScope.intro_done, "in getPendingOnboardingState first check, $rootScope.intro_done", JSON.stringify($rootScope.intro_done)); + return 'root.intro'; + } else { + // intro is done. Now let's check consent + console.assert(is_intro_done, "in getPendingOnboardingState, local is_intro_done", is_intro_done); + console.assert($rootScope.is_intro_done, "in getPendingOnboardingState, $rootScope.intro_done", $rootScope.intro_done); + if (is_consented) { + return null; } else { - return 'root.reconsent'; + return 'root.reconsent'; } - }); - } + } + }); + }; + + /* + * Read the intro_done and consent_done variables into the $rootScope so that + * we can use them without making multiple native calls + */ + startprefs.readStartupState = function() { + var readIntroPromise = startprefs.readIntroDone() + .then(startprefs.isIntroDone); + var readConsentPromise = startprefs.readConsentState() + .then(startprefs.isConsented); + return Promise.all([readIntroPromise, readConsentPromise]); }; startprefs.getConsentDocument = function() { @@ -171,61 +150,17 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', startprefs.checkNativeConsent = function() { startprefs.getConsentDocument().then(function(resultDoc) { if (resultDoc == null) { - startprefs.readConsentState() - .then(startprefs.isConsented) - .then(function(consentState) { - if (consentState == true) { - $ionicPopup.alert({template: "Local consent found, native consent missing, writing consent to native"}); - return writeConsentToNative(); - } - }); - } - }); - } - - startprefs.checkUsercacheStorage = function(key) { - // console.log("checkUsercacheStorage called"); - var ls_stored_val = storage.get(key); - $window.cordova.plugins.BEMUserCache.getLocalStorage(key, false).then(function(uc_stored_val) { - logger.log("uc_stored_val = "+JSON.stringify(uc_stored_val)+" ls_stored_val = "+ls_stored_val); - if(angular.isDefined(uc_stored_val) && (uc_stored_val != null) - && (key in uc_stored_val) && angular.isDefined(uc_stored_val[key])) { - if (ls_stored_val == true) { - logger.log("local intro_done true, remote intro_done "+uc_stored_val[key]+", already synced"); - } else { - logger.log("local intro_done false, remote intro_done "+uc_stored_val[key]+", setting local"); - $ionicPopup.alert({template: "Local "+key+" not found, native "+key+" found, writing "+key+" to local"}) - storage.put(key, true); - } - } else { - if (ls_stored_val == true) { - logger.log("local intro_done found, remote intro_done not found, setting remote"); - - // Need to initialize this first because if we try to - // create it inlike with {key: value}, the key becomes the - // word "key" and the stored object is - // {"key":"2018-01-31T06:26:02+00:00"} - var to_put = {}; - to_put[key] = moment().format(); - $window.cordova.plugins.BEMUserCache.putLocalStorage(key, to_put); - $ionicPopup.alert({template: "Local "+key+" found, native "+key+" missing, writing "+key+" to native"}) + if(startprefs.isConsented()) { + logger.log("Local consent found, native consent missing, writing consent to native"); + $ionicPopup.alert({template: "Local consent found, native consent missing, writing consent to native"}); + return writeConsentToNative(); } else { - logger.log("local intro_done false, remote intro_done not found, already synced"); + logger.log("Both local and native consent not found, nothing to sync"); } } - }).catch(function(error) { - var display_msg = error.message + "\n" + error.stack; - logger.log("error in checkUsercacheStorage = "+display_msg); - $ionicPopup.alert({template: display_msg}); }); } - startprefs.checkStorageConsistency = function() { - // console.log("checkStorageConsistency called"); - startprefs.checkNativeConsent(); - startprefs.checkUsercacheStorage(INTRO_DONE_KEY); - } - startprefs.getNextState = function() { return startprefs.getPendingOnboardingState().then(function(result){ if (result == null) { @@ -283,7 +218,6 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', alert("ionic is ready, but logger not present?"); } logger = Logger; - startprefs.loadDefaultTheme(); startprefs.loadPreferredScreen(); }; @@ -295,7 +229,6 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', Logger.log("ionicPlatform.ready() called " + nTimesCalled+" times!"); nTimesCalled = nTimesCalled + 1; startprefs.startWithPrefs(); - startprefs.checkStorageConsistency(); Logger.log("startprefs startup done"); }); diff --git a/www/js/splash/updatecheck.js b/www/js/splash/updatecheck.js index 215a1ce72..a2714ab92 100644 --- a/www/js/splash/updatecheck.js +++ b/www/js/splash/updatecheck.js @@ -2,9 +2,9 @@ angular.module('emission.splash.updatecheck', ['emission.plugin.logger', 'emission.services', - 'angularLocalStorage']) + 'emission.plugin.kvstore']) -.factory('UpdateCheck', function($ionicPopup, $ionicPlatform, $rootScope, $window, CommHelper, Logger, storage) { +.factory('UpdateCheck', function($ionicPopup, $ionicPlatform, $rootScope, $window, CommHelper, Logger, KVStore) { var uc = {}; var CHANNEL_KEY = 'deploy_channel'; @@ -14,17 +14,17 @@ angular.module('emission.splash.updatecheck', ['emission.plugin.logger', * to load UI updates from. */ uc.getChannel = function() { - return storage.get(CHANNEL_KEY); + return KVStore.get(CHANNEL_KEY); }; uc.setChannel = function(channelName) { - storage.set(CHANNEL_KEY, channelName); - CommHelper.updateUser({ - client: channelName - }); + return Promise.all([KVStore.set(CHANNEL_KEY, channelName), + CommHelper.updateUser({ + client: channelName + })]); }; - uc.setChannelPromise = function(currChannel) { + uc.initChannelPromise = function(currChannel) { var deploy = $window.IonicCordova.deploy; if (currChannel == null) { Logger.log("currChannel == null, skipping deploy init"); @@ -94,30 +94,36 @@ angular.module('emission.splash.updatecheck', ['emission.plugin.logger', uc.handleClientChangeURL = function(urlComponents) { Logger.log("handleClientChangeURL = "+JSON.stringify(urlComponents)); - if (urlComponents['clear_local_storage'] == "true") { - Logger.log("About to clear all local storage"); - storage.clearAll(); - } + var operationArray = [] if (urlComponents['clear_usercache'] == "true") { Logger.log("About to clear usercache"); - window.cordova.plugins.BEMUserCache.clearAll(); + operationArray.push(KVStore.clearAll()); } - uc.setChannel(urlComponents['new_client']); - uc.checkForUpdates(); + operationArray.push(uc.setChannel(urlComponents['new_client'])); + Promise.all(operationArray).then(function() { + Logger.log("successfully set the channel to "+urlComponents['new_client']); + uc.checkForUpdates(); + }).catch(function(error) { + var display_msg = error.message + "\n" + error.stack; + if (!angular.isDefined(error.message)) { + display_msg = JSON.stringify(error); + } + $ionicPopup.alert({"title": "Unable to handle client change", + "template": display_msg}); + Logger.log('Ionic Deploy: Unable to handle client change URL '+display_msg); + }) }; // Default to dev var getChannelToUse = function() { - var channel = uc.getChannel(); + return uc.getChannel().then(function(channel) { if (channel == null || channel == "") { console.log("No saved channel found, skipping channel config") channel = null; }; console.log("Returning channel "+channel) return channel; - } - - var showProgressDialog = function(title) { + }); } var applyUpdate = function() { @@ -159,8 +165,8 @@ angular.module('emission.splash.updatecheck', ['emission.plugin.logger', // Check Ionic Deploy for new code uc.checkForUpdates = function() { console.log('Ionic Deploy: Checking for updates'); - var currChannel = getChannelToUse(); - uc.setChannelPromise(currChannel).then(function() { + getChannelToUse().then(function(currChannel) { + uc.initChannelPromise(currChannel).then(function() { Logger.log("deploy init complete "); uc.checkPromise().then(function(hasUpdate) { Logger.log('Ionic Deploy: Update available: ' + hasUpdate); @@ -194,6 +200,7 @@ angular.module('emission.splash.updatecheck', ['emission.plugin.logger', // $ionicPopup.alert({title: "Up to date!"}); } }) + }) }).catch(function(err) { Logger.log('Ionic Deploy: Unable to check for updates'+err); console.error('Ionic Deploy: Unable to check for updates',err) diff --git a/www/json/connectionConfig.token_list.json.sample b/www/json/connectionConfig.token_list.json.sample index 4e1268fe0..d967050ef 100644 --- a/www/json/connectionConfig.token_list.json.sample +++ b/www/json/connectionConfig.token_list.json.sample @@ -3,13 +3,13 @@ "android": { "auth": { "method": "prompted-auth", - "prompt": "Enter your unique token" + "prompt": "" } }, "ios": { "auth": { "method": "prompted-auth", - "prompt": "Enter your unique token" + "prompt": "" } } } diff --git a/www/templates/control/main-control.html b/www/templates/control/main-control.html index a29feefd3..4cad61d88 100644 --- a/www/templates/control/main-control.html +++ b/www/templates/control/main-control.html @@ -1,4 +1,4 @@ - +
{{settings.auth.email}}
@@ -7,7 +7,7 @@
Tracking