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;
}
#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 @@
<div hidden$="[[loading]]">~ the end ~</div>
</div>
</app-drawer-layout>
<div id="pager">pager</div>
<paper-toast id="toast"></paper-toast>
<photo-lightbox tabindex="0" id="lightbox" on-close="lightBoxClose" on-next="lightBoxNext" on-previous="lightBoxPrevious"></photo-lightbox>
</template>
@ -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();
}
},
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));

View File

@ -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 taken<DATE(:cursor))";
} else {
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(/\?.*$/, ""),
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,7 +68,6 @@ router.get("/*", function(req, res/*, next*/) {
}
});
if (order == "DESC") {
if (cursor) {
cursor = moment(cursor);
photos = photos.filter(function(photo) {
@ -86,17 +77,6 @@ router.get("/*", function(req, res/*, next*/) {
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 */

View File

@ -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;
}
}