Dynamically load items as viewed.
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
parent
c49310ef71
commit
35258af897
@ -48,7 +48,8 @@
|
|||||||
"iron-a11y-keys": "PolymerElements/iron-a11y-keys#^1.0.0",
|
"iron-a11y-keys": "PolymerElements/iron-a11y-keys#^1.0.0",
|
||||||
"iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0",
|
"iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0",
|
||||||
"es6-shim": "^0.35.3",
|
"es6-shim": "^0.35.3",
|
||||||
"paper-radio-group": "PolymerElements/paper-radio-group#^2.2.0"
|
"paper-radio-group": "PolymerElements/paper-radio-group#^2.2.0",
|
||||||
|
"moment": "^2.22.2"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"polymer": "^1.4.0",
|
"polymer": "^1.4.0",
|
||||||
|
10
frontend/elements/photo-thumbnail.html
Normal file → Executable file
10
frontend/elements/photo-thumbnail.html
Normal file → Executable file
@ -14,10 +14,10 @@
|
|||||||
@apply --photo-thumbnail;
|
@apply --photo-thumbnail;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background-color: #ccc;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: 50% 50%;
|
background-position: 50% 50%;
|
||||||
border-radius: 3px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: white;
|
color: white;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -71,11 +71,15 @@
|
|||||||
|
|
||||||
observers: [
|
observers: [
|
||||||
"widthChanged(width)",
|
"widthChanged(width)",
|
||||||
"thumbChanged(thumbpath)"
|
"thumbChanged(thumbpath, visible)"
|
||||||
],
|
],
|
||||||
|
|
||||||
thumbChanged: function(thumbpath) {
|
thumbChanged: function(thumbpath, visible) {
|
||||||
|
if (visible) {
|
||||||
this.style.backgroundImage = "url(" + thumbpath + ")";
|
this.style.backgroundImage = "url(" + thumbpath + ")";
|
||||||
|
} else {
|
||||||
|
this.style.backgroundImage = "";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
widthChanged: function(width) {
|
widthChanged: function(width) {
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
<link rel="import" href="../../bower_components/paper-radio-button/paper-radio-button.html">
|
<link rel="import" href="../../bower_components/paper-radio-button/paper-radio-button.html">
|
||||||
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
|
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
|
||||||
<link rel="import" href="../../bower_components/paper-toast/paper-toast.html">
|
<link rel="import" href="../../bower_components/paper-toast/paper-toast.html">
|
||||||
|
<script src="../../bower_components/moment/moment.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" />
|
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" />
|
||||||
|
|
||||||
@ -101,29 +102,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.date-line {
|
.date-line {
|
||||||
display: block;
|
display: inline-block;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
padding: 0.5em 0;
|
padding: 0.5em 0;
|
||||||
width: 100%;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-line {
|
.date-line .album-line {
|
||||||
display: block;
|
|
||||||
padding: 0.5em 0;
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.album-line > div {
|
.album-line > div:not(:last-child) {
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.album-line > div:first-child {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.album-line > div:hover {
|
.album-line > div:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
photo-thumbnail {
|
photo-thumbnail {
|
||||||
--photo-thumbnail: {
|
--photo-thumbnail: {
|
||||||
border: 3px solid rgba(0, 0, 0, 0);
|
border: 3px solid white;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +163,6 @@
|
|||||||
<paper-radio-button name="by-date">By date</paper-radio-button>
|
<paper-radio-button name="by-date">By date</paper-radio-button>
|
||||||
<paper-radio-button name="by-album">By album</paper-radio-button>
|
<paper-radio-button name="by-album">By album</paper-radio-button>
|
||||||
</paper-radio-group>
|
</paper-radio-group>
|
||||||
<paper-checkbox checked$="[[limitPerFolder]]" on-checked-changed="onLimitPerFolderChanged">Limit per folder</paper-checkbox>
|
|
||||||
<paper-checkbox checked$="[[breakOnDayChange]]" on-checked-changed="onBreakOnDayChanged">Break on day change</paper-checkbox>
|
<paper-checkbox checked$="[[breakOnDayChange]]" on-checked-changed="onBreakOnDayChanged">Break on day change</paper-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div id="breadcrumb" class="horizontal layout center"><template is="dom-repeat" items="[[breadcrumb(path)]]">
|
<div id="breadcrumb" class="horizontal layout center"><template is="dom-repeat" items="[[breadcrumb(path)]]">
|
||||||
@ -166,7 +171,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</app-header>
|
</app-header>
|
||||||
<div id="content" fullbleed class="flex layout vertical">
|
<div id="content" fullbleed class="flex layout vertical">
|
||||||
<div id="thumbnails" class="thumbnails layout horizontal wrap"></div>
|
<div id="thumbnails" class="layout horizontal wrap"></div>
|
||||||
<div id="magic"></div>
|
<div id="magic"></div>
|
||||||
<div class="layout horizontal">
|
<div class="layout horizontal">
|
||||||
<paper-button disabled$="[[!prev]]" on-tap="loadPrevPhotos">prev</paper-button>
|
<paper-button disabled$="[[!prev]]" on-tap="loadPrevPhotos">prev</paper-button>
|
||||||
@ -205,11 +210,6 @@
|
|||||||
value: true,
|
value: true,
|
||||||
reflectToAttribute: true
|
reflectToAttribute: true
|
||||||
},
|
},
|
||||||
limitPerFolder: {
|
|
||||||
type: Boolean,
|
|
||||||
value: false,
|
|
||||||
reflectToAttribute: true
|
|
||||||
},
|
|
||||||
showAlbums: {
|
showAlbums: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
computed: "shouldShowAlbums(order)"
|
computed: "shouldShowAlbums(order)"
|
||||||
@ -259,17 +259,6 @@
|
|||||||
this.appendItems(this.photos);
|
this.appendItems(this.photos);
|
||||||
},
|
},
|
||||||
|
|
||||||
onLimitPerFolderChanged: function(event) {
|
|
||||||
if (!this.photos) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.limitPerFolder = event.detail.value;
|
|
||||||
|
|
||||||
Polymer.dom(this.$.thumbnails).innerHTML = "";
|
|
||||||
|
|
||||||
this.appendItems(this.photos);
|
|
||||||
},
|
|
||||||
onBreakOnDayChanged: function(event) {
|
onBreakOnDayChanged: function(event) {
|
||||||
if (!this.photos) {
|
if (!this.photos) {
|
||||||
return;
|
return;
|
||||||
@ -308,11 +297,37 @@
|
|||||||
this._loadPhotos();
|
this._loadPhotos();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
isThumbInView: function(el) {
|
||||||
|
var rect = el.getBoundingClientRect(),
|
||||||
|
height = (window.innerHeight || document.documentElement.clientHeight),
|
||||||
|
width = (window.innerWidth || document.documentElement.clientWidth);
|
||||||
|
|
||||||
|
return ((rect.top <= height) && ((rect.top + rect.height) >= 0) &&
|
||||||
|
(rect.left <= width) && ((rect.left + rect.width) >= 0));
|
||||||
|
},
|
||||||
|
|
||||||
onScroll: function(event) {
|
onScroll: function(event) {
|
||||||
if (this.disableScrolling) {
|
if (this.disableScrolling) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
window.scrollTo(this.topStickX, this.topStickY);
|
window.scrollTo(this.topStickX, this.topStickY);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.triggerVisibilityChecks();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
triggerVisibilityChecks: function() {
|
||||||
|
this.debounce("hide-or-show", function() {
|
||||||
|
var thumbs = this.querySelectorAll("photo-thumbnail"), visible;
|
||||||
|
thumbs.forEach(function(thumb) {
|
||||||
|
visible = this.isThumbInView(thumb);
|
||||||
|
if (thumb.visible != visible) {
|
||||||
|
thumb.visible = visible;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}, 250);
|
||||||
},
|
},
|
||||||
|
|
||||||
findPhoto: function(photo) {
|
findPhoto: function(photo) {
|
||||||
@ -422,17 +437,12 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var thisDay, lastPath = null;
|
var lastPath = null;
|
||||||
if (this.limitPerFolder) {
|
|
||||||
console.log("Max per day: " + this.cols);
|
|
||||||
}
|
|
||||||
|
|
||||||
var albums = this.querySelectorAll(".album-line");
|
var albums = this.querySelectorAll(".album-line");
|
||||||
if (albums.length) {
|
if (albums.length) {
|
||||||
lastPath = albums[albums.length - 1];
|
lastPath = albums[albums.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
thisDay = 0;
|
|
||||||
for (var i = 0; i < photos.length; i++) {
|
for (var i = 0; i < photos.length; i++) {
|
||||||
var photo = photos[i],
|
var photo = photos[i],
|
||||||
thumbnail = document.createElement("photo-thumbnail"),
|
thumbnail = document.createElement("photo-thumbnail"),
|
||||||
@ -443,6 +453,34 @@
|
|||||||
thumbnail.addEventListener("load-album", this.loadAlbum.bind(this));
|
thumbnail.addEventListener("load-album", this.loadAlbum.bind(this));
|
||||||
datetime = (photo.taken || photo.modified || photo.added).replace(/T.*$/, "");
|
datetime = (photo.taken || photo.modified || photo.added).replace(/T.*$/, "");
|
||||||
|
|
||||||
|
var dateBlock = this.querySelector("#date-" + datetime), thumbnails;
|
||||||
|
if (!dateBlock) {
|
||||||
|
dateBlock = document.createElement("div");
|
||||||
|
dateBlock.id = "date-" + datetime;
|
||||||
|
dateBlock.classList.add("date-line");
|
||||||
|
dateBlock.classList.add("layout");
|
||||||
|
dateBlock.classList.add("vertical");
|
||||||
|
var header = document.createElement("div");
|
||||||
|
header.classList.add("header");
|
||||||
|
header.classList.add("layout");
|
||||||
|
header.classList.add("center");
|
||||||
|
header.classList.add("horizontal");
|
||||||
|
var div = document.createElement("div");
|
||||||
|
div.classList.add("date");
|
||||||
|
div.textContent = window.moment(datetime, "YYYY-MM-DD").calendar(null, { sameElse: "MMM DD, YYYY" });
|
||||||
|
Polymer.dom(dateBlock).appendChild(header);
|
||||||
|
Polymer.dom(header).appendChild(div);
|
||||||
|
thumbnails = document.createElement("div");
|
||||||
|
thumbnails.classList.add("thumbnails");
|
||||||
|
thumbnails.classList.add("layout");
|
||||||
|
thumbnails.classList.add("horizontal");
|
||||||
|
thumbnails.classList.add("wrap");
|
||||||
|
Polymer.dom(dateBlock).appendChild(thumbnails);
|
||||||
|
Polymer.dom(this.$.thumbnails).appendChild(dateBlock);
|
||||||
|
} else {
|
||||||
|
thumbnails = Polymer.dom(dateBlock).querySelector(".thumbnails");
|
||||||
|
}
|
||||||
|
|
||||||
if (this.order == "by-album") {
|
if (this.order == "by-album") {
|
||||||
if (lastPath != photo.path) {
|
if (lastPath != photo.path) {
|
||||||
lastPath = photo.path;
|
lastPath = photo.path;
|
||||||
@ -459,52 +497,15 @@
|
|||||||
albumBlock.appendChild(div);
|
albumBlock.appendChild(div);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
Polymer.dom(this.$.thumbnails).appendChild(albumBlock);
|
var header = dateBlock.querySelector(".header");
|
||||||
|
Polymer.dom(header).appendChild(albumBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.breakOnDayChange) {
|
Polymer.dom(thumbnails).appendChild(thumbnail);
|
||||||
var dateBlock = this.querySelector("#date-" + datetime);
|
|
||||||
if (!dateBlock) {
|
|
||||||
dateBlock = document.createElement("div");
|
|
||||||
dateBlock.id = "date-" + datetime;
|
|
||||||
dateBlock.classList.add("date-line");
|
|
||||||
dateBlock.textContent = datetime;
|
|
||||||
Polymer.dom(this.$.thumbnails).appendChild(dateBlock);
|
|
||||||
thisDay = 0;
|
|
||||||
} else {
|
|
||||||
if (this.limitPerFolder) {
|
|
||||||
var thumbs = [], el = dateBlock.nextElementSibling;
|
|
||||||
while (el && el.tagName == "PHOTO-THUMBNAIL") {
|
|
||||||
thumbs.push(el);
|
|
||||||
el = el.nextElementSibling;
|
|
||||||
}
|
|
||||||
thisDay = thumbs.length;
|
|
||||||
while (thisDay > this.cols) {
|
|
||||||
Polymer.dom(thumbs[thisDay - 1].parentElement).removeChild(thumbs[thisDay - 1]);
|
|
||||||
thisDay--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.triggerVisibilityChecks();
|
||||||
if (!this.limitPerFolder || thisDay < this.cols) {
|
|
||||||
Polymer.dom(this.$.thumbnails).appendChild(thumbnail);
|
|
||||||
thisDay++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.limitPerFolder && thisDay == this.cols) {
|
|
||||||
while (i + 1 < photos.length) {
|
|
||||||
photo = photos[i + 1];
|
|
||||||
if (datetime != (photo.taken || photo.modified || photo.added).replace(/T.*$/, "")) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
thisDay = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
pathTapped: function(event) {
|
pathTapped: function(event) {
|
||||||
@ -617,6 +618,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
onResize: function(event) {
|
onResize: function(event) {
|
||||||
|
this.triggerVisibilityChecks();
|
||||||
this.debounce("resize", function() {
|
this.debounce("resize", function() {
|
||||||
var width = Math.max(this.$.placeholder.offsetWidth || 0, 200);
|
var width = Math.max(this.$.placeholder.offsetWidth || 0, 200);
|
||||||
|
|
||||||
|
8
server/app.js
Normal file → Executable file
8
server/app.js
Normal file → Executable file
@ -84,10 +84,14 @@ app.set("port", serverConfig.port);
|
|||||||
const server = require("http").createServer(app);
|
const server = require("http").createServer(app);
|
||||||
|
|
||||||
db.then(function(photoDB) {
|
db.then(function(photoDB) {
|
||||||
|
console.log("DB connected. Opening server.");
|
||||||
|
server.listen(serverConfig.port);
|
||||||
|
return photoDB;
|
||||||
|
}).then(function(photoDB) {
|
||||||
|
console.log("Scanning.");
|
||||||
return scanner.scan(photoDB);
|
return scanner.scan(photoDB);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log("Done scanning. Opening server.");
|
console.log("Scanning completed.");
|
||||||
server.listen(serverConfig.port);
|
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
|
2
server/routes/photos.js
Normal file → Executable file
2
server/routes/photos.js
Normal file → Executable file
@ -55,7 +55,7 @@ router.get("/*", function(req, res/*, next*/) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let query = "SELECT * FROM photos WHERE path LIKE :path " + index + " ORDER BY taken " + order + ",id " + order + " LIMIT " + (limit * 2 + 1);
|
let query = "SELECT * FROM photos WHERE path LIKE :path " + index + " ORDER BY taken " + order + ",id " + order;// + " LIMIT " + (limit * 2 + 1);
|
||||||
return photoDB.sequelize.query(query, {
|
return photoDB.sequelize.query(query, {
|
||||||
replacements: {
|
replacements: {
|
||||||
cursor: cursor,
|
cursor: cursor,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user