diff options
| author | Pliable Pixels <pliablepixels@users.noreply.github.com> | 2020-09-05 08:00:45 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-05 08:00:45 -0400 |
| commit | 058fcb07bf1529339fa5c18cab233c48cdce6a1b (patch) | |
| tree | 4900fbda885dc985cd936bb20cdac63284fce604 /www | |
| parent | e54b8659ff385c667b7590bc383e8315769d47a7 (diff) | |
| parent | 1a4449aeadeb88db971f0960d14fd679a7364dbb (diff) | |
Merge pull request #963 from lucasnz/master
Event list improvements
Diffstat (limited to 'www')
| -rw-r--r-- | www/js/DevOptionsCtrl.js | 29 | ||||
| -rw-r--r-- | www/js/EventCtrl.js | 483 | ||||
| -rw-r--r-- | www/js/EventDateTimeFilterCtrl.js | 71 | ||||
| -rw-r--r-- | www/js/MontageCtrl.js | 9 | ||||
| -rw-r--r-- | www/js/NVR.js | 6 | ||||
| -rwxr-xr-x | www/js/app.js | 2 | ||||
| -rw-r--r-- | www/lang/locale-en.json | 2 | ||||
| -rw-r--r-- | www/templates/devoptions.html | 11 | ||||
| -rw-r--r-- | www/templates/events.html | 114 | ||||
| -rw-r--r-- | www/templates/menu.html | 4 |
10 files changed, 401 insertions, 330 deletions
diff --git a/www/js/DevOptionsCtrl.js b/www/js/DevOptionsCtrl.js index 2ad40bfa..d735f967 100644 --- a/www/js/DevOptionsCtrl.js +++ b/www/js/DevOptionsCtrl.js @@ -181,6 +181,35 @@ angular.module('zmApp.controllers').controller('zmApp.DevOptionsCtrl', ['$scope' }); }; + $scope.selectEventViewThumbs = function() { + + var buttons = [ + { text: $translate.instant('kNone').toLowerCase(), value:'none' }, + { text: 'snapshot', value:'snapshot' }, + { text: 'objdetect', value:'objdetect' }, + { text: 'objdetect_jpg', value:'objdetect_jpg' }, + { text: 'objdetect_gif', value:'objdetect_gif' }, + + ]; + + $ionicActionSheet.show({ + titleText: $translate.instant('kSelect'), + buttons: buttons, + + cancelText: $translate.instant('kButtonCancel'), + cancel: function() { + NVR.debug ('obfuscation actionsheet cancelled'); + }, + buttonClicked: function(index) { + + $scope.loginData.eventViewThumbs = buttons[index].value; + NVR.debug ('changed event view thumbs to:'+$scope.loginData.eventViewThumbs ); + return true; + }, + + }); + }; + $scope.saveDevOptions = function () { saveDevOptions(); diff --git a/www/js/EventCtrl.js b/www/js/EventCtrl.js index a6e89d6c..d7dd4fc1 100644 --- a/www/js/EventCtrl.js +++ b/www/js/EventCtrl.js @@ -48,7 +48,6 @@ angular.module('zmApp.controllers') var currEventsPage = 1; var maxEventsPage = 1; var moreEvents; - var pageLoaded; var enableLoadMore; var lData; var showHiddenMonitors; @@ -58,14 +57,17 @@ angular.module('zmApp.controllers') var nolangTo; var broadcastHandles = []; var intervalReloadEvents; + var eventHeight = 0; + var currentPagePosition = 0; + var currentPageLength = 0; + var currentPageData; + var loadMoreTime; + var maxEventsToLoad = 5; //limit to 5 to minimise memory usage when displaying gifs $scope.typeOfFrames = $translate.instant('kShowTimeDiffFrames'); $scope.outlineMotion = false; $scope.outlineMotionParam = "&show=capture"; - - - var eventsListScrubHeight = eventsListScrubHeight; - var eventsListDetailsHeight = eventsListDetailsHeight; + $scope.eventsBeingLoaded = true; var eHandle; var scrubOngoing = false; @@ -229,40 +231,29 @@ angular.module('zmApp.controllers') document.addEventListener("pause", onPause, false); //console.log("I got STATE PARAM " + $stateParams.id); $scope.id = parseInt($stateParams.id, 10); - if (isNaN($scope.id)) $scope.id = 0; $scope.showEvent = $stateParams.playEvent || false; $scope.monitors = NVR.getMonitorsNow(); + //console.log("lastCheckTime: " + $stateParams.lastCheckTime); + if ($stateParams.lastCheckTime != undefined && $stateParams.lastCheckTime != '' && moment($stateParams.lastCheckTime).isValid()) { + $rootScope.fromString = $stateParams.lastCheckTime; + var mToDate = moment().tz(NVR.getTimeZoneNow()); + $rootScope.toString = mToDate + .format("YYYY-MM-DD") + " " + mToDate.format("HH:mm:ss"); + $rootScope.isEventFilterOn = true; + $rootScope.fromDate = moment($rootScope.fromString).toDate(); + $rootScope.fromTime = moment($rootScope.fromString).toDate(); + $rootScope.toDate = moment($rootScope.toString).toDate(); + $rootScope.toTime = moment($rootScope.toString).toDate(); + //console.log("toString: " + $rootScope.toString); + } + //console.log("BEFORE ENTER >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); NVR.log("EventCtrl called with: E/MID=" + $scope.id + " playEvent = " + $scope.showEvent); - - - // This is the only view that hardcodes row size due to - // collection repeat, so lets re-get the text size if it has changed - // note that there may be a delay as its a callback - so might involve - // a UI jiggle - - /* if (window.cordova) - MobileAccessibility.getTextZoom(getTextZoomCallback);*/ - - eventsListDetailsHeight = parseInt(zm.eventsListDetailsHeight * $rootScope.textScaleFactor); - eventsListScrubHeight = parseInt(zm.eventsListScrubHeight * $rootScope.textScaleFactor); - - - if (NVR.getLogin().enableThumbs) { - // NVR.debug("--> thumbnail means increasing row size"); - eventsListScrubHeight = 370; - eventsListDetailsHeight = 330; - - } - - NVR.debug(">>>height of list/scrub set to " + eventsListDetailsHeight + " and " + eventsListScrubHeight); - - pageLoaded = false; enableLoadMore = true; $scope.mycarousel = { @@ -397,6 +388,8 @@ angular.module('zmApp.controllers') function getInitialEvents() { NVR.debug("getInitialEvents called"); + $scope.eventsBeingLoaded = true; + $ionicScrollDelegate.$getByHandle("mainScroll").scrollTop(); var lData = NVR.getLogin(); // If you came from Monitors, disregard hidden monitors in montage @@ -407,6 +400,8 @@ angular.module('zmApp.controllers') $scope.monitors = message; currEventsPage = 1; maxEventsPage = 1; + currentPagePosition = 0; + currentPageLength = 0; if ($scope.monitors.length == 0) { var pTitle = $translate.instant('kNoMonitors'); @@ -426,11 +421,23 @@ angular.module('zmApp.controllers') } $scope.events = []; + + if ($scope.id) { + $rootScope.monitorsFilter = "/MonitorId =:" + $scope.id; + //console.log("monitors.length: " + $scope.monitors.length); + for (var i=0; i <= $scope.monitors.length; i++) { + //console.log("i: " + i); + if ($scope.monitors[i] != undefined) { + //console.log("$scope.monitors[i].Id: " + $scope.monitors[i].Monitor.Id); + if ($scope.monitors[i].Monitor.Id == $scope.id) + $scope.monitors[i].Monitor.isChecked = true; + else + $scope.monitors[i].Monitor.isChecked = false; + } + } + $scope.id = 0; + } - // First get total pages and then - // start from the latest. If this fails, nothing displays - - NVR.debug("EventCtrl: grabbing # of event pages"); nolangFrom = ""; nolangTo = ""; if ($rootScope.fromString) @@ -439,122 +446,44 @@ angular.module('zmApp.controllers') nolangTo = moment($rootScope.toString).locale('en').format("YYYY-MM-DD HH:mm:ss"); //NVR.debug ("GETTING EVENTS USING "+$scope.id+" "+nolangFrom+" "+ nolangTo); - - NVR.debug("EventCtrl: grabbing events for: id=" + $scope.id + " Date/Time:" + $rootScope.fromString + "-" + $rootScope.toString); - nolangFrom = ""; - nolangTo = ""; - if ($rootScope.fromString) - 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"); + + if ($scope.loginData.eventViewThumbs != 'objdetect_gif') { + maxEventsToLoad = 50; //limit to 5 to minimise memory usage when displaying gifs + } + NVR.debug("maxEventsToLoad: " + maxEventsToLoad); NVR.getEvents($scope.id, currEventsPage, "", nolangFrom, nolangTo, false, $rootScope.monitorsFilter) .then(function (data) { - - pageLoaded = true; - //$scope.viewTitle.title = data.pagination.count; - // console.log(JSON.stringify(data.pagination)); if (data.pagination && data.pagination.pageCount) maxEventsPage = data.pagination.pageCount; - NVR.debug("We have a total of " + maxEventsPage + " and are at page=" + currEventsPage); + NVR.debug("maxEventsPage: " + maxEventsPage + ", currEventsPage: " + currEventsPage); // console.log ("WE GOT EVENTS="+JSON.stringify(data)); - var myevents = data.events; - - NVR.debug("EventCtrl: success, got " + myevents.length + " events"); - var loginData = NVR.getLogin(); - - //console.log ("-------->MON LEN"+$scope.monitors.length); - - for (var i = 0; i < myevents.length; i++) { - - var idfound = true; - if (loginData.persistMontageOrder) { - idfound = false; - for (var ii = 0; ii < $scope.monitors.length; ii++) { - if ($scope.monitors[ii].Monitor.Id == myevents[i].Event.MonitorId && (NVR.isNotHidden(myevents[i].Event.MonitorId) || showHiddenMonitors)) { - // console.log ("FOUND IT"); - - idfound = true; - break; - } - } - } - - //console.log ("IDFOUND="+idfound + " AND MON LEN="+$scope.monitors.length); - - myevents[i].Event.humanizeTime = humanizeTime(myevents[i].Event.StartTime); - myevents[i].Event.streamingURL = NVR.getStreamingURL(myevents[i].Event.MonitorId); - myevents[i].Event.recordingURL = NVR.getRecordingURL(myevents[i].Event.MonitorId); - myevents[i].Event.imageMode = NVR.getImageMode(myevents[i].Event.MonitorId); - - //console.log ("***** MULTISERVER STREAMING URL FOR EVENTS " + myevents[i].Event.streamingURL); - - // console.log ("***** MULTISERVER BASE URL FOR EVENTS " + myevents[i].Event.recordingURL); - - myevents[i].Event.MonitorName = NVR.getMonitorName(myevents[i].Event.MonitorId); - myevents[i].Event.ShowScrub = false; - myevents[i].Event.height = eventsListDetailsHeight; - // now construct base path - - - // get thumbW/H - - var tempMon = NVR.getMonitorObject(myevents[i].Event.MonitorId); - if (tempMon != undefined) { - - var mw = parseInt(tempMon.Monitor.Width); - var mh = parseInt(tempMon.Monitor.Height); - - var mo = parseInt(tempMon.Monitor.Orientation); - myevents[i].Event.Rotation = ''; - - var th = computeThumbnailSize(mw, mh, mo); - myevents[i].Event.thumbWidth = th.w; - myevents[i].Event.thumbHeight = th.h; - } - - // in multiserver BasePath is login url for frames - // http://login.url/index.php?view=frame&eid=19696772&fid=21 - - // console.log ("COMPARING "+NVR.getLogin().url+ " TO " +myevents[i].Event.recordingURL); + //NVR.debug("EventCtrl: success, got " + data.events.length + " events"); + loadEvents(data); - - - myevents[i].Event.videoPath = myevents[i].Event.recordingURL + "/index.php?view=view_video&eid=" + myevents[i].Event.Id; - - // if (idfound) - if (idfound) { - - //NVR.debug ("PUSHING "+JSON.stringify(myevents[i])); - $scope.events.push(myevents[i]); - //console.log ("SCOPE EVENTS LEN="+$scope.events.length); - } else { - //NVR.debug ("Skipping Event MID = " + myevents[i].Event.MonitorId); - } - - } //for - - //$scope.events = myevents; + currentPageData = data; + //$scope.events = data.events; // we only need to stop the template from loading when the list is empty // so this can be false once we have _some_ content - // FIXME: check reload $scope.eventsBeingLoaded = false; + moreEvents = true; // to avoid only few events being displayed // if last page has less events //console.log("**Loading Next Page ***"); - if (myevents.length < 50) { + if ($scope.events < maxEventsToLoad) { //console.log ("EVENTS LOADED="+JSON.stringify($scope.events)); NVR.debug("EventCtrl:loading one more page just in case we don't have enough to display"); loadMore(); } + navTitle(); }); - + loadMoreTime = Date.now(); } //------------------------------------------------------- @@ -1159,6 +1088,54 @@ angular.module('zmApp.controllers') reload: true });*/ }; + + $scope.nextEventsLoad = function () { + NVR.debug("nextEventsLoad called"); + $scope.nextEvents = false; + //$scope.eventsBeingLoaded = true; + var lData = NVR.getLogin(); + + currEventsPage = 1; + maxEventsPage = 1; + currentPagePosition = 0; + currentPageLength = 0; + + nolangFrom = ""; + nolangTo = ""; + if ($rootScope.toString && $rootScope.fromString) { + //nolangTo = moment($rootScope.fromString).locale('en').format("YYYY-MM-DD HH:mm:ss"); + nolangTo = moment($scope.events[$scope.events.length-1].Event.StartTime).subtract(1, 'seconds').locale('en').format("YYYY-MM-DD HH:mm:ss"); + //$rootScope.fromString = new Date('01/01/2000'); + nolangFrom = moment(new Date('01/01/2000')).locale('en').format("YYYY-MM-DD HH:mm:ss"); + } + + //NVR.debug ("GETTING EVENTS USING "+$scope.id+" "+nolangFrom+" "+ nolangTo); + NVR.debug("EventCtrl: grabbing events for: id=" + $scope.id + " Date/Time:" + nolangFrom + + "-" + nolangTo); + + NVR.getEvents($scope.id, currEventsPage, "", nolangFrom, nolangTo, false, $rootScope.monitorsFilter) + .then(function (data) { + // console.log(JSON.stringify(data.pagination)); + if (data.pagination && data.pagination.pageCount) + maxEventsPage = data.pagination.pageCount; + + NVR.debug("maxEventsPage: " + maxEventsPage + ", currEventsPage: " + currEventsPage); + + // console.log ("WE GOT EVENTS="+JSON.stringify(data)); + + //NVR.debug("EventCtrl: success, got " + data.events.length + " events"); + loadEvents(data); + + currentPageData = data; + //$scope.events = data.events; + // we only need to stop the template from loading when the list is empty + // so this can be false once we have _some_ content + // FIXME: check reload + //$scope.eventsBeingLoaded = false; + moreEvents = true; + }); + loadMoreTime = Date.now(); + }; //---------------------------------------------------------------- // Alarm notification handling @@ -2028,19 +2005,33 @@ angular.module('zmApp.controllers') $ionicSideMenuDelegate.toggleLeft(); }; - $scope.scrollPosition = function () { - if (!$ionicScrollDelegate.$getByHandle("mainScroll")) return ""; - if (!$ionicScrollDelegate.$getByHandle("mainScroll").getScrollPosition()) return ""; + $scope.scrolling = function() { + //console.log("scrolling : When Scrolling"); + navTitle(); + }; + + function navTitle() { + if (!$ionicScrollDelegate.$getByHandle("mainScroll")) $scope.navTitle = ""; + if (!$ionicScrollDelegate.$getByHandle("mainScroll").getScrollPosition()) $scope.navTitle = ""; var scrl = parseFloat($ionicScrollDelegate.$getByHandle("mainScroll").getScrollPosition().top); - var item = Math.round(scrl / eventsListDetailsHeight); + if (eventHeight == 0 && !$scope.eventsBeingLoaded && document.getElementById('item-0') != null) { + eventHeight = document.getElementById('item-0').offsetHeight; + NVR.debug("scrl: " + scrl + ", eventHeight: " + eventHeight); + } + var item = 0; + if (eventHeight) { + item = Math.floor(scrl / eventHeight); + } + //NVR.debug("scrl: " + scrl + ", events[0].Event.Height: " + eventHeight + ", item: " + item); if ($scope.events == undefined || !$scope.events.length || $scope.events[item] == undefined) { - return ""; + $scope.navTitle = ""; } else { //return prettifyDate($scope.events[item].Event.StartTime); - return ($scope.events[item].Event.humanizeTime); + $scope.navTitle = ($scope.events[item].Event.humanizeTime); } + $scope.$evalAsync(); //return Math.random(); - }; + } //------------------------------------------------------------------------- // called when user switches to background @@ -2112,8 +2103,6 @@ angular.module('zmApp.controllers') }; function toggleGroup(event, ndx, frames, groupType) { - - // If we are here and there is a record of a previous scroll // then we need to scroll back to hide that view if (scrollbynumber) { @@ -2130,7 +2119,6 @@ angular.module('zmApp.controllers') NVR.debug("EventCtrl:Old event scrub will hide now"); oldEvent.Event.ShowScrub = false; - oldEvent.Event.height = eventsListDetailsHeight; oldEvent = ""; } @@ -2162,7 +2150,6 @@ angular.module('zmApp.controllers') // $ionicListDelegate.canSwipeItems(false); //NVR.debug ("Disabling flag swipe as alarms are swipable"); $scope.alarm_images = []; - event.Event.height = (eventsListDetailsHeight + eventsListScrubHeight); $ionicScrollDelegate.resize(); var myurl = loginData.apiurl + '/events/' + event.Event.Id + ".json?"+$rootScope.authSession; NVR.log("API for event details" + myurl); @@ -2266,7 +2253,6 @@ angular.module('zmApp.controllers') }; - event.Event.height = (eventsListDetailsHeight + eventsListScrubHeight); $ionicScrollDelegate.resize(); $scope.mycarousel.index = 0; $scope.ionRange.index = 1; @@ -2376,15 +2362,6 @@ angular.module('zmApp.controllers') // console.log("top location is " + toplocation); var distdiff = parseInt($rootScope.devHeight) - toplocation - objheight; // console.log("*****Space at bottom is " + distdiff); - - if (distdiff < eventsListScrubHeight) // size of the scroller with bars - { - scrollbynumber = eventsListScrubHeight - distdiff; - $ionicScrollDelegate.$getByHandle("mainScroll").scrollBy(0, scrollbynumber, true); - - // we need to scroll up to make space - } - } // end of groupType == scrub } // end of ShowScrub == true else { @@ -2394,7 +2371,6 @@ angular.module('zmApp.controllers') // NVR.debug ("enabling options swipe"); $ionicSideMenuDelegate.canDragContent(true); - event.Event.height = eventsListDetailsHeight; $ionicScrollDelegate.resize(); if (scrollbynumber) { @@ -2417,7 +2393,6 @@ angular.module('zmApp.controllers') $scope.isGroupShown = function (event) { // console.log ("IS SHOW INDEX is " + ndx); //console.log ("SHOW GROUP IS " + showGroup); - return (event == undefined) ? false : event.Event.ShowScrub; }; @@ -2740,6 +2715,7 @@ angular.module('zmApp.controllers') //-------------------------------------------------------- $scope.moreDataCanBeLoaded = function () { + //console.log(new Date() + ' ' + moreEvents); return moreEvents; }; @@ -2770,9 +2746,18 @@ angular.module('zmApp.controllers') // except greater page limits than reported //console.log("***** LOADING MORE INFINITE SCROLL ****"); + loadMoreTime = Date.now(); + + if (currentPagePosition > 0 && currentPagePosition >= currentPageLength) { + currEventsPage++; + currentPagePosition = 0; + currentPageLength = 0; + } + NVR.debug("EventCtrl:loadMore() currEventsPage: " + currEventsPage + ", currentPagePosition: " + currentPagePosition + ", currentPageLength: " + currentPageLength); - if ((currEventsPage >= maxEventsPage) && (pageLoaded)) { + if (currEventsPage > maxEventsPage) { moreEvents = false; + $scope.nextEvents = true; NVR.debug("No more - We have a total of " + maxEventsPage + " and are at page=" + currEventsPage); // console.log("*** At Page " + currEventsPage + " of " + maxEventsPage + ", not proceeding"); @@ -2780,10 +2765,10 @@ angular.module('zmApp.controllers') return; } - currEventsPage++; if (!enableLoadMore) { $ionicLoading.hide(); moreEvents = false; // Don't ion-scroll till enableLoadMore is true; + $scope.nextEvents = true; $scope.$broadcast('scroll.infiniteScrollComplete'); // console.log("**** LOADMORE ARTIFICALLY DISABLED"); @@ -2813,88 +2798,131 @@ angular.module('zmApp.controllers') if ($rootScope.toString) nolangTo = moment($rootScope.toString).locale('en').format("YYYY-MM-DD HH:mm:ss"); + if (currentPagePosition && currentPageData) { + loadEvents(currentPageData); + //console.log("Got new page of events"); + moreEvents = true; + } + else { NVR.getEvents($scope.id, currEventsPage, loadingStr, nolangFrom, nolangTo, false,$rootScope.monitorsFilter) - .then(function (data) { - var loginData = NVR.getLogin(); - // console.log("Got new page of events with Page=" + eventsPage); - var myevents = data.events; + .then( function (data) { + // console.log(JSON.stringify(data.pagination)); + if (data.pagination && data.pagination.pageCount) + maxEventsPage = data.pagination.pageCount; + loadEvents(data); + currentPageData = data; + //console.log("Got new page of events"); + moreEvents = true; + }, - for (var i = 0; i < myevents.length; i++) { - - var idfound = true; - var ld = NVR.getLogin(); + function (error) { + // console.log("*** No More Events to Load, Stop Infinite Scroll ****"); + moreEvents = false; + $ionicLoading.hide(); + }); + } + } - if (ld.persistMontageOrder) { - idfound = false; - for (var ii = 0; ii < $scope.monitors.length; ii++) { - if ($scope.monitors[ii].Monitor.Id == myevents[i].Event.MonitorId && (NVR.isNotHidden(myevents[i].Event.MonitorId) || showHiddenMonitors)) { + $scope.loadMore = function () { + var now = Date.now(); + if (now - loadMoreTime > 1500) { + NVR.debug("$scope.loadMore > loadMore() ... delta: " + (now - loadMoreTime)); + loadMore(); + $scope.$broadcast('scroll.infiniteScrollComplete'); + } + else { + NVR.debug("$scope.loadMore ... delta: " + (now - loadMoreTime)); + $timeout(function () { + $scope.$broadcast('scroll.infiniteScrollComplete'); + }, 250); + } + }; + + function loadEvents(data) { + var loginData = NVR.getLogin(); + var myevents = data.events; + NVR.debug("EventCtrl:loadEvents() myevents.length: " + myevents.length + ", currEventsPage: " + currEventsPage + ", currentPagePosition: " + currentPagePosition); + + if (data.events.length == 0) { + NVR.debug("EventCtrl:loadEvents() no events so we must have reached the end."); + moreEvents = false; + $ionicLoading.hide(); + currEventsPage++; + return; + } - //console.log ( $scope.monitors[ii].Monitor.Id + " MATCHES " + myevents[i].Event.MonitorId); - idfound = true; + //console.log ("-------->MON LEN"+$scope.monitors.length); + currentPageLength = myevents.length; + var eventsLoaded = 0; + var prevPagePosition = currentPagePosition; + NVR.debug("maxEventsToLoad: " + maxEventsToLoad); + for (currentPagePosition; currentPagePosition < myevents.length && eventsLoaded < maxEventsToLoad; currentPagePosition++) { + var idfound = true; + if (loginData.persistMontageOrder) { + idfound = false; + for (var i = 0; i < $scope.monitors.length; i++) { + if ($scope.monitors[i].Monitor.Id == myevents[currentPagePosition].Event.MonitorId && (NVR.isNotHidden(myevents[currentPagePosition].Event.MonitorId) || showHiddenMonitors)) { + // console.log ("FOUND IT"); - break; - } + //console.log ( $scope.monitors[i].Monitor.Id + " MATCHES " + myevents[currentPagePosition].Event.MonitorId); + idfound = true; + break; } } + } - myevents[i].Event.humanizeTime = humanizeTime(myevents[i].Event.StartTime); - myevents[i].Event.MonitorName = NVR.getMonitorName(myevents[i].Event.MonitorId); - // now construct base path - - myevents[i].Event.streamingURL = NVR.getStreamingURL(myevents[i].Event.MonitorId); - myevents[i].Event.recordingURL = NVR.getRecordingURL(myevents[i].Event.MonitorId); - myevents[i].Event.imageMode = NVR.getImageMode(myevents[i].Event.MonitorId); - // console.log ("***** MULTISERVER STREAMING URL FOR EVENTS " + myevents[i].Event.streamingURL); - - // console.log ("***** MULTISERVER BASE URL FOR EVENTS " + myevents[i].Event.recordingURL); + //console.log ("IDFOUND="+idfound + " AND MON LEN="+$scope.monitors.length); - myevents[i].Event.ShowScrub = false; - myevents[i].Event.height = eventsListDetailsHeight; + myevents[currentPagePosition].Event.humanizeTime = humanizeTime(myevents[currentPagePosition].Event.StartTime); + myevents[currentPagePosition].Event.streamingURL = NVR.getStreamingURL(myevents[currentPagePosition].Event.MonitorId); + myevents[currentPagePosition].Event.recordingURL = NVR.getRecordingURL(myevents[currentPagePosition].Event.MonitorId); + myevents[currentPagePosition].Event.imageMode = NVR.getImageMode(myevents[currentPagePosition].Event.MonitorId); - // get thumbW/H + // console.log ("***** MULTISERVER STREAMING URL FOR EVENTS " + myevents[currentPagePosition].Event.streamingURL); + // console.log ("***** MULTISERVER BASE URL FOR EVENTS " + myevents[currentPagePosition].Event.recordingURL); - var tempMon = NVR.getMonitorObject(myevents[i].Event.MonitorId); - if (tempMon != undefined) { - var mw = parseInt(tempMon.Monitor.Width); - var mh = parseInt(tempMon.Monitor.Height); - var mo = parseInt(tempMon.Monitor.Orientation); + myevents[currentPagePosition].Event.MonitorName = NVR.getMonitorName(myevents[currentPagePosition].Event.MonitorId); + myevents[currentPagePosition].Event.ShowScrub = false; + //myevents[currentPagePosition].Event.height = eventsListDetailsHeight; + // now construct base path - myevents[i].Event.Rotation = ''; + // get thumbW/H + var tempMon = NVR.getMonitorObject(myevents[currentPagePosition].Event.MonitorId); + if (tempMon != undefined) { + var mw = parseInt(tempMon.Monitor.Width); + var mh = parseInt(tempMon.Monitor.Height); + var mo = parseInt(tempMon.Monitor.Orientation); + myevents[currentPagePosition].Event.Rotation = ''; + var th = computeThumbnailSize(mw, mh, mo); + myevents[currentPagePosition].Event.thumbWidth = th.w; + myevents[currentPagePosition].Event.thumbHeight = th.h; + } - var th = computeThumbnailSize(mw, mh, mo); - myevents[i].Event.thumbWidth = th.w; - myevents[i].Event.thumbHeight = th.h; + // in multiserver BasePath is login url for frames + // http://login.url/index.php?view=frame&eid=19696772&fid=21 - } + // console.log ("COMPARING "+NVR.getLogin().url+ " TO " +myevents[currentPagePosition].Event.recordingURL); + myevents[currentPagePosition].Event.videoPath = myevents[currentPagePosition].Event.recordingURL + "/index.php?view=view_video&eid=" + myevents[currentPagePosition].Event.Id; - - myevents[i].Event.videoPath = myevents[i].Event.recordingURL + "/index.php?view=view_video&eid=" + myevents[i].Event.Id; + // if (idfound) + if (idfound) { - if (idfound) $scope.events.push(myevents[i]); + //NVR.debug ("PUSHING "+JSON.stringify(myevents[currentPagePosition])); + $scope.events.push(myevents[currentPagePosition]); + eventsLoaded++; + //console.log ("SCOPE EVENTS LEN="+$scope.events.length); + } else { + //NVR.debug ("Skipping Event MID = " + myevents[currentPagePosition].Event.MonitorId); } - //console.log("Got new page of events"); - moreEvents = true; - $scope.$broadcast('scroll.infiniteScrollComplete'); - }, - - function (error) { - // console.log("*** No More Events to Load, Stop Infinite Scroll ****"); - moreEvents = false; - $ionicLoading.hide(); - $scope.$broadcast('scroll.infiniteScrollComplete'); - - }); + } //for + + NVR.debug("EventCtrl:loadEvents() Events added to view: " + (currentPagePosition - prevPagePosition)); } - $scope.loadMore = function () { - loadMore(); - - }; - function recomputeThumbSize() { // NVR.debug("EventCtrl: recompute thumbnails"); @@ -2913,6 +2941,8 @@ angular.module('zmApp.controllers') $scope.events[i].Event.thumbWidth = th.w; $scope.events[i].Event.thumbHeight = th.h; //console.log ("Setting to "+th.w+"*"+th.h); + + eventHeight = document.getElementById('item-0').offsetHeight; } @@ -2924,12 +2954,9 @@ angular.module('zmApp.controllers') } function computeThumbnailSize(mw, mh, mo) { - - - - - tw = Math.min(Math.round(0.35 * $rootScope.devWidth), 200); - th = 150; + + tw = Math.round(0.9 * $rootScope.devWidth); + th = Math.round(0.7 * $rootScope.devHeight); var ratio = mw / mh; var result = { @@ -2956,15 +2983,17 @@ angular.module('zmApp.controllers') } if (mw > mh) { - ratio = mh / mw; mw = tw; - mh = tw * ratio; + mh = tw / ratio; + if (mh > th) { + mw = th * ratio; + mh = th; + } } else if (mh > mw) { - ratio = mw / mh; mh = th; mw = th * ratio; } else { - mw = tw; + mh = th; mw = tw; } mw = Math.round(mw); @@ -2979,14 +3008,20 @@ angular.module('zmApp.controllers') $scope.constructThumbnail = function (event) { var stream = ""; + //console.log(event.Event.Notes); + var snapshotFrame = NVR.getSnapshotFrame(); + if (($scope.loginData.eventViewThumbs.substring(0, 9) == 'objdetect') && event.Event.Notes.includes("detected:")) { + snapshotFrame = $scope.loginData.eventViewThumbs; + } stream = event.Event.recordingURL + "/index.php?view=image&fid=" + - NVR.getSnapshotFrame()+"&eid="+event.Event.Id + + snapshotFrame+"&eid="+event.Event.Id + "&width=" + event.Event.thumbWidth * 2 + "&height=" + event.Event.thumbHeight * 2; stream += $rootScope.authSession; stream += NVR.insertSpecialTokens(); + return stream; }; @@ -3020,7 +3055,7 @@ angular.module('zmApp.controllers') return stream; }; - + $scope.toggleObjectDetectionFilter = function () { var ld = NVR.getLogin(); @@ -3125,6 +3160,9 @@ angular.module('zmApp.controllers') NVR.debug("Reloading monitors"); maxEventsPage = 1; currEventsPage = 1; + currentLength = 0; + currentPagePosition = 0; + currentPageLength = 0; var refresh = NVR.getMonitors(1); refresh.then(function (data) { $scope.monitors = data; @@ -3142,6 +3180,7 @@ angular.module('zmApp.controllers') moreEvents = true; }); + $scope.$broadcast('scroll.refreshComplete'); } }]); diff --git a/www/js/EventDateTimeFilterCtrl.js b/www/js/EventDateTimeFilterCtrl.js index e2d7b22e..2de8dd15 100644 --- a/www/js/EventDateTimeFilterCtrl.js +++ b/www/js/EventDateTimeFilterCtrl.js @@ -63,6 +63,7 @@ angular.module('zmApp.controllers') $rootScope.toTime = ""; $rootScope.fromString = ""; $rootScope.toString = ""; + $rootScope.monitorsFilter = ''; // if you come here via the events pullup // you are looking at a specific monitor ID @@ -100,42 +101,54 @@ angular.module('zmApp.controllers') // don't root. //-------------------------------------------------------------------------- $scope.saveFilters = function () { - if (!$rootScope.fromDate) { - //console.log("RESET fromDate"); - $rootScope.fromDate = new Date(); - NVR.debug("DateTimeFilter: resetting from date"); - } + // only reset date/time if at least one of them is set. + if ($rootScope.fromDate || $rootScope.toDate || $rootScope.fromTime || $rootScope.toTime) { + if (!$rootScope.fromDate) { + //console.log("RESET fromDate"); + $rootScope.fromDate = new Date(); + NVR.debug("DateTimeFilter: resetting from date"); + } - if (!$rootScope.toDate) { - // console.log("RESET toDate"); - $rootScope.toDate = new Date(); - NVR.debug("DateTimeFilter: resetting to date"); - } + if (!$rootScope.toDate) { + // console.log("RESET toDate"); + $rootScope.toDate = new Date(); + NVR.debug("DateTimeFilter: resetting to date"); + } - if (!$rootScope.fromTime) { - // console.log("RESET fromTime"); - $rootScope.fromTime = new Date(99, 5, 24, 0, 0, 0, 0); //moment().format("hh:mm:ss"); - NVR.debug("DateTimeFilter: resetting from time"); - } + if (!$rootScope.fromTime) { + // console.log("RESET fromTime"); + $rootScope.fromTime = new Date(99, 5, 24, 0, 0, 0, 0); //moment().format("hh:mm:ss"); + NVR.debug("DateTimeFilter: resetting from time"); + } - if (!$rootScope.toTime) { - //console.log("RESET toTime"); - $rootScope.toTime = new Date(99, 5, 24, 23, 59, 59, 0); - //$rootScope.toTime = "01:01:02"; //moment().format("hh:mm:ss"); - NVR.debug("DateTimeFilter: resetting to time"); - } + if (!$rootScope.toTime) { + //console.log("RESET toTime"); + $rootScope.toTime = new Date(99, 5, 24, 23, 59, 59, 0); + //$rootScope.toTime = "01:01:02"; //moment().format("hh:mm:ss"); + NVR.debug("DateTimeFilter: resetting to time"); + } + + if ($rootScope.fromDate > $rootScope.toDate) { + NVR.log("From date > To Date, swapping"); + var t = $rootScope.fromDate; + $rootScope.fromDate = $rootScope.toDate; + $rootScope.toDate = t; + } + + $rootScope.fromString = moment($rootScope.fromDate).format("YYYY-MM-DD") + " " + moment($rootScope.fromTime).format("HH:mm:ss"); - if ($rootScope.fromDate > $rootScope.toDate) { - NVR.log("From date > To Date, swapping"); - var t = $rootScope.fromDate; - $rootScope.fromDate = $rootScope.toDate; - $rootScope.toDate = t; + $rootScope.toString = moment($rootScope.toDate).format("YYYY-MM-DD") + " " + moment($rootScope.toTime).format("HH:mm:ss"); + } + else { + $rootScope.fromDate = null; + $rootScope.toDate = null; + $rootScope.fromTime = null; + $rootScope.toTime = null; + $rootScope.fromString = null; + $rootScope.toString = null; } $rootScope.isEventFilterOn = true; - $rootScope.fromString = moment($rootScope.fromDate).format("YYYY-MM-DD") + " " + moment($rootScope.fromTime).format("HH:mm:ss"); - - $rootScope.toString = moment($rootScope.toDate).format("YYYY-MM-DD") + " " + moment($rootScope.toTime).format("HH:mm:ss"); //console.log("CONCAT DATES " + temp); // diff --git a/www/js/MontageCtrl.js b/www/js/MontageCtrl.js index 967decfe..c3500aee 100644 --- a/www/js/MontageCtrl.js +++ b/www/js/MontageCtrl.js @@ -2611,15 +2611,20 @@ angular.module('zmApp.controllers') var ld = NVR.getLogin(); mid = monitor.Monitor.Id; // always use server tz to avoid confusion + var lastCheckTime = ld.lastEventCheckTimes[mid]; ld.lastEventCheckTimes[mid] = (new moment()).tz(NVR.getTimeZoneNow()).format('YYYY-MM-DD HH:mm:ss'); - NVR.debug ("Updating monitor:"+mid+" event check time (server tz) to " + ld.lastEventCheckTimes[mid] ); + NVR.debug ("Updating monitor:"+mid+" event check time (server tz) to " + lastCheckTime); NVR.setLogin(ld); + if (!monitor.Monitor.lastEvent) { + lastCheckTime = ""; + } monitor.Monitor.lastEvent = undefined; monitor.Monitor.showSidebar = false; if (!showEvents) return; $state.go("app.events", { "id": monitor.Monitor.Id, - "playEvent": false + "playEvent": false, + "lastCheckTime": lastCheckTime }); return; diff --git a/www/js/NVR.js b/www/js/NVR.js index f1c369c3..5bdc23b9 100644 --- a/www/js/NVR.js +++ b/www/js/NVR.js @@ -188,7 +188,6 @@ angular.module('zmApp.controllers') 'timelineScale': -1, 'hideArchived': false, 'videoPlaybackSpeed': 2, - 'enableThumbs': true, 'enableStrictSSL': false, 'enableSlowLoading': false, 'isFullScreen': false, @@ -1562,10 +1561,9 @@ angular.module('zmApp.controllers') } + if (typeof loginData.eventViewThumbs == 'undefined') { - if (typeof loginData.enableThumbs == 'undefined') { - - loginData.enableThumbs = true; + loginData.eventViewThumbs = 'snapshot'; } diff --git a/www/js/app.js b/www/js/app.js index f84673a5..8799784d 100755 --- a/www/js/app.js +++ b/www/js/app.js @@ -2388,7 +2388,7 @@ angular.module('zmApp', [ } }, cache: false, - url: "/events/:id/:playEvent", + url: "/events/:id/:playEvent/:lastCheckTime", templateUrl: "templates/events.html", controller: 'zmApp.EventCtrl', diff --git a/www/lang/locale-en.json b/www/lang/locale-en.json index 0410273d..088f21b3 100644 --- a/www/lang/locale-en.json +++ b/www/lang/locale-en.json @@ -334,7 +334,7 @@ "kReconfirmPin" :"Reconfirm PIN", "kRecordingProgress" :"recording in progress", "kReflow" :"reflow", - "kRefresh" :"refresh", + "kRefresh" :"Refresh", "kRefreshedView" :"refreshed view", "kReportEvents" :"report events", "kReportedVersion" :"Reported Version", diff --git a/www/templates/devoptions.html b/www/templates/devoptions.html index 435c4c40..00361460 100644 --- a/www/templates/devoptions.html +++ b/www/templates/devoptions.html @@ -189,12 +189,13 @@ </ion-toggle> </label> - <label> - <ion-toggle ng-model="loginData.enableThumbs" toggle-class="toggle-calm"> - <span class="item-text-wrap">{{'kEnableThumbs' | translate}} - </span> - </ion-toggle> + <div class="item item-button-right"> + {{'kEnableThumbs' | translate}}: <button class="button button-calm" ng-click="selectEventViewThumbs()"> + <i class="icon ion-gear-b"></i> + </button> + <p>{{loginData.eventViewThumbs}}</p> + </div> </label> <label> diff --git a/www/templates/events.html b/www/templates/events.html index 3878921a..00fd0951 100644 --- a/www/templates/events.html +++ b/www/templates/events.html @@ -1,5 +1,5 @@ <ion-view cache-view="false"> - <ion-nav-title>{{scrollPosition();}}</ion-nav-title> + <ion-nav-title>{{navTitle;}}</ion-nav-title> <ion-nav-buttons side="left"> <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"> </button> @@ -21,14 +21,19 @@ </ion-header-bar> </div> <!-- collection repeat forces js scrolling, thing to remember --> - <ion-content ng-cloak on-tap="tapped();" delegate-handle="mainScroll" mouse-wheel-scroll> + <ion-content ng-cloak on-tap="tapped();" delegate-handle="mainScroll" mouse-wheel-scroll on-scroll="scrolling();"> + <ion-refresher + pulling-text="Pull to refresh..." + on-refresh="doRefresh()"> + </ion-refresher> <!-- needed for header-shrink so first item doesn't go below header--> <!-- <div style="height: 64px;"></div>--> <!-- lets make sure the events list is not empty as collection repeat needs height --> <div ng-if="!eventsBeingLoaded"> <ion-list show-delete="eventList.showDelete"> - <ion-item force-refresh-images="true" collection-repeat="event in events| filter:search.text | eventListFilter" force-refresh-images=true - item-height="event.Event.height" id="item-{{$index}}" on-swipe-left="checkSwipe($index);" force-refresh-images="true" > + <div ng-repeat="event in events| filter:search.text | eventListFilter" id="item-{{$index}}" style="min-height: 50px;"> + <ion-item force-refresh-images="true" + on-swipe-left="checkSwipe($index);" force-refresh-images="true" > <span style="float:left;margin-top:-18px;background-color:#96281B;color:#fff;font-size:11px;opacity:0.7;border-radius: 0px 0px 5px 5px;"> <i class="ion-calendar"></i> {{prettifyTime(event.Event.StartTime)}} {{tzAbbr}} </span> <span style="float:left;margin-top:-18px;background-color:#fff;color:#888;font-size:11px;opacity:1;"> @@ -40,7 +45,19 @@ <i class="ion-clock"></i> {{prettifyDate(event.Event.StartTime)}} {{tzAbbr}} </span> <div class="row" style="font-size:90%;"> - <div class="col col-60"> + <div ng-if="loginData.eventViewThumbs!='none'" style="margin-left: auto;margin-right: auto;"> + + + <img bg-color="#6C7A89" ng-src="{{constructThumbnail(event)}}" on-tap="closeIfOpen(event);openModalWithSnapshot(event)" + width="{{event.Event.thumbWidth}}px" height="{{event.Event.thumbHeight}}px" fallback-src="img/noimage.png" /> + + + </div> + </div> + <!--row--> + <div class="row" style="font-size:80%; color:rgb(110,110,110)"> + <div class="col"> + <div class="item-text-wrap"> <!-- this ngswitch displays different icons depending on the cause of the event --> <span ng-switch on="event.Event.Cause"> @@ -69,46 +86,21 @@ <b> <i ng-if="event.Event.Archived=='1'" class="ion-ios-flag" style="color:red"> </i>{{event.Event.MonitorName}}</b> - <span ng-if="!loginData.enableThumbs">({{event.Event.Id}})</span> - <br /> - <i class="ion-images"></i> {{event.Event.Frames}} <i class="ion-ios-bell-outline"></i> {{event.Event.AlarmFrames}} - <i class="ion-monitor"></i> {{event.Event.MonitorId}} - <br /> <span style="font-size:80%; color:rgb(110,110,110)"> - {{humanize(event.Event.Length)}} + {{humanize(event.Event.Length)}} </span> - <br /> - - </div> - - - <div align="right" class="col col-40" ng-if="loginData.enableThumbs"> - - - <img bg-color="#6C7A89" ng-src="{{constructThumbnail(event)}}" on-tap="closeIfOpen(event);openModalWithSnapshot(event)" - width="{{event.Event.thumbWidth}}px" height="{{event.Event.thumbHeight}}px" fallback-src="img/noimage.png" /> - - - </div> - - </div> - <!--row--> - <div class="row" style="font-size:80%; color:rgb(110,110,110)"> - <div class="col"> - <div class="item-text-wrap"> <i class="ion-ios-pricetags-outline"></i> {{event.Event.Name}} <br /> - <i class="ion-calendar"></i> {{prettify(event.Event.StartTime)}} {{tzAbbr}} - <br /> <i class="ion-clipboard"></i> {{event.Event.Notes}} <!-- <br/> Default video:{{event.Event.relativePath}}{{event.Event.DefaultVideo}}--> </div> </div> </div> + <div class="row" style="float:right; margin-right: 10px; display: block;"> <span style="float:right"> <div ng-if="event.Event.EndTime || 1"> <button class="button button-stable button-small button-outline icon icon-left ion-stats-bars" ng-click="closeIfOpen(event);analyzeEvent(event)"> @@ -130,12 +122,24 @@ </div> </span> + </div> + + <ion-delete-button class="ion-minus-circled" ng-click="deleteEvent(event.Event.Id, $index)"> + </ion-delete-button> + + + <ion-option-button ng-if="event.Event.Archived == 1" class="button-balanced" ng-click="archiveUnarchiveEvent($index,event.Event.Id)">{{'kUnflag' + | translate}}</ion-option-button> + + <ion-option-button ng-if="event.Event.Archived == 0" class="button-assertive" ng-click="archiveUnarchiveEvent($index, event.Event.Id)">{{'kFlag' + | translate}}</ion-option-button> + <!-- this is the event scrub/alarm frames area --> - <div ng-if="isGroupShown(event)"> + <div ng-if="isGroupShown(event)" style="min-height: 50px;"> <div ng-if="groupType=='alarms'"> <br /> <br /> - <div style="height:190px;"> + <div> <p> <!--scroll <i class="icon ion-arrow-left-c"></i> <i class="icon ion-arrow-right-c"></i>--> @@ -220,45 +224,27 @@ <!-- DefaultVideo --> </div> <!-- type = scrub --> - </div> <!-- isGroupShown --> - <ion-delete-button class="ion-minus-circled" ng-click="deleteEvent(event.Event.Id, $index)"> - </ion-delete-button> - - - <ion-option-button ng-if="event.Event.Archived == 1" class="button-balanced" ng-click="archiveUnarchiveEvent($index,event.Event.Id)">{{'kUnflag' - | translate}}</ion-option-button> - - <ion-option-button ng-if="event.Event.Archived == 0" class="button-assertive" ng-click="archiveUnarchiveEvent($index, event.Event.Id)">{{'kFlag' - | translate}}</ion-option-button> - - - <!-- hack to make sure swipe left displays well - if there is no content and our list height is set - to a larger height, the swipe display acts weird --> - - <br /> - <br /> - <br /> - <br /> - <br /> - <br /> - <br /> - <br /> - <br /> - <br /> - - </ion-item> + </div> + </ion-item> + </div> </ion-list> - </div> + </div> <!-- !eventsBeingLoaded--> <ion-item ng-show="!events.length"> <span translate="kNoEvents"></span> </ion-item> + <ion-item ng-show="nextEvents"> + <div style="margin-left: auto;margin-right: auto;width: min-content;"> + <button ng-click="nextEventsLoad();" class="button button-stable button-outline button-small icon icon-left "> + <span translate="kMore"></span> + </button> + </div> + </ion-item> <div ng-if="!eventsBeingLoaded"> - <ion-infinite-scroll ng-if="moreDataCanBeLoaded()" icon="ion-loading-c" on-infinite="loadMore()" distance="2%"> + <ion-infinite-scroll ng-if="moreDataCanBeLoaded()" icon="ion-loading-c" on-infinite="loadMore()" distance="400px"> </ion-infinite-scroll> </div> <canvas id="canvas" class="hiddengifcanvas"></canvas> diff --git a/www/templates/menu.html b/www/templates/menu.html index f00578b3..2a78bb6e 100644 --- a/www/templates/menu.html +++ b/www/templates/menu.html @@ -42,8 +42,8 @@ </span>{{'kMenuTimeline'|translate}} </ion-item> - <!--<ion-item ng-click="navigateView('app.events', {id:0,playEvent:false})" menu-close>--> - <ion-item id="testaut_menu_events" href="#/app/events/0/false" ng-click="go('/app/events/0/false')"> + <!--<ion-item ng-click="navigateView('app.events', {id:0,playEvent:false,lastCheckTime:''})" menu-close>--> + <ion-item id="testaut_menu_events" href="#/app/events/0/false/" ng-click="go('/app/events/0/false/')"> <span class=" item-icon-left"> <i class="icon ion-ios-calendar-outline"></i> </span>{{'kMenuEvents'|translate}} |
