1
0

uiMedia.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. $(() => {
  2. var fullPageMediaDisplayed = false;
  3. var selectedThumbnails = [];
  4. var lastKeyboardEvent = null;
  5. var lastSelection = null;
  6. function onItemSelected(mediaItem) {
  7. document.getElementById("pch-mediaList").classList.add("selection");
  8. }
  9. function onItemDeselected(mediaItem) {
  10. if (!selectedThumbnails.length)
  11. document.getElementById("pch-mediaList").classList.remove("selection");
  12. }
  13. function buildThumbnail(mediaItem) {
  14. if (mediaItem.ui)
  15. return mediaItem.ui;
  16. let checkbox = document.createElement("input");
  17. let editButton = document.createElement("button");
  18. let img = document.createElement("img");
  19. let container = document.createElement("li");
  20. let loadingImg = document.createElement("div");
  21. checkbox.type = "checkbox";
  22. editButton.type = "button";
  23. if (!mediaItem.writeAccess)
  24. editButton.classList.add("hidden");
  25. let editButtonSpan = document.createElement("span");
  26. editButtonSpan.className = "bi bi-pen";
  27. editButton.appendChild(editButtonSpan);
  28. container.className = "pch-image loading col-12 col-md-6 col-xl-4";
  29. loadingImg.classList.add("spinner");
  30. loadingImg.innerHTML = "<span class='spinner-grow'></span>";
  31. container.dataset.md5sum = mediaItem.md5sum;
  32. img.loading = "lazy";
  33. let requestSize = mediaItem.resize(450, 450);
  34. requestSize = requestSize ? `w=${requestSize.width}&h=${requestSize.height}&` : "";
  35. img.src = `${mediaItem.thumbnail}?${requestSize}q=4`;
  36. img.classList.add("img-fluid");
  37. img.classList.add("img-thumbnail");
  38. img.addEventListener("load", () => {
  39. container.classList.remove("loading");
  40. container.classList.remove("spinner-grow");
  41. });
  42. container.style.width = `${requestSize.width}px`;
  43. container.appendChild(loadingImg);
  44. container.appendChild(img);
  45. container.appendChild(checkbox);
  46. container.appendChild(editButton);
  47. let setSelectionCheckboxValue = function(media, value) {
  48. media.ui.checkbox.checked = value;
  49. let indexInSelection = selectedThumbnails.indexOf(media.md5sum);
  50. if (value && indexInSelection < 0) {
  51. selectedThumbnails.push(media.md5sum);
  52. onItemSelected(media);
  53. return true;
  54. } else if (!value && indexInSelection >= 0) {
  55. selectedThumbnails.splice(indexInSelection, 1);
  56. onItemDeselected(media);
  57. return true;
  58. }
  59. return false;
  60. }
  61. mediaItem.setSelectionCheckboxValue = value => setSelectionCheckboxValue(mediaItem, value);
  62. let cascadeSetSelectionCheckboxValue = function(value) {
  63. if (!setSelectionCheckboxValue(mediaItem, value))
  64. return;
  65. if (lastKeyboardEvent?.shiftKey && lastSelection) {
  66. let _lastKeyboardEvent = lastKeyboardEvent;
  67. lastKeyboardEvent = null;
  68. for (let i of MediaStorage.Instance.getMediaBetween(lastSelection, mediaItem)) {
  69. if (i === mediaItem)
  70. continue;
  71. i.ui.checkbox.setAttribute("checked", value);
  72. i.ui.checkbox.checked = value;
  73. setSelectionCheckboxValue(i, value);
  74. }
  75. lastKeyboardEvent = _lastKeyboardEvent;
  76. }
  77. lastSelection = mediaItem;
  78. }
  79. editButton.addEventListener("click", e => {
  80. e.stopPropagation();
  81. if (!checkbox.checked) {
  82. checkbox.checked = true;
  83. setSelectionCheckboxValue(mediaItem, true);
  84. }
  85. let sel = selectedThumbnails.map(x => MediaStorage.Instance.getMediaLocal(x)).filter(x => x.writeAccess);
  86. if (sel.length === 1 && sel[0].md5sum === mediaItem.md5sum) {
  87. checkbox.checked = false;
  88. setSelectionCheckboxValue(mediaItem, false);
  89. document.location.hash = mediaItem.md5sum;
  90. return;
  91. }
  92. console.log(sel);
  93. });
  94. container.addEventListener("click", () => {
  95. if (selectedThumbnails.length || lastKeyboardEvent?.ctrlKey) {
  96. let value = !checkbox.checked;
  97. checkbox.setAttribute("checked", value);
  98. checkbox.checked = value;
  99. cascadeSetSelectionCheckboxValue(value);
  100. return;
  101. }
  102. document.location.hash = mediaItem.md5sum;
  103. });
  104. checkbox.addEventListener("click", evt => {
  105. evt.stopPropagation();
  106. });
  107. checkbox.addEventListener("change", evt => {
  108. cascadeSetSelectionCheckboxValue(checkbox.checked);
  109. });
  110. return mediaItem.ui = {
  111. root: container,
  112. img: img,
  113. checkbox: checkbox
  114. };
  115. }
  116. function buildYear(date) {
  117. let result = document.createElement('h3');
  118. result.className = "col-12";
  119. result.textContent = date.getUTCFullYear();
  120. return result;
  121. }
  122. function buildMonth(date) {
  123. let result = document.createElement('h4');
  124. result.className = "col-12";
  125. result.textContent = date.toLocaleString('default', { month: 'long' });
  126. return result;
  127. }
  128. let lastItemDisplayed = null;
  129. let displayedItemCount = 0;
  130. const displayItemBatchCount = 15;
  131. let targetDisplayedItems = displayItemBatchCount;
  132. function redraw(container, media) {
  133. buildThumbnail(media);
  134. if (!media.ui)
  135. return;
  136. let yearUpdated = !container.dataset.lastItemYear || container.dataset.lastItemYear != media.date.getUTCFullYear();
  137. if (yearUpdated) {
  138. container.appendChild(buildYear(media.date));
  139. container.dataset.lastItemYear = media.date.getUTCFullYear();
  140. }
  141. if (yearUpdated || container.dataset.lastItemMonth === undefined || container.dataset.lastItemMonth != media.date.getUTCMonth()) {
  142. container.appendChild(buildMonth(media.date));
  143. container.dataset.lastItemMonth = media.date.getUTCMonth();
  144. }
  145. container.appendChild(media.ui.root);
  146. lastItemDisplayed = media;
  147. displayedItemCount++;
  148. }
  149. MediaStorage.Instance.addEventListener("rebuildMedia", (evt) => {
  150. let newContainer = document.getElementById('pch-mediaList');
  151. newContainer.textContent = '';
  152. newContainer.dataset.lastItemYear = null;
  153. newContainer.dataset.lastItemMonth = null;
  154. lastItemDisplayed = null;
  155. displayedItemCount = 0;
  156. targetDisplayedItems = displayItemBatchCount;
  157. for (let i of selectedThumbnails) {
  158. let media = MediaStorage.Instance.getMediaLocal(i);
  159. media?.setSelectionCheckboxValue(false);
  160. }
  161. lastSelection = null;
  162. for (let i of MediaStorage.Instance.medias)
  163. if (window.FilterManager.match(i)) {
  164. redraw(newContainer, i);
  165. if (displayedItemCount >= targetDisplayedItems)
  166. break;
  167. }
  168. });
  169. MediaStorage.Instance.addEventListener("newMedia", (evt) => {
  170. if (displayedItemCount < targetDisplayedItems && window.FilterManager.match(evt.detail)) {
  171. let container = document.getElementById('pch-mediaList');
  172. redraw(container, evt.detail);
  173. }
  174. });
  175. window.displayMoreMedia = () => {
  176. targetDisplayedItems += displayItemBatchCount;
  177. let container = document.getElementById('pch-mediaList');
  178. for (let index = lastItemDisplayed ? (MediaStorage.Instance.getMediaIndex(lastItemDisplayed) +1) : 0;
  179. displayedItemCount < targetDisplayedItems; ++index) {
  180. let media = MediaStorage.Instance.medias[index];
  181. if (!media)
  182. return;
  183. if (window.FilterManager.match(media))
  184. redraw(container, media);
  185. }
  186. }
  187. });