diff --git a/libs/timelapse.js b/libs/timelapse.js index 02b4452c..8dffb305 100644 --- a/libs/timelapse.js +++ b/libs/timelapse.js @@ -2,6 +2,8 @@ var fs = require('fs') var moment = require('moment') var express = require('express') module.exports = function(s,config,lang,app,io){ + const timelapseFramesCache = {} + const timelapseFramesCacheTimeouts = {} s.getTimelapseFrameDirectory = function(e){ if(e.mid&&!e.id){e.id=e.mid} s.checkDetails(e) @@ -131,6 +133,37 @@ module.exports = function(s,config,lang,app,io){ }) }else{ // console.log('Delete Failed',e) +// console.error(err) + } + }) + } + const deleteTimelapseFrame = function(e){ + // e = video object + s.checkDetails(e) + var frameSelector = { + ke: e.ke, + mid: e.mid, + filename: e.filename, + } + s.knexQuery({ + action: "select", + columns: "*", + table: "Timelapse Frames", + where: frameSelector, + limit: 1 + },function(err,r){ + if(r && r[0]){ + r = r[0] + s.knexQuery({ + action: "delete", + table: "Timelapse Frames", + where: frameSelector, + limit: 1 + },function(){ + s.file('delete',e.fileLocation) + }) + }else{ +// console.log('Delete Failed',e) // console.error(err) } }) @@ -267,6 +300,7 @@ module.exports = function(s,config,lang,app,io){ */ app.get([ config.webPaths.apiPrefix+':auth/timelapse/:ke/:id/:date/:filename', + config.webPaths.apiPrefix+':auth/timelapse/:ke/:id/:date/:filename/:action', ], function (req,res){ res.setHeader('Content-Type', 'application/json'); s.auth(req.params,function(user){ @@ -279,41 +313,64 @@ module.exports = function(s,config,lang,app,io){ return } const monitorRestrictions = s.getMonitorRestrictions(user.details,req.params.id) - s.getDatabaseRows({ - monitorRestrictions: monitorRestrictions, - table: 'Timelapse Frames', - groupKey: req.params.ke, - archived: req.query.archived, - filename: req.params.filename, - rowType: 'frames', - endIsStartTo: true - },(response) => { - var frame = response.frames[0] - if(frame){ - var fileLocation - if(frame.details.dir){ - fileLocation = `${s.checkCorrectPathEnding(frame.details.dir)}` - }else{ - fileLocation = `${s.dir.videos}` - } - var selectedDate = req.params.date - if(selectedDate.indexOf('-') === -1){ - selectedDate = req.params.filename.split('T')[0] - } - fileLocation = `${fileLocation}${frame.ke}/${frame.mid}_timelapse/${selectedDate}/${req.params.filename}` - fs.stat(fileLocation,function(err,stats){ - if(!err){ + const cacheKey = req.params.ke + req.params.id + req.params.filename + const processFrame = (frame) => { + var fileLocation + if(frame.details.dir){ + fileLocation = `${s.checkCorrectPathEnding(frame.details.dir)}` + }else{ + fileLocation = `${s.dir.videos}` + } + var selectedDate = req.params.date + if(selectedDate.indexOf('-') === -1){ + selectedDate = req.params.filename.split('T')[0] + } + fileLocation = `${fileLocation}${frame.ke}/${frame.mid}_timelapse/${selectedDate}/${req.params.filename}` + fs.stat(fileLocation,function(err,stats){ + if(!err){ + if(req.params.action === 'delete'){ + deleteTimelapseFrame({ + ke: frame.ke, + mid: frame.mid, + filename: req.params.filename, + fileLocation: fileLocation, + }) + delete(timelapseFramesCache[cacheKey]) + s.closeJsonResponse(res,{ok: true}) + }else{ res.contentType('image/jpeg') res.on('finish',function(){res.end()}) fs.createReadStream(fileLocation).pipe(res) - }else{ - s.closeJsonResponse(res,{ok: false, msg: lang[`Nothing exists`]}) } - }) - }else{ - s.closeJsonResponse(res,{ok: false, msg: lang[`Nothing exists`]}) - } - }) + }else{ + s.closeJsonResponse(res,{ok: false, msg: lang[`Nothing exists`]}) + } + }) + } + if(timelapseFramesCache[cacheKey]){ + processFrame(timelapseFramesCache[cacheKey]) + }else{ + s.getDatabaseRows({ + monitorRestrictions: monitorRestrictions, + table: 'Timelapse Frames', + groupKey: req.params.ke, + archived: req.query.archived, + filename: req.params.filename, + rowType: 'frames', + endIsStartTo: true + },(response) => { + var frame = response.frames[0] + if(frame){ + timelapseFramesCache[cacheKey] = frame + timelapseFramesCacheTimeouts[cacheKey] = setTimeout(function(){ + delete(timelapseFramesCache[cacheKey]) + },1000 * 60 * 10) + processFrame(frame) + }else{ + s.closeJsonResponse(res,{ok: false, msg: lang[`Nothing exists`]}) + } + }) + } },res,req); }); /** diff --git a/libs/videos.js b/libs/videos.js index f96d7e7e..5be8ce22 100644 --- a/libs/videos.js +++ b/libs/videos.js @@ -543,6 +543,7 @@ module.exports = function(s,config,lang){ fs.unlink(commandTempLocation,function(){ }) + s.purgeDiskForGroup(ke) setTimeout(() => { delete(s.group[ke].activeMonitors[mid].buildingTimelapseVideo) },5000) diff --git a/web/libs/css/dash2.timelapse.jpeg.css b/web/libs/css/dash2.timelapse.jpeg.css index 56f1ea99..df880dd3 100644 --- a/web/libs/css/dash2.timelapse.jpeg.css +++ b/web/libs/css/dash2.timelapse.jpeg.css @@ -38,7 +38,8 @@ position: relative; cursor: pointer; } -#timelapsejpeg .frameIcons .frame .shade{ +#timelapsejpeg .frameIcons .frame .shade, +#timelapsejpeg .frameIcons .button-strip{ position: absolute; bottom: 0; left: 0; @@ -48,6 +49,16 @@ background: rgba(0,0,0,0.6); color: #fff } +#timelapsejpeg .frameIcons .button-strip{ + top: 0; + bottom: auto; + opacity: 0; + transition: 0.2; + text-align: right; +} +#timelapsejpeg .frameIcons .frame:hover .button-strip{ + opacity: 1; +} #timelapsejpeg .playBackView{ position:absolute; height: 50%; diff --git a/web/libs/js/dash2.timelapse.jpeg.js b/web/libs/js/dash2.timelapse.jpeg.js index d2676c22..6cebbee5 100644 --- a/web/libs/js/dash2.timelapse.jpeg.js +++ b/web/libs/js/dash2.timelapse.jpeg.js @@ -82,7 +82,7 @@ $(document).ready(function(e){ $.each(data.reverse(),function(n,fileInfo){ fileInfo.href = apiURL + '/' + fileInfo.filename.split('T')[0] + '/' + fileInfo.filename fileInfo.number = n - frameIconsHtml += '