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