From 41ef4637996cac5c2c4daaa65cf1c34dd1f9d701 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Sat, 8 Sep 2018 19:33:17 -0700 Subject: [PATCH] Load all photos into pendingPhotos, then create DIVs on demand. Also add scroller pager Signed-off-by: James Ketrenos --- frontend/src/ketr-photos/ketr-photos.html | 87 +++++++++++++---------- server/routes/photos.js | 44 ++++-------- server/scanner.js | 34 ++++----- 3 files changed, 80 insertions(+), 85 deletions(-) diff --git a/frontend/src/ketr-photos/ketr-photos.html b/frontend/src/ketr-photos/ketr-photos.html index 6dcc243..13b41ce 100755 --- a/frontend/src/ketr-photos/ketr-photos.html +++ b/frontend/src/ketr-photos/ketr-photos.html @@ -90,15 +90,27 @@ color: white; } + #pager { + margin-top: 0.5em; + position: fixed; + display: block; + opacity: 0; + right: 5px; + border-radius: 0.25em; + padding: 0.5em; + width: 120px; + background-color: rgb(16, 0, 16); + color: white; + text-align: center; + transition: opacity 0.5s ease-in-out; + -webkit-transition: opacity 0.5s ease-in-out; + } + #toast[error] { --paper-toast-background-color: red; --paper-toast-color: white; } - app-header { - background-color: yellow; - } - #thumbnails { /* justify-content: space-between;*/ } @@ -192,6 +204,7 @@
~ the end ~
+
pager
@@ -309,11 +322,37 @@ } if (this.$.bottom.getBoundingClientRect().bottom < window.innerHeight + 200) { - if (this.next) { - this.loadNextPhotos(); + if (this.pendingPhotos.length) { + this.async(this.processItems.bind(this)); } } + var headerHeight = this.$.header.offsetHeight; + + var i, date = null, top = null, lowest = window.innerHeight; + for (i = 0; i < this.visibleThumbs.length; i++) { + var thumb = this.thumbnails[this.visibleThumbs[i]], rect = thumb.getBoundingClientRect(); + /* If no thumb is chosen yet, or this one is the highest on the page, use it */ + if (rect.top > 0 && (!top || lowest > rect.top)) { + lowest = rect.top + top = thumb; + } + } + + if (top) { + var photo = top.item; + this.$.pager.style.opacity = 1; + var date = window.moment(new Date((photo.taken || photo.modified || photo.added) + " GMT")); + date = date.calendar(null, { sameElse: "MMM DD, YYYY" }).replace(/ at.*/, ""); + this.$.pager.textContent = date; + this.$.pager.style.top = headerHeight + + Math.floor((window.innerHeight - 2 * headerHeight) * (window.scrollY / document.scrollingElement.scrollHeight)) + 'px'; + + this.debounce("hide-pager", function() { + this.$.pager.style.opacity = 0; + }, 250); + } + this.triggerVisibilityChecks(); }, @@ -527,13 +566,6 @@ window.location.href = event.model.item.filepath; }, - loadNextPhotos: function() { - if (!this.cursor) { - return; - } - this._loadPhotos(this.cursor.taken.toString().replace(/T.*/, "") + "_" + this.cursor.id, -1, true); - }, - appendItems: function(photos) { if (!this.pendingPhotos || !photos || photos.length == 0) { return; @@ -622,19 +654,8 @@ this.thumbnails.push(thumbnail); } - if (this.pendingPhotos.length) { - this.async(this.processItems.bind(this)); - } else { -// if (this.next && this.cursor) { -// this.async(function() { -// this._loadPhotos(this.cursor.taken.toString().replace(/T.*/, "") + "_" + this.cursor.id, -1, true, this.limit * 2); -// }, 250); -// } else { -// console.log("All photos are loaded: " + this.thumbnails.length); -// } - /* If the viewport is at the bottom when it finishes processing, trigger to load more. */ - this.onScroll(); - } + /* If the viewport is at the bottom when it finishes processing, trigger to load more. */ + this.onScroll(); }, pathTapped: function(event) { @@ -645,7 +666,7 @@ this._loadPhotos(); }, - _loadPhotos: function(start, dir, append, limit) { + _loadPhotos: function(start, append, limit) { if (this.loading == true) { return; } @@ -653,10 +674,8 @@ this.limit = limit || 100; - dir = dir || -1; var params = { limit: this.limit, - dir: dir }, query = ""; if (start) { params.next = start; @@ -674,7 +693,6 @@ } console.log("Requesting " + this.limit + " photos."); - window.fetch("api/v1/photos" + (this.path || "") + query, function(error, xhr) { this.loading = false; if (error) { @@ -705,12 +723,9 @@ this.appendItems(results.items); - this.cursor = results.items[results.items.length - 1]; - - if (dir == -1) { - this.next = results.more ? true : false; - } else { - this.next = true; + if (results.more) { + var cursor = results.items[results.items.length - 1]; + this._loadPhotos(cursor.taken.toString().replace(/T.*/, "") + "_" + cursor.id, true, this.limit * 2); } }.bind(this)); diff --git a/server/routes/photos.js b/server/routes/photos.js index e04530a..e913ed0 100755 --- a/server/routes/photos.js +++ b/server/routes/photos.js @@ -26,7 +26,7 @@ const router = express.Router(); router.get("/*", function(req, res/*, next*/) { let limit = parseInt(req.query.limit) || 50, - order = (parseInt(req.query.dir) == -1) ? "DESC" : "", id, cursor, index; + id, cursor, index; if (req.query.next) { let parts = req.query.next.split("_"); @@ -40,23 +40,15 @@ router.get("/*", function(req, res/*, next*/) { if (id == -1) { index = ""; } else { - if (order == "DESC") { - if (id != -1) { - index = " AND ((taken=DATE(:cursor) AND id<"+id+ ") OR takenDATE(:cursor))"; - } else { - index = " AND (taken>=DATE(:cursor))"; - } + index = " AND (taken<=DATE(:cursor))"; } } let path = decodeURI(req.url).replace(/\?.*$/, ""), - query = "SELECT * FROM photos WHERE path LIKE :path " + index + " ORDER BY taken " + order + ",id " + order + " LIMIT " + (limit * 2 + 1); + query = "SELECT * FROM photos WHERE path LIKE :path " + index + " ORDER BY taken DESC,id DESC LIMIT " + (limit * 2 + 1); console.log("Fetching from: " + path); @@ -76,26 +68,14 @@ router.get("/*", function(req, res/*, next*/) { } }); - if (order == "DESC") { - if (cursor) { - cursor = moment(cursor); - photos = photos.filter(function(photo) { - if (!cursor.isSame(photo.taken, "day")) { - return true; - } - return photo.id < id; - }); - } - } else { - if (cursor) { - cursor = moment(cursor); + if (cursor) { + cursor = moment(cursor); photos = photos.filter(function(photo) { - if (!cursor.isSame(photo.taken, "day")) { - return true; - } - return photo.id > id; - }); - } + if (!cursor.isSame(photo.taken, "day")) { + return true; + } + return photo.id < id; + }); } let more = photos.length > limit; /* We queried one extra item to see if there are more than LIMIT available */ diff --git a/server/scanner.js b/server/scanner.js index 2366d85..baa06e4 100644 --- a/server/scanner.js +++ b/server/scanner.js @@ -34,7 +34,7 @@ function removeNewerFile(path, fileA, fileB) { } function scanDir(parent, path) { - let extensions = [ "jpg", "jpeg", "png", "gif", "nef" ], + let extensions = [ "jpg", "jpeg", "png", "gif", "nef", "orf" ], re = new RegExp("\.((" + extensions.join(")|(") + "))$", "i"), replacements = { path: path.slice(picturesPath.length), @@ -96,8 +96,8 @@ function scanDir(parent, path) { /* Remove 'thumbs' and 'raw' directories from being processed */ files = files.filter(function(file) { for (var i = 0; i < files.length; i++) { - /* If this file has an original NEF on the system, don't add the JPG to the DB */ - if (/\.nef$/i.exec(files[i]) && file == files[i].replace(/\.nef$/i, ".jpg")) { + /* If this file has an original NEF/ORF on the system, don't add the JPG to the DB */ + if (/\.(nef|orf)$/i.exec(files[i]) && file == files[i].replace(/\.(nef|orf)$/i, ".jpg")) { return false; } @@ -138,7 +138,7 @@ function scanDir(parent, path) { const replacements = { path: path.slice(picturesPath.length), - filename: file.replace(/\.nef$/i, ".jpg") /* We will be converting from NEF => JPG */ + filename: file.replace(/\.(nef|orf)$/i, ".jpg") /* We will be converting from NEF/ORF => JPG */ }; replacements.path = replacements.path || "/"; @@ -218,13 +218,13 @@ function existsPromise(path) { }) } -function convertNefToJpg(path, file) { +function convertRawToJpg(path, file) { console.log("Converting " + path + "/" + file); path = picturesPath + path; return new Promise(function(resolve, reject) { - fs.stat(path + "/" + file.replace(/\.nef$/i, ".jpg"), function(err, stats) { + fs.stat(path + "/" + file.replace(/\.(nef|orf)$/i, ".jpg"), function(err, stats) { if (!err) { console.log("Skipping already converted file: " + file); return resolve(); @@ -238,7 +238,7 @@ function convertNefToJpg(path, file) { "--compression=90", "--exif", "--overwrite", - "--output", path + "/" + file.replace(/\.nef$/i, ".jpg"), + "--output", path + "/" + file.replace(/\.(nef|orf)$/i, ".jpg"), path + "/" + file ]); @@ -309,16 +309,16 @@ function triggerWatcher() { let tmp = Promise.resolve(file); /* If this is a Nikon RAW file, convert it to JPG and move to /raw dir */ - if (/\.nef$/i.exec(file)) { - tmp = existsPromise(picturesPath + path + "/" + file.replace(/\.nef$/i, ".jpg")).then(function(exists) { + if (/\.(nef|orf)$/i.exec(file)) { + tmp = existsPromise(picturesPath + path + "/" + file.replace(/\.(nef|orf)$/i, ".jpg")).then(function(exists) { if (exists) { - return file.replace(/\.nef$/i, ".jpg"); /* We converted from NEF => JPG */ + return file.replace(/\.(nef|orf)$/i, ".jpg"); /* We converted from NEF/ORF => JPG */ } return mkdirPromise(picturesPath + path + "/raw").then(function() { - return convertNefToJpg(path, file); + return convertRawToJpg(path, file); }).then(function() { - return file.replace(/\.nef$/i, ".jpg"); /* We converted from NEF => JPG */ + return file.replace(/\.(nef|orf)$/i, ".jpg"); /* We converted from NEF/ORF => JPG */ }); }); } @@ -418,18 +418,18 @@ function triggerWatcher() { console.error("Error reading image " + src + ": ", error); return moveCorrupt(path, file).then(function() { - /* If the original file was not a NEF, we are done... */ - if (!/\.nef$/i.exec(entry[1])) { + /* If the original file was not a NEF/ORF, we are done... */ + if (!/\.(nef|orf)$/i.exec(entry[1])) { return; } - /* ... otherwise, attempt to re-convert the NEF->JPG and then resize again */ + /* ... otherwise, attempt to re-convert the NEF/ORF->JPG and then resize again */ for (var i = 0; i < triedClean.length; i++) { if (triedClean[i] == path + "/" + file) { - /* Move the NEF to /corrupt as well so it isn't re-checked again and again... */ + /* Move the NEF/ORF to /corrupt as well so it isn't re-checked again and again... */ // return moveCorrupt(path, entry[1]); - console.error("Already attempted to convert NEF to JPG: " + path + "/" + file); + console.error("Already attempted to convert NEF/ORF to JPG: " + path + "/" + file); return; } }