class Media { constructor(data) { this.date = new Date(data.date); this.md5sum = data.md5sum; this.path = data.path; this.fileName = data.fileName; this.meta = data.meta || {}; this.meta.height = this.meta.height ? parseInt(this.meta.height) : undefined; this.meta.width = this.meta.width ? parseInt(this.meta.width) : undefined; this.tags = data.tags || []; this.thumbnail = `/api/media/thumbnail/${data.md5sum}.jpg`; this.original = `/api/media/original/${data.md5sum}`; this.ui = null; } resize(maxWidth, maxHeight) { let ratio = Math.min(1, Math.max( maxWidth / (this.meta?.width || maxWidth), maxHeight / (this.meta?.height || maxHeight))); return { width: Math.floor(this.meta.width *ratio), height: Math.floor(this.meta.height *ratio), }; } } function tryLoadMedia(md5sum) { return new Promise((ok, ko) => { $.get("/api/media/" +md5sum, data => { let item = new Media(data); MediaStorage.Instance.pushAll([item], true); ok(item); }).fail(err => { console.error("Trying to get media with md5sum " +md5sum +" failed:", err.responseText); ok(null); }); }); } class MediaStorage extends EventTarget { constructor() { super(); this.medias = []; this.oldest = null; this.newest = null; } pushAll(arr, partialLoad) { let result = []; let reorder = false; for (let i of arr) { if (this.medias.find(x => x.md5sum === i.md5sum)) continue; if (this.medias.length && this.medias[this.medias.length -1].date.getTime() < i.date.getTime()) reorder = true; this.medias.push(i); if (partialLoad !== true) { this.oldest = !this.oldest || this.oldest.date.getTime() > i.date.getTime() ? i : this.oldest; this.newest = !this.newest || this.newest.date.getTime() < i.date.getTime() ? i : this.newest; } result.push(i); } for (let i of result) this.dispatchEvent(new CustomEvent("newMedia", { detail: i })); if (reorder) { this.medias.sort((a, b) => b.date.getTime() - a.date.getTime()); this.dispatchEvent(new CustomEvent("rebuildMedia")); } } getMediaIndex(media) { return this.medias.indexOf(media); } nextMedia(current) { return this.medias[this.getMediaIndex(current) +1]; } previousMedia(current) { return this.medias[this.getMediaIndex(current) -1]; } getMediaBetweenIndexes(a, b) { if (a > b) return this.getMediaBetweenIndexes(b, a); return this.medias.slice(a, b +1); } getMediaBetween(a, b) { let aIndex = this.medias.indexOf(a); let bIndex = this.medias.indexOf(b); if (aIndex < 0 || bIndex < 0 || aIndex === bIndex) return []; return this.getMediaBetweenIndexes(aIndex, bIndex); } async getMedia(md5sum) { let media = this.medias.find(x => x.md5sum === md5sum); if (media) return media; return await tryLoadMedia(md5sum); } } MediaStorage.Instance = new MediaStorage();