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:
parent
588a261796
commit
41ef463799
@ -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) {
|
/* If the viewport is at the bottom when it finishes processing, trigger to load more. */
|
||||||
this.async(this.processItems.bind(this));
|
this.onScroll();
|
||||||
} 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) {
|
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));
|
||||||
|
@ -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 {
|
|
||||||
index = " AND (taken<=DATE(:cursor))";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (id != -1) {
|
index = " AND (taken<=DATE(:cursor))";
|
||||||
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,26 +68,14 @@ router.get("/*", function(req, res/*, next*/) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (order == "DESC") {
|
if (cursor) {
|
||||||
if (cursor) {
|
cursor = moment(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);
|
|
||||||
photos = photos.filter(function(photo) {
|
photos = photos.filter(function(photo) {
|
||||||
if (!cursor.isSame(photo.taken, "day")) {
|
if (!cursor.isSame(photo.taken, "day")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return photo.id > id;
|
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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user