diff --git a/web/src/lightbox.ts b/web/src/lightbox.ts index 94cbc291d2..35eb9699ca 100644 --- a/web/src/lightbox.ts +++ b/web/src/lightbox.ts @@ -23,8 +23,10 @@ type Payload = { }; let is_open = false; -// the asset map is a map of all retrieved images and YouTube videos that are -// memoized instead of being looked up multiple times. + +// The asset map is a map of all retrieved images and YouTube videos that are memoized instead of +// being looked up multiple times. It is keyed by the asset's "canonical URL," which is likely the +// `src` used in the message feed, but for thumbnailed images is the full-resolution original URL. const asset_map = new Map(); export class PanZoomControl { @@ -200,7 +202,15 @@ export function clear_for_testing(): void { asset_map.clear(); } -export function render_lightbox_media_list(preview_source: string): void { +export function canonical_url_of_media(media: HTMLElement): string { + let media_src = media.getAttribute("src"); + if (!media_src || media_src.startsWith("/user_uploads/thumbnail/")) { + media_src = media.parentElement!.getAttribute("href")!; + } + return media_src; +} + +export function render_lightbox_media_list(displayed_source: string): void { if (!is_open) { const media_list = $( ".focused-message-list .message_inline_image img, .focused-message-list .message_inline_video video", @@ -208,17 +218,22 @@ export function render_lightbox_media_list(preview_source: string): void { const $media_list = $("#lightbox_overlay .image-list").empty(); for (const media of media_list) { - const unverified_src = media.getAttribute("src")!; - const src = util.is_valid_url(unverified_src) ? unverified_src : ""; - const className = preview_source === src ? "image selected" : "image"; + const src = canonical_url_of_media(media); + const className = displayed_source === src ? "image selected" : "image"; const is_video = media.tagName === "VIDEO"; + // We parse the data for each image to show in the list, + // while we still have its original DOM element handy, so + // that navigating within the list only needs the `src` + // attribute used to construct the node object above. + const payload = parse_media_data(media); + let $node: JQuery; if (is_video) { $node = $("
") .addClass(className) .addClass("lightbox_video") - .attr("data-src", src); + .attr("data-url", payload.url); const $video = $("