diff options
Diffstat (limited to 'www')
| -rw-r--r-- | www/index.html | 153 | ||||
| -rwxr-xr-x | www/js/DataModel.js | 18 | ||||
| -rw-r--r-- | www/js/DevOptionsCtrl.js | 2 | ||||
| -rw-r--r-- | www/js/EventCtrl.js | 41 | ||||
| -rw-r--r-- | www/js/EventDateTimeFilterCtrl.js | 4 | ||||
| -rw-r--r-- | www/js/EventServerSettingsCtrl.js | 2 | ||||
| -rw-r--r-- | www/js/EventsGraphsCtrl.js | 2 | ||||
| -rw-r--r-- | www/js/FirstUseCtrl.js | 4 | ||||
| -rw-r--r-- | www/js/HelpCtrl.js | 2 | ||||
| -rw-r--r-- | www/js/LogCtrl.js | 30 | ||||
| -rw-r--r-- | www/js/LoginCtrl.js | 4 | ||||
| -rw-r--r-- | www/js/MonitorCtrl.js | 4 | ||||
| -rw-r--r-- | www/js/MonitorModalCtrl.js | 5 | ||||
| -rw-r--r-- | www/js/MontageCtrl.js | 16 | ||||
| -rw-r--r-- | www/js/MontageHistoryCtrl.js | 6 | ||||
| -rw-r--r-- | www/js/NewsCtrl.js | 2 | ||||
| -rw-r--r-- | www/js/PortalLoginCtrl.js | 30 | ||||
| -rw-r--r-- | www/js/StateCtrl.js | 2 | ||||
| -rw-r--r-- | www/js/TimelineCtrl.js | 4 | ||||
| -rw-r--r-- | www/js/TimelineModalCtrl.js | 2 | ||||
| -rw-r--r-- | www/js/WizardCtrl.js | 2 | ||||
| -rwxr-xr-x | www/js/app.js | 3745 | ||||
| -rw-r--r-- | www/templates/events.html | 2 | ||||
| -rw-r--r-- | www/templates/menu.html | 119 | ||||
| -rw-r--r-- | www/templates/monitors.html | 2 | ||||
| -rw-r--r-- | www/templates/montage.html | 2 | ||||
| -rw-r--r-- | www/templates/timeline.html | 1 |
27 files changed, 2150 insertions, 2056 deletions
diff --git a/www/index.html b/www/index.html index 615d22c1..90fd465c 100644 --- a/www/index.html +++ b/www/index.html @@ -9,6 +9,9 @@ <meta http-equiv="Content-Security-Policy" content="img-src * blob: android-webview-video-poster: cdvphotolibrary: 'self' data: ws: wss://*; default-src * blob: 'self' gap: wss: ws: data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src * http: https: ws: wss://*;"> + + + <!--<meta http-equiv="Content-Security-Policy" content="img-src * blob: android-webview-video-poster: cdvphotolibrary: 'self' data:; default-src * blob: 'self' gap: wss: ws: ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval';connect-src * http: https: ws: wss:;">--> <title></title> <meta name="format-detection" content="telephone=no"> @@ -32,8 +35,10 @@ <script src="lib/ionic/js/ionic.bundle.js"></script> <script src="lib/ngCordova/dist/ng-cordova.min.js"></script> + <script src="cordova.js"></script> - <script src="lib/filelogger/dist/filelogger.min.js"></script> + + <script src="lib/localforage/dist/localforage.js"></script> <script src="lib/localforage-cordovasqlitedriver/dist/localforage-cordovasqlitedriver.js"></script> <script src="js/ionicUtils.js"></script> @@ -54,6 +59,7 @@ <script src="lib/moment/min/moment-with-locales.min.js"></script> <script src="lib/ng-mfb/src/mfb-directive.js"></script> <script src="lib/angular-touch/angular-touch.min.js"></script> + <script src="lib/filelogger/dist/filelogger.min.js"></script> <!-- unmanaged externals --> @@ -111,146 +117,25 @@ <script src="js/MenuController.js"></script> <script src="js/EventsModalGraphCtrl.js"></script> <script src="js/InvalidApiCtrl.js"></script> + + + + </head> <!-- <body ng-app="starter" > --> <!-- I want to start angular only after cordova device is ready, so I'll tag it on device ready --> -<body bgcolor="#555555"> +<body bgcolor="#555555"> <!-- For some reason - which I haven't debugged yet, when I was using the ionic side menu template I was having problems with tabs/sliders in views, I think its to do with controls being alive in the menu. this approach puts controls in each page and that works well --> <!-- This is the Side menu options --> <!-- ng-cloak makes sure no HTML items load up before Angular is initialized --> <!-- This avoids sudden flashes of odd/mis-aligned icons--> - <ion-side-menus delegate-handle="sideMenu" ng-cloak> - <ion-side-menu-content> - <ion-nav-bar class="bar-stable nav-title-slide-ios7"> - <ion-nav-back-button class="button-icon"> - <span class="icon ion-ios7-arrow-left"></span> - </ion-nav-back-button> - </ion-nav-bar> - <ion-nav-view></ion-nav-view> - </ion-side-menu-content> - <ion-side-menu> - <ion-header-bar class="bar bar-header bar-stable"> - <h1 class="title">{{'kMenuOptions'|translate}}</h1> - </ion-header-bar> - <ion-content has-header="true" mouse-wheel-scroll> - <!-- <ion-scroll scrollbar-y="false" style="height:100%" >--> - <ion-list> - <ion-item href="#/montage" menu-close> - <!--<span ng-if="$root.runMode=='lowbw'" style="float:right;margin-top:-18px;background-color:#f1c40f;color:#000;font-size:11px;opacity:0.7;width:20px;border-radius: 0px 0px 5px 5px;display:inline-block;text-align:center;"> <i class="icon ion-arrow-graph-down-left"></i> </span>--> - <span class=" item-icon-left"> - <i class="icon ion-grid"></i> - </span>{{'kMenuMontage'|translate}} - </ion-item> - - <ion-item href="#/timeline" menu-close> - <span class=" item-icon-left"> - <i class="icon ion-android-time"></i> - </span>{{'kMenuTimeline'|translate}} - </ion-item> - <ion-item href="#/events/0/false" menu-close> - <span class=" item-icon-left"> - <i class="icon ion-ios-calendar-outline"></i> - </span>{{'kMenuEvents'|translate}} - </ion-item> - - <ion-item href="#/montage-history" menu-close> - <span class=" item-icon-left"> - <i class="icon ion-ios-keypad-outline"></i> - </span>{{'kMenuEventMontage'|translate}} - </ion-item> - - <ion-item href="#/monitors" menu-close> - <span class=" item-icon-left"> - <i class="icon ion-ios-videocam-outline"></i> - </span>{{'kMenuMonitors'|translate}} - </ion-item> - <ion-item href="#/state" menu-close> - <span class=" item-icon-left"> - <i class="icon ion-information-circled"></i> - </span> {{'kMenuSystemStatus'|translate}} - </ion-item> - <ion-item nav-clear menu-close href="#/login/false"> - <span class=" item-icon-left"> - <i class="icon ion-person"></i> - {{'kMenuZMSettings'|translate}} - <!--<span class="item-note" style="width:90px"> - {{$root.getProfileName();}} - </span>--> - <span style="float:right;margin-top:-18px;background-color:#444444;color:#fff;font-size:11px;opacity:0.7;width:90px;border-radius: 0px 0px 5px 5px;:text-overflow:ellipsis;overflow:hidden;white-space:nowrap;display:inline-block;text-align:center;"> {{$root.getProfileName();}} </span> - </span> - </ion-item> - <ion-item nav-clear menu-close href="#/devoptions"> - <span class=" item-icon-left"> - <i class="icon ion-settings"></i> - </span> {{'kMenuDevSettings'|translate}} - </ion-item> - <div ng-controller="MenuController"> - <ion-item ng-click="switchLang()" nav-clear menu-close href=""> - <span class=" item-icon-left"> - <i class="icon ion-earth"></i> - </span> {{'kLanguage'|translate}} - </ion-item> - </div> - <ion-item nav-clear menu-close href="#/help"> - <span class=" item-icon-left"> - <i class="icon ion-help"></i> - </span> {{'kMenuHelp'|translate}} - </ion-item> - <ion-item nav-clear menu-close href="#/wizard"> - <span class=" item-icon-left"> - <i class="icon ion-wand"></i> - </span> {{'kMenuWizard'|translate}} - </ion-item> - <div ng-if="$root.showBlog"> - <ion-item nav-clear menu-close href="#/news"> - <span class=" item-icon-left"> - <i class="icon ion-radio-waves"></i> - </span>{{'kMenuNews'|translate}}<span style="color:#268d3a;"> {{$root.newBlogPost}}</span> - </ion-item> - </div> - <ion-item nav-clear menu-close href="#/log"> - <span class=" item-icon-left"> - <i class="icon ion-clipboard"></i> - </span> {{'kMenuLogs'|translate}} - </ion-item> - <div ng-if="$root.newVersionAvailable && $root.platformOS=='desktop'"> - <ion-item nav-clear menu-close href=""> - <span class=" item-icon-left"> - <i class="icon ion-email-unread"></i> - </span> <span style="color:#268d3a;">{{$root.newVersionAvailable}}</span> - </ion-item> - </div> - <!-- <div ng-if="$root.platformOS=='android'"> - <ion-item ng-click="$root.exitApp();"> - <span class=" item-icon-left"> - <i class="icon ion-close-circled"></i> - </span> {{'kMenuExit'|translate}} - </ion-item> - </div>--> - <ion-item style="color:rgb(106, 106, 106); font-size:90%;"> - <i class="ion-ios-location"></i> {{$root.getLocalTimeZone();}} - <br/> - <span ng-if="$root.isTzSupported()"><i class="icon icon-server"></i> {{$root.getServerTimeZoneNow();}} </span> - </ion-item> - </ion-list> - <!--</ion-scroll>--> - </ion-content> - </ion-side-menu> - </ion-side-menus> <!-- This is where is bootstrap angular - if I don't do this, then the window jumps around after the status bar comes on - because the window kicked in before phonegap got ready --> - <script> - window.ionic.Platform.ready(function() - { - console.log("******* PLATFORM READY ****"); - - angular.bootstrap(document, ['zmApp']); - }); - </script> + <!-- keyboard input jump fix https://forum.ionicframework.com/t/ionic-keyboard-scroll-issue-ios/34420/2?u=pliablepixels --> @@ -259,6 +144,15 @@ // window.addEventListener('native.keyboardshow', keyboardShowHandler); //alert ('Hello'); + + + window.ionic.Platform.ready(function() + { + console.log("******* PLATFORM READY ****"); + angular.bootstrap(document, ['zmApp']); + }); + + function keyboardShowHandler(e) { setTimeout(function() @@ -270,6 +164,9 @@ }, 0); } </script> + + + <ion-nav-view></ion-nav-view> </body> </html> diff --git a/www/js/DataModel.js b/www/js/DataModel.js index 8f702c66..12e90ab3 100755 --- a/www/js/DataModel.js +++ b/www/js/DataModel.js @@ -9,8 +9,8 @@ angular.module('zmApp.controllers') -.service('NVRDataModel', ['$http', '$q', '$ionicLoading', '$ionicBackdrop', '$fileLogger', 'zm', '$rootScope', '$ionicContentBanner', '$timeout', '$cordovaPinDialog', '$ionicPopup', '$localstorage', '$state', '$ionicNativeTransitions', '$translate', '$cordovaSQLite', - function($http, $q, $ionicLoading, $ionicBackdrop, $fileLogger, +.service('NVRDataModel', ['$ionicPlatform', '$http', '$q', '$ionicLoading', '$ionicBackdrop', '$fileLogger', 'zm', '$rootScope', '$ionicContentBanner', '$timeout', '$cordovaPinDialog', '$ionicPopup', '$localstorage', '$state', '$ionicNativeTransitions', '$translate', '$cordovaSQLite', + function($ionicPlatform, $http, $q, $ionicLoading, $ionicBackdrop, $fileLogger, zm, $rootScope, $ionicContentBanner, $timeout, $cordovaPinDialog, $ionicPopup, $localstorage, $state, $ionicNativeTransitions, $translate) { @@ -276,13 +276,18 @@ angular.module('zmApp.controllers') val = val.replace(regex1, "<password removed>"); val = val.replace(regex2, "<password removed>"); } - $fileLogger.debug(val); + + $ionicPlatform.ready(function () { + $fileLogger.debug(val); + }); //console.log (val); } } function log(val, logtype) { + + if (loginData.enableLogs) { if (val !== undefined) @@ -298,7 +303,9 @@ angular.module('zmApp.controllers') // make sure password is removed //"username":"zmninja","password":"xyz", //val = val.replace(/\"password:\", - $fileLogger.log(logtype, val); + $ionicPlatform.ready(function () { + $fileLogger.log(logtype, val); + }); // console.log (val); } } @@ -652,6 +659,9 @@ angular.module('zmApp.controllers') { // console.log("****** DATAMODEL INIT SERVICE CALLED ********"); + + + log("ZMData init: checking for stored variables & setting up log file"); localforage.getItem("latestBlogPostChecked") diff --git a/www/js/DevOptionsCtrl.js b/www/js/DevOptionsCtrl.js index 970c690d..e6f107c2 100644 --- a/www/js/DevOptionsCtrl.js +++ b/www/js/DevOptionsCtrl.js @@ -25,7 +25,7 @@ angular.module('zmApp.controllers').controller('zmApp.DevOptionsCtrl', ['$scope' { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/EventCtrl.js b/www/js/EventCtrl.js index 260ecf47..8a8673e4 100644 --- a/www/js/EventCtrl.js +++ b/www/js/EventCtrl.js @@ -87,7 +87,7 @@ angular.module('zmApp.controllers') $scope.$on('$ionicView.afterEnter', function() { - //console.log ("********* AFTER ENTER"); + console.log ("********* AFTER ENTER"); // $ionicListDelegate.canSwipeItems(true); NVRDataModel.debug ("enabling options swipe"); @@ -112,9 +112,14 @@ angular.module('zmApp.controllers') } $scope.events = []; - getInitialEvents(); - setupWatchers(); - footerExpand(); + + $timeout ( function() { + console.log ("DEFERRED ACTION EVENTS"); + getInitialEvents(); + setupWatchers(); + footerExpand(); + },100); + }); $scope.$on('$ionicView.beforeEnter', function() @@ -128,7 +133,7 @@ angular.module('zmApp.controllers') $scope.id = parseInt($stateParams.id, 10); $scope.showEvent = $stateParams.playEvent || false; - console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + console.log("BEFORE ENTER >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); NVRDataModel.log("EventCtrl called with: EID=" + $scope.id + " playEvent = " + $scope.showEvent); @@ -319,7 +324,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("login", + $state.go("app.login", { "wizard": false }); @@ -338,9 +343,12 @@ angular.module('zmApp.controllers') nolangFrom = moment($rootScope.fromString).locale('en').format("YYYY-MM-DD HH:mm:ss"); if ($rootScope.toString) nolangTo = moment($rootScope.toString).locale('en').format("YYYY-MM-DD HH:mm:ss"); + + // console.log ("GETTING EVENTS USING "+$scope.id+" "+nolangFrom+" "+ nolangTo) NVRDataModel.getEventsPages($scope.id, nolangFrom, nolangTo) .then(function(data) { + // console.log ("WE GOT PAGES="+JSON.stringify(data)); eventsPage = data.pageCount || 1; NVRDataModel.debug("EventCtrl: found " + eventsPage + " pages of events"); @@ -359,6 +367,7 @@ angular.module('zmApp.controllers') .then(function(data) { + // console.log ("WE GOT EVENTS="+JSON.stringify(data)); var myevents = data; NVRDataModel.debug("EventCtrl: success, got " + myevents.length + " events"); var loginData = NVRDataModel.getLogin(); @@ -380,6 +389,8 @@ angular.module('zmApp.controllers') } } + console.log ("IDFOUND="+idfound + " AND MON LEN="+$scope.monitors.length); + myevents[i].Event.humanizeTime = humanizeTime(myevents[i].Event.StartTime); myevents[i].Event.streamingURL = NVRDataModel.getStreamingURL(myevents[i].Event.MonitorId); myevents[i].Event.baseURL = NVRDataModel.getBaseURL(myevents[i].Event.MonitorId); @@ -413,13 +424,17 @@ angular.module('zmApp.controllers') else myevents[i].Event.videoPath = myevents[i].Event.baseURL + "/index.php?view=view_video&eid=" + myevents[i].Event.Id; - if (idfound) + // if (idfound) + if (idfound) { + + console.log ("PUSHING "+JSON.stringify(myevents[i])); $scope.events.push(myevents[i]); + console.log ("SCOPE EVENTS LEN="+$scope.events.length); } else { - //console.log ("Skipping Event MID = " + myevents[i].Event.MonitorId); + console.log ("Skipping Event MID = " + myevents[i].Event.MonitorId); } } //for @@ -1023,7 +1038,9 @@ angular.module('zmApp.controllers') // reloading - may solve https://github.com/pliablepixels/zmNinja/issues/36 // if you are in the same mid event page $state.go won't work - $state.go("events", + + console.log ("---> SENDING TO EVENTS WITH mid " + monitorId); + $state.go("app.events", { "id": monitorId, "playEvent": false @@ -1046,7 +1063,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -1783,7 +1800,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -1988,6 +2005,8 @@ angular.module('zmApp.controllers') $scope.scrollPosition = function() { + if (!$ionicScrollDelegate.$getByHandle("mainScroll")) return ""; + if (!$ionicScrollDelegate.$getByHandle("mainScroll").getScrollPosition()) return ""; var scrl = parseFloat($ionicScrollDelegate.$getByHandle("mainScroll").getScrollPosition().top); var item = Math.round(scrl / eventsListDetailsHeight); if ($scope.events == undefined || !$scope.events.length || $scope.events[item] == undefined) diff --git a/www/js/EventDateTimeFilterCtrl.js b/www/js/EventDateTimeFilterCtrl.js index 772b16be..df7f774a 100644 --- a/www/js/EventDateTimeFilterCtrl.js +++ b/www/js/EventDateTimeFilterCtrl.js @@ -19,7 +19,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -67,7 +67,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/EventServerSettingsCtrl.js b/www/js/EventServerSettingsCtrl.js index efa868ea..e80c9f01 100644 --- a/www/js/EventServerSettingsCtrl.js +++ b/www/js/EventServerSettingsCtrl.js @@ -28,7 +28,7 @@ disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/EventsGraphsCtrl.js b/www/js/EventsGraphsCtrl.js index 5f21b09b..d57472e4 100644 --- a/www/js/EventsGraphsCtrl.js +++ b/www/js/EventsGraphsCtrl.js @@ -34,7 +34,7 @@ angular.module('zmApp.controllers').controller('zmApp.EventsGraphsCtrl', ['$ioni { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/FirstUseCtrl.js b/www/js/FirstUseCtrl.js index 1dc6c514..02293f77 100644 --- a/www/js/FirstUseCtrl.js +++ b/www/js/FirstUseCtrl.js @@ -74,7 +74,7 @@ angular.module('zmApp.controllers').controller('zmApp.FirstUseCtrl', ['$scope', disableAnimate: false, disableBack: true }); - $state.go("login", + $state.go("app.login", { "wizard": false }); @@ -88,7 +88,7 @@ angular.module('zmApp.controllers').controller('zmApp.FirstUseCtrl', ['$scope', disableAnimate: false, disableBack: true }); - $state.go("wizard"); + $state.go("app.wizard"); return; }; diff --git a/www/js/HelpCtrl.js b/www/js/HelpCtrl.js index 51da877b..005b7df1 100644 --- a/www/js/HelpCtrl.js +++ b/www/js/HelpCtrl.js @@ -22,7 +22,7 @@ angular.module('zmApp.controllers').controller('zmApp.HelpCtrl', ['$scope', '$ro { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/LogCtrl.js b/www/js/LogCtrl.js index af7b037e..e3f4da35 100644 --- a/www/js/LogCtrl.js +++ b/www/js/LogCtrl.js @@ -79,7 +79,7 @@ angular.module('zmApp.controllers').controller('zmApp.LogCtrl', ['$scope', '$roo { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -97,6 +97,7 @@ angular.module('zmApp.controllers').controller('zmApp.LogCtrl', ['$scope', '$roo $scope.sendEmail = function(logstring) { + logstring = logstring.substring (0,20000); $ionicPopup.confirm( { title: $translate.instant('kSensitiveTitle'), @@ -155,7 +156,32 @@ angular.module('zmApp.controllers').controller('zmApp.LogCtrl', ['$scope', '$roo logstring = logstring.replace(re4, "<server>"); } - window.plugins.emailComposer.showEmailComposerWithCallback(callback, $rootScope.appName + ' logs', logstring, [zm.authoremail]); + /* window.plugins.emailComposer.showEmailComposerWithCallback(callback, $rootScope.appName + ' logs', logstring, [zm.authoremail]);*/ + + + cordova.plugins.email.isAvailable( + function (isAvailable) { + + if (isAvailable) { + cordova.plugins.email.open({ + to: zm.authoremail, + subject: $rootScope.appName + ' logs', + body: logstring + }); + } + else { + // kEmailNotConfigured + $rootScope.zmPopup = SecuredPopups.show('alert', + { + title: $translate.instant('kError'), + template: $translate.instant('kEmailNotConfigured'), + okText: $translate.instant('kButtonOk'), + cancelText: $translate.instant('kButtonCancel'), + }); + } + + }); + } else diff --git a/www/js/LoginCtrl.js b/www/js/LoginCtrl.js index 300e4fbf..7757b79b 100644 --- a/www/js/LoginCtrl.js +++ b/www/js/LoginCtrl.js @@ -55,7 +55,7 @@ angular.module('zmApp.controllers').controller('zmApp.LoginCtrl', ['$scope', '$r { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -247,7 +247,7 @@ angular.module('zmApp.controllers').controller('zmApp.LoginCtrl', ['$scope', '$r NVRDataModel.debug("Saving settings before going to Event Server settings"); //console.log ( "My loginData saved " + JSON.stringify($scope.loginData)); NVRDataModel.setLogin($scope.loginData); - $state.go("eventserversettings"); + $state.go("app.eventserversettings"); return; }; diff --git a/www/js/MonitorCtrl.js b/www/js/MonitorCtrl.js index 6a91a52e..eca22d15 100644 --- a/www/js/MonitorCtrl.js +++ b/www/js/MonitorCtrl.js @@ -71,7 +71,7 @@ angular.module('zmApp.controllers') disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -315,7 +315,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("login", + $state.go("app.login", { "wizard": false }); diff --git a/www/js/MonitorModalCtrl.js b/www/js/MonitorModalCtrl.js index 01169130..2815cb2e 100644 --- a/www/js/MonitorModalCtrl.js +++ b/www/js/MonitorModalCtrl.js @@ -1511,6 +1511,11 @@ angular.module('zmApp.controllers').controller('MonitorModalCtrl', ['$scope', '$ data.control.Control.HasHomePreset = '1';*/ // *** Only for testing - comment out - end // + + //data.control.Control.HasPresets = '1'; + //data.control.Control.HasHomePreset = '1' + + $scope.ptzMoveCommand = "move"; // start with as move; $scope.ptzStopCommand = ""; diff --git a/www/js/MontageCtrl.js b/www/js/MontageCtrl.js index e2e26c00..92bec795 100644 --- a/www/js/MontageCtrl.js +++ b/www/js/MontageCtrl.js @@ -730,20 +730,21 @@ angular.module('zmApp.controllers') { $rootScope.isAlarm = !$rootScope.isAlarm; if (!$rootScope.isAlarm) + // if (1) { $rootScope.alarmCount = "0"; $ionicHistory.nextViewOptions( { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false - }, + }/*, { reload: true - }); + }*/); return; } }; @@ -767,7 +768,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -811,7 +812,7 @@ angular.module('zmApp.controllers') disableAnimate: true, disableBack: true }); - $state.go("montage", + $state.go("app.montage", { minimal: $scope.minimal, isRefresh: true @@ -934,7 +935,7 @@ angular.module('zmApp.controllers') { $scope.MontageMonitors[ndx].Monitor.selectStyle = "dragborder-selected"; } - //console.log ("Switched value to " + $scope.MontageMonitors[ndx].Monitor.selectStyle); + //console.log ("Switched value to " + $scope.MontageMonitors[ndx] .Monitor.selectStyle); }; //--------------------------------------------------------------------- @@ -1157,7 +1158,6 @@ angular.module('zmApp.controllers') $interval.cancel(intervalHandleMontageCycle); $interval.cancel(intervalHandleAlarmStatus); // $interval.cancel(modalIntervalHandle); - // FIXME: Do I need to setAwake(false) here? } @@ -1651,7 +1651,7 @@ angular.module('zmApp.controllers') { disableBack: true }); - $state.go("login", + $state.go("app.login", { "wizard": false }); diff --git a/www/js/MontageHistoryCtrl.js b/www/js/MontageHistoryCtrl.js index 8aff342e..67b48707 100644 --- a/www/js/MontageHistoryCtrl.js +++ b/www/js/MontageHistoryCtrl.js @@ -695,7 +695,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -721,7 +721,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false, @@ -1386,7 +1386,7 @@ angular.module('zmApp.controllers').controller('zmApp.MontageHistoryCtrl', ['$sc { disableBack: true }); - $state.go("login"); + $state.go("app.login"); return; } diff --git a/www/js/NewsCtrl.js b/www/js/NewsCtrl.js index e1e030ec..f5d1fd35 100644 --- a/www/js/NewsCtrl.js +++ b/www/js/NewsCtrl.js @@ -22,7 +22,7 @@ angular.module('zmApp.controllers').controller('zmApp.NewsCtrl', ['$scope', '$ro { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/PortalLoginCtrl.js b/www/js/PortalLoginCtrl.js index 6a9a9f2d..d5107ff0 100644 --- a/www/js/PortalLoginCtrl.js +++ b/www/js/PortalLoginCtrl.js @@ -85,7 +85,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic disableAnimate: true, disableBack: true }); - $state.go('first-use'); + $state.go('app.first-use'); return; } else @@ -97,7 +97,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic disableAnimate: true, disableBack: true }); - $state.go("login", + $state.go("app.login", { "wizard": false }); @@ -156,7 +156,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic if (NVRDataModel.versionCompare(data, zm.minAppVersion) == -1 && data != "0.0.0") { - $state.go('lowversion', + $state.go('app.lowversion', { "ver": data }); @@ -166,7 +166,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic if (NVRDataModel.versionCompare(data, zm.recommendedAppVersion) == -1 && data != "0.0.0") { - $state.go('importantmessage', + $state.go('app.importantmessage', { "ver": data }); @@ -187,7 +187,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic // coming here means continue EventServer.refresh(); - var statetoGo = $rootScope.lastState ? $rootScope.lastState : 'montage'; + var statetoGo = $rootScope.lastState ? $rootScope.lastState : 'app.montage'; //NVRDataModel.debug ("logging state transition"); NVRDataModel.debug("2nd Auth: Transitioning state to: " + statetoGo + " with param " + JSON.stringify($rootScope.lastStateParam)); @@ -231,7 +231,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic if (ld.onTapScreen == $translate.instant('kTapMontage')) { NVRDataModel.debug("Going to montage"); - $state.go("montage", + $state.go("app.montage", {}, { reload: true @@ -242,7 +242,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic else if (ld.onTapScreen == $translate.instant('kTapEvents')) { NVRDataModel.debug("Going to events"); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -255,7 +255,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic else // we go to live { NVRDataModel.debug("Going to live view "); - $state.go("monitors", + $state.go("app.monitors", {}, { reload: true @@ -299,7 +299,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic if (NVRDataModel.versionCompare(data, zm.minAppVersion) == -1 && data != "0.0.0") { - $state.go('lowversion', + $state.go('app.lowversion', { "ver": data }); @@ -311,7 +311,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic // console.log (">>>>>>>>>>>>> HERE AND VERSION SAYS " +NVRDataModel.versionCompare(data, zm.recommendedAppVersion)); //console.log ("GOING TO IMPORTANT"); - $state.go('importantmessage', + $state.go('app.importantmessage', { "ver": data }); @@ -339,7 +339,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic if ($rootScope.tappedNotification != 1) { console.log ("NOTIFICATION TAPPED INSIDE CHECK IS "+$rootScope.tappedNotification); - var statetoGo = $rootScope.lastState ? $rootScope.lastState : 'montage'; + var statetoGo = $rootScope.lastState ? $rootScope.lastState : 'app.montage'; NVRDataModel.debug("logging state transition"); NVRDataModel.debug("Transitioning state to: " + statetoGo + " with param " + JSON.stringify($rootScope.lastStateParam)); @@ -372,7 +372,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic if ($rootScope.apiValid == true) { - $state.go("login", + $state.go("app.login", { "wizard": false }); @@ -380,7 +380,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic } else { - $state.go("invalidapi"); + $state.go("app.invalidapi"); return; } @@ -409,7 +409,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic disableAnimate: true, disableBack: true }); - $state.go("login", + $state.go("app.login", { "wizard": false }); @@ -419,7 +419,7 @@ angular.module('zmApp.controllers').controller('zmApp.PortalLoginCtrl', ['$ionic { // if user cancelled auth I guess we go to login $rootScope.userCancelledAuth = false; - $state.go("login", + $state.go("app.login", { "wizard": false }); diff --git a/www/js/StateCtrl.js b/www/js/StateCtrl.js index 4faec748..8a7a3c1d 100644 --- a/www/js/StateCtrl.js +++ b/www/js/StateCtrl.js @@ -120,7 +120,7 @@ angular.module('zmApp.controllers').controller('zmApp.StateCtrl', ['$ionicPopup' { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/TimelineCtrl.js b/www/js/TimelineCtrl.js index 101e7166..58c58a62 100644 --- a/www/js/TimelineCtrl.js +++ b/www/js/TimelineCtrl.js @@ -34,7 +34,7 @@ angular.module('zmApp.controllers').controller('zmApp.TimelineCtrl', ['$ionicPla { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false @@ -642,7 +642,7 @@ angular.module('zmApp.controllers').controller('zmApp.TimelineCtrl', ['$ionicPla $scope.follow.time = NVRDataModel.getLogin().followTimeLine; $scope.currentMode = "custom"; $rootScope.customTimelineRange = true; - $state.go('events-date-time-filter'); + $state.go('app.events-date-time-filter'); return; } diff --git a/www/js/TimelineModalCtrl.js b/www/js/TimelineModalCtrl.js index 506c6efa..76c16fb3 100644 --- a/www/js/TimelineModalCtrl.js +++ b/www/js/TimelineModalCtrl.js @@ -37,7 +37,7 @@ angular.module('zmApp.controllers').controller('TimelineModalCtrl', ['$scope', ' { disableBack: true }); - $state.go("events", + $state.go("app.events", { "id": 0, "playEvent": false diff --git a/www/js/WizardCtrl.js b/www/js/WizardCtrl.js index 8f481d2d..821783bd 100644 --- a/www/js/WizardCtrl.js +++ b/www/js/WizardCtrl.js @@ -802,7 +802,7 @@ angular.module('zmApp.controllers').controller('zmApp.WizardCtrl', ['$scope', '$ { disableBack: true }); - $state.go("login", + $state.go("app.login", { "wizard": true }); diff --git a/www/js/app.js b/www/js/app.js index aca3f33d..5d82d78c 100755 --- a/www/js/app.js +++ b/www/js/app.js @@ -13,2172 +13,2189 @@ var appVersion = "0.0.0"; // core app start stuff angular.module('zmApp', [ - 'ionic', - 'ion-datetime-picker', - 'ngIOS9UIWebViewPatch', - 'zmApp.controllers', - 'fileLogger', - 'angular-carousel', - 'angularAwesomeSlider', - 'com.2fdevs.videogular', - 'com.2fdevs.videogular.plugins.controls', - 'com.2fdevs.videogular.plugins.overlayplay', - 'ionic-native-transitions', - 'mgo-angular-wizard', - 'pascalprecht.translate', - 'jett.ionic.scroll.sista', - 'uk.ac.soton.ecs.videogular.plugins.cuepoints', - 'dcbImgFallback' - - ]) - - // ------------------------------------------ - // Various constants central repository - // Feel free to change them as you see fit - //------------------------------------------------ - - .constant('zm', { - minAppVersion: '1.28.107', // if ZM is less than this, the app won't work - recommendedAppVersion: '1.29', - minEventServerVersion: '0.9', - castAppId: 'BA30FB4C', - alarmFlashTimer: 20000, // time to flash alarm - gcmSenderId: '710936220256', - httpTimeout: 15000, - largeHttpTimeout: 60000, - logFile: 'zmNinjaLog.txt', - authoremail: 'pliablepixels+zmNinja@gmail.com', - logFileMaxSize: 20000, // after this limit log gets reset - //loginInterval: 300000, //5m*60s*1000 - ZM auto login after 5 mins - loginInterval: 1800000, //30m*60s*1000 - ZM auto login after 30 mins - - //loginInterval: 30000, - updateCheckInterval: 86400000, // 24 hrs - loadingTimeout: 15000, - slowLoadingTimeout: 60000, - safeMontageLimit: 100, - safeImageQuality: 10, - maxFPS: 30, - defaultFPS: 3, - maxMontageQuality: 70, - defaultMontageQuality: 50, - progressIntervalCheck: 5000, // used for progress indicator on event playback - graphFillColor: 'rgba(151,187,205,0.5)', - graphStrokeColor: 'rgba(151,187,205,0.8)', - graphHighlightFill: 'rgba(0,163,124,0.5)', - graphItemMax: 2000, - graphDesktopItemMax: 2000, - monitorCheckingColor: '#03A9F4', - monitorNotRunningColor: '#F44336', - monitorPendingColor: '#FF9800', - monitorRunningColor: '#4CAF50', - monitorErrorColor: '#795548', - montageScaleFrequency: 300, - eventsListDetailsHeight: 230.0, - eventsListScrubHeight: 330, - loginScreenString: "var currentView = 'login'", // Isn't there a better way? - desktopUrl: "/zm", - desktopApiUrl: "/api/zm", - latestRelease: "https://api.github.com/repos/pliablepixels/zmNinja/releases/latest", - blogUrl: "https://medium.com/zmninja/latest?format=json", - nphSwitchTimer: 3000, - eventHistoryTimer: 5000, - eventPlaybackQuery: 3000, - - packeryTimer: 500, - dbName: 'zmninja', - cipherKey: 'sdf#@#%FSXSA_AR', - minCycleTime: 5, - - eventPlaybackQueryLowBW: 6000, - loginIntervalLowBW: 1800000, //30m login - eventSingleImageQualityLowBW: 70, - monSingleImageQualityLowBW: 70, - montageQualityLowBW: 50, - eventMontageQualityLowBW: 50, - maxGifCount: 60, - maxGifCount2: 100, - maxGifWidth: 800.0, - quantSample: 15, - hashSecret: 'unused at the moment' - - }) - - //http://stackoverflow.com/a/24519069/1361529 - .filter('trusted', ['$sce', function ($sce) { - return function (url) { - return $sce.trustAsResourceUrl(url); - }; - }]) + 'ionic', + 'ion-datetime-picker', + 'ngIOS9UIWebViewPatch', + 'zmApp.controllers', + 'fileLogger', + 'angular-carousel', + 'angularAwesomeSlider', + 'com.2fdevs.videogular', + 'com.2fdevs.videogular.plugins.controls', + 'com.2fdevs.videogular.plugins.overlayplay', + 'ionic-native-transitions', + 'mgo-angular-wizard', + 'pascalprecht.translate', + 'jett.ionic.scroll.sista', + 'uk.ac.soton.ecs.videogular.plugins.cuepoints', + 'dcbImgFallback' + + ]) + + // ------------------------------------------ + // Various constants central repository + // Feel free to change them as you see fit + //------------------------------------------------ + + .constant('zm', { + minAppVersion: '1.28.107', // if ZM is less than this, the app won't work + recommendedAppVersion: '1.29', + minEventServerVersion: '0.9', + castAppId: 'BA30FB4C', + alarmFlashTimer: 20000, // time to flash alarm + gcmSenderId: '710936220256', + httpTimeout: 15000, + largeHttpTimeout: 60000, + logFile: 'zmNinjaLog.txt', + authoremail: 'pliablepixels+zmNinja@gmail.com', + logFileMaxSize: 20000, // after this limit log gets reset + //loginInterval: 300000, //5m*60s*1000 - ZM auto login after 5 mins + loginInterval: 1800000, //30m*60s*1000 - ZM auto login after 30 mins + + //loginInterval: 30000, + updateCheckInterval: 86400000, // 24 hrs + loadingTimeout: 15000, + slowLoadingTimeout: 60000, + safeMontageLimit: 100, + safeImageQuality: 10, + maxFPS: 30, + defaultFPS: 3, + maxMontageQuality: 70, + defaultMontageQuality: 50, + progressIntervalCheck: 5000, // used for progress indicator on event playback + graphFillColor: 'rgba(151,187,205,0.5)', + graphStrokeColor: 'rgba(151,187,205,0.8)', + graphHighlightFill: 'rgba(0,163,124,0.5)', + graphItemMax: 2000, + graphDesktopItemMax: 2000, + monitorCheckingColor: '#03A9F4', + monitorNotRunningColor: '#F44336', + monitorPendingColor: '#FF9800', + monitorRunningColor: '#4CAF50', + monitorErrorColor: '#795548', + montageScaleFrequency: 300, + eventsListDetailsHeight: 230.0, + eventsListScrubHeight: 330, + loginScreenString: "var currentView = 'login'", // Isn't there a better way? + desktopUrl: "/zm", + desktopApiUrl: "/api/zm", + latestRelease: "https://api.github.com/repos/pliablepixels/zmNinja/releases/latest", + blogUrl: "https://medium.com/zmninja/latest?format=json", + nphSwitchTimer: 3000, + eventHistoryTimer: 5000, + eventPlaybackQuery: 3000, + + packeryTimer: 500, + dbName: 'zmninja', + cipherKey: 'sdf#@#%FSXSA_AR', + minCycleTime: 5, + + eventPlaybackQueryLowBW: 6000, + loginIntervalLowBW: 1800000, //30m login + eventSingleImageQualityLowBW: 70, + monSingleImageQualityLowBW: 70, + montageQualityLowBW: 50, + eventMontageQualityLowBW: 50, + maxGifCount: 60, + maxGifCount2: 100, + maxGifWidth: 800.0, + quantSample: 15, + hashSecret: 'unused at the moment' + + }) + + //http://stackoverflow.com/a/24519069/1361529 + .filter('trusted', ['$sce', function ($sce) { + return function (url) { + return $sce.trustAsResourceUrl(url); + }; + }]) + + + // for events view + .filter('eventListFilter', function (NVRDataModel) { + return function (input) { + var ld = NVRDataModel.getLogin(); + var out = []; + angular.forEach(input, function (item) { + if (item.Event.Archived == '0' || !ld.hideArchived) { + out.push(item); + } + }); + return out; + }; + }) - // for events view - .filter('eventListFilter', function (NVRDataModel) { - return function (input) { - var ld = NVRDataModel.getLogin(); - var out = []; - angular.forEach(input, function (item) { - if (item.Event.Archived == '0' || !ld.hideArchived) { - out.push(item); - } - }); - return out; - }; + // filter for montage iteration + .filter('onlyEnabled', function () { - }) + // Create the return function and set the required parameter name to **input** + return function (input) { - // filter for montage iteration - .filter('onlyEnabled', function () { + var out = []; - // Create the return function and set the required parameter name to **input** - return function (input) { + angular.forEach(input, function (item) { - var out = []; + if ((item.Monitor.Function != 'None') && + (item.Monitor.Enabled != '0') + ) { + out.push(item); + } - angular.forEach(input, function (item) { + }); - if ((item.Monitor.Function != 'None') && - (item.Monitor.Enabled != '0') - ) { - out.push(item); - } + return out; + }; - }); + }) - return out; - }; + // filter for EH iteration + .filter('onlyEnabledAndEventHas', function () { - }) + // Create the return function and set the required parameter name to **input** + return function (input) { - // filter for EH iteration - .filter('onlyEnabledAndEventHas', function () { + var out = []; - // Create the return function and set the required parameter name to **input** - return function (input) { + angular.forEach(input, function (item) { - var out = []; + if ((item.Monitor.Function != 'None') && (item.Monitor.Enabled != '0') && (item.Monitor.eventUrl != 'img/noevent.png') && (item.Monitor.listDisplay != 'noshow')) { + out.push(item); + } - angular.forEach(input, function (item) { + }); - if ((item.Monitor.Function != 'None') && (item.Monitor.Enabled != '0') && (item.Monitor.eventUrl != 'img/noevent.png') && (item.Monitor.listDisplay != 'noshow')) { - out.push(item); - } + return out; + }; - }); + }) - return out; - }; - }) + //credit: http://stackoverflow.com/a/23931217/1361529 + .directive('hidepassword', function () { + var modelSet = function (str) { - //credit: http://stackoverflow.com/a/23931217/1361529 - .directive('hidepassword', function () { + return str; + }; - var modelSet = function (str) { + var viewSet = function (str) { + //https://github.com/garycourt/uri-js + if (!str) return str; + var c = URI.parse(str); + //if (c.userinfo) c.userinfo="***:***"; + if (c.userinfo) c.userinfo = "\u2022\u2022\u2022:\u2022\u2022\u2022"; - return str; - }; + var ostr = ""; + if (c.scheme) ostr = ostr + c.scheme + "://"; + if (c.userinfo) ostr = ostr + c.userinfo + "@"; + if (c.host) ostr = ostr + c.host; + if (c.port) ostr = ostr + ":" + c.port; + if (c.path) ostr = ostr + c.path; + if (c.query) ostr = ostr + c.query; + if (c.fragment) ostr = ostr + c.fragment; - var viewSet = function (str) { - //https://github.com/garycourt/uri-js - if (!str) return str; - var c = URI.parse(str); - //if (c.userinfo) c.userinfo="***:***"; - if (c.userinfo) c.userinfo = "\u2022\u2022\u2022:\u2022\u2022\u2022"; - - var ostr = ""; - if (c.scheme) ostr = ostr + c.scheme + "://"; - if (c.userinfo) ostr = ostr + c.userinfo + "@"; - if (c.host) ostr = ostr + c.host; - if (c.port) ostr = ostr + ":" + c.port; - if (c.path) ostr = ostr + c.path; - if (c.query) ostr = ostr + c.query; - if (c.fragment) ostr = ostr + c.fragment; - - return ostr; - }; + return ostr; + }; - return { + return { - restrict: 'A', - require: 'ngModel', - link: function (scope, element, attr, ngModel) { - ngModel.$parsers.push(modelSet); - ngModel.$formatters.push(viewSet); + restrict: 'A', + require: 'ngModel', + link: function (scope, element, attr, ngModel) { + ngModel.$parsers.push(modelSet); + ngModel.$formatters.push(viewSet); - element.bind('blur', function () { - element.val(viewSet(ngModel.$modelValue)); - }); - element.bind('focus', function () { - element.val(ngModel.$modelValue); - }); + element.bind('blur', function () { + element.val(viewSet(ngModel.$modelValue)); + }); + element.bind('focus', function () { + element.val(ngModel.$modelValue); + }); - } - }; - }) + } + }; + }) - // credit https://gist.github.com/Zren/beaafd64f395e23f4604 + // credit https://gist.github.com/Zren/beaafd64f395e23f4604 - .directive('mouseWheelScroll', function ($timeout) { - return { - restrict: 'A', - link: function ($scope, $element, $attrs) { - var onMouseWheel, scrollCtrl; - scrollCtrl = $element.controller('$ionicScroll'); - //console.log(scrollCtrl); - if (!scrollCtrl) { - return console.error('mouseWheelScroll must be attached to a $ionicScroll controller.'); - } - onMouseWheel = function (e) { - return scrollCtrl.scrollBy(0, -e.wheelDeltaY, false); - }; - return scrollCtrl.element.addEventListener('wheel', onMouseWheel); - } + .directive('mouseWheelScroll', function ($timeout) { + return { + restrict: 'A', + link: function ($scope, $element, $attrs) { + var onMouseWheel, scrollCtrl; + scrollCtrl = $element.controller('$ionicScroll'); + //console.log(scrollCtrl); + if (!scrollCtrl) { + return console.error('mouseWheelScroll must be attached to a $ionicScroll controller.'); + } + onMouseWheel = function (e) { + return scrollCtrl.scrollBy(0, -e.wheelDeltaY, false); + }; + return scrollCtrl.element.addEventListener('wheel', onMouseWheel); + } + }; + }) + + // this can be used to route img-src through interceptors. Works well, but when + // nph-zms streams images it doesn't work as success is never received + // (keeps reading data). Hence not using it now + //credit: http://stackoverflow.com/questions/34958575/intercepting-img-src-via-http-interceptor-as-well-as-not-lose-the-ability-to-kee + .directive('httpSrc', [ + '$http', 'imageLoadingDataShare', 'NVRDataModel', + function ($http, imageLoadingDataShare, NVRDataModel) { + var directive = { + link: postLink, + restrict: 'A' + }; + return directive; + + function postLink(scope, element, attrs) { + //console.log ("HELLO NEW"); + var requestConfig = { + method: 'GET', + //url: attrs.httpSrc, + responseType: 'arraybuffer', + cache: 'true' }; - }) - - // this can be used to route img-src through interceptors. Works well, but when - // nph-zms streams images it doesn't work as success is never received - // (keeps reading data). Hence not using it now - //credit: http://stackoverflow.com/questions/34958575/intercepting-img-src-via-http-interceptor-as-well-as-not-lose-the-ability-to-kee - .directive('httpSrc', [ - '$http', 'imageLoadingDataShare', 'NVRDataModel', - function ($http, imageLoadingDataShare, NVRDataModel) { - var directive = { - link: postLink, - restrict: 'A' - }; - return directive; - - function postLink(scope, element, attrs) { - //console.log ("HELLO NEW"); - var requestConfig = { - method: 'GET', - //url: attrs.httpSrc, - responseType: 'arraybuffer', - cache: 'true' - }; - - function base64Img(data) { - var arr = new Uint8Array(data); - var raw = ''; - var i, j, subArray, chunk = 5000; - for (i = 0, j = arr.length; i < j; i += chunk) { - subArray = arr.subarray(i, i + chunk); - raw += String.fromCharCode.apply(null, subArray); - } - return btoa(raw); - } - attrs.$observe('httpSrc', function (newValue) { - requestConfig.url = newValue; - //console.log ("requestConfig is " + JSON.stringify(requestConfig)); - imageLoadingDataShare.set(1); - $http(requestConfig) - .success(function (data) { - //console.log ("Inside HTTP after Calling " + requestConfig.url); - //console.log ("data got " + JSON.stringify(data)); - - var b64 = base64Img(data); - attrs.$set('src', "data:image/jpeg;base64," + b64); - imageLoadingDataShare.set(0); - }); - }); - } + function base64Img(data) { + var arr = new Uint8Array(data); + var raw = ''; + var i, j, subArray, chunk = 5000; + for (i = 0, j = arr.length; i < j; i += chunk) { + subArray = arr.subarray(i, i + chunk); + raw += String.fromCharCode.apply(null, subArray); + } + return btoa(raw); } - ]) + attrs.$observe('httpSrc', function (newValue) { + requestConfig.url = newValue; + //console.log ("requestConfig is " + JSON.stringify(requestConfig)); + imageLoadingDataShare.set(1); + $http(requestConfig) + .success(function (data) { + //console.log ("Inside HTTP after Calling " + requestConfig.url); + //console.log ("data got " + JSON.stringify(data)); + + var b64 = base64Img(data); + attrs.$set('src', "data:image/jpeg;base64," + b64); + imageLoadingDataShare.set(0); + }); + }); - //------------------------------------------------------------------ - // switch between collection repeat or ng-repeat - //------------------------------------------------------------------- - .directive('repeatsmart', function ($compile, $rootScope) { - return { - restrict: 'A', - priority: 2000, - terminal: true, - link: function (scope, element) { - var repeatDirective = ($rootScope.platformOS == 'desktop') ? 'ng-repeat' : 'collection-repeat'; - //console.log("*********** REPEAT SCROLL IS " + repeatDirective); - - element.attr(repeatDirective, element.attr('repeatsmart')); - element.removeAttr('repeatsmart'); - $compile(element)(scope); - } + } + } + ]) + + //------------------------------------------------------------------ + // switch between collection repeat or ng-repeat + //------------------------------------------------------------------- + .directive('repeatsmart', function ($compile, $rootScope) { + return { + restrict: 'A', + priority: 2000, + terminal: true, + link: function (scope, element) { + var repeatDirective = ($rootScope.platformOS == 'desktop') ? 'ng-repeat' : 'collection-repeat'; + //console.log("*********** REPEAT SCROLL IS " + repeatDirective); + + element.attr(repeatDirective, element.attr('repeatsmart')); + element.removeAttr('repeatsmart'); + $compile(element)(scope); + } + }; + }) + + //------------------------------------------------------------------ + // I use this factory to share data between carousel and lazy load + // carousel will not progress autoslide till imageLoading is 0 or -1 + //------------------------------------------------------------------- + .factory('imageLoadingDataShare', function () { + var imageLoading = 0; // 0 = not loading, 1 = loading, -1 = error; + return { + 'set': function (val) { + imageLoading = val; + //console.log ("** IMAGE LOADING **"+val); + }, + 'get': function () { + + return imageLoading; + } + }; + }) + + /*.factory('qHttp', function($q, $http) { + //credit: http://stackoverflow.com/a/29719693 + var queue = $q.when(); + + return function queuedHttp(httpConf) { + var f = function(data) { + return $http(httpConf); + }; + return queue = queue.then(f, f); }; - }) - - //------------------------------------------------------------------ - // I use this factory to share data between carousel and lazy load - // carousel will not progress autoslide till imageLoading is 0 or -1 - //------------------------------------------------------------------- - .factory('imageLoadingDataShare', function () { - var imageLoading = 0; // 0 = not loading, 1 = loading, -1 = error; - return { - 'set': function (val) { - imageLoading = val; - //console.log ("** IMAGE LOADING **"+val); - }, - 'get': function () { - - return imageLoading; + })*/ + + //credit: http://stackoverflow.com/a/14468276 + .factory('qHttp', function ($q, $http) { + + var queue = []; + var execNext = function () { + var task = queue[0]; + //console.log ("qHTTP>>> Executing:"+JSON.stringify(task.c)+">>> pending:"+queue.length); + + $http(task.c).then(function (data) { + queue.shift(); + task.d.resolve(data); + if (queue.length > 0) execNext(); + }, function (err) { + queue.shift(); + task.d.reject(err); + if (queue.length > 0) execNext(); + }); + }; + return function (config) { + var d = $q.defer(); + //config.headers.push({'X-qHttp':'enabled'}); + queue.push({ + c: config, + d: d + }); + if (queue.length === 1) { + execNext(); + } + //else + //console.log ("qHTTP>>> Queuing:"+JSON.stringify(config)); + return d.promise; + }; + }) + + //credit: https://github.com/driftyco/ionic/issues/3131 + .factory('SecuredPopups', [ + '$ionicPopup', + '$q', + function ($ionicPopup, $q) { + + var firstDeferred = $q.defer(); + firstDeferred.resolve(); + + var lastPopupPromise = firstDeferred.promise; + + // Change this var to true if you want that popups will automaticly close before opening another + var closeAndOpen = false; + + return { + 'show': function (method, object) { + var deferred = $q.defer(); + var closeMethod = null; + deferred.promise.isOpen = false; + deferred.promise.close = function () { + if (deferred.promise.isOpen && angular.isFunction(closeMethod)) { + closeMethod(); } - }; - }) - - /*.factory('qHttp', function($q, $http) { - //credit: http://stackoverflow.com/a/29719693 - var queue = $q.when(); - - return function queuedHttp(httpConf) { - var f = function(data) { - return $http(httpConf); - }; - return queue = queue.then(f, f); }; - })*/ - //credit: http://stackoverflow.com/a/14468276 - .factory('qHttp', function ($q, $http) { + if (closeAndOpen && lastPopupPromise.isOpen) { + lastPopupPromise.close(); + } - var queue = []; - var execNext = function () { - var task = queue[0]; - //console.log ("qHTTP>>> Executing:"+JSON.stringify(task.c)+">>> pending:"+queue.length); + lastPopupPromise.then(function () { + deferred.promise.isOpen = true; + var popupInstance = $ionicPopup[method](object); - $http(task.c).then(function (data) { - queue.shift(); - task.d.resolve(data); - if (queue.length > 0) execNext(); - }, function (err) { - queue.shift(); - task.d.reject(err); - if (queue.length > 0) execNext(); + closeMethod = popupInstance.close; + popupInstance.then(function (res) { + deferred.promise.isOpen = false; + deferred.resolve(res); }); - }; - return function (config) { - var d = $q.defer(); - //config.headers.push({'X-qHttp':'enabled'}); - queue.push({ - c: config, - d: d - }); - if (queue.length === 1) { - execNext(); - } - //else - //console.log ("qHTTP>>> Queuing:"+JSON.stringify(config)); - return d.promise; - }; - }) - - //credit: https://github.com/driftyco/ionic/issues/3131 - .factory('SecuredPopups', [ - '$ionicPopup', - '$q', - function ($ionicPopup, $q) { - - var firstDeferred = $q.defer(); - firstDeferred.resolve(); - - var lastPopupPromise = firstDeferred.promise; - - // Change this var to true if you want that popups will automaticly close before opening another - var closeAndOpen = false; - - return { - 'show': function (method, object) { - var deferred = $q.defer(); - var closeMethod = null; - deferred.promise.isOpen = false; - deferred.promise.close = function () { - if (deferred.promise.isOpen && angular.isFunction(closeMethod)) { - closeMethod(); - } - }; - - if (closeAndOpen && lastPopupPromise.isOpen) { - lastPopupPromise.close(); - } - - lastPopupPromise.then(function () { - deferred.promise.isOpen = true; - var popupInstance = $ionicPopup[method](object); - - closeMethod = popupInstance.close; - popupInstance.then(function (res) { - deferred.promise.isOpen = false; - deferred.resolve(res); - }); - }); + }); - lastPopupPromise = deferred.promise; + lastPopupPromise = deferred.promise; - return deferred.promise; - } - }; + return deferred.promise; } - ]) - - //------------------------------------------------------------------ - // this directive will be called any time an image completes loading - // via img tags where this directive is added (I am using this in - // events and monitor view to show a loader while the image is - // downloading from ZM - //------------------------------------------------------------------ - - .directive('imageonload', function () { - return { - restrict: 'A', - link: function (scope, element, attrs) { - element.bind('load', function () { - //call the function that was passed - scope.$apply(attrs.imageonload); - }); - } - - }; - }) - - //-------------------------------------------------------------------------------------------- - // This directive is adapted from https://github.com/paveisistemas/ionic-image-lazy-load - // I've removed lazyLoad and only made it show a spinner when an image is loading - //-------------------------------------------------------------------------------------------- - .directive('imageSpinnerSrc', ['$document', '$compile', 'imageLoadingDataShare', '$timeout', - function ($document, $compile, imageLoadingDataShare, $timeout) { - return { - restrict: 'A', - scope: { - imageSpinnerBackgroundImage: "@imageSpinnerBackgroundImage" - }, - link: function ($scope, $element, $attributes) { - - /*if ($attributes.imageSpinnerLoader) { - var loader = $compile('<div class="image-loader-container"><ion-spinner class="image-loader" icon="' + $attributes.imageSpinnerLoader + '"></ion-spinner></div>')($scope); - $element.after(loader); - }*/ - - if ($attributes.imageSpinnerLoader) { - var loader = $compile('<div class="image-loader-container"><ion-spinner class="image-loader" icon="' + 'bubbles' + '"></ion-spinner></div>')($scope); - $element.after(loader); - } - imageLoadingDataShare.set(1); - loadImage(); - - $attributes.$observe('imageSpinnerSrc', function (value) { - //console.log ("DIRECTIVE SOURCE CHANGED"); - imageLoadingDataShare.set(1); - loadImage(); - //deregistration(); - - }); - - // show an image-missing image - $element.bind('error', function () { - // console.log ("DIRECTIVE: IMAGE ERROR"); - loader.remove(); - - var url = 'img/novideo.png'; - $element.prop('src', url); - imageLoadingDataShare.set(0); - }); + }; + } + ]) + + //------------------------------------------------------------------ + // this directive will be called any time an image completes loading + // via img tags where this directive is added (I am using this in + // events and monitor view to show a loader while the image is + // downloading from ZM + //------------------------------------------------------------------ + + .directive('imageonload', function () { + return { + restrict: 'A', + link: function (scope, element, attrs) { + element.bind('load', function () { + //call the function that was passed + scope.$apply(attrs.imageonload); + }); + } + + }; + }) + + //-------------------------------------------------------------------------------------------- + // This directive is adapted from https://github.com/paveisistemas/ionic-image-lazy-load + // I've removed lazyLoad and only made it show a spinner when an image is loading + //-------------------------------------------------------------------------------------------- + .directive('imageSpinnerSrc', ['$document', '$compile', 'imageLoadingDataShare', '$timeout', + function ($document, $compile, imageLoadingDataShare, $timeout) { + return { + restrict: 'A', + scope: { + imageSpinnerBackgroundImage: "@imageSpinnerBackgroundImage" + }, + link: function ($scope, $element, $attributes) { + + /*if ($attributes.imageSpinnerLoader) { + var loader = $compile('<div class="image-loader-container"><ion-spinner class="image-loader" icon="' + $attributes.imageSpinnerLoader + '"></ion-spinner></div>')($scope); + $element.after(loader); + }*/ + + if ($attributes.imageSpinnerLoader) { + var loader = $compile('<div class="image-loader-container"><ion-spinner class="image-loader" icon="' + 'bubbles' + '"></ion-spinner></div>')($scope); + $element.after(loader); + } + imageLoadingDataShare.set(1); + loadImage(); + + $attributes.$observe('imageSpinnerSrc', function (value) { + //console.log ("DIRECTIVE SOURCE CHANGED"); + imageLoadingDataShare.set(1); + loadImage(); + //deregistration(); + + }); + + // show an image-missing image + $element.bind('error', function () { + // console.log ("DIRECTIVE: IMAGE ERROR"); + loader.remove(); + + var url = 'img/novideo.png'; + $element.prop('src', url); + imageLoadingDataShare.set(0); + }); + + function waitForFrame1() { + ionic.DomUtil.requestAnimationFrame( + function () { + imageLoadingDataShare.set(0); + //console.log ("IMAGE LOADED"); + }); + + } + + function loadImage() { + $element.bind("load", function (e) { + if ($attributes.imageSpinnerLoader) { + //console.log ("DIRECTIVE: IMAGE LOADED"); + loader.remove(); + //imageLoadingDataShare.set(0); + //console.log ("rendered"); + + // lets wait for 2 frames for animation + // to render - hoping this will improve tear + // of images + ionic.DomUtil.requestAnimationFrame( + function () { + waitForFrame1(); + }); + + } + }); - function waitForFrame1() { - ionic.DomUtil.requestAnimationFrame( - function () { - imageLoadingDataShare.set(0); - //console.log ("IMAGE LOADED"); - }); + if ($scope.imageSpinnerBackgroundImage == "true") { + var bgImg = new Image(); + bgImg.onload = function () { + if ($attributes.imageSpinnerLoader) { + loader.remove(); + } + // set style attribute on element (it will load image) + if (imageLoadingDataShare.get() != 1) - } + $element[0].style.backgroundImage = 'url(' + $attributes.imageSpinnerSrc + ')'; - function loadImage() { - $element.bind("load", function (e) { - if ($attributes.imageSpinnerLoader) { - //console.log ("DIRECTIVE: IMAGE LOADED"); - loader.remove(); - //imageLoadingDataShare.set(0); - //console.log ("rendered"); + //$element[0].style.backgroundImage = 'url(' + 'img/novideo.png'+ ')'; - // lets wait for 2 frames for animation - // to render - hoping this will improve tear - // of images - ionic.DomUtil.requestAnimationFrame( - function () { - waitForFrame1(); - }); + }; - } - }); + bgImg.src = $attributes.imageSpinnerSrc; - if ($scope.imageSpinnerBackgroundImage == "true") { - var bgImg = new Image(); - bgImg.onload = function () { - if ($attributes.imageSpinnerLoader) { - loader.remove(); - } - // set style attribute on element (it will load image) - if (imageLoadingDataShare.get() != 1) + } else { + $element[0].src = $attributes.imageSpinnerSrc; // set src attribute on element (it will load image) - $element[0].style.backgroundImage = 'url(' + $attributes.imageSpinnerSrc + ')'; + } + } - //$element[0].style.backgroundImage = 'url(' + 'img/novideo.png'+ ')'; + function isInView() { + return true; + } - }; + $element.on('$destroy', function () { - bgImg.src = $attributes.imageSpinnerSrc; + }); - } else { - $element[0].src = $attributes.imageSpinnerSrc; // set src attribute on element (it will load image) + } + }; + } + ]) + + //------------------------------------------------------------------ + // In Android, HTTP requests seem to get stuck once in a while + // It may be a crosswalk issue. + // To tackle this gracefully, I've set up a global interceptor + // If the HTTP request does not complete in 15 seconds, it cancels + // That way the user can try again, and won't get stuck + // Also remember you need to add it to .config + //------------------------------------------------------------------ + .factory('timeoutHttpIntercept', ['$rootScope', '$q', 'zm', '$injector', function ($rootScope, $q, zm, $injector) { + $rootScope.zmCookie = ""; + //console.log ("HHHHHHHHHHHHHH**************************"); + + return { + + 'request': function (config) { + if (!config) return config; + if (!config.url) return config; + + // NOTE ON TIMEOUTS: As of Oct 10 2016, it seems + // the Http queue often gets messed up when there is a timeout + // and the # of requests are plentiful. I'm going to disable it and see + + // console.log (">>>>"+config.url); + // handle basic auth properly + if (config.url.indexOf("@") > -1) { + //console.log ("HTTP basic auth INTERCEPTOR URL IS " + config.url); + var components = URI.parse(config.url); + // console.log ("Parsed data is " + JSON.stringify(components)); + var credentials = btoa(components.userinfo); + //var authorization = {'Authorization': 'Basic ' + credentials}; + //config.headers.Authorization = 'Basic ' + credentials; + + // console.log ("Full headers: " + JSON.stringify(config.headers)); - } - } + } - function isInView() { - return true; - } + //console.log (">>>>>>>>>>>>> INTERCEPT OBJECT " + JSON.stringify(config)); - $element.on('$destroy', function () { + if ($rootScope.zmCookie) { + config.headers.Cookie = "ZMSESSID=" + $rootScope.zmCookie; + } else { + // console.log ("No cookie present in " + config.url); + } - }); + if ($rootScope.apiAuth) { + console.log("********** API AUTH"); + if (config.url.indexOf("/api/") > -1) { + config.url = config.url + "&auth=" + $rootScope.authSession; + console.log("********** API AUTH muggled to:" + config.url); - } - }; + } } - ]) - - //------------------------------------------------------------------ - // In Android, HTTP requests seem to get stuck once in a while - // It may be a crosswalk issue. - // To tackle this gracefully, I've set up a global interceptor - // If the HTTP request does not complete in 15 seconds, it cancels - // That way the user can try again, and won't get stuck - // Also remember you need to add it to .config - //------------------------------------------------------------------ - .factory('timeoutHttpIntercept', ['$rootScope', '$q', 'zm', '$injector', function ($rootScope, $q, zm, $injector) { - $rootScope.zmCookie = ""; - //console.log ("HHHHHHHHHHHHHH**************************"); - return { + if ((config.url.indexOf("/api/states/change/") > -1) || + (config.url.indexOf("getDiskPercent.json") > -1) || + (config.url.indexOf("daemonCheck.json") > -1) || + (config.url.indexOf("getLoad.json") > -1)) - 'request': function (config) { - if (!config) return config; - if (!config.url) return config; + { - // NOTE ON TIMEOUTS: As of Oct 10 2016, it seems - // the Http queue often gets messed up when there is a timeout - // and the # of requests are plentiful. I'm going to disable it and see + // these can take time, so lets bump up timeout + config.timeout = zm.largeHttpTimeout; - // console.log (">>>>"+config.url); - // handle basic auth properly - if (config.url.indexOf("@") > -1) { - //console.log ("HTTP basic auth INTERCEPTOR URL IS " + config.url); - var components = URI.parse(config.url); - // console.log ("Parsed data is " + JSON.stringify(components)); - var credentials = btoa(components.userinfo); - //var authorization = {'Authorization': 'Basic ' + credentials}; - //config.headers.Authorization = 'Basic ' + credentials; + } else if ((config.url.indexOf("view=view_video") > -1) || + config.url.indexOf(".mp4") > -1) { + // console.log(">>> skipping timers for MP4"); + // put a timeout for zms urls + } else if (config.url.indexOf("zms?") > -1) { + // config.timeout = zm.httpTimeout; - // console.log ("Full headers: " + JSON.stringify(config.headers)); + } - } + return config; + }, - //console.log (">>>>>>>>>>>>> INTERCEPT OBJECT " + JSON.stringify(config)); + 'response': function (response) { + var cookies = response.headers("Set-Cookie"); + if (cookies != null) { - if ($rootScope.zmCookie) { - config.headers.Cookie = "ZMSESSID=" + $rootScope.zmCookie; - } else { - // console.log ("No cookie present in " + config.url); - } + var zmSess = cookies.match("ZMSESSID=(.*?);"); - if ($rootScope.apiAuth) - { - console.log ("********** API AUTH"); - if (config.url.indexOf("/api/") > -1 ) - { - config.url = config.url + "&auth="+$rootScope.authSession; - console.log ("********** API AUTH muggled to:"+config.url); - - } - } + if (zmSess) { + if (zmSess[1]) { - if ((config.url.indexOf("/api/states/change/") > -1) || - (config.url.indexOf("getDiskPercent.json") > -1) || - (config.url.indexOf("daemonCheck.json") > -1) || - (config.url.indexOf("getLoad.json") > -1)) - - { + // console.log ("***** SETTING COOKIE TO " + zmCookie); + $rootScope.zmCookie = zmSess[1]; + } + } + } - // these can take time, so lets bump up timeout - config.timeout = zm.largeHttpTimeout; + //console.log ("HTTP response"); + return response; + } - } else if ((config.url.indexOf("view=view_video") > -1) || - config.url.indexOf(".mp4") > -1) { - // console.log(">>> skipping timers for MP4"); - // put a timeout for zms urls - } else if (config.url.indexOf("zms?") > -1) { - // config.timeout = zm.httpTimeout; + }; + }]) - } + //----------------------------------------------------------------- + // This service automatically checks for new versions every 24 hrs + //------------------------------------------------------------------ + .factory('zmCheckUpdates', function ($interval, $http, zm, $timeout, $localstorage, NVRDataModel, $rootScope, $translate) { + var zmUpdateHandle; + var zmUpdateVersion = ""; - return config; - }, + function start() { + checkUpdate(); + $interval.cancel(zmUpdateHandle); + zmUpdateHandle = $interval(function () { + checkUpdate(); - 'response': function (response) { - var cookies = response.headers("Set-Cookie"); - if (cookies != null) { + }, zm.updateCheckInterval); - var zmSess = cookies.match("ZMSESSID=(.*?);"); + function checkUpdate() { + var lastdateString = NVRDataModel.getLastUpdateCheck(); + var lastdate; + if (!lastdateString) { - if (zmSess) { - if (zmSess[1]) { + lastdate = moment().subtract(2, 'day'); - // console.log ("***** SETTING COOKIE TO " + zmCookie); - $rootScope.zmCookie = zmSess[1]; - } - } - } + } else { + lastdate = moment(lastdateString); + } + var timdiff = moment().diff(lastdate, 'hours'); + if (timdiff < 24) { + NVRDataModel.log("Checked for update " + timdiff + " hours ago. Not checking again"); - //console.log ("HTTP response"); - return response; + return; + } + NVRDataModel.log("Checking for new version updates..."); + + $http.get(zm.latestRelease) + .then(function (success) { + + NVRDataModel.setLastUpdateCheck(moment().toISOString()); + // $localstorage.set("lastUpdateCheck", moment().toISOString()); + //console.log ("FULL STRING " + success.data.tag_name); + var res = success.data.tag_name.match("v(.*)"); + zmUpdateVersion = res[1]; + var currentVersion = NVRDataModel.getAppVersion(); + if ($rootScope.platformOS == "desktop") { + zmUpdateVersion = zmUpdateVersion + "D"; } + //if (NVRDataModel.getAppVersion() != zmUpdateVersion) { + if (NVRDataModel.versionCompare(NVRDataModel.getAppVersion(), zmUpdateVersion) == -1) { + $rootScope.newVersionAvailable = "v" + zmUpdateVersion + " available"; + } else { + $rootScope.newVersionAvailable = ""; + } + NVRDataModel.debug("current version: " + currentVersion + " & available version " + zmUpdateVersion); + //console.log ("Version compare returned: " + NVRDataModel.versionCompare(currentVersion, //zmUpdateVersion)); + // console.log ("Version compare returned: " + NVRDataModel.versionCompare(zmUpdateVersion, currentVersion)); + //console.log ("UPDATE " + zmVersion); + }); + + NVRDataModel.log("Checking for news updates"); + $http.get(zm.blogUrl, { + transformResponse: function (d, h) { + var trunc = "])}while(1);</x>"; + d = d.substr(trunc.length); + return d; + } + }) - }; - }]) - - //----------------------------------------------------------------- - // This service automatically checks for new versions every 24 hrs - //------------------------------------------------------------------ - .factory('zmCheckUpdates', function ($interval, $http, zm, $timeout, $localstorage, NVRDataModel, $rootScope, $translate) { - var zmUpdateHandle; - var zmUpdateVersion = ""; - - function start() { - checkUpdate(); - $interval.cancel(zmUpdateHandle); - zmUpdateHandle = $interval(function () { - checkUpdate(); - - }, zm.updateCheckInterval); - - function checkUpdate() { - var lastdateString = NVRDataModel.getLastUpdateCheck(); - var lastdate; - if (!lastdateString) { - - lastdate = moment().subtract(2, 'day'); + .success(function (datastr) { - } else { - lastdate = moment(lastdateString); - } - var timdiff = moment().diff(lastdate, 'hours'); - if (timdiff < 24) { - NVRDataModel.log("Checked for update " + timdiff + " hours ago. Not checking again"); + var data = JSON.parse(datastr); + $rootScope.newBlogPost = ""; + if (data.payload.posts.length <= 0) { + $rootScope.newBlogPost = ""; + return; + } - return; - } - NVRDataModel.log("Checking for new version updates..."); + var lastDate = NVRDataModel.getLatestBlogPostChecked(); + //console.log ("************ BLOG LAST DATE " + lastDate); + if (!lastDate) { - $http.get(zm.latestRelease) - .then(function (success) { + $rootScope.newBlogPost = "(" + $translate.instant('kNewPost') + ")"; + NVRDataModel.setLatestBlogPostChecked(moment().format("YYYY-MM-DD HH:mm:ss")); + return; - NVRDataModel.setLastUpdateCheck(moment().toISOString()); - // $localstorage.set("lastUpdateCheck", moment().toISOString()); - //console.log ("FULL STRING " + success.data.tag_name); - var res = success.data.tag_name.match("v(.*)"); - zmUpdateVersion = res[1]; - var currentVersion = NVRDataModel.getAppVersion(); - if ($rootScope.platformOS == "desktop") { - zmUpdateVersion = zmUpdateVersion + "D"; - } - //if (NVRDataModel.getAppVersion() != zmUpdateVersion) { - if (NVRDataModel.versionCompare(NVRDataModel.getAppVersion(), zmUpdateVersion) == -1) { - $rootScope.newVersionAvailable = "v" + zmUpdateVersion + " available"; - } else { - $rootScope.newVersionAvailable = ""; - } - NVRDataModel.debug("current version: " + currentVersion + " & available version " + zmUpdateVersion); - //console.log ("Version compare returned: " + NVRDataModel.versionCompare(currentVersion, //zmUpdateVersion)); - // console.log ("Version compare returned: " + NVRDataModel.versionCompare(zmUpdateVersion, currentVersion)); - //console.log ("UPDATE " + zmVersion); - }); + } + var mLastDate = moment(lastDate); + var mItemDate = moment(data.payload.posts[0].createdAt); - NVRDataModel.log("Checking for news updates"); - $http.get(zm.blogUrl, { - transformResponse: function (d, h) { - var trunc = "])}while(1);</x>"; - d = d.substr(trunc.length); - return d; - } - }) + if (mItemDate.diff(mLastDate, 'seconds') > 0) { + /*console.log ("DIFF IS "+mItemDate.diff(mLastDate, 'seconds')); + console.log ("DIFF mLastDate="+mLastDate); + console.log ("DIFF mItemDate="+mItemDate); + console.log ("FORMAT DIFF mLastDate="+mLastDate.format("YYYY-MM-DD HH:mm:ss") ); + console.log ("FORMAT DIFF mItemDate="+mItemDate.format("YYYY-MM-DD HH:mm:ss") );*/ - .success(function (datastr) { + NVRDataModel.debug("New post dated " + mItemDate.format("YYYY-MM-DD HH:mm:ss") + " found, last date checked was " + mLastDate.format("YYYY-MM-DD HH:mm:ss")); - var data = JSON.parse(datastr); - $rootScope.newBlogPost = ""; - if (data.payload.posts.length <= 0) { - $rootScope.newBlogPost = ""; - return; - } + $rootScope.newBlogPost = "(" + $translate.instant('kNewPost') + ")"; + NVRDataModel.setLatestBlogPostChecked(mItemDate.format("YYYY-MM-DD HH:mm:ss")); - var lastDate = NVRDataModel.getLatestBlogPostChecked(); - //console.log ("************ BLOG LAST DATE " + lastDate); - if (!lastDate) { - $rootScope.newBlogPost = "(" + $translate.instant('kNewPost') + ")"; - NVRDataModel.setLatestBlogPostChecked(moment().format("YYYY-MM-DD HH:mm:ss")); - return; - } - var mLastDate = moment(lastDate); - var mItemDate = moment(data.payload.posts[0].createdAt); + } else { + NVRDataModel.debug("Latest post dated " + mItemDate.format("YYYY-MM-DD HH:mm:ss") + " but you read " + lastDate); + } - if (mItemDate.diff(mLastDate, 'seconds') > 0) { - /*console.log ("DIFF IS "+mItemDate.diff(mLastDate, 'seconds')); - console.log ("DIFF mLastDate="+mLastDate); - console.log ("DIFF mItemDate="+mItemDate); - console.log ("FORMAT DIFF mLastDate="+mLastDate.format("YYYY-MM-DD HH:mm:ss") ); - console.log ("FORMAT DIFF mItemDate="+mItemDate.format("YYYY-MM-DD HH:mm:ss") );*/ + }); - NVRDataModel.debug("New post dated " + mItemDate.format("YYYY-MM-DD HH:mm:ss") + " found, last date checked was " + mLastDate.format("YYYY-MM-DD HH:mm:ss")); + } + } - $rootScope.newBlogPost = "(" + $translate.instant('kNewPost') + ")"; - NVRDataModel.setLatestBlogPostChecked(mItemDate.format("YYYY-MM-DD HH:mm:ss")); + function getLatestUpdateVersion() { + return (zmUpdateVersion == "") ? "(unknown)" : zmUpdateVersion; + } + return { + start: start, + getLatestUpdateVersion: getLatestUpdateVersion + //stop: stop, + }; - } else { - NVRDataModel.debug("Latest post dated " + mItemDate.format("YYYY-MM-DD HH:mm:ss") + " but you read " + lastDate); - } + }) - }); + //----------------------------------------------------------------- + // This service automatically logs into ZM at periodic intervals + //------------------------------------------------------------------ - } - } + .factory('zmAutoLogin', function ($interval, NVRDataModel, $http, zm, $browser, $timeout, $q, $rootScope, $ionicLoading, $ionicPopup, $state, $ionicContentBanner, EventServer, $ionicHistory, $translate) { + var zmAutoLoginHandle; - function getLatestUpdateVersion() { - return (zmUpdateVersion == "") ? "(unknown)" : zmUpdateVersion; - } + //------------------------------------------------------------------ + // doLogin() emits this when there is an auth error in the portal + //------------------------------------------------------------------ - return { - start: start, - getLatestUpdateVersion: getLatestUpdateVersion - //stop: stop, + $rootScope.$on("auth-error", function () { - }; + NVRDataModel.debug("zmAutoLogin: Inside auth-error emit"); + NVRDataModel.displayBanner('error', ['ZoneMinder authentication failed', 'Please check settings']); - }) + }); - //----------------------------------------------------------------- - // This service automatically logs into ZM at periodic intervals + //------------------------------------------------------------------ + // broadcasted after : + // a) device is ready + // b) language loaded + // c) localforage data loaded //------------------------------------------------------------------ - .factory('zmAutoLogin', function ($interval, NVRDataModel, $http, zm, $browser, $timeout, $q, $rootScope, $ionicLoading, $ionicPopup, $state, $ionicContentBanner, EventServer, $ionicHistory, $translate) { - var zmAutoLoginHandle; + $rootScope.$on("init-complete", function () { + NVRDataModel.log(">>>>>>>>>>>>>>> All init over, going to portal login"); + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); + $state.go("app.zm-portal-login"); + return; + }); - //------------------------------------------------------------------ - // doLogin() emits this when there is an auth error in the portal - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // doLogin() emits this when our auth credentials work + //------------------------------------------------------------------ - $rootScope.$on("auth-error", function () { + $rootScope.$on("auth-success", function () { + var contentBannerInstance = $ionicContentBanner.show({ + text: ['ZoneMinder' + $translate.instant('kAuthSuccess')], + interval: 2000, + type: 'info', + transition: 'vertical' + }); - NVRDataModel.debug("zmAutoLogin: Inside auth-error emit"); - NVRDataModel.displayBanner('error', ['ZoneMinder authentication failed', 'Please check settings']); + $timeout(function () { + contentBannerInstance(); + }, 2000); + NVRDataModel.debug("auth-success emit:Successful"); + }); - }); + $rootScope.getProfileName = function () { + var ld = NVRDataModel.getLogin(); + return (ld.serverName || '(none)'); + }; - //------------------------------------------------------------------ - // broadcasted after : - // a) device is ready - // b) language loaded - // c) localforage data loaded - //------------------------------------------------------------------ - - $rootScope.$on("init-complete", function () { - NVRDataModel.log(">>>>>>>>>>>>>>> All init over, going to portal login"); - $ionicHistory.nextViewOptions({ - disableAnimate: true - }); - $state.go("zm-portal-login"); - return; - }); + $rootScope.getLocalTimeZone = function () { + return moment.tz.guess(); + }; - //------------------------------------------------------------------ - // doLogin() emits this when our auth credentials work - //------------------------------------------------------------------ + $rootScope.getServerTimeZoneNow = function () { - $rootScope.$on("auth-success", function () { - var contentBannerInstance = $ionicContentBanner.show({ - text: ['ZoneMinder' + $translate.instant('kAuthSuccess')], - interval: 2000, - type: 'info', - transition: 'vertical' - }); + return NVRDataModel.getTimeZoneNow(); - $timeout(function () { - contentBannerInstance(); - }, 2000); - NVRDataModel.debug("auth-success emit:Successful"); - }); + }; - $rootScope.getProfileName = function () { - var ld = NVRDataModel.getLogin(); - return (ld.serverName || '(none)'); - }; + $rootScope.isTzSupported = function () { + return NVRDataModel.isTzSupported(); + }; - $rootScope.getLocalTimeZone = function () { - return moment.tz.guess(); - }; - - $rootScope.getServerTimeZoneNow = function () { - - return NVRDataModel.getTimeZoneNow(); + //------------------------------------------------------------------ + // doLogin() is the function that tries to login to ZM + // it also makes sure we are not back to the same page + // which actually means auth failed, but ZM treats it as a success + //------------------------------------------------------------------ - }; + function doLogin(str) { - $rootScope.isTzSupported = function () { - return NVRDataModel.isTzSupported(); - }; - //------------------------------------------------------------------ - // doLogin() is the function that tries to login to ZM - // it also makes sure we are not back to the same page - // which actually means auth failed, but ZM treats it as a success - //------------------------------------------------------------------ + var d = $q.defer(); + var ld = NVRDataModel.getLogin(); - function doLogin(str) { + /*$rootScope.authSession = 'Test'; + $rootScope.apiAuth = true; + d.resolve ("Login Success"); + $rootScope.loggedIntoZm = 1; + $rootScope.$emit('auth-success', 'hash API mode'); - var d = $q.defer(); - var ld = NVRDataModel.getLogin(); + console.log(">>>>>>>>>>> DO LOGIN"); + if (1) {return (d.promise);}*/ - /*$rootScope.authSession = 'Test'; - $rootScope.apiAuth = true; - d.resolve ("Login Success"); - $rootScope.loggedIntoZm = 1; - $rootScope.$emit('auth-success', 'hash API mode'); - - console.log(">>>>>>>>>>> DO LOGIN"); - if (1) {return (d.promise);}*/ + NVRDataModel.processFastLogin() + // coming here means login not needed, old login is valid + .then(function (success) { + d.resolve("Login Success due to fast login"); + $rootScope.$emit('auth-success', "fast login mode"); + return d.promise; + }, - - NVRDataModel.processFastLogin() - // coming here means login not needed, old login is valid - .then(function (success) { - d.resolve("Login Success due to fast login"); - $rootScope.$emit('auth-success', "fast login mode"); - return d.promise; - }, + // coming here means login is needed + function (error) { + console.log(">>>>>>>>>>>> FAST FAILED - THIS IS OK"); - // coming here means login is needed - function (error) { - console.log(">>>>>>>>>>>> FAST FAILED - THIS IS OK"); + var statename = $ionicHistory.currentStateName(); - var statename = $ionicHistory.currentStateName(); + if (statename == "montage-history") { + NVRDataModel.log("Skipping login process as we are in montage history. Re-logging will mess up the stream"); + d.resolve("success"); + return d.promise; - if (statename == "montage-history") { - NVRDataModel.log("Skipping login process as we are in montage history. Re-logging will mess up the stream"); - d.resolve("success"); - return d.promise; + } - } + if ($rootScope.isDownloading) { + NVRDataModel.log("Skipping login process as we are downloading..."); + d.resolve("success"); + return d.promise; + } - if ($rootScope.isDownloading) { - NVRDataModel.log("Skipping login process as we are downloading..."); - d.resolve("success"); - return d.promise; - } + NVRDataModel.debug("Resetting zmCookie..."); + $rootScope.zmCookie = ''; + // first try to login, if it works, good + // else try to do reachability - NVRDataModel.debug("Resetting zmCookie..."); - $rootScope.zmCookie = ''; - // first try to login, if it works, good - // else try to do reachability + console.log(">>>>>>>>>>>> CALLING DO LOGIN"); + proceedWithLogin() + .then(function (success) { - console.log(">>>>>>>>>>>> CALLING DO LOGIN"); + NVRDataModel.debug("Storing login time as " + moment().toString()); + localforage.setItem("lastLogin", moment().toString()); + d.resolve(success); + return d.promise; + }, + function (error) + // login to main failed, so try others + { + console.log(">>>>>>>>>>>> Failed first login, trying reachability"); + NVRDataModel.getReachableConfig(true) + .then(function (data) { proceedWithLogin() - .then(function (success) { - - NVRDataModel.debug("Storing login time as " + moment().toString()); - localforage.setItem("lastLogin", moment().toString()); - d.resolve(success); - return d.promise; - }, - function (error) - // login to main failed, so try others - { - console.log(">>>>>>>>>>>> Failed first login, trying reachability"); - NVRDataModel.getReachableConfig(true) - .then(function (data) { - proceedWithLogin() - .then(function (success) { - d.resolve(success); - return d.promise; - }, - function (error) { - d.reject(error); - return d.promise; - }); - - }, - function (error) { - d.reject(error); - return d.promise; - }); - - }); + .then(function (success) { + d.resolve(success); + return d.promise; + }, + function (error) { + d.reject(error); + return d.promise; + }); + }, + function (error) { + d.reject(error); return d.promise; + }); - function proceedWithLogin() { - // recompute rand anyway so even if you don't have auth - // your stream should not get frozen - $rootScope.rand = Math.floor((Math.random() * 100000) + 1); - $rootScope.modalRand = Math.floor((Math.random() * 100000) + 1); - - // console.log ("***** STATENAME IS " + statename); - - var d = $q.defer(); - var ld = NVRDataModel.getLogin(); - NVRDataModel.log("zmAutologin called"); + }); + return d.promise; - // This is a good time to check if auth is used :-p - if (!ld.isUseAuth) { - NVRDataModel.log("Auth is disabled!"); - d.resolve("Login Success"); + function proceedWithLogin() { + // recompute rand anyway so even if you don't have auth + // your stream should not get frozen + $rootScope.rand = Math.floor((Math.random() * 100000) + 1); + $rootScope.modalRand = Math.floor((Math.random() * 100000) + 1); - $rootScope.$emit('auth-success', 'no auth'); - return (d.promise); + // console.log ("***** STATENAME IS " + statename); - } + var d = $q.defer(); + var ld = NVRDataModel.getLogin(); + NVRDataModel.log("zmAutologin called"); - if (str) { - $ionicLoading.show({ - template: str, - noBackdrop: true, - duration: zm.httpTimeout - }); - } - - + // This is a good time to check if auth is used :-p + if (!ld.isUseAuth) { + NVRDataModel.log("Auth is disabled!"); + d.resolve("Login Success"); - + $rootScope.$emit('auth-success', 'no auth'); + return (d.promise); - console.log(">>>>>>>>>>>>>> ISRECAPTCHA"); + } - NVRDataModel.isReCaptcha() - .then(function (result) { - if (result == true) { - $ionicLoading.hide(); - NVRDataModel.displayBanner('error', ['reCaptcha must be disabled', ], "", 8000); - var alertPopup = $ionicPopup.alert({ - title: 'reCaptcha enabled', - template: $translate.instant('kRecaptcha'), - okText: $translate.instant('kButtonOk'), - cancelText: $translate.instant('kButtonCancel'), - }); + if (str) { + $ionicLoading.show({ + template: str, + noBackdrop: true, + duration: zm.httpTimeout + }); + } - // close it after 5 seconds - $timeout(function () { - alertPopup.close(); - }, 5000); - d.reject("Error-disable recaptcha"); - return (d.promise); - } - }); - var loginData = NVRDataModel.getLogin(); - console.log(">>>>>>>>>>>>>> PARALLEL POST WITH RECAPTCHA TO " + loginData.url); - /* console.log ("-----------------------SECRET IS "+zm.hashSecret); - $http.get (ld.apiurl+'/host/remoteIp.json') - .then (function (data) { - $ionicLoading.hide(); - var ip = (data.data.auth_hash_ip) ? data.data.remote_ip: ""; - var composite = zm.hashSecret + ld.username + ld.password + ip + data.data.time_frag; - var hash = CryptoJS.MD5(composite); - console.log ("MD5 HASH IS "+hash); - $rootScope.authSession = hash; - d.resolve ("Login Success"); - $rootScope.loggedIntoZm = 1; - $rootScope.$emit('auth-success', data); + console.log(">>>>>>>>>>>>>> ISRECAPTCHA"); + NVRDataModel.isReCaptcha() + .then(function (result) { + if (result == true) { + $ionicLoading.hide(); + NVRDataModel.displayBanner('error', ['reCaptcha must be disabled', ], "", 8000); + var alertPopup = $ionicPopup.alert({ + title: 'reCaptcha enabled', + template: $translate.instant('kRecaptcha'), + okText: $translate.instant('kButtonOk'), + cancelText: $translate.instant('kButtonCancel'), + }); - //ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5] - //$rootScope.authSession - // data.data.remote_ip - // data.data.is_auth + // close it after 5 seconds + $timeout(function () { - console.log (JSON.stringify(data)); - }, - function (error) { - $ionicLoading.hide(); - console.log (JSON.stringify(error)); - $rootScope.authSession = ""; - d.reject ("Login Error"); - $rootScope.loggedIntoZm = 1; - $rootScope.$emit('auth-error', "incorrect credentials"); - } - - ); - - return (d.promise); - - console.log ("*****************NEVER HERE***********"); - */ - var hDelay = loginData.enableSlowLoading ? zm.largeHttpTimeout : zm.httpTimeout; - //NVRDataModel.debug ("*** AUTH LOGIN URL IS " + loginData.url); - $http({ - - method: 'POST', - timeout: hDelay, - //withCredentials: true, - url: loginData.url + '/index.php', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'application/json', - }, - transformRequest: function (obj) { - var str = []; - for (var p in obj) - str.push(encodeURIComponent(p) + "=" + - encodeURIComponent(obj[p])); - var params = str.join("&"); - return params; - }, - - data: { - username: loginData.username, - password: loginData.password, - action: "login", - view: "console" - } - }) - .success(function (data, status, headers) { - console.log(">>>>>>>>>>>>>> PARALLEL POST SUCCESS"); - $ionicLoading.hide(); - - // Coming here does not mean success - // it could also be a bad login, but - // ZM returns you to login.php and returns 200 OK - // so we will check if the data has - // <title>ZM - Login</title> -- it it does then its the login page - - if (data.indexOf(zm.loginScreenString) == -1) { - //eventServer.start(); - $rootScope.loggedIntoZm = 1; - - NVRDataModel.log("zmAutologin successfully logged into Zoneminder"); - - d.resolve("Login Success"); - - $rootScope.$emit('auth-success', data); - - } else // this means login error - { - $rootScope.loggedIntoZm = -1; - //console.log("**** ZM Login FAILED"); - NVRDataModel.log("zmAutologin Error: Bad Credentials ", "error"); - $rootScope.$emit('auth-error', "incorrect credentials"); - - d.reject("Login Error"); - return (d.promise); - } - - // Now go ahead and re-get auth key - // if login was a success - $rootScope.authSession = "undefined"; - var ld = NVRDataModel.getLogin(); - NVRDataModel.getAuthKey($rootScope.validMonitorId) - .then(function (success) { - - //console.log(success); - $rootScope.authSession = success; - NVRDataModel.log("Stream authentication construction: " + - $rootScope.authSession); - - }, - function (error) { - //console.log(error); - - NVRDataModel.log("Modal: Error returned Stream authentication construction. Retaining old value of: " + $rootScope.authSession); - NVRDataModel.debug("Error was: " + JSON.stringify(error)); - }); - - return (d.promise); - - }) - .error(function (error, status) { - - console.log(">>>>>>>>>>>>>> PARALLEL POST ERROR"); - $ionicLoading.hide(); - - //console.log("**** ZM Login FAILED"); - - // FIXME: Is this sometimes results in null - - NVRDataModel.log("zmAutologin Error " + JSON.stringify(error) + " and status " + status); - // bad urls etc come here - $rootScope.loggedIntoZm = -1; - $rootScope.$emit('auth-error', error); - - d.reject("Login Error"); - return d.promise; - }); - return d.promise; - } - }); - return d.promise; + alertPopup.close(); + }, 5000); - } + d.reject("Error-disable recaptcha"); + return (d.promise); + } - function start() { - var ld = NVRDataModel.getLogin(); - // lets keep this timer irrespective of auth or no auth - $rootScope.loggedIntoZm = 0; - $interval.cancel(zmAutoLoginHandle); - //doLogin(); - zmAutoLoginHandle = $interval(function () { - doLogin(""); + }); - }, zm.loginInterval); // Auto login every 5 minutes - // PHP timeout is around 10 minutes - // should be ok? + var loginData = NVRDataModel.getLogin(); + console.log(">>>>>>>>>>>>>> PARALLEL POST WITH RECAPTCHA TO " + loginData.url); + + /* console.log ("-----------------------SECRET IS "+zm.hashSecret); + $http.get (ld.apiurl+'/host/remoteIp.json') + .then (function (data) { + $ionicLoading.hide(); + var ip = (data.data.auth_hash_ip) ? data.data.remote_ip: ""; + var composite = zm.hashSecret + ld.username + ld.password + ip + data.data.time_frag; + var hash = CryptoJS.MD5(composite); + console.log ("MD5 HASH IS "+hash); + $rootScope.authSession = hash; + d.resolve ("Login Success"); + $rootScope.loggedIntoZm = 1; + $rootScope.$emit('auth-success', data); + + + //ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5] + //$rootScope.authSession + // data.data.remote_ip + // data.data.is_auth + + console.log (JSON.stringify(data)); + }, + function (error) { + $ionicLoading.hide(); + console.log (JSON.stringify(error)); + $rootScope.authSession = ""; + d.reject ("Login Error"); + $rootScope.loggedIntoZm = 1; + $rootScope.$emit('auth-error', "incorrect credentials"); + } + + ); + + return (d.promise); + + console.log ("*****************NEVER HERE***********"); + */ + var hDelay = loginData.enableSlowLoading ? zm.largeHttpTimeout : zm.httpTimeout; + //NVRDataModel.debug ("*** AUTH LOGIN URL IS " + loginData.url); + $http({ + + method: 'POST', + timeout: hDelay, + //withCredentials: true, + url: loginData.url + '/index.php', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + }, + transformRequest: function (obj) { + var str = []; + for (var p in obj) + str.push(encodeURIComponent(p) + "=" + + encodeURIComponent(obj[p])); + var params = str.join("&"); + return params; + }, + + data: { + username: loginData.username, + password: loginData.password, + action: "login", + view: "console" + } + }) + .success(function (data, status, headers) { + console.log(">>>>>>>>>>>>>> PARALLEL POST SUCCESS"); + $ionicLoading.hide(); + + // Coming here does not mean success + // it could also be a bad login, but + // ZM returns you to login.php and returns 200 OK + // so we will check if the data has + // <title>ZM - Login</title> -- it it does then its the login page + + if (data.indexOf(zm.loginScreenString) == -1) { + //eventServer.start(); + $rootScope.loggedIntoZm = 1; + + NVRDataModel.log("zmAutologin successfully logged into Zoneminder"); + + d.resolve("Login Success"); + + $rootScope.$emit('auth-success', data); + + } else // this means login error + { + $rootScope.loggedIntoZm = -1; + //console.log("**** ZM Login FAILED"); + NVRDataModel.log("zmAutologin Error: Bad Credentials ", "error"); + $rootScope.$emit('auth-error', "incorrect credentials"); + + d.reject("Login Error"); + return (d.promise); + } + + // Now go ahead and re-get auth key + // if login was a success + $rootScope.authSession = "undefined"; + var ld = NVRDataModel.getLogin(); + NVRDataModel.getAuthKey($rootScope.validMonitorId) + .then(function (success) { - } + //console.log(success); + $rootScope.authSession = success; + NVRDataModel.log("Stream authentication construction: " + + $rootScope.authSession); - function stop() { - var ld = NVRDataModel.getLogin(); + }, + function (error) { + //console.log(error); - $interval.cancel(zmAutoLoginHandle); - $rootScope.loggedIntoZm = 0; - NVRDataModel.log("Cancelling zmAutologin timer"); + NVRDataModel.log("Modal: Error returned Stream authentication construction. Retaining old value of: " + $rootScope.authSession); + NVRDataModel.debug("Error was: " + JSON.stringify(error)); + }); - } + return (d.promise); - return { - start: start, - stop: stop, - doLogin: doLogin - }; - }) - - //==================================================================== - // First run in ionic - //==================================================================== - - .run(function ($ionicPlatform, $ionicPopup, $rootScope, zm, $state, $stateParams, NVRDataModel, $cordovaSplashscreen, $http, $interval, zmAutoLogin, zmCheckUpdates, $fileLogger, $timeout, $ionicHistory, $window, $ionicSideMenuDelegate, EventServer, $ionicContentBanner, $ionicLoading, $ionicNativeTransitions, $translate, $localstorage) { - - - $ionicPlatform.ready(function () { - console.log (">>>>>>>>>>>>>>>>>>>>>>>>>>>>>INSIDE RUN"); - - $rootScope.appName = "zmNinja"; - $rootScope.zmGlobalCookie = ""; - $rootScope.isEventFilterOn = false; - $rootScope.fromDate = ""; - $rootScope.fromTime = ""; - $rootScope.toDate = ""; - $rootScope.toTime = ""; - $rootScope.fromString = ""; - $rootScope.toString = ""; - $rootScope.loggedIntoZm = 0; - $rootScope.apnsToken = ''; - $rootScope.tappedNotification = 0; - $rootScope.tappedMid = 0; - //var eventsToDisplay=[]; - $rootScope.alarmCount = "0"; - $rootScope.platformOS = "desktop"; - $rootScope.currentServerGroup = "defaultServer"; - $rootScope.validMonitorId = ""; - $rootScope.newVersionAvailable = ""; - $rootScope.userCancelledAuth = false; - $rootScope.online = true; - $rootScope.showBlog = false; - $rootScope.newBlogPost = ""; - $rootScope.apiVersion = ""; - - // only for android - $rootScope.exitApp = function () { - NVRDataModel.log("user exited app"); + }) + .error(function (error, status) { - ionic.Platform.exitApp(); - //navigator.app.exitApp(); + console.log(">>>>>>>>>>>>>> PARALLEL POST ERROR"); + $ionicLoading.hide(); - }; + //console.log("**** ZM Login FAILED"); - // This is a global exception interceptor - $rootScope.exceptionMessage = function (error) { - NVRDataModel.debug("**EXCEPTION**" + error.reason + " caused by " + error.cause); - }; + // FIXME: Is this sometimes results in null - window.addEventListener('beforeunload', function (ev) { + NVRDataModel.log("zmAutologin Error " + JSON.stringify(error) + " and status " + status); + // bad urls etc come here + $rootScope.loggedIntoZm = -1; + $rootScope.$emit('auth-error', error); - if ($rootScope.platformOS != 'desktop') { - ev.returnValue = "true"; - return; + d.reject("Login Error"); + return d.promise; + }); + return d.promise; } + }); + return d.promise; - localforage.setItem('last-desktop-state', { - 'name': $ionicHistory.currentView().stateName, - 'params': $ionicHistory.currentView().stateParams - }).then(function () { - return localforage.getItem('last-desktop-state'); - }).then(function (value) { - ev.returnValue = "true"; - }).catch(function (err) { - ev.returnValue = "true"; - }); + } - }); + function start() { + var ld = NVRDataModel.getLogin(); + // lets keep this timer irrespective of auth or no auth + $rootScope.loggedIntoZm = 0; + $interval.cancel(zmAutoLoginHandle); + //doLogin(); + zmAutoLoginHandle = $interval(function () { + doLogin(""); - // register callbacks for online/offline - // lets see if it really works - $rootScope.online = navigator.onLine; + }, zm.loginInterval); // Auto login every 5 minutes + // PHP timeout is around 10 minutes + // should be ok? - $window.addEventListener("offline", function () { - $rootScope.$apply(function () { - $rootScope.online = false; - NVRDataModel.log("Your network went offline"); + } + + function stop() { + var ld = NVRDataModel.getLogin(); + + $interval.cancel(zmAutoLoginHandle); + $rootScope.loggedIntoZm = 0; + NVRDataModel.log("Cancelling zmAutologin timer"); + + } + + return { + start: start, + stop: stop, + doLogin: doLogin + }; + }) + + //==================================================================== + // First run in ionic + //==================================================================== + + .run(function ($ionicPlatform, $ionicPopup, $rootScope, zm, $state, $stateParams, NVRDataModel, $cordovaSplashscreen, $http, $interval, zmAutoLogin, zmCheckUpdates, $fileLogger, $timeout, $ionicHistory, $window, $ionicSideMenuDelegate, EventServer, $ionicContentBanner, $ionicLoading, $ionicNativeTransitions, $translate, $localstorage) { + + + $ionicPlatform.ready(function () { + console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>INSIDE RUN"); + + + if (window.cordova) { + + cordova.plugins.diagnostic.requestExternalStorageAuthorization(okperm, nopermerr); + + + } + + + function nopermerr() { + NVRDataModel.displayBanner('error', ['Storage permission must be allowed'], "", 4000); + } + + function okperm() { + console.log("cool"); + NVRDataModel.displayBanner('success', ['Storage permission acquired'], "", 4000); + } + + $rootScope.appName = "zmNinja"; + $rootScope.zmGlobalCookie = ""; + $rootScope.isEventFilterOn = false; + $rootScope.fromDate = ""; + $rootScope.fromTime = ""; + $rootScope.toDate = ""; + $rootScope.toTime = ""; + $rootScope.fromString = ""; + $rootScope.toString = ""; + $rootScope.loggedIntoZm = 0; + $rootScope.apnsToken = ''; + $rootScope.tappedNotification = 0; + $rootScope.tappedMid = 0; + //var eventsToDisplay=[]; + $rootScope.alarmCount = "0"; + $rootScope.platformOS = "desktop"; + $rootScope.currentServerGroup = "defaultServer"; + $rootScope.validMonitorId = ""; + $rootScope.newVersionAvailable = ""; + $rootScope.userCancelledAuth = false; + $rootScope.online = true; + $rootScope.showBlog = false; + $rootScope.newBlogPost = ""; + $rootScope.apiVersion = ""; + + // only for android + $rootScope.exitApp = function () { + NVRDataModel.log("user exited app"); + + //window.stop(); + ionic.Platform.exitApp(); + //navigator.app.exitApp(); + + }; + + // This is a global exception interceptor + $rootScope.exceptionMessage = function (error) { + NVRDataModel.debug("**EXCEPTION**" + error.reason + " caused by " + error.cause); + }; + + if ($rootScope.platformOS == 'desktop') { + + window.addEventListener('beforeunload', function (ev) { + + /* if ($rootScope.platformOS != 'desktop') { + ev.returnValue = "true"; + return; + }*/ - //$rootScope.$emit('network-change', "offline"); + localforage.setItem('last-desktop-state', { + 'name': $ionicHistory.currentView().stateName, + 'params': $ionicHistory.currentView().stateParams + }).then(function () { + return localforage.getItem('last-desktop-state'); + }).then(function (value) { + ev.returnValue = "true"; + }).catch(function (err) { + ev.returnValue = "true"; + }); - }); - }, false); + }); + } - $window.addEventListener("online", function () { - $rootScope.$apply(function () { - $rootScope.online = true; - - $timeout(function () { - var networkState = navigator.connection.type; - NVRDataModel.debug("Detected network type as: " + networkState); - var strState = NVRDataModel.getBandwidth(); - NVRDataModel.debug("getBandwidth() normalized it as: " + strState); - $rootScope.runMode = strState; - if ((NVRDataModel.getLogin().autoSwitchBandwidth == true) && - (NVRDataModel.getLogin().enableLowBandwidth == true)) { - NVRDataModel.debug("Setting app state to: " + strState); - $rootScope.$emit('bandwidth-change', strState); - } else { - NVRDataModel.debug("Not changing bandwidth state, as auto change is not on"); - } + // register callbacks for online/offline + // lets see if it really works + $rootScope.online = navigator.onLine; - }, 1000); // need a time gap, seems network type registers late + $window.addEventListener("offline", function () { + $rootScope.$apply(function () { + $rootScope.online = false; + NVRDataModel.log("Your network went offline"); - NVRDataModel.log("Your network is online, re-authenticating"); - zmAutoLogin.doLogin($translate.instant('kReAuthenticating')); + //$rootScope.$emit('network-change', "offline"); - }); - }, false); - - // This code takes care of trapping the Android back button - // and takes it to the menu. - //console.log (">>>>>>>>>>>>>>>>>>BACK BUTTON REGISTERED"); - $ionicPlatform.registerBackButtonAction(function (e) { - - //console.log ("******** back called with isOpenLeft: " + $ionicSideMenuDelegate.isOpenLeft()); - if (!$ionicSideMenuDelegate.isOpenLeft()) { - e.preventDefault(); - $ionicSideMenuDelegate.toggleLeft(); - //console.log("Status of SIDE MENU IS : " + $ionicSideMenuDelegate.isOpen()); + }); + }, false); + + $window.addEventListener("online", function () { + $rootScope.$apply(function () { + $rootScope.online = true; + + $timeout(function () { + var networkState = navigator.connection.type; + NVRDataModel.debug("Detected network type as: " + networkState); + var strState = NVRDataModel.getBandwidth(); + NVRDataModel.debug("getBandwidth() normalized it as: " + strState); + $rootScope.runMode = strState; + if ((NVRDataModel.getLogin().autoSwitchBandwidth == true) && + (NVRDataModel.getLogin().enableLowBandwidth == true)) { + NVRDataModel.debug("Setting app state to: " + strState); + $rootScope.$emit('bandwidth-change', strState); } else { - - window.stop(); - //ionic.Platform.exitApp(); - //navigator.app.exitApp(); + NVRDataModel.debug("Not changing bandwidth state, as auto change is not on"); } - }, 501); - // this works reliably on both Android and iOS. The "onorientation" seems to reverse w/h in Android. Go figure. - // http://stackoverflow.com/questions/1649086/detect-rotation-of-android-phone-in-the-browser-with-javascript + }, 1000); // need a time gap, seems network type registers late - var checkOrientation = function () { - var pixelRatio = window.devicePixelRatio || 1; - $rootScope.devWidth = ((window.innerWidth > 0) ? window.innerWidth : screen.width); - $rootScope.devHeight = ((window.innerHeight > 0) ? window.innerHeight : screen.height); - //console.log("********NEW Computed Dev Width & Height as" + $rootScope.devWidth + "*" + $rootScope.devHeight); + NVRDataModel.log("Your network is online, re-authenticating"); + zmAutoLogin.doLogin($translate.instant('kReAuthenticating')); - }; + }); + }, false); + + // This code takes care of trapping the Android back button + // and takes it to the menu. + //console.log (">>>>>>>>>>>>>>>>>>BACK BUTTON REGISTERED"); + $ionicPlatform.registerBackButtonAction(function (e) { + + //console.log ("******** back called with isOpenLeft: " + $ionicSideMenuDelegate.isOpenLeft()); + if (!$ionicSideMenuDelegate.isOpenLeft()) { + e.preventDefault(); + $ionicSideMenuDelegate.toggleLeft(); + //console.log("Status of SIDE MENU IS : " + $ionicSideMenuDelegate.isOpen()); + } else { + + window.stop(); + //ionic.Platform.exitApp(); + //navigator.app.exitApp(); + } + }, 501); + + // this works reliably on both Android and iOS. The "onorientation" seems to reverse w/h in Android. Go figure. + // http://stackoverflow.com/questions/1649086/detect-rotation-of-android-phone-in-the-browser-with-javascript + + var checkOrientation = function () { + var pixelRatio = window.devicePixelRatio || 1; + $rootScope.devWidth = ((window.innerWidth > 0) ? window.innerWidth : screen.width); + $rootScope.devHeight = ((window.innerHeight > 0) ? window.innerHeight : screen.height); + //console.log("********NEW Computed Dev Width & Height as" + $rootScope.devWidth + "*" + $rootScope.devHeight); + + }; + + window.addEventListener("resize", checkOrientation, false); + + // we come here when a user forcibly cancels portal auth + // useful when you know your auth won't succeed and you need to + // switch to another server + $rootScope.cancelAuth = function () { + $ionicLoading.hide(); + NVRDataModel.log("User cancelled login"); + $ionicHistory.nextViewOptions({ + disableAnimate: true, + disableBack: true + }); + $rootScope.userCancelledAuth = true; + window.stop(); - window.addEventListener("resize", checkOrientation, false); + //console.log ("inside cancelAuth , calling wizard"); + $state.go("app.login", { + "wizard": false + }); + return; + }; - // we come here when a user forcibly cancels portal auth - // useful when you know your auth won't succeed and you need to - // switch to another server - $rootScope.cancelAuth = function () { - $ionicLoading.hide(); - NVRDataModel.log("User cancelled login"); - $ionicHistory.nextViewOptions({ - disableAnimate: true, - disableBack: true - }); - $rootScope.userCancelledAuth = true; - window.stop(); + //--------------------------------------------------------------------------- + // authorize state transitions + //---------------------------------------------------------------------------- - //console.log ("inside cancelAuth , calling wizard"); - $state.go("login", { - "wizard": false - }); - return; - }; + $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { + var requireLogin = toState.data.requireLogin; - //--------------------------------------------------------------------------- - // authorize state transitions - //---------------------------------------------------------------------------- - $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { - var requireLogin = toState.data.requireLogin; + console.log("HERE"); - if ($rootScope.apiValid == false && toState.name != 'invalidapi' && toState.data.requireLogin == true) { - event.preventDefault(); - $state.transitionTo('invalidapi'); - return; + if ($rootScope.apiValid == false && toState.name != 'invalidapi' && toState.data.requireLogin == true) { + event.preventDefault(); + $state.transitionTo('app.invalidapi'); + return; - } + } - if (NVRDataModel.isLoggedIn() || toState.data.requireLogin == false) { - //console.log("State transition is authorized"); + if (NVRDataModel.isLoggedIn() || toState.data.requireLogin == false) { + //console.log("State transition is authorized"); - return; - } else { - NVRDataModel.log("In Auth State trans: Not logged in, requested to go to " + JSON.stringify(toState)); - // event.preventDefault(); - // + return; + } else { + NVRDataModel.log("In Auth State trans: Not logged in, requested to go to " + JSON.stringify(toState)); + // event.preventDefault(); + // - $state.transitionTo('login'); + $state.transitionTo('app.login'); - } + } - if (requireLogin) { + if (requireLogin) { + + $ionicPopup.alert({ + title: $translate.instant('kCredentialsTitle'), + template: $translate.instant('kCredentialsBody') + }); + // for whatever reason, .go was resulting in digest loops. + // if you don't prevent, states will stack + event.preventDefault(); + $state.transitionTo('app.login'); + return; + } - $ionicPopup.alert({ - title: $translate.instant('kCredentialsTitle'), - template: $translate.instant('kCredentialsBody') - }); - // for whatever reason, .go was resulting in digest loops. - // if you don't prevent, states will stack - event.preventDefault(); - $state.transitionTo('login'); - return; - } + return; - return; + }); - }); - - // credit http://stackoverflow.com/a/2091331/1361529 - function getQueryVariable(query, variable) { - var vars = query.split('&'); - for (var i = 0; i < vars.length; i++) { - var pair = vars[i].split('='); - if (decodeURIComponent(pair[0]) == variable) { - return decodeURIComponent(pair[1]); - } - } - return ""; - //console.log('Query variable %s not found', variable); + // credit http://stackoverflow.com/a/2091331/1361529 + function getQueryVariable(query, variable) { + var vars = query.split('&'); + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split('='); + if (decodeURIComponent(pair[0]) == variable) { + return decodeURIComponent(pair[1]); + } } + return ""; + //console.log('Query variable %s not found', variable); + } - //--------------------------------------------------------------------- - // called when device is ready - //--------------------------------------------------------------------- + //--------------------------------------------------------------------- + // called when device is ready + //--------------------------------------------------------------------- - function getTextZoomCallback(tz) { - $rootScope.textScaleFactor = parseFloat(tz + "%") / 100.0; - NVRDataModel.debug("text zoom factor is " + $rootScope.textScaleFactor); - } + function getTextZoomCallback(tz) { + $rootScope.textScaleFactor = parseFloat(tz + "%") / 100.0; + NVRDataModel.debug("text zoom factor is " + $rootScope.textScaleFactor); + } + + // $ionicPlatform.ready(function () { - // $ionicPlatform.ready(function () { - /*if (window.cordova) { - - alert ("Permissions"); - var permissions = cordova.plugins.permissions; - permissions.requestPermission(permissions.READ_EXTERNAL_STORAGE, null, nopermerr); - } - - function nopermerr() { - displayBanner('error', ['Storage permission must be allowed'], "", 4000); - }*/ + // handles URL launches + // if you just launch zmninja:// then it will honor the settings in "tap screen" -> events or montage + // if you launch with zmninja://<mid> it will take you to live view for that mid + window.handleOpenURL = function (url) { + $rootScope.tappedNotification = 1; + $rootScope.tappedMid = 0; + var c = URI.parse(url); + //NVRDataModel.log ("***********launched with "+ JSON.stringify(c)); + if (c.query) { + var qm = getQueryVariable(c.query, "mid"); + if (qm) $rootScope.tappedMid = parseInt(qm); + NVRDataModel.log("external URL called with MID=" + $rootScope.tappedMid); + //console.log (">>>>>>>>> EID="+getQueryVariable(c.query, "eid")); - // handles URL launches - // if you just launch zmninja:// then it will honor the settings in "tap screen" -> events or montage - // if you launch with zmninja://<mid> it will take you to live view for that mid - window.handleOpenURL = function (url) { - $rootScope.tappedNotification = 1; - $rootScope.tappedMid = 0; - var c = URI.parse(url); - //NVRDataModel.log ("***********launched with "+ JSON.stringify(c)); - if (c.query) { - var qm = getQueryVariable(c.query, "mid"); - if (qm) $rootScope.tappedMid = parseInt(qm); - NVRDataModel.log("external URL called with MID=" + $rootScope.tappedMid); - //console.log (">>>>>>>>> EID="+getQueryVariable(c.query, "eid")); + } - } + }; - }; + $rootScope.textScaleFactor = 1.0; + $rootScope.apiValid = false; - $rootScope.textScaleFactor = 1.0; - $rootScope.apiValid = false; + $rootScope.db = null; + $rootScope.runMode = NVRDataModel.getBandwidth(); - $rootScope.db = null; - $rootScope.runMode = NVRDataModel.getBandwidth(); + $rootScope.platformOS = "desktop"; + NVRDataModel.log("Device is ready"); - $rootScope.platformOS = "desktop"; - NVRDataModel.log("Device is ready"); + // var ld = NVRDataModel.getLogin(); + if ($ionicPlatform.is('ios')) + $rootScope.platformOS = "ios"; + if ($ionicPlatform.is('android')) + $rootScope.platformOS = "android"; - // var ld = NVRDataModel.getLogin(); - if ($ionicPlatform.is('ios')) - $rootScope.platformOS = "ios"; - if ($ionicPlatform.is('android')) - $rootScope.platformOS = "android"; + NVRDataModel.log("You are running on " + $rootScope.platformOS); - NVRDataModel.log("You are running on " + $rootScope.platformOS); + console.log("Mobile acc"); + if (window.cordova) + MobileAccessibility.getTextZoom(getTextZoomCallback); - console.log ("Mobile acc"); - if (window.cordova) - MobileAccessibility.getTextZoom(getTextZoomCallback); + // $rootScope.lastState = "events"; + //$rootScope.lastStateParam = "0"; - // $rootScope.lastState = "events"; - //$rootScope.lastStateParam = "0"; + console.log("localforage config"); + localforage.config({ + name: zm.dbName -console.log ("localforage config"); - localforage.config({ - name: zm.dbName + }); - }); + var order = []; - var order = []; + if ($rootScope.platformOS == 'ios') { + order = [window.cordovaSQLiteDriver._driver, + localforage.INDEXEDDB, + localforage.WEBSQL, + localforage.LOCALSTORAGE + ]; + } else - if ($rootScope.platformOS == 'ios') { - order = [window.cordovaSQLiteDriver._driver, - localforage.INDEXEDDB, - localforage.WEBSQL, - localforage.LOCALSTORAGE - ]; - } else + { + // don't do SQL for non IOS - seems to hang? + order = [ - { - // don't do SQL for non IOS - seems to hang? - order = [ + localforage.INDEXEDDB, + localforage.WEBSQL, + localforage.LOCALSTORAGE, + ]; - localforage.INDEXEDDB, - localforage.WEBSQL, - localforage.LOCALSTORAGE, - ]; + } - } + console.log("forage driver"); + localforage.defineDriver(window.cordovaSQLiteDriver).then(function () { + return localforage.setDriver( + // Try setting cordovaSQLiteDriver if available, + order + + ); + }).then(function () { + // this should alert "cordovaSQLiteDriver" when in an emulator or a device + NVRDataModel.log("localforage driver for storage:" + localforage.driver()); -console.log ("forage driver"); - localforage.defineDriver(window.cordovaSQLiteDriver).then(function () { - return localforage.setDriver( - // Try setting cordovaSQLiteDriver if available, - order - - ); - }).then(function () { - // this should alert "cordovaSQLiteDriver" when in an emulator or a device - NVRDataModel.log("localforage driver for storage:" + localforage.driver()); - - // Now lets import old data if it exists: - var defaultServerName = $localstorage.get("defaultServerName"); - - localforage.getItem("defaultServerName") - .then(function (val) { - // console.log (">>>> localforage reported defaultServerName as " + val); - // if neither, we are in first use, mates! - if (!val && !defaultServerName) { - continueInitialInit(); - /* NVRDataModel.debug ("Neither localstorage or forage - First use, showing warm and fuzzy..."); + // Now lets import old data if it exists: + var defaultServerName = $localstorage.get("defaultServerName"); + + localforage.getItem("defaultServerName") + .then(function (val) { + // console.log (">>>> localforage reported defaultServerName as " + val); + // if neither, we are in first use, mates! + if (!val && !defaultServerName) { + continueInitialInit(); + /* NVRDataModel.debug ("Neither localstorage or forage - First use, showing warm and fuzzy..."); $ionicHistory.nextViewOptions({ disableAnimate: true, disableBack: true }); $state.go('first-use');*/ - } else if (!val && defaultServerName) { - NVRDataModel.log(">>>>Importing data from localstorage...."); - - var dsn = defaultServerName; - var dl = $localstorage.get('defaultLang') || 'en'; - var ifu = ($localstorage.get('isFirstUse') == '0' ? false : true); - var luc = $localstorage.get('lastUpdateCheck'); - var lbpc = $localstorage.get('latestBlogPostChecked'); - var sgl = $localstorage.getObject('serverGroupList'); - - NVRDataModel.log(">>>Localstorage data found as below:"); - NVRDataModel.log("server name:" + dsn); - NVRDataModel.log("default lang :" + dl); - NVRDataModel.log("is first use:" + ifu); - NVRDataModel.log("last update check:" + luc); - NVRDataModel.log("latest blog post check:" + lbpc); - NVRDataModel.log("server group list:" + JSON.stringify(sgl)); - - localforage.setItem('defaultLang', dl) - .then(function () { - - NVRDataModel.log(">>>>migrated defaultLang..."); - NVRDataModel.setFirstUse(ifu); - return localforage.setItem('isFirstUse', ifu); - }) - .then(function () { - NVRDataModel.log(">>>>migrated isFirstUse..."); - return localforage.setItem('lastUpdateCheck', ifu); - }) - .then(function () { - NVRDataModel.log(">>>>migrated lastUpdateCheck..."); - return localforage.setItem('latestBlogPostChecked', lbpc); - }) - .then(function () { - NVRDataModel.log(">>>>migrated latestBlogPostChecked..."); - // lets encrypt serverGroupList - NVRDataModel.log("server group list is " + JSON.stringify(sgl)); - var ct = CryptoJS.AES.encrypt(JSON.stringify(sgl), zm.cipherKey); - NVRDataModel.log("encrypted server group list is " + ct); - ct = sgl; - return localforage.setItem('serverGroupList', ct); - }) - .then(function () { - NVRDataModel.log(">>>>migrated serverGroupList..."); - return localforage.setItem('defaultServerName', dsn); - }) - .then(function () { - NVRDataModel.log(">>>>migrated defaultServerName..."); - NVRDataModel.log(">>>>Migrated all values, continuing..."); - //NVRDataModel.migrationComplete(); - continueInitialInit(); - }) - .catch(function (err) { - NVRDataModel.log("Migration error : " + JSON.stringify(err)); - continueInitialInit(); - }); - - } else { - NVRDataModel.log(">>>>No data to import...."); - //NVRDataModel.migrationComplete(); - continueInitialInit(); - } - - }); - - }); - - function continueInitialInit() { - console.log ("continueinit"); - var pixelRatio = window.devicePixelRatio || 1; - $rootScope.devWidth = ((window.innerWidth > 0) ? window.innerWidth : screen.width); - $rootScope.devHeight = ((window.innerHeight > 0) ? window.innerHeight : screen.height); - // for making sure we canuse $state.go with ng-click - // needed for views that use popovers - $rootScope.$state = $state; - $rootScope.$stateParams = $stateParams; - - if (window.cordova && window.cordova.plugins.Keyboard) { - console.log ("no keyboard"); - // cordova.plugins.Keyboard.disableScroll(true); - } - if (window.StatusBar) { - // org.apache.cordova.statusbar required - console.log ("statusbar"); - NVRDataModel.log("Updating statusbar"); - StatusBar.styleDefault(); - //StatusBar.overlaysWebView(false); - StatusBar.backgroundColorByHexString("#2980b9"); - } - - if (window.cordova) { - console.log ("Hiding splash"); - $cordovaSplashscreen.hide(); - - - - console.log ("app version"); - cordova.getAppVersion.getVersionNumber().then(function (version) { - appVersion = version; - NVRDataModel.log("App Version: " + appVersion); - NVRDataModel.setAppVersion(appVersion); - }); - } - - console.log ("file logger"); - $fileLogger.checkFile().then(function (resp) { - if (parseInt(resp.size) > zm.logFileMaxSize) { - console.log ("inside file logger"); - - $fileLogger.deleteLogfile().then(function () { - NVRDataModel.log("Deleting old log file as it exceeds " + zm.logFileMaxSize + " bytes"); - - }); - } + } else if (!val && defaultServerName) { + NVRDataModel.log(">>>>Importing data from localstorage...."); + + var dsn = defaultServerName; + var dl = $localstorage.get('defaultLang') || 'en'; + var ifu = ($localstorage.get('isFirstUse') == '0' ? false : true); + var luc = $localstorage.get('lastUpdateCheck'); + var lbpc = $localstorage.get('latestBlogPostChecked'); + var sgl = $localstorage.getObject('serverGroupList'); + + NVRDataModel.log(">>>Localstorage data found as below:"); + NVRDataModel.log("server name:" + dsn); + NVRDataModel.log("default lang :" + dl); + NVRDataModel.log("is first use:" + ifu); + NVRDataModel.log("last update check:" + luc); + NVRDataModel.log("latest blog post check:" + lbpc); + NVRDataModel.log("server group list:" + JSON.stringify(sgl)); + + localforage.setItem('defaultLang', dl) + .then(function () { + + NVRDataModel.log(">>>>migrated defaultLang..."); + NVRDataModel.setFirstUse(ifu); + return localforage.setItem('isFirstUse', ifu); + }) + .then(function () { + NVRDataModel.log(">>>>migrated isFirstUse..."); + return localforage.setItem('lastUpdateCheck', ifu); + }) + .then(function () { + NVRDataModel.log(">>>>migrated lastUpdateCheck..."); + return localforage.setItem('latestBlogPostChecked', lbpc); + }) + .then(function () { + NVRDataModel.log(">>>>migrated latestBlogPostChecked..."); + // lets encrypt serverGroupList + NVRDataModel.log("server group list is " + JSON.stringify(sgl)); + var ct = CryptoJS.AES.encrypt(JSON.stringify(sgl), zm.cipherKey); + NVRDataModel.log("encrypted server group list is " + ct); + ct = sgl; + return localforage.setItem('serverGroupList', ct); + }) + .then(function () { + NVRDataModel.log(">>>>migrated serverGroupList..."); + return localforage.setItem('defaultServerName', dsn); + }) + .then(function () { + NVRDataModel.log(">>>>migrated defaultServerName..."); + NVRDataModel.log(">>>>Migrated all values, continuing..."); + //NVRDataModel.migrationComplete(); + continueInitialInit(); + }) + .catch(function (err) { + NVRDataModel.log("Migration error : " + JSON.stringify(err)); + continueInitialInit(); }); - $fileLogger.setStorageFilename(zm.logFile); - $fileLogger.setTimestampFormat('MMM d, y ' + NVRDataModel.getTimeFormat()); - - if (NVRDataModel.getLogin().disableNative) { - NVRDataModel.log("Disabling native transitions..."); - $ionicNativeTransitions.enable(false); - } else { - NVRDataModel.log("Enabling native transitions..."); - $ionicNativeTransitions.enable(true); - } - // At this stage, DataModel.init is not called yet - // but I do need to know the language - - NVRDataModel.log("Retrieving language before init is called..."); - localforage.getItem("defaultLang") - .then(function (val) { - - var lang = val; - //console.log (">>>>>>>>>>>>>> LANG IS " + val); - - if (lang == undefined || lang == null) { - NVRDataModel.log("No language set, switching to en"); - lang = "en"; - - } else { - NVRDataModel.log("Language stored as:" + lang); - - } - - NVRDataModel.setDefaultLanguage(lang, false) - .then(function (success) { - NVRDataModel.log(">>>>Language to be used:" + $translate.proposedLanguage()); - moment.locale($translate.proposedLanguage()); - - // Remember this is before data Init - // so I need to do a direct forage fetch - localforage.getItem("isFirstUse") - .then(function (val) { - //console.log ("isFirstUse is " + val); - if (val == null || val == true) { - NVRDataModel.log("First time detected"); - $state.go("first-use"); - return; - } else { - continueRestOfInit(); - } - - }); - - }); - }); + } else { + NVRDataModel.log(">>>>No data to import...."); + //NVRDataModel.migrationComplete(); + continueInitialInit(); } - function continueRestOfInit() { - - if ($rootScope.platformOS == 'desktop') { - $rootScope.lastState = ""; - $rootScope.lastStateParam = {}; - - localforage.getItem('last-desktop-state') - .then(function (succ) { - // console.log ("FOUND " + JSON.stringify(succ) + ":"+succ); - if (succ) { - $rootScope.lastState = succ.name; - $rootScope.lastStateParam = succ.params; - - } - loadServices(); - }, function (err) { - console.log("ERR " + JSON.stringify(err)); - loadServices(); - }); - } else - - { - - loadServices(); - } - - function loadServices() { - NVRDataModel.log("Language file loaded, continuing with rest"); - NVRDataModel.init(); - - // now do SSL check - //setSSLCerts(); + }); - EventServer.init(); - zmCheckUpdates.start(); - NVRDataModel.log("Setting up POST LOGIN timer"); - zmAutoLogin.start(); - setupPauseAndResume(); + }); + function continueInitialInit() { + console.log("continueinit"); + var pixelRatio = window.devicePixelRatio || 1; + $rootScope.devWidth = ((window.innerWidth > 0) ? window.innerWidth : screen.width); + $rootScope.devHeight = ((window.innerHeight > 0) ? window.innerHeight : screen.height); + // for making sure we canuse $state.go with ng-click + // needed for views that use popovers + $rootScope.$state = $state; + $rootScope.$stateParams = $stateParams; + if (window.cordova && window.cordova.plugins.Keyboard) { + console.log("no keyboard"); + // cordova.plugins.Keyboard.disableScroll(true); + } + if (window.StatusBar) { + // org.apache.cordova.statusbar required + console.log("statusbar"); + NVRDataModel.log("Updating statusbar"); + StatusBar.styleDefault(); + //StatusBar.overlaysWebView(false); + StatusBar.backgroundColorByHexString("#2980b9"); + } - } - - } - - - function setupPauseAndResume() { - NVRDataModel.log("Setting up pause and resume handler AFTER language is loaded..."); - //--------------------------------------------------------------------------- - // resume handler - //---------------------------------------------------------------------------- - document.addEventListener("resume", function () { - - $ionicPlatform.ready(function () { - NVRDataModel.log("App is resuming from background"); - $rootScope.isDownloading = false; - var forceDelay = NVRDataModel.getLogin().resumeDelay; - NVRDataModel.log(">>> Resume delayed for " + forceDelay + " ms, to wait for network stack..."); + if (window.cordova) { + console.log("Hiding splash"); + $cordovaSplashscreen.hide(); - $timeout(function () { - var ld = NVRDataModel.getLogin(); - - NVRDataModel.setBackground(false); - // don't animate - $ionicHistory.nextViewOptions({ - disableAnimate: true, - disableBack: true - }); - - // remember the last state so we can - // go back there after auth - if ($ionicHistory.currentView()) { - $rootScope.lastState = $ionicHistory.currentView().stateName; - $rootScope.lastStateParam = - $ionicHistory.currentView().stateParams; - NVRDataModel.debug("Last State recorded:" + - JSON.stringify($ionicHistory.currentView())); - - if ($rootScope.lastState == "zm-portal-login") { - NVRDataModel.debug("Last state was portal-login, so forcing montage"); - $rootScope.lastState = "montage"; - } - - NVRDataModel.debug("going to portal login"); - $ionicHistory.nextViewOptions({ - disableAnimate: true - }); - $state.go("zm-portal-login"); - return; - } else { - $rootScope.lastState = ""; - $rootScope.lastStateParam = ""; - NVRDataModel.debug("reset lastState to null"); - $ionicHistory.nextViewOptions({ - disableAnimate: true - }); - $state.go("zm-portal-login"); - return; - } - }, forceDelay); - }); - }, false); - //--------------------------------------------------------------------------- - // background handler - //---------------------------------------------------------------------------- - document.addEventListener("pause", function () { - NVRDataModel.setBackground(true); - NVRDataModel.setJustResumed(true); // used for window stop + console.log("app version"); + cordova.getAppVersion.getVersionNumber().then(function (version) { + appVersion = version; + NVRDataModel.log("App Version: " + appVersion); + NVRDataModel.setAppVersion(appVersion); + }); + } - NVRDataModel.log("ROOT APP:App is going into background"); + console.log("file logger"); + $fileLogger.checkFile().then(function (resp) { + if (parseInt(resp.size) > zm.logFileMaxSize) { + console.log("inside file logger"); - $interval.cancel($rootScope.eventQueryInterval); - $interval.cancel($rootScope.intervalHandle); + $fileLogger.deleteLogfile().then(function () { + NVRDataModel.log("Deleting old log file as it exceeds " + zm.logFileMaxSize + " bytes"); - NVRDataModel.log("ROOT APP: Stopping network pull..."); - window.stop(); // dont call stopNetwork - we need to stop here + }); + } + }); - var ld = NVRDataModel.getLogin(); + $fileLogger.setStorageFilename(zm.logFile); + $fileLogger.setTimestampFormat('MMM d, y ' + NVRDataModel.getTimeFormat()); - + if (NVRDataModel.getLogin().disableNative) { + NVRDataModel.log("Disabling native transitions..."); + $ionicNativeTransitions.enable(false); + } else { + NVRDataModel.log("Enabling native transitions..."); + $ionicNativeTransitions.enable(true); + } + // At this stage, DataModel.init is not called yet + // but I do need to know the language - zmAutoLogin.stop(); - if ($rootScope.zmPopup) - $rootScope.zmPopup.close(); + NVRDataModel.log("Retrieving language before init is called..."); + localforage.getItem("defaultLang") + .then(function (val) { + var lang = val; + //console.log (">>>>>>>>>>>>>> LANG IS " + val); - if (ld.exitOnSleep && $rootScope.platformOS == "android") { - NVRDataModel.log("user exited app"); - ionic.Platform.exitApp(); - } + if (lang == undefined || lang == null) { + NVRDataModel.log("No language set, switching to en"); + lang = "en"; - }, false); + } else { + NVRDataModel.log("Language stored as:" + lang); } - // URL interceptor - - - }); //platformReady - - }) //run - - //------------------------------------------------------------------ - // Route configuration - //------------------------------------------------------------------ - - // My route map connecting menu options to their respective templates and controllers - .config(function ($stateProvider, $urlRouterProvider, $httpProvider, $ionicConfigProvider, $provide, $compileProvider, $ionicNativeTransitionsProvider, $logProvider, $translateProvider) { - - //$logProvider.debugEnabled(false); - //$compileProvider.debugInfoEnabled(false); - - // This is an exception interceptor so it can show up in app logs - // if they occur. I suspect digest and other errors will be useful - // for me to see - //$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|cdvphotolibrary):/); - - $provide.decorator("$exceptionHandler", ['$delegate', '$injector', function ($delegate, $injector) { - return function (exception, cause) { - - var $rootScope = $injector.get("$rootScope"); - $rootScope.exceptionMessage({ - reason: exception, - cause: cause - }); - - $delegate(exception, cause); - - }; - }]); - - // If you do this, Allow Origin can't be * - //$httpProvider.defaults.withCredentials = true; - $httpProvider.interceptors.push('timeoutHttpIntercept'); - $ionicConfigProvider.navBar.alignTitle('center'); - //$ionicConfigProvider.backButton.text('').icon('ion-chevron-left'); - //$ionicConfigProvider.backButton.text('').icon('ion-chevron-left').previousTitleText(false); - // use overflow-scroll=false in ion-content - // removing it here doesn't allow you to enable it per view - // so it messes up scrolldelegate zoom and possibly others - //$ionicConfigProvider.scrolling.jsScrolling(false); - $compileProvider.debugInfoEnabled(false); - - $ionicNativeTransitionsProvider.setDefaultOptions({ - duration: 250, - }); - - $translateProvider.useStaticFilesLoader({ - prefix: 'lang/locale-', - suffix: '.json' - }); - - //$translateProvider.useLocalStorage(); - - $translateProvider.registerAvailableLanguageKeys(['en', 'de', 'es', 'fr', 'it', 'ru', 'ja', 'ko', 'nl', 'pl', 'zh', 'zh_CN', 'zh_TW', 'pt', 'ar', 'hi', 'hu'], { - 'en_*': 'en', - 'de_*': 'de', - 'es_*': 'es', - 'fr_*': 'fr', - 'it_*': 'it', - 'ru_*': 'ru', - 'ja_*': 'ja', - 'ko_*': 'ko', - 'nl_*': 'nl', - 'pt_*': 'pt', - 'pl_*': 'pl', - 'ar_*': 'ar', - 'hi_*': 'hi', - 'hu_*':'hu', - '*': 'en' // must be last - }); - - //$translateProvider.determinePreferredLanguage(); - //$translateProvider.preferredLanguage("en"); - $translateProvider.fallbackLanguage("en"); - $translateProvider.useSanitizeValueStrategy('escape'); - - $stateProvider - .state('app', { - url: '/', - abstract: true, - templateUrl: 'index.html', - cache: false, + NVRDataModel.setDefaultLanguage(lang, false) + .then(function (success) { + NVRDataModel.log(">>>>Language to be used:" + $translate.proposedLanguage()); + moment.locale($translate.proposedLanguage()); + + // Remember this is before data Init + // so I need to do a direct forage fetch + localforage.getItem("isFirstUse") + .then(function (val) { + //console.log ("isFirstUse is " + val); + if (val == null || val == true) { + NVRDataModel.log("First time detected"); + $state.go("app.first-use"); + return; + } else { + continueRestOfInit(); + } - //controller: 'AppCtrl' - }) + }); - .state('login', { - data: { - requireLogin: false - }, - url: "/login/:wizard", - cache: false, - templateUrl: "templates/login.html", - controller: 'zmApp.LoginCtrl', + }); + }); + } - }) + function continueRestOfInit() { - .state('help', { - data: { - requireLogin: false - }, - url: "/help", - cache: false, - templateUrl: "templates/help.html", - controller: 'zmApp.HelpCtrl', + if ($rootScope.platformOS == 'desktop') { + $rootScope.lastState = ""; + $rootScope.lastStateParam = {}; - }) + localforage.getItem('last-desktop-state') + .then(function (succ) { + // console.log ("FOUND " + JSON.stringify(succ) + ":"+succ); + if (succ) { + $rootScope.lastState = succ.name; + if ($rootScope.lastState.indexOf("app.") == -1) { + $rootScope.lastState = "app."+$rootScope.lastState; + } + $rootScope.lastStateParam = succ.params; - .state('news', { - data: { - requireLogin: false - }, - url: "/news", - cache: false, - templateUrl: "templates/news.html", - controller: 'zmApp.NewsCtrl', + } + loadServices(); + }, function (err) { + console.log("ERR " + JSON.stringify(err)); + loadServices(); + }); + } else - }) + { - .state('monitors', { - data: { - requireLogin: true - }, - resolve: { - message: function (NVRDataModel) { - // console.log("Inside app.montage resolve"); - return NVRDataModel.getMonitors(0); - } - }, - url: "/monitors", - cache: false, - templateUrl: "templates/monitors.html", - controller: 'zmApp.MonitorCtrl', + loadServices(); + } - }) + function loadServices() { + NVRDataModel.log("Language file loaded, continuing with rest"); + NVRDataModel.init(); - .state('events', { - data: { - requireLogin: true - }, - resolve: { - message: function (NVRDataModel) { - //console.log("Inside app.events resolve"); - return NVRDataModel.getMonitors(0); - } - }, - cache: false, - url: "/events/:id/:playEvent", - templateUrl: "templates/events.html", - controller: 'zmApp.EventCtrl', + // now do SSL check + //setSSLCerts(); - }) + EventServer.init(); + zmCheckUpdates.start(); + NVRDataModel.log("Setting up POST LOGIN timer"); + zmAutoLogin.start(); + setupPauseAndResume(); - .state('lowversion', { - data: { - requireLogin: false - }, - url: "/lowversion/:ver", - cache: false, - templateUrl: "templates/lowversion.html", - controller: 'zmApp.LowVersionCtrl', - }) - - .state('importantmessage', { - data: { - requireLogin: false - }, + } - cache: false, - url: "/importantmessage/:ver", - templateUrl: "templates/important_message.html", - controller: 'zmApp.ImportantMessageCtrl', + } - }) - .state('invalidapi', { - data: { - requireLogin: false - }, + function setupPauseAndResume() { + NVRDataModel.log("Setting up pause and resume handler AFTER language is loaded..."); + //--------------------------------------------------------------------------- + // resume handler + //---------------------------------------------------------------------------- + document.addEventListener("resume", function () { - cache: false, - url: "/invalidapi", - templateUrl: "templates/invalidapi.html", - controller: 'zmApp.InvalidApiCtrl', + $ionicPlatform.ready(function () { + NVRDataModel.log("App is resuming from background"); + $rootScope.isDownloading = false; + var forceDelay = NVRDataModel.getLogin().resumeDelay; + NVRDataModel.log(">>> Resume delayed for " + forceDelay + " ms, to wait for network stack..."); - }) + $timeout(function () { + var ld = NVRDataModel.getLogin(); - .state('events-graphs', { - data: { - requireLogin: true - }, - cache: false, - url: "/events-graphs", - templateUrl: "templates/events-graphs.html", - controller: 'zmApp.EventsGraphsCtrl', + NVRDataModel.setBackground(false); + // don't animate + $ionicHistory.nextViewOptions({ + disableAnimate: true, + disableBack: true + }); + + // remember the last state so we can + // go back there after auth + if ($ionicHistory.currentView()) { + $rootScope.lastState = $ionicHistory.currentView().stateName; + $rootScope.lastStateParam = + $ionicHistory.currentView().stateParams; + NVRDataModel.debug("Last State recorded:" + + JSON.stringify($ionicHistory.currentView())); + + if ($rootScope.lastState == "app.zm-portal-login") { + NVRDataModel.debug("Last state was portal-login, so forcing montage"); + $rootScope.lastState = "app.montage"; + } - }) + NVRDataModel.debug("going to portal login"); + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); + $state.go("app.zm-portal-login"); + return; + } else { + $rootScope.lastState = ""; + $rootScope.lastStateParam = ""; + NVRDataModel.debug("reset lastState to null"); + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); + $state.go("app.zm-portal-login"); + return; + } - .state('events-date-time-filter', { - data: { - requireLogin: true - }, - cache: false, - url: "/events-date-time-filter", - templateUrl: "templates/events-date-time-filter.html", - controller: 'zmApp.EventDateTimeFilterCtrl', + }, forceDelay); + }); + }, false); - }) + //--------------------------------------------------------------------------- + // background handler + //---------------------------------------------------------------------------- + document.addEventListener("pause", function () { + NVRDataModel.setBackground(true); + NVRDataModel.setJustResumed(true); // used for window stop - .state('state', { - data: { - requireLogin: true - }, - cache: false, - url: "/state", - templateUrl: "templates/state.html", - controller: 'zmApp.StateCtrl', + NVRDataModel.log("ROOT APP:App is going into background"); - }) + $interval.cancel($rootScope.eventQueryInterval); + $interval.cancel($rootScope.intervalHandle); - .state('devoptions', { - data: { - requireLogin: false - }, - url: "/devoptions", - cache: false, - templateUrl: "templates/devoptions.html", - controller: 'zmApp.DevOptionsCtrl', - }) - - .state('timeline', { - data: { - requireLogin: true - }, - resolve: { - message: function (NVRDataModel) { - //console.log("Inside app.events resolve"); - return NVRDataModel.getMonitors(0); - } - }, - url: "/timeline", - cache: false, - templateUrl: "templates/timeline.html", - controller: 'zmApp.TimelineCtrl', + NVRDataModel.log("ROOT APP: Stopping network pull..."); + window.stop(); // dont call stopNetwork - we need to stop here - }) + var ld = NVRDataModel.getLogin(); - .state('eventserversettings', { - data: { - requireLogin: true - }, - resolve: { - message: function (NVRDataModel) { - return NVRDataModel.getMonitors(0); - } - }, - url: "/eventserversettings", - cache: false, - templateUrl: "templates/eventserversettings.html", - controller: 'zmApp.EventServerSettingsCtrl', - }) - .state('log', { - data: { - requireLogin: false - }, - url: "/log", - cache: false, - templateUrl: "templates/log.html", - controller: 'zmApp.LogCtrl', + zmAutoLogin.stop(); + if ($rootScope.zmPopup) + $rootScope.zmPopup.close(); - }) - .state('wizard', { - data: { - requireLogin: false - }, - url: "/wizard", - cache: false, - templateUrl: "templates/wizard.html", - controller: 'zmApp.WizardCtrl', + if (ld.exitOnSleep && $rootScope.platformOS == "android") { + NVRDataModel.log("user exited app"); + window.stop(); + // ionic.Platform.exitApp(); + } - }) + }, false); - .state('zm-portal-login', { - data: { - requireLogin: false - }, - url: "/zm-portal-login", - cache: false, - templateUrl: "templates/zm-portal-login.html", - controller: 'zmApp.PortalLoginCtrl', - nativeTransitions: null // disable for speed + } - }) + // URL interceptor - .state('first-use', { - data: { - requireLogin: false - }, - url: "/first-use", - cache: false, - templateUrl: "templates/first-use.html", - controller: 'zmApp.FirstUseCtrl', - }) + }); //platformReady - .state('montage-history', { - data: { - requireLogin: true - }, - resolve: { - message: function (NVRDataModel) { - //console.log("Inside app.events resolve"); - return NVRDataModel.getMonitors(0); - } + }) //run - }, - cache: false, - url: "/montage-history", - templateUrl: "templates/montage-history.html", - controller: 'zmApp.MontageHistoryCtrl', - params: { - minimal: false, - isRefresh: false - }, + //------------------------------------------------------------------ + // Route configuration + //------------------------------------------------------------------ - }) + // My route map connecting menu options to their respective templates and controllers + .config(function ($stateProvider, $urlRouterProvider, $httpProvider, $ionicConfigProvider, $provide, $compileProvider, $ionicNativeTransitionsProvider, $logProvider, $translateProvider) { - .state('montage', { - data: { - requireLogin: true - }, - resolve: { - message: function (NVRDataModel) { - //console.log("Inside app.events resolve"); - return NVRDataModel.getMonitors(0); - } + //$logProvider.debugEnabled(false); + //$compileProvider.debugInfoEnabled(false); - }, - url: "/montage", - cache: false, - templateUrl: "templates/montage.html", - controller: 'zmApp.MontageCtrl', - params: { - minimal: false, - isRefresh: false - }, + // This is an exception interceptor so it can show up in app logs + // if they occur. I suspect digest and other errors will be useful + // for me to see + //$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|cdvphotolibrary):/); - }); + $provide.decorator("$exceptionHandler", ['$delegate', '$injector', function ($delegate, $injector) { + return function (exception, cause) { - // We are NOT going to default route. Routing to a view will start on - // a broadcast of "init-complete" + var $rootScope = $injector.get("$rootScope"); + $rootScope.exceptionMessage({ + reason: exception, + cause: cause + }); - }); //config
\ No newline at end of file + $delegate(exception, cause); + + }; + }]); + + // If you do this, Allow Origin can't be * + //$httpProvider.defaults.withCredentials = true; + $httpProvider.interceptors.push('timeoutHttpIntercept'); + $ionicConfigProvider.navBar.alignTitle('center'); + //$ionicConfigProvider.backButton.text('').icon('ion-chevron-left'); + //$ionicConfigProvider.backButton.text('').icon('ion-chevron-left').previousTitleText(false); + // use overflow-scroll=false in ion-content + // removing it here doesn't allow you to enable it per view + // so it messes up scrolldelegate zoom and possibly others + //$ionicConfigProvider.scrolling.jsScrolling(false); + $compileProvider.debugInfoEnabled(false); + + $ionicNativeTransitionsProvider.setDefaultOptions({ + duration: 250, + }); + + $translateProvider.useStaticFilesLoader({ + prefix: 'lang/locale-', + suffix: '.json' + }); + + //$translateProvider.useLocalStorage(); + + $translateProvider.registerAvailableLanguageKeys(['en', 'de', 'es', 'fr', 'it', 'ru', 'ja', 'ko', 'nl', 'pl', 'zh', 'zh_CN', 'zh_TW', 'pt', 'ar', 'hi', 'hu'], { + 'en_*': 'en', + 'de_*': 'de', + 'es_*': 'es', + 'fr_*': 'fr', + 'it_*': 'it', + 'ru_*': 'ru', + 'ja_*': 'ja', + 'ko_*': 'ko', + 'nl_*': 'nl', + 'pt_*': 'pt', + 'pl_*': 'pl', + 'ar_*': 'ar', + 'hi_*': 'hi', + 'hu_*': 'hu', + '*': 'en' // must be last + }); + + //$translateProvider.determinePreferredLanguage(); + //$translateProvider.preferredLanguage("en"); + $translateProvider.fallbackLanguage("en"); + $translateProvider.useSanitizeValueStrategy('escape'); + + $stateProvider + .state('app', { + url: '/app', + abstract: true, + templateUrl: 'templates/menu.html', + cache: false, + + //controller: 'AppCtrl' + }) + + .state('app.login', { + data: { + requireLogin: false + }, + url: "/login/:wizard", + cache: false, + templateUrl: "templates/login.html", + controller: 'zmApp.LoginCtrl', + + }) + + .state('app.help', { + data: { + requireLogin: false + }, + url: "/help", + cache: false, + templateUrl: "templates/help.html", + controller: 'zmApp.HelpCtrl', + + }) + + .state('app.news', { + data: { + requireLogin: false + }, + url: "/news", + cache: false, + templateUrl: "templates/news.html", + controller: 'zmApp.NewsCtrl', + + }) + + .state('app.monitors', { + data: { + requireLogin: true + }, + resolve: { + message: function (NVRDataModel) { + // console.log("Inside app.montage resolve"); + return NVRDataModel.getMonitors(0); + } + }, + url: "/monitors", + cache: false, + templateUrl: "templates/monitors.html", + controller: 'zmApp.MonitorCtrl', + + }) + + .state('app.events', { + data: { + requireLogin: true + }, + resolve: { + message: function (NVRDataModel) { + //console.log("Inside app.events resolve"); + return NVRDataModel.getMonitors(0); + } + }, + cache: false, + url: "/events/:id/:playEvent", + templateUrl: "templates/events.html", + controller: 'zmApp.EventCtrl', + + }) + + .state('app.lowversion', { + data: { + requireLogin: false + }, + + url: "/lowversion/:ver", + cache: false, + templateUrl: "templates/lowversion.html", + controller: 'zmApp.LowVersionCtrl', + + }) + + .state('app.importantmessage', { + data: { + requireLogin: false + }, + + cache: false, + url: "/importantmessage/:ver", + templateUrl: "templates/important_message.html", + controller: 'zmApp.ImportantMessageCtrl', + + }) + + .state('app.invalidapi', { + data: { + requireLogin: false + }, + + cache: false, + url: "/invalidapi", + templateUrl: "templates/invalidapi.html", + controller: 'zmApp.InvalidApiCtrl', + + }) + + .state('app.events-graphs', { + data: { + requireLogin: true + }, + cache: false, + url: "/events-graphs", + templateUrl: "templates/events-graphs.html", + controller: 'zmApp.EventsGraphsCtrl', + + }) + + .state('app.events-date-time-filter', { + data: { + requireLogin: true + }, + cache: false, + url: "/events-date-time-filter", + templateUrl: "templates/events-date-time-filter.html", + controller: 'zmApp.EventDateTimeFilterCtrl', + + }) + + .state('app.state', { + data: { + requireLogin: true + }, + cache: false, + url: "/state", + templateUrl: "templates/state.html", + controller: 'zmApp.StateCtrl', + + }) + + .state('app.devoptions', { + data: { + requireLogin: false + }, + url: "/devoptions", + cache: false, + templateUrl: "templates/devoptions.html", + controller: 'zmApp.DevOptionsCtrl', + }) + + .state('app.timeline', { + data: { + requireLogin: true + }, + resolve: { + message: function (NVRDataModel) { + //console.log("Inside app.events resolve"); + return NVRDataModel.getMonitors(0); + } + }, + url: "/timeline", + cache: false, + templateUrl: "templates/timeline.html", + controller: 'zmApp.TimelineCtrl', + + }) + + .state('app.eventserversettings', { + data: { + requireLogin: true + }, + resolve: { + message: function (NVRDataModel) { + return NVRDataModel.getMonitors(0); + } + }, + url: "/eventserversettings", + cache: false, + templateUrl: "templates/eventserversettings.html", + controller: 'zmApp.EventServerSettingsCtrl', + + }) + + .state('app.log', { + data: { + requireLogin: false + }, + url: "/log", + cache: false, + templateUrl: "templates/log.html", + controller: 'zmApp.LogCtrl', + + }) + + .state('app.wizard', { + data: { + requireLogin: false + }, + url: "/wizard", + cache: false, + templateUrl: "templates/wizard.html", + controller: 'zmApp.WizardCtrl', + + }) + + .state('app.zm-portal-login', { + data: { + requireLogin: false + }, + url: "/zm-portal-login", + cache: false, + templateUrl: "templates/zm-portal-login.html", + controller: 'zmApp.PortalLoginCtrl', + nativeTransitions: null // disable for speed + + }) + + .state('app.first-use', { + data: { + requireLogin: false + }, + url: "/first-use", + cache: false, + templateUrl: "templates/first-use.html", + controller: 'zmApp.FirstUseCtrl', + + }) + + .state('app.montage-history', { + data: { + requireLogin: true + }, + resolve: { + message: function (NVRDataModel) { + //console.log("Inside app.events resolve"); + return NVRDataModel.getMonitors(0); + } + + }, + cache: false, + url: "/montage-history", + templateUrl: "templates/montage-history.html", + controller: 'zmApp.MontageHistoryCtrl', + params: { + minimal: false, + isRefresh: false + }, + + }) + + .state('app.montage', { + data: { + requireLogin: true + }, + resolve: { + message: function (NVRDataModel) { + //console.log("Inside app.events resolve"); + return NVRDataModel.getMonitors(0); + } + + }, + url: "/montage", + cache: false, + templateUrl: "templates/montage.html", + controller: 'zmApp.MontageCtrl', + params: { + minimal: false, + isRefresh: false + }, + + }); + + // We are NOT going to default route. Routing to a view will start on + // a broadcast of "init-complete" + + }); //config diff --git a/www/templates/events.html b/www/templates/events.html index 01aef4a8..5666ea61 100644 --- a/www/templates/events.html +++ b/www/templates/events.html @@ -139,7 +139,7 @@ <figure class = "animated slideInLeft" style="display:inline-block"> <!--{{event.Event.baseURL}} p:{{event.Event.imageMode}}--> <figcaption class="smallnote"><span translate="kFrame"></span>:{{alarm.frameid}},<span translate="kScore"></span>:{{alarm.score}}, <span translate="kTime"></span>: {{prettifyTimeSec(alarm.time)}}</figcaption> - <img ng-if="event.Event.imageMode=='path'" ng-src="{{event.Event.baseURL}}/index.php?view=image&path={{event.Event.relativePath}}{{outlineMotion? alarm.aname:alarm.fname}}&height=380" fallback-src="{{event.Event.baseURL}}/index.php?view=image&path={{event.Event.relativePath}}{{alarm.fname}}&height=380"" style="width: auto; height: auto;max-width: 100%;max-height: 170px" on-tap="showImage(event.Event.baseURL,event.Event.relativePath,alarm.fname, alarm.frameid, event.Event.Id, event.Event.imageMode, alarm.id, alarm_images, $index)" /> + <img ng-if="event.Event.imageMode=='path'" ng-src="{{event.Event.baseURL}}/index.php?view=image&path={{event.Event.relativePath}}{{outlineMotion? alarm.aname:alarm.fname}}&height=380" fallback-src="{{event.Event.baseURL}}/index.php?view=image&path={{event.Event.relativePath}}{{alarm.fname}}&height=380" style="width: auto; height: auto;max-width: 100%;max-height: 170px" on-tap="showImage(event.Event.baseURL,event.Event.relativePath,alarm.fname, alarm.frameid, event.Event.Id, event.Event.imageMode, alarm.id, alarm_images, $index)" /> <img ng-if="event.Event.imageMode=='fid'" ng-src="{{event.Event.baseURL}}/index.php?view=image&fid={{alarm.id}}{{outlineMotionParam}}" fallback-src="{{event.Event.baseURL}}/index.php?view=image&fid={{alarm.id}}" style="width: auto; height: auto;max-width: 100%;max-height: 170px" on-tap="showImage(event.Event.baseURL,event.Event.relativePath,alarm.fname, alarm.frameid, event.Event.Id, event.Event.imageMode, alarm.id, alarm_images, $index)" /> </figure> diff --git a/www/templates/menu.html b/www/templates/menu.html new file mode 100644 index 00000000..3caacfd2 --- /dev/null +++ b/www/templates/menu.html @@ -0,0 +1,119 @@ +<ion-side-menus delegate-handle="sideMenu" ng-cloak> + <ion-side-menu-content> + <ion-nav-bar class="bar-stable nav-title-slide-ios7"> + <ion-nav-back-button class="button-icon"> + <span class="icon ion-ios7-arrow-left"></span> + </ion-nav-back-button> + </ion-nav-bar> + <ion-nav-view></ion-nav-view> + </ion-side-menu-content> + <ion-side-menu> + <ion-header-bar class="bar bar-header bar-stable"> + <h1 class="title">{{'kMenuOptions'|translate}}</h1> + </ion-header-bar> + <ion-content has-header="true" mouse-wheel-scroll> + <!-- <ion-scroll scrollbar-y="false" style="height:100%" >--> + <ion-list> + <ion-item href="#/app/montage" menu-close> + <!--<span ng-if="$root.runMode=='lowbw'" style="float:right;margin-top:-18px;background-color:#f1c40f;color:#000;font-size:11px;opacity:0.7;width:20px;border-radius: 0px 0px 5px 5px;display:inline-block;text-align:center;"> <i class="icon ion-arrow-graph-down-left"></i> </span>--> + <span class=" item-icon-left"> + <i class="icon ion-grid"></i> + </span>{{'kMenuMontage'|translate}} + </ion-item> + + <ion-item href="#/app/timeline" menu-close> + <span class=" item-icon-left"> + <i class="icon ion-android-time"></i> + </span>{{'kMenuTimeline'|translate}} + </ion-item> + <ion-item href="#/app/events/0/false" menu-close> + <span class=" item-icon-left"> + <i class="icon ion-ios-calendar-outline"></i> + </span>{{'kMenuEvents'|translate}} + </ion-item> + + <ion-item href="#/app/montage-history" menu-close> + <span class=" item-icon-left"> + <i class="icon ion-ios-keypad-outline"></i> + </span>{{'kMenuEventMontage'|translate}} + </ion-item> + + + <ion-item href="#/app/monitors" menu-close> + <span class=" item-icon-left"> + <i class="icon ion-ios-videocam-outline"></i> + </span>{{'kMenuMonitors'|translate}} + </ion-item> + <ion-item href="#/app/state" menu-close> + <span class=" item-icon-left"> + <i class="icon ion-information-circled"></i> + </span> {{'kMenuSystemStatus'|translate}} + </ion-item> + <ion-item nav-clear menu-close href="#/app/login/false"> + <span class=" item-icon-left"> + <i class="icon ion-person"></i> + {{'kMenuZMSettings'|translate}} + <!--<span class="item-note" style="width:90px"> + {{$root.getProfileName();}} + </span>--> + <span style="float:right; margin-top:-18px;background-color:#444444;color:#fff;font-size:11px;opacity:0.7;width:90px;border-radius: 0px 0px 5px 5px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;display:inline-block;text-align:center;"> {{$root.getProfileName();}} </span> + </span> + </ion-item> + <ion-item nav-clear menu-close href="#/app/devoptions"> + <span class=" item-icon-left"> + <i class="icon ion-settings"></i> + </span> {{'kMenuDevSettings'|translate}} + </ion-item> + <div ng-controller="MenuController"> + <ion-item ng-click="switchLang()" nav-clear menu-close href=""> + <span class=" item-icon-left"> + <i class="icon ion-earth"></i> + </span> {{'kLanguage'|translate}} + </ion-item> + </div> + <ion-item nav-clear menu-close href="#/app/help"> + <span class=" item-icon-left"> + <i class="icon ion-help"></i> + </span> {{'kMenuHelp'|translate}} + </ion-item> + <ion-item nav-clear menu-close href="#/app/wizard"> + <span class=" item-icon-left"> + <i class="icon ion-wand"></i> + </span> {{'kMenuWizard'|translate}} + </ion-item> + <div ng-if="$root.showBlog"> + <ion-item nav-clear menu-close href="#/app/news"> + <span class=" item-icon-left"> + <i class="icon ion-radio-waves"></i> + </span>{{'kMenuNews'|translate}}<span style="color:#268d3a;"> {{$root.newBlogPost}}</span> + </ion-item> + </div> + <ion-item nav-clear menu-close href="#/app/log"> + <span class=" item-icon-left"> + <i class="icon ion-clipboard"></i> + </span> {{'kMenuLogs'|translate}} + </ion-item> + <div ng-if="$root.newVersionAvailable && $root.platformOS=='desktop'"> + <ion-item nav-clear menu-close href=""> + <span class=" item-icon-left"> + <i class="icon ion-email-unread"></i> + </span> <span style="color:#268d3a;">{{$root.newVersionAvailable}}</span> + </ion-item> + </div> + <div ng-if="$root.platformOS=='android'"> + <ion-item ng-click="$root.exitApp();"> + <span class=" item-icon-left"> + <i class="icon ion-close-circled"></i> + </span> {{'kMenuExit'|translate}} + </ion-item> + </div> + <ion-item style="color:rgb(106, 106, 106); font-size:90%;"> + <i class="ion-ios-location"></i> {{$root.getLocalTimeZone();}} + <br/> + <span ng-if="$root.isTzSupported()"><i class="icon icon-server"></i> {{$root.getServerTimeZoneNow();}} </span> + </ion-item> + </ion-list> + <!--</ion-scroll>--> + </ion-content> + </ion-side-menu> +</ion-side-menus>
\ No newline at end of file diff --git a/www/templates/monitors.html b/www/templates/monitors.html index cd9e8e8e..9bd2d5fa 100644 --- a/www/templates/monitors.html +++ b/www/templates/monitors.html @@ -50,7 +50,7 @@ </p> <div style="float:right;"> <a class="button button-small icon icon-left icon ion-gear-a" href="" ng-click="changeConfig(monitor.Monitor.Name, monitor.Monitor.Id,monitor.Monitor.Enabled,monitor.Monitor.Function);">{{'kConfiguration' | translate}}</a> - <a class="button button-small icon icon-left ion-calendar" href="#/events/{{monitor.Monitor.Id}}/false">{{'kEventsCap'|translate}}</a> + <a class="button button-small icon icon-left ion-calendar" href="#/app/events/{{monitor.Monitor.Id}}/false">{{'kEventsCap'|translate}}</a> <a class="button button-small icon icon-left ion-ios-eye" ng-click="openModal(monitor.Monitor.Id, monitor.Monitor.Controllable, monitor.Monitor.ControlId, monitor.Monitor.connKey, monitor)">{{'kLiveView' | translate}}</a> </div> </div> diff --git a/www/templates/montage.html b/www/templates/montage.html index e591179f..336ef214 100644 --- a/www/templates/montage.html +++ b/www/templates/montage.html @@ -167,7 +167,7 @@ </nav> <span class="modal-alarm-badge"> <a data-badge="{{$root.alarmCount}}" class="animated infinite tada button icon ion-ios-bell notification-badge button-assertive" - ng-click="handleAlarmsWhileMinimized();" ng-if="$root.isAlarm"></a> + ng-click="handleAlarmsWhileMinimized();" ng-if="!$root.isAlarm"></a> </span> </div> <br/> diff --git a/www/templates/timeline.html b/www/templates/timeline.html index a64edceb..02bf0eb4 100644 --- a/www/templates/timeline.html +++ b/www/templates/timeline.html @@ -54,3 +54,4 @@ <!-- --> </div> </div> + |
