Merge 4d89987d1a
into 0935d9fab0
This commit is contained in:
commit
3f4cab25b8
6 changed files with 92 additions and 155 deletions
|
@ -27,8 +27,6 @@ import PhotoSwipe from "photoswipe";
|
|||
import PhotoSwipeUI_Default from "photoswipe/dist/photoswipe-ui-default.js";
|
||||
import Event from "pubsub-js";
|
||||
import Util from "util.js";
|
||||
import Api from "./api";
|
||||
import Thumb from "model/thumb";
|
||||
|
||||
const thumbs = window.__CONFIG__.thumbs;
|
||||
|
||||
|
@ -219,85 +217,6 @@ class Viewer {
|
|||
|
||||
return "fit_7680";
|
||||
}
|
||||
|
||||
static show(ctx, index) {
|
||||
if (ctx.loading || !ctx.listen || ctx.viewer.loading || !ctx.results[index]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const selected = ctx.results[index];
|
||||
|
||||
if (!ctx.viewer.dirty && ctx.viewer.results && ctx.viewer.results.length > index) {
|
||||
// Reuse existing viewer result if possible.
|
||||
let i = -1;
|
||||
|
||||
if (ctx.viewer.results[index] && ctx.viewer.results[index].UID === selected.UID) {
|
||||
i = index;
|
||||
} else {
|
||||
i = ctx.viewer.results.findIndex((p) => p.UID === selected.UID);
|
||||
}
|
||||
|
||||
if (
|
||||
i > -1 &&
|
||||
(((ctx.viewer.complete || ctx.complete) &&
|
||||
ctx.viewer.results.length >= ctx.results.length) ||
|
||||
i + ctx.viewer.batchSize <= ctx.viewer.results.length)
|
||||
) {
|
||||
ctx.$viewer.show(ctx.viewer.results, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch photos from server API.
|
||||
ctx.viewer.loading = true;
|
||||
|
||||
const params = ctx.searchParams();
|
||||
params.count = params.offset + ctx.viewer.batchSize;
|
||||
params.offset = 0;
|
||||
|
||||
// Fetch viewer results from API.
|
||||
return Api.get("photos/view", { params })
|
||||
.then((response) => {
|
||||
const count = response && response.data ? response.data.length : 0;
|
||||
if (count === 0) {
|
||||
ctx.$notify.warn(ctx.$gettext("No pictures found"));
|
||||
ctx.viewer.dirty = true;
|
||||
ctx.viewer.complete = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Process response.
|
||||
if (response.headers && response.headers["x-count"]) {
|
||||
const c = parseInt(response.headers["x-count"]);
|
||||
const l = parseInt(response.headers["x-limit"]);
|
||||
ctx.viewer.complete = c < l;
|
||||
} else {
|
||||
ctx.viewer.complete = ctx.complete;
|
||||
}
|
||||
|
||||
let i;
|
||||
|
||||
if (response.data[index] && response.data[index].UID === selected.UID) {
|
||||
i = index;
|
||||
} else {
|
||||
i = response.data.findIndex((p) => p.UID === selected.UID);
|
||||
}
|
||||
|
||||
ctx.viewer.results = Thumb.wrap(response.data);
|
||||
|
||||
// Show photos.
|
||||
ctx.$viewer.show(ctx.viewer.results, i);
|
||||
ctx.viewer.dirty = false;
|
||||
})
|
||||
.catch(() => {
|
||||
ctx.viewer.dirty = true;
|
||||
ctx.viewer.complete = false;
|
||||
})
|
||||
.finally(() => {
|
||||
// Unblock.
|
||||
ctx.viewer.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default Viewer;
|
||||
|
|
|
@ -71,6 +71,7 @@ export const TimeZoneUTC = "UTC";
|
|||
const num = "numeric";
|
||||
const short = "short";
|
||||
const long = "long";
|
||||
const thumbs = window.__CONFIG__.thumbs;
|
||||
|
||||
export const DATE_FULL = {
|
||||
year: num,
|
||||
|
@ -96,6 +97,51 @@ export let BatchSize = 120;
|
|||
export class Photo extends RestModel {
|
||||
constructor(values) {
|
||||
super(values);
|
||||
|
||||
let mainFile;
|
||||
if (this.Files) {
|
||||
mainFile = this.mainFile();
|
||||
}
|
||||
const mainFileHash = this.generateMainFileHash(mainFile, this.Hash);
|
||||
this.Thumbs = this.generateThumbs(mainFile, mainFileHash);
|
||||
this.DownloadUrl = this.getDownloadUrl(mainFileHash);
|
||||
}
|
||||
|
||||
generateThumbs(mainFile, mainFileHash) {
|
||||
let sourceWidth = this.Width;
|
||||
let sourceHeight = this.Height;
|
||||
if (mainFile) {
|
||||
sourceWidth = mainFile.Width;
|
||||
sourceHeight = mainFile.Height;
|
||||
}
|
||||
|
||||
if (!this.Hash) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const result = {};
|
||||
for (let i = 0; i < thumbs.length; i++) {
|
||||
let t = thumbs[i];
|
||||
const size = this.calculateSizeFromProps(t.w, t.h, sourceWidth, sourceHeight);
|
||||
|
||||
// we know the thumbnail url can't be cached because the size-parameter changes on every call
|
||||
const url = this.generateThumbnailUrlUnmemoized(
|
||||
mainFileHash,
|
||||
this.videoFile(),
|
||||
config.staticUri,
|
||||
config.contentUri,
|
||||
config.previewToken,
|
||||
t.size
|
||||
);
|
||||
|
||||
result[t.size] = {
|
||||
src: url,
|
||||
w: size.width,
|
||||
h: size.height,
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
getDefaults() {
|
||||
|
@ -195,6 +241,8 @@ export class Photo extends RestModel {
|
|||
EditedAt: null,
|
||||
CheckedAt: null,
|
||||
DeletedAt: null,
|
||||
Thumbs: {},
|
||||
DownloadUrl: "",
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -656,24 +704,39 @@ export class Photo extends RestModel {
|
|||
);
|
||||
}
|
||||
|
||||
generateThumbnailUrl = memoizeOne(
|
||||
(mainFileHash, videoFile, staticUri, contentUri, previewToken, size) => {
|
||||
let hash = mainFileHash;
|
||||
/**
|
||||
* use this one if you know the parameters changed AND yout task is so
|
||||
* performance critical, that you benefit from skipping the parameter-changed
|
||||
* -check from memoizeOne.
|
||||
*
|
||||
* If you don't know wether the parameters changed or if your task is not
|
||||
* incredibly performance critical, use the memoized 'generateThumbnailUrl'
|
||||
*/
|
||||
generateThumbnailUrlUnmemoized = (
|
||||
mainFileHash,
|
||||
videoFile,
|
||||
staticUri,
|
||||
contentUri,
|
||||
previewToken,
|
||||
size
|
||||
) => {
|
||||
let hash = mainFileHash;
|
||||
|
||||
if (!hash) {
|
||||
if (videoFile && videoFile.Hash) {
|
||||
return `${contentUri}/t/${videoFile.Hash}/${previewToken}/${size}`;
|
||||
}
|
||||
|
||||
return `${staticUri}/img/404.jpg`;
|
||||
if (!hash) {
|
||||
if (videoFile && videoFile.Hash) {
|
||||
return `${contentUri}/t/${videoFile.Hash}/${previewToken}/${size}`;
|
||||
}
|
||||
|
||||
return `${contentUri}/t/${hash}/${previewToken}/${size}`;
|
||||
return `${staticUri}/img/404.jpg`;
|
||||
}
|
||||
);
|
||||
|
||||
getDownloadUrl() {
|
||||
return `${config.apiUri}/dl/${this.mainFileHash()}?t=${config.downloadToken}`;
|
||||
return `${contentUri}/t/${hash}/${previewToken}/${size}`;
|
||||
};
|
||||
|
||||
generateThumbnailUrl = memoizeOne(this.generateThumbnailUrlUnmemoized);
|
||||
|
||||
getDownloadUrl(mainFileHash = this.mainFileHash()) {
|
||||
return `${config.apiUri}/dl/${mainFileHash}?t=${config.downloadToken}`;
|
||||
}
|
||||
|
||||
downloadAll() {
|
||||
|
@ -734,13 +797,13 @@ export class Photo extends RestModel {
|
|||
});
|
||||
}
|
||||
|
||||
calculateSize(width, height) {
|
||||
if (width >= this.Width && height >= this.Height) {
|
||||
calculateSizeFromProps(width, height, sourceWidth, sourceHeight) {
|
||||
if (width >= sourceWidth && height >= sourceHeight) {
|
||||
// Smaller
|
||||
return { width: this.Width, height: this.Height };
|
||||
return { width: sourceWidth, height: sourceHeight };
|
||||
}
|
||||
|
||||
const srcAspectRatio = this.Width / this.Height;
|
||||
const srcAspectRatio = sourceWidth / sourceHeight;
|
||||
const maxAspectRatio = width / height;
|
||||
|
||||
let newW, newH;
|
||||
|
@ -756,6 +819,10 @@ export class Photo extends RestModel {
|
|||
return { width: newW, height: newH };
|
||||
}
|
||||
|
||||
calculateSize(width, height) {
|
||||
return this.calculateSizeFromProps(width, height, this.Width, this.Height);
|
||||
}
|
||||
|
||||
getDateString(showTimeZone) {
|
||||
return this.generateDateString(
|
||||
showTimeZone,
|
||||
|
|
|
@ -95,53 +95,6 @@ export class Thumb extends Model {
|
|||
return result;
|
||||
}
|
||||
|
||||
static fromPhotos(photos) {
|
||||
let result = [];
|
||||
const n = photos.length;
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
result.push(this.fromPhoto(photos[i]));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static fromPhoto(photo) {
|
||||
if (photo.Files) {
|
||||
return this.fromFile(photo, photo.mainFile());
|
||||
}
|
||||
|
||||
if (!photo || !photo.Hash) {
|
||||
return this.notFound();
|
||||
}
|
||||
|
||||
const result = {
|
||||
UID: photo.UID,
|
||||
Title: photo.Title,
|
||||
TakenAtLocal: photo.getDateString(),
|
||||
Description: photo.Description,
|
||||
Favorite: photo.Favorite,
|
||||
Playable: photo.isPlayable(),
|
||||
DownloadUrl: this.downloadUrl(photo),
|
||||
Width: photo.Width,
|
||||
Height: photo.Height,
|
||||
Thumbs: {},
|
||||
};
|
||||
|
||||
for (let i = 0; i < thumbs.length; i++) {
|
||||
let t = thumbs[i];
|
||||
let size = photo.calculateSize(t.w, t.h);
|
||||
|
||||
result.Thumbs[t.size] = {
|
||||
src: photo.thumbnailUrl(t.size),
|
||||
w: size.width,
|
||||
h: size.height,
|
||||
};
|
||||
}
|
||||
|
||||
return new this(result);
|
||||
}
|
||||
|
||||
static fromFile(photo, file) {
|
||||
if (!photo || !file || !file.Hash) {
|
||||
return this.notFound();
|
||||
|
|
|
@ -53,7 +53,6 @@ import {Photo, MediaLive, MediaRaw, MediaVideo, MediaAnimated} from "model/photo
|
|||
import Album from "model/album";
|
||||
import Thumb from "model/thumb";
|
||||
import Event from "pubsub-js";
|
||||
import Viewer from "common/viewer";
|
||||
|
||||
export default {
|
||||
name: 'PPageAlbumPhotos',
|
||||
|
@ -244,12 +243,12 @@ export default {
|
|||
if (selected.isPlayable()) {
|
||||
this.$viewer.play({video: selected, album: this.album});
|
||||
} else {
|
||||
this.$viewer.show(Thumb.fromPhotos(this.results), index);
|
||||
this.$viewer.show(this.results, index);
|
||||
}
|
||||
} else if (showMerged) {
|
||||
this.$viewer.show(Thumb.fromFiles([selected]), 0);
|
||||
} else {
|
||||
Viewer.show(this, index);
|
||||
this.$viewer.show(this.results, index);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
<script>
|
||||
import {MediaAnimated, MediaLive, MediaRaw, MediaVideo, Photo} from "model/photo";
|
||||
import Thumb from "model/thumb";
|
||||
import Viewer from "common/viewer";
|
||||
import Event from "pubsub-js";
|
||||
|
||||
export default {
|
||||
|
@ -353,12 +352,12 @@ export default {
|
|||
if (selected.isPlayable()) {
|
||||
this.$viewer.play({video: selected});
|
||||
} else {
|
||||
this.$viewer.show(Thumb.fromPhotos(this.results), index);
|
||||
this.$viewer.show(this.results, index);
|
||||
}
|
||||
} else if (showMerged) {
|
||||
this.$viewer.show(Thumb.fromFiles([selected]), 0);
|
||||
} else {
|
||||
Viewer.show(this, index);
|
||||
this.$viewer.show(this.results, index);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -198,7 +198,7 @@ describe("model/thumb", () => {
|
|||
],
|
||||
};
|
||||
const photo = new Photo(values);
|
||||
const result = Thumb.fromPhoto(photo);
|
||||
const result = photo;
|
||||
assert.equal(result.UID, "ABC123");
|
||||
assert.equal(result.Description, "Nice description 3");
|
||||
assert.equal(result.Width, 500);
|
||||
|
@ -208,7 +208,7 @@ describe("model/thumb", () => {
|
|||
Description: "Nice description 3",
|
||||
};
|
||||
const photo3 = new Photo(values3);
|
||||
const result2 = Thumb.fromPhoto(photo3);
|
||||
const result2 = photo3;
|
||||
assert.equal(result2.UID, "");
|
||||
const values2 = {
|
||||
ID: 8,
|
||||
|
@ -221,7 +221,7 @@ describe("model/thumb", () => {
|
|||
Hash: "xdf45m",
|
||||
};
|
||||
const photo2 = new Photo(values2);
|
||||
const result3 = Thumb.fromPhoto(photo2);
|
||||
const result3 = photo2;
|
||||
assert.equal(result3.UID, "ABC123");
|
||||
assert.equal(result3.Title, "Crazy Cat");
|
||||
assert.equal(result3.Description, "Nice description");
|
||||
|
@ -247,7 +247,7 @@ describe("model/thumb", () => {
|
|||
};
|
||||
const photo = new Photo(values);
|
||||
const Photos = [photo];
|
||||
const result = Thumb.fromPhotos(Photos);
|
||||
const result = Photos;
|
||||
assert.equal(result[0].UID, "ABC123");
|
||||
assert.equal(result[0].Description, "Nice description 3");
|
||||
assert.equal(result[0].Width, 500);
|
||||
|
|
Loading…
Add table
Reference in a new issue