|
|
@@ -129,6 +129,11 @@ $(() => {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ let lastItemDisplayed = null;
|
|
|
+ let displayedItemCount = 0;
|
|
|
+ const displayItemBatchCount = 15;
|
|
|
+ let targetDisplayedItems = displayItemBatchCount;
|
|
|
+
|
|
|
function redraw(container, media) {
|
|
|
buildThumbnail(media);
|
|
|
if (!media.ui)
|
|
|
@@ -143,6 +148,9 @@ $(() => {
|
|
|
container.dataset.lastItemMonth = media.date.getUTCMonth();
|
|
|
}
|
|
|
container.appendChild(media.ui.root);
|
|
|
+
|
|
|
+ lastItemDisplayed = media;
|
|
|
+ displayedItemCount++;
|
|
|
}
|
|
|
|
|
|
MediaStorage.Instance.addEventListener("rebuildMedia", (evt) => {
|
|
|
@@ -150,239 +158,33 @@ $(() => {
|
|
|
newContainer.textContent = '';
|
|
|
newContainer.dataset.lastItemYear = null;
|
|
|
newContainer.dataset.lastItemMonth = null;
|
|
|
+ lastItemDisplayed = null;
|
|
|
+ displayedItemCount = 0;
|
|
|
+ targetDisplayedItems = displayItemBatchCount;
|
|
|
for (let i of MediaStorage.Instance.medias)
|
|
|
- if (window.FilterManager.match(i))
|
|
|
+ if (window.FilterManager.match(i)) {
|
|
|
redraw(newContainer, i);
|
|
|
+ if (displayedItemCount >= targetDisplayedItems)
|
|
|
+ break;
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
MediaStorage.Instance.addEventListener("newMedia", (evt) => {
|
|
|
- let container = document.getElementById('pch-mediaList');
|
|
|
- if (window.FilterManager.match(evt.detail))
|
|
|
+ if (displayedItemCount < targetDisplayedItems && window.FilterManager.match(evt.detail)) {
|
|
|
+ let container = document.getElementById('pch-mediaList');
|
|
|
redraw(container, evt.detail);
|
|
|
- });
|
|
|
-
|
|
|
- function serializeFileSize(size) {
|
|
|
- let units = [ 'o', 'Ko', 'Mo', 'Go', 'To' ];
|
|
|
- let idx = 0;
|
|
|
- while (size >= 800 && idx < units.length) {
|
|
|
- ++idx;
|
|
|
- size /= 1024;
|
|
|
- }
|
|
|
- size = Math.floor(size * 100) / 100;
|
|
|
- return `${size} ${units[idx]}`;
|
|
|
- }
|
|
|
-
|
|
|
- function displayMeta(key, value, isRo) {
|
|
|
- let li = document.createElement("li");
|
|
|
- let type = value?.type || null;
|
|
|
- let val = (value?.value !== undefined ? value.value : value);
|
|
|
- if (!val && val !== '')
|
|
|
- return null;
|
|
|
- if (type === 'date')
|
|
|
- val = val.toLocaleString();
|
|
|
- if (["dimension", "height", "width"].indexOf(key) >= 0)
|
|
|
- val += ' px';
|
|
|
- if (["fileSize"].indexOf(key) >= 0)
|
|
|
- val = serializeFileSize(val);
|
|
|
- if (key == 'fNumber')
|
|
|
- val = `f/ ${val}`;
|
|
|
- let keyTranslate = {
|
|
|
- fileSize: "File Size",
|
|
|
- photochamberImport: "Photochamber Imported",
|
|
|
- lensModel: "Lens Model",
|
|
|
- exposureTimeStr: "Exposure Time"
|
|
|
- };
|
|
|
- let keySpan = document.createElement('span');
|
|
|
- let valSpan = document.createElement('div');
|
|
|
- li.classList.add("row");
|
|
|
- keySpan.className = "metaKey col-xl-12 col-4";
|
|
|
- valSpan.className = "metaVal col-xl-12 col-8";
|
|
|
- let inputGroup = document.createElement('form');
|
|
|
- valSpan.appendChild(inputGroup);
|
|
|
- inputGroup.classList.add('input-group');
|
|
|
- keySpan.innerText = (keyTranslate[key] || (key[0].toUpperCase()+key.substr(1))) + ':';
|
|
|
- let valInput = document.createElement("input");
|
|
|
- valInput.classList.add("form-control");
|
|
|
- valInput.value = val;
|
|
|
- valInput.disabled = isRo;
|
|
|
- valInput.addEventListener('keyup', evt => evt.stopPropagation());
|
|
|
- valInput.addEventListener('keydown', evt => evt.stopPropagation());
|
|
|
- inputGroup.appendChild(valInput);
|
|
|
- if (!isRo) {
|
|
|
- let bt = document.createElement('button');
|
|
|
- bt.className = 'btn btn-outline-secondary';
|
|
|
- bt.type = 'button';
|
|
|
- bt.innerHTML = '<i class="bi bi-pen"></i>';
|
|
|
- inputGroup.appendChild(bt);
|
|
|
- bt.addEventListener('click', () => MediaStorage.Instance.setMetaValue(fullPageMediaDisplayed.md5sum, key, valInput.value));
|
|
|
- inputGroup.addEventListener('submit', evt => {
|
|
|
- evt.preventDefault();
|
|
|
- MediaStorage.Instance.setMetaValue(fullPageMediaDisplayed.md5sum, key, valInput.value);
|
|
|
- });
|
|
|
- }
|
|
|
- li.appendChild(keySpan);
|
|
|
- li.appendChild(valSpan);
|
|
|
- return li;
|
|
|
- }
|
|
|
-
|
|
|
- function displayMetas(metaData, isRo) {
|
|
|
- let metaList = document.createElement("ul");
|
|
|
-
|
|
|
- metaData.libraryPath = null;
|
|
|
-
|
|
|
- metaData.tags = metaData.fixedTags = null;
|
|
|
-
|
|
|
- if (metaData.exposureTime && metaData.exposureTimeStr)
|
|
|
- metaData.exposureTime = null;
|
|
|
-
|
|
|
- if (metaData.date && metaData.dateTime)
|
|
|
- metaData.dateTime = null;
|
|
|
-
|
|
|
- if (metaData.height && metaData.width) {
|
|
|
- metaData.dimension = { type: "string", value: `${metaData.width.value} x ${metaData.height.value}` }
|
|
|
- metaData.height = metaData.width = null;
|
|
|
- }
|
|
|
-
|
|
|
- for (let i of [ "date", "dimension", "height", "width", "fileSize" ]) {
|
|
|
- let metaItem = displayMeta(i, metaData[i], true);
|
|
|
- metaItem && metaList.appendChild(metaItem);
|
|
|
- metaData[i] = null;
|
|
|
}
|
|
|
+ });
|
|
|
|
|
|
- for (let i of Object.keys(metaData).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))) {
|
|
|
- let metaItem = displayMeta(i, metaData[i], isRo || !MediaStorage.Instance.allMetaTypes[i]?.canWrite);
|
|
|
- metaItem && metaList.appendChild(metaItem);
|
|
|
+ window.displayMoreMedia = () => {
|
|
|
+ targetDisplayedItems += displayItemBatchCount;
|
|
|
+ let container = document.getElementById('pch-mediaList');
|
|
|
+ for (let index = lastItemDisplayed ? (MediaStorage.Instance.getMediaIndex(lastItemDisplayed) +1) : 0;
|
|
|
+ displayedItemCount < targetDisplayedItems; ++index) {
|
|
|
+ let media = MediaStorage.Instance.medias[index];
|
|
|
+ if (window.FilterManager.match(media))
|
|
|
+ redraw(container, media);
|
|
|
}
|
|
|
-
|
|
|
- if (!isRo)
|
|
|
- for (let i of ['geoCountry']) {
|
|
|
- if (!metaData[i]) {
|
|
|
- let metaItem = displayMeta(i, "", false);
|
|
|
- metaItem && metaList.appendChild(metaItem);
|
|
|
- }
|
|
|
- }
|
|
|
- return metaList;
|
|
|
}
|
|
|
-
|
|
|
- function displayTags(fixedTagList, tagList, writeAccess) {
|
|
|
- let tagListUi = document.createElement("ul");
|
|
|
- tagListUi.className = "taglist";
|
|
|
- let createTagUiItem = (i, roTag) => {
|
|
|
- let uiItem = document.createElement("li");
|
|
|
- uiItem.className = "badge text-bg-light";
|
|
|
- let textItem = document.createElement("span");
|
|
|
- textItem.textContent = i;
|
|
|
- uiItem.appendChild(textItem);
|
|
|
- if (!roTag) {
|
|
|
- let btItem = document.createElement("a");
|
|
|
- btItem.className = "border-start bi bi-x removeBt";
|
|
|
- btItem.href = '#';
|
|
|
- btItem.addEventListener('click', e => {
|
|
|
- e.preventDefault();
|
|
|
- });
|
|
|
- uiItem.appendChild(btItem);
|
|
|
- }
|
|
|
- tagListUi.appendChild(uiItem);
|
|
|
- };
|
|
|
- for (let i of fixedTagList)
|
|
|
- createTagUiItem(i, true);
|
|
|
- for (let i of tagList)
|
|
|
- createTagUiItem(i, !writeAccess);
|
|
|
- return tagListUi;
|
|
|
- }
|
|
|
-
|
|
|
- function _displayMediaFullPage(fileName, imgUrl, metaData, downloadLink, writeAccess) {
|
|
|
- return new Promise(ok => {
|
|
|
- document.getElementById("pch-fullPagePreviewContainer").classList.add("loading");
|
|
|
- document.getElementById("pch-fullPageMedia-title").innerText = fileName;
|
|
|
- document.getElementById("pch-fullPagePreview").onceLoaded = ok;
|
|
|
- document.getElementById("pch-fullPagePreview").src = imgUrl;
|
|
|
- document.getElementById("pch-fullPageDetail").innerText = "";
|
|
|
- document.getElementById("pch-fullPageDetail").appendChild(displayMetas(Object.assign({}, metaData || {}), !writeAccess));
|
|
|
- document.getElementById("pch-fullPageDetail").appendChild(displayTags(metaData?.fixedTags || [], metaData?.tags || [], writeAccess));
|
|
|
- if (downloadLink) {
|
|
|
- document.getElementById("pch-fullPageDetail-dlButton").classList.remove("hidden");
|
|
|
- document.getElementById("pch-fullPageDetail-dlButton").dataset["link"] = downloadLink;
|
|
|
- } else {
|
|
|
- document.getElementById("pch-fullPageDetail-dlButton").classList.add("hidden");
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- function LoadPreviousMedia() {
|
|
|
- let media = MediaStorage.Instance.previousMedia(fullPageMediaDisplayed);
|
|
|
- if (media)
|
|
|
- window.displayMediaFullPage(media);
|
|
|
- }
|
|
|
-
|
|
|
- function LoadNextMedia() {
|
|
|
- let media = MediaStorage.Instance.nextMedia(fullPageMediaDisplayed);
|
|
|
- if (media)
|
|
|
- window.displayMediaFullPage(media);
|
|
|
- }
|
|
|
-
|
|
|
- function CloseFullpageMedia() {
|
|
|
- document.getElementById("pch-fullPageMedia").classList.add("hidden");
|
|
|
- fullPageMediaDisplayed = false;
|
|
|
- history.pushState({}, '', '#');
|
|
|
- }
|
|
|
-
|
|
|
- window.displayMediaFullPage = function(mediaItem) {
|
|
|
- document.getElementById("pch-fullPageMedia").classList.remove("hidden");
|
|
|
- fullPageMediaDisplayed = mediaItem;
|
|
|
- if (!mediaItem)
|
|
|
- return _displayMediaFullPage("Error", null, {}, [], null, false);
|
|
|
- let containerSize = document.getElementById("pch-fullPageMedia").getBoundingClientRect();
|
|
|
- let requestSize = mediaItem.resize(containerSize.width, containerSize.height);
|
|
|
- document.getElementById("pch-fullPagePreview").parentNode.style.maxWidth = "100%";
|
|
|
- document.getElementById("pch-fullPagePreview").parentNode.style.maxHeight = "100%";
|
|
|
- let meta = {
|
|
|
- ...mediaItem.meta,
|
|
|
- date: { type: 'date', value: mediaItem.date } || undefined,
|
|
|
- filename: mediaItem.filename ? { type: 'string', value: mediaItem.fileName } : undefined,
|
|
|
- fixedTags: mediaItem.fixedTags,
|
|
|
- tags: mediaItem.tags
|
|
|
- };
|
|
|
- if (document.location.hash != `#${mediaItem.md5sum}`)
|
|
|
- history.pushState({}, '', `#${mediaItem.md5sum}`);
|
|
|
- return _displayMediaFullPage(mediaItem.fileName, `${mediaItem.thumbnail}?w=${requestSize.width}&h=${requestSize.height}&q=6`, meta, mediaItem.original, mediaItem.writeAccess);
|
|
|
- }
|
|
|
-
|
|
|
- document.getElementById("pch-fullPageMedia-closeBt")
|
|
|
- .addEventListener("click", () => CloseFullpageMedia());
|
|
|
- document.getElementById("pch-fullPagePreview").addEventListener("load", () => {
|
|
|
- document.getElementById("pch-fullPagePreviewContainer").classList.remove("loading");
|
|
|
- let domItem = document.getElementById("pch-fullPagePreview");
|
|
|
- domItem.onceLoaded && domItem.onceLoaded();
|
|
|
- domItem.onceLoaded = null;
|
|
|
- });
|
|
|
- document.getElementById('pch-fullPageDetail-dlButton').addEventListener("click", (evt) => {
|
|
|
- if (!evt.target?.dataset?.link)
|
|
|
- return;
|
|
|
- let link = document.createElement('a');
|
|
|
- link.target='_blank';
|
|
|
- link.setAttribute("download", "");
|
|
|
- link.href = evt.target.dataset.link;
|
|
|
- link.click();
|
|
|
- });
|
|
|
- document.addEventListener("keyup", evt => {
|
|
|
- lastKeyboardEvent = evt;
|
|
|
- });
|
|
|
- document.addEventListener("keydown", evt => {
|
|
|
- lastKeyboardEvent = evt;
|
|
|
- if (!fullPageMediaDisplayed)
|
|
|
- return;
|
|
|
- if (evt.keyCode === 37 || evt.keyCode === 38)
|
|
|
- LoadPreviousMedia();
|
|
|
- else if (evt.keyCode === 39 || evt.keyCode === 40)
|
|
|
- LoadNextMedia();
|
|
|
- else if (evt.keyCode === 27)
|
|
|
- CloseFullpageMedia();
|
|
|
- else {
|
|
|
- console.log("Unregistered key event", evt.key, evt.keyCode);
|
|
|
- return;
|
|
|
- }
|
|
|
- evt.preventDefault();
|
|
|
- });
|
|
|
});
|
|
|
|