Load all photos into pendingPhotos, then create DIVs on demand. Also add scroller pager

Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
James Ketr 2018-09-08 19:33:17 -07:00
parent 588a261796
commit 41ef463799
3 changed files with 80 additions and 85 deletions

View File

@ -90,15 +90,27 @@
color: white; 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] { #toast[error] {
--paper-toast-background-color: red; --paper-toast-background-color: red;
--paper-toast-color: white; --paper-toast-color: white;
} }
app-header {
background-color: yellow;
}
#thumbnails { #thumbnails {
/* justify-content: space-between;*/ /* justify-content: space-between;*/
} }
@ -192,6 +204,7 @@
<div hidden$="[[loading]]">~ the end ~</div> <div hidden$="[[loading]]">~ the end ~</div>
</div> </div>
</app-drawer-layout> </app-drawer-layout>
<div id="pager">pager</div>
<paper-toast id="toast"></paper-toast> <paper-toast id="toast"></paper-toast>
<photo-lightbox tabindex="0" id="lightbox" on-close="lightBoxClose" on-next="lightBoxNext" on-previous="lightBoxPrevious"></photo-lightbox> <photo-lightbox tabindex="0" id="lightbox" on-close="lightBoxClose" on-next="lightBoxNext" on-previous="lightBoxPrevious"></photo-lightbox>
</template> </template>
@ -309,11 +322,37 @@
} }
if (this.$.bottom.getBoundingClientRect().bottom < window.innerHeight + 200) { if (this.$.bottom.getBoundingClientRect().bottom < window.innerHeight + 200) {
if (this.next) { if (this.pendingPhotos.length) {
this.loadNextPhotos(); 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(); this.triggerVisibilityChecks();
}, },
@ -527,13 +566,6 @@
window.location.href = event.model.item.filepath; 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) { appendItems: function(photos) {
if (!this.pendingPhotos || !photos || photos.length == 0) { if (!this.pendingPhotos || !photos || photos.length == 0) {
return; return;
@ -622,19 +654,8 @@
this.thumbnails.push(thumbnail); 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. */ /* If the viewport is at the bottom when it finishes processing, trigger to load more. */
this.onScroll(); this.onScroll();
}
}, },
pathTapped: function(event) { pathTapped: function(event) {
@ -645,7 +666,7 @@
this._loadPhotos(); this._loadPhotos();
}, },
_loadPhotos: function(start, dir, append, limit) { _loadPhotos: function(start, append, limit) {
if (this.loading == true) { if (this.loading == true) {
return; return;
} }
@ -653,10 +674,8 @@
this.limit = limit || 100; this.limit = limit || 100;
dir = dir || -1;
var params = { var params = {
limit: this.limit, limit: this.limit,
dir: dir
}, query = ""; }, query = "";
if (start) { if (start) {
params.next = start; params.next = start;
@ -674,7 +693,6 @@
} }
console.log("Requesting " + this.limit + " photos."); console.log("Requesting " + this.limit + " photos.");
window.fetch("api/v1/photos" + (this.path || "") + query, function(error, xhr) { window.fetch("api/v1/photos" + (this.path || "") + query, function(error, xhr) {
this.loading = false; this.loading = false;
if (error) { if (error) {
@ -705,12 +723,9 @@
this.appendItems(results.items); this.appendItems(results.items);
this.cursor = results.items[results.items.length - 1]; if (results.more) {
var cursor = results.items[results.items.length - 1];
if (dir == -1) { this._loadPhotos(cursor.taken.toString().replace(/T.*/, "") + "_" + cursor.id, true, this.limit * 2);
this.next = results.more ? true : false;
} else {
this.next = true;
} }
}.bind(this)); }.bind(this));

View File

@ -26,7 +26,7 @@ const router = express.Router();
router.get("/*", function(req, res/*, next*/) { router.get("/*", function(req, res/*, next*/) {
let limit = parseInt(req.query.limit) || 50, let limit = parseInt(req.query.limit) || 50,
order = (parseInt(req.query.dir) == -1) ? "DESC" : "", id, cursor, index; id, cursor, index;
if (req.query.next) { if (req.query.next) {
let parts = req.query.next.split("_"); let parts = req.query.next.split("_");
@ -40,23 +40,15 @@ router.get("/*", function(req, res/*, next*/) {
if (id == -1) { if (id == -1) {
index = ""; index = "";
} else { } else {
if (order == "DESC") {
if (id != -1) { if (id != -1) {
index = " AND ((taken=DATE(:cursor) AND id<"+id+ ") OR taken<DATE(:cursor))"; index = " AND ((taken=DATE(:cursor) AND id<"+id+ ") OR taken<DATE(:cursor))";
} else { } else {
index = " AND (taken<=DATE(:cursor))"; index = " AND (taken<=DATE(:cursor))";
} }
} else {
if (id != -1) {
index = " AND ((taken=DATE(:cursor) AND id>"+id+ ") OR taken>DATE(:cursor))";
} else {
index = " AND (taken>=DATE(:cursor))";
}
}
} }
let path = decodeURI(req.url).replace(/\?.*$/, ""), 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); console.log("Fetching from: " + path);
@ -76,7 +68,6 @@ router.get("/*", function(req, res/*, next*/) {
} }
}); });
if (order == "DESC") {
if (cursor) { if (cursor) {
cursor = moment(cursor); cursor = moment(cursor);
photos = photos.filter(function(photo) { photos = photos.filter(function(photo) {
@ -86,17 +77,6 @@ router.get("/*", function(req, res/*, next*/) {
return photo.id < id; return photo.id < id;
}); });
} }
} else {
if (cursor) {
cursor = moment(cursor);
photos = photos.filter(function(photo) {
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 */ let more = photos.length > limit; /* We queried one extra item to see if there are more than LIMIT available */

View File

@ -34,7 +34,7 @@ function removeNewerFile(path, fileA, fileB) {
} }
function scanDir(parent, path) { 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"), re = new RegExp("\.((" + extensions.join(")|(") + "))$", "i"),
replacements = { replacements = {
path: path.slice(picturesPath.length), path: path.slice(picturesPath.length),
@ -96,8 +96,8 @@ function scanDir(parent, path) {
/* Remove 'thumbs' and 'raw' directories from being processed */ /* Remove 'thumbs' and 'raw' directories from being processed */
files = files.filter(function(file) { files = files.filter(function(file) {
for (var i = 0; i < files.length; i++) { 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 this file has an original NEF/ORF 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 (/\.(nef|orf)$/i.exec(files[i]) && file == files[i].replace(/\.(nef|orf)$/i, ".jpg")) {
return false; return false;
} }
@ -138,7 +138,7 @@ function scanDir(parent, path) {
const replacements = { const replacements = {
path: path.slice(picturesPath.length), 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 || "/"; replacements.path = replacements.path || "/";
@ -218,13 +218,13 @@ function existsPromise(path) {
}) })
} }
function convertNefToJpg(path, file) { function convertRawToJpg(path, file) {
console.log("Converting " + path + "/" + file); console.log("Converting " + path + "/" + file);
path = picturesPath + path; path = picturesPath + path;
return new Promise(function(resolve, reject) { 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) { if (!err) {
console.log("Skipping already converted file: " + file); console.log("Skipping already converted file: " + file);
return resolve(); return resolve();
@ -238,7 +238,7 @@ function convertNefToJpg(path, file) {
"--compression=90", "--compression=90",
"--exif", "--exif",
"--overwrite", "--overwrite",
"--output", path + "/" + file.replace(/\.nef$/i, ".jpg"), "--output", path + "/" + file.replace(/\.(nef|orf)$/i, ".jpg"),
path + "/" + file path + "/" + file
]); ]);
@ -309,16 +309,16 @@ function triggerWatcher() {
let tmp = Promise.resolve(file); let tmp = Promise.resolve(file);
/* If this is a Nikon RAW file, convert it to JPG and move to /raw dir */ /* If this is a Nikon RAW file, convert it to JPG and move to /raw dir */
if (/\.nef$/i.exec(file)) { if (/\.(nef|orf)$/i.exec(file)) {
tmp = existsPromise(picturesPath + path + "/" + file.replace(/\.nef$/i, ".jpg")).then(function(exists) { tmp = existsPromise(picturesPath + path + "/" + file.replace(/\.(nef|orf)$/i, ".jpg")).then(function(exists) {
if (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 mkdirPromise(picturesPath + path + "/raw").then(function() {
return convertNefToJpg(path, file); return convertRawToJpg(path, file);
}).then(function() { }).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); console.error("Error reading image " + src + ": ", error);
return moveCorrupt(path, file).then(function() { return moveCorrupt(path, file).then(function() {
/* If the original file was not a NEF, we are done... */ /* If the original file was not a NEF/ORF, we are done... */
if (!/\.nef$/i.exec(entry[1])) { if (!/\.(nef|orf)$/i.exec(entry[1])) {
return; 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++) { for (var i = 0; i < triedClean.length; i++) {
if (triedClean[i] == path + "/" + file) { 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]); // 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; return;
} }
} }