medias.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. class Media {
  2. constructor(data) {
  3. this.date = new Date(data.date);
  4. this.md5sum = data.md5sum;
  5. this.path = data.path;
  6. this.fileName = data.fileName;
  7. this.meta = data.meta || {};
  8. this.fixedTags = data.fixedTags || [];
  9. this.tags = data.tags || [];
  10. this.writeAccess = data.accessType === 2;
  11. this.thumbnail = `/api/media/thumbnail/${data.md5sum}.jpg`;
  12. this.original = `/api/media/original/${data.md5sum}`;
  13. this.ui = null;
  14. this.tags = this.tags.reduce((acc, tag) => { acc.add(tag.replaceAll(/\/\/+/gi, '/')); return acc; }, new Set());
  15. this.fixedTags = this.fixedTags.reduce((acc, tag) => { acc.add(tag.replaceAll(/\/\/+/gi, '/')); return acc; }, new Set());
  16. for (let i in this.meta) {
  17. if (this.meta[i].type === 'date')
  18. this.meta[i].value = new Date(parseInt(this.meta[i].value));
  19. else if (this.meta[i].type === 'number' || this.meta[i].type === 'octet')
  20. this.meta[i].value = parseInt(this.meta[i].value);
  21. else if (this.meta[i].type === 'string')
  22. this.meta[i].value = '' + this.meta[i].value;
  23. }
  24. }
  25. resize(maxWidth, maxHeight) {
  26. let ratio = Math.min(1, Math.max(
  27. maxWidth / (this.meta?.width || maxWidth),
  28. maxHeight / (this.meta?.height || maxHeight)));
  29. return {
  30. width: Math.floor(this.meta.width *ratio),
  31. height: Math.floor(this.meta.height *ratio),
  32. };
  33. }
  34. allTags() {
  35. return Array.from(new Set([...this.fixedTags, ...this.tags])).sort();
  36. }
  37. }
  38. function tryLoadMedia(md5sum) {
  39. return new Promise((ok, ko) => {
  40. $.get("/api/media/" +md5sum, data => {
  41. let item = new Media(data);
  42. MediaStorage.Instance.pushAll([item], true);
  43. ok(item);
  44. }).fail(err => {
  45. console.error("Trying to get media with md5sum " +md5sum +" failed:", err.responseText);
  46. ok(null);
  47. });
  48. });
  49. }
  50. class MediaStorage extends EventTarget
  51. {
  52. constructor() {
  53. super();
  54. this.allMeta = {};
  55. this.allMetaTypes = {};
  56. this.allTags = new Set();
  57. this.medias = [];
  58. this.oldest = null;
  59. this.newest = null;
  60. }
  61. #pushMeta(metaKey, metaVal) {
  62. if (metaKey === 'dateTime')
  63. return;
  64. if (!this.allMeta[metaKey])
  65. this.allMeta[metaKey] = new Set();
  66. this.allMeta[metaKey].add(metaVal.value);
  67. if (!this.allMetaTypes[metaKey])
  68. this.allMetaTypes[metaKey] = { type: metaVal.type, canBeEmpty: !!this.medias.length };
  69. }
  70. #pushTag(tag, first) {
  71. while (tag.length && tag.endsWith('/'))
  72. tag = tag.substr(0, tag.length -1);
  73. this.allTags.add(tag);
  74. let index = tag.lastIndexOf('/');
  75. if (index >= 0)
  76. this.#pushTag(tag.substr(0, index));
  77. }
  78. #pushUnique(media) {
  79. for (let i of media.tags)
  80. this.#pushTag(i, true);
  81. for (let i of media.fixedTags)
  82. this.#pushTag(i, true);
  83. for (let key in media.meta)
  84. this.#pushMeta(key, media.meta[key]);
  85. for (let key in this.allMetaTypes)
  86. if (!media.meta[key])
  87. this.allMetaTypes[key].canBeEmpty = true;
  88. this.medias.push(media);
  89. media.md5sum === 'b1bc7614d67333cacb60af149ed5ee1f' && console.log(this);
  90. }
  91. pushAll(arr, partialLoad) {
  92. let result = [];
  93. let reorder = false;
  94. for (let i of arr) {
  95. if (partialLoad !== true) {
  96. this.oldest = !this.oldest || this.oldest.date.getTime() > i.date.getTime() ? i : this.oldest;
  97. this.newest = !this.newest || this.newest.date.getTime() < i.date.getTime() ? i : this.newest;
  98. }
  99. if (this.medias.length && this.medias[this.medias.length -1].date.getTime() < i.date.getTime())
  100. reorder = true;
  101. if (this.medias.find(x => x.md5sum === i.md5sum))
  102. continue;
  103. this.#pushUnique(i);
  104. result.push(i);
  105. }
  106. for (let i of result)
  107. this.dispatchEvent(new CustomEvent("newMedia", { detail: i }));
  108. if (reorder) {
  109. this.medias.sort((a, b) => b.date.getTime() - a.date.getTime());
  110. this.dispatchEvent(new CustomEvent("rebuildMedia"));
  111. }
  112. }
  113. onFilterUpdated() {
  114. this.dispatchEvent(new CustomEvent("rebuildMedia"));
  115. }
  116. getMediaIndex(media) {
  117. return this.medias.indexOf(media);
  118. }
  119. nextMedia(current) {
  120. return this.medias[this.getMediaIndex(current) +1];
  121. }
  122. previousMedia(current) {
  123. return this.medias[this.getMediaIndex(current) -1];
  124. }
  125. getMediaBetweenIndexes(a, b) {
  126. if (a > b)
  127. return this.getMediaBetweenIndexes(b, a);
  128. return this.medias.slice(a, b +1);
  129. }
  130. getMediaBetween(a, b) {
  131. let aIndex = this.medias.indexOf(a);
  132. let bIndex = this.medias.indexOf(b);
  133. if (aIndex < 0 || bIndex < 0 || aIndex === bIndex)
  134. return [];
  135. return this.getMediaBetweenIndexes(aIndex, bIndex);
  136. }
  137. async getMedia(md5sum) {
  138. let media = this.medias.find(x => x.md5sum === md5sum);
  139. if (media)
  140. return media;
  141. return await tryLoadMedia(md5sum);
  142. }
  143. }
  144. MediaStorage.Instance = new MediaStorage();