mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
media: Replace legacy .message_inline_image class.
This introduces two new replacement classes, depending on whether the inner content is an image or a video.
This commit is contained in:
@@ -117,7 +117,7 @@ export function initialize(): void {
|
||||
|
||||
// Inline image, video and twitter previews.
|
||||
if (
|
||||
$target.is("img.message_inline_image") ||
|
||||
$target.is(".media-image-element") ||
|
||||
$target.is(".message_inline_animated_image_still") ||
|
||||
$target.is("video") ||
|
||||
$target.is(".message_inline_video") ||
|
||||
|
@@ -241,7 +241,7 @@ export function canonical_url_of_media(media: HTMLMediaElement | HTMLImageElemen
|
||||
export function render_lightbox_media_list(): void {
|
||||
if (!is_open) {
|
||||
const message_media_list = $<HTMLMediaElement | HTMLImageElement>(
|
||||
".focused-message-list .message_inline_image img, .focused-message-list .message_inline_video video",
|
||||
".focused-message-list .message-media-preview-image img, .focused-message-list .message_inline_video video",
|
||||
).toArray();
|
||||
const $lightbox_media_list = $("#lightbox_overlay .image-list").empty();
|
||||
for (const media of message_media_list) {
|
||||
@@ -413,7 +413,8 @@ export function show_from_selected_message(): void {
|
||||
const $message_selected = $(".selected_message");
|
||||
let $message = $message_selected;
|
||||
// This is a function to satisfy eslint unicorn/no-array-callback-reference
|
||||
const media_classes = (): string => ".message_inline_image img, .message_inline_image video";
|
||||
const media_classes = (): string =>
|
||||
".message-media-preview-image img, .message-media-preview-video video";
|
||||
let $media = $message.find<HTMLMediaElement | HTMLImageElement>(media_classes());
|
||||
let $prev_traverse = false;
|
||||
|
||||
@@ -644,7 +645,7 @@ export function initialize(): void {
|
||||
|
||||
$("#main_div, #compose .preview_content").on(
|
||||
"click",
|
||||
".message_inline_image:not(.message_inline_video) a, .message_inline_animated_image_still",
|
||||
".message-media-preview-image:not(.message_inline_video) a, .message_inline_animated_image_still",
|
||||
function (e) {
|
||||
// prevent the link from opening in a new page.
|
||||
e.preventDefault();
|
||||
|
@@ -120,13 +120,13 @@ export function initialize(): void {
|
||||
|
||||
$("#main_div").on(
|
||||
"mouseover",
|
||||
'.message-list div.message_inline_image img[data-animated="true"]',
|
||||
'.message-list .message-media-preview-image img[data-animated="true"]',
|
||||
function (this: HTMLElement) {
|
||||
if (user_settings.web_animate_image_previews !== "on_hover") {
|
||||
return;
|
||||
}
|
||||
const $img = $(this);
|
||||
$img.closest(".message_inline_image").removeClass(
|
||||
$img.closest(".message-media-preview-image").removeClass(
|
||||
"message_inline_animated_image_still",
|
||||
);
|
||||
$img.attr(
|
||||
@@ -138,13 +138,15 @@ export function initialize(): void {
|
||||
|
||||
$("#main_div").on(
|
||||
"mouseout",
|
||||
'.message-list div.message_inline_image img[data-animated="true"]',
|
||||
'.message-list .message-media-preview-image img[data-animated="true"]',
|
||||
function (this: HTMLElement) {
|
||||
if (user_settings.web_animate_image_previews !== "on_hover") {
|
||||
return;
|
||||
}
|
||||
const $img = $(this);
|
||||
$img.closest(".message_inline_image").addClass("message_inline_animated_image_still");
|
||||
$img.closest(".message-media-preview-image").addClass(
|
||||
"message_inline_animated_image_still",
|
||||
);
|
||||
$img.attr(
|
||||
"src",
|
||||
$img.attr("src")!.replace(/\/[^/]+$/, "/" + thumbnail.preferred_format.name),
|
||||
|
@@ -341,13 +341,13 @@ export function initialize(): void {
|
||||
},
|
||||
});
|
||||
|
||||
message_list_tooltip(".message_inline_image > a > img", {
|
||||
message_list_tooltip(".media-image-element", {
|
||||
// Add a short delay so the user can mouseover several inline images without
|
||||
// tooltips showing and hiding rapidly
|
||||
delay: [300, 20],
|
||||
onShow(instance) {
|
||||
// Some message_inline_images aren't actually images with a title,
|
||||
// for example youtube videos, so we default to the actual href
|
||||
// Some message images do not include a title, such as YouTube
|
||||
// video previews, so we fall back to displaying the href value
|
||||
const title =
|
||||
$(instance.reference).parent().attr("aria-label") ??
|
||||
$(instance.reference).parent().attr("href");
|
||||
|
@@ -1038,9 +1038,9 @@ export class MessageListView {
|
||||
if (page_params.is_spectator) {
|
||||
// For images that fail to load due to being rate limited or being denied access
|
||||
// by server in general, we tell user to login to be able to view the image.
|
||||
$message_rows.find(".message_inline_image img").on("error", (e) => {
|
||||
$message_rows.find(".media-image-element").on("error", (e) => {
|
||||
$(e.target)
|
||||
.closest(".message_inline_image")
|
||||
.closest(".message-media-preview-image")
|
||||
.replaceWith($(render_login_to_view_image_button()));
|
||||
});
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ export function message_has_link(message_content: string): boolean {
|
||||
}
|
||||
|
||||
export function message_has_image(message_content: string): boolean {
|
||||
return is_element_in_message_content(message_content, ".message_inline_image");
|
||||
return is_element_in_message_content(message_content, ".message-media-preview-image");
|
||||
}
|
||||
|
||||
export function message_has_attachment(message_content: string): boolean {
|
||||
|
@@ -53,12 +53,25 @@ export function postprocess_content(html: string): string {
|
||||
}
|
||||
|
||||
if (elt.querySelector("img") || elt.querySelector("video")) {
|
||||
// Rewrite the legacy .message_inline_image class, whose name would add
|
||||
// confusion when Zulip supports inline images via standard Markdown.
|
||||
// We further adjust this class below for when the element contains a
|
||||
// video.
|
||||
elt.parentElement?.classList.replace(
|
||||
"message_inline_image",
|
||||
"message-media-preview-image",
|
||||
);
|
||||
// We want a class to refer to media links
|
||||
elt.classList.add("media-anchor-element");
|
||||
// Add a class to the video, if it exists, including
|
||||
// the .media-image-element class for properly treating
|
||||
// video thumbnails
|
||||
if (elt.querySelector("video")) {
|
||||
// We use a different class name to distinguish videos from images
|
||||
elt.parentElement?.classList.replace(
|
||||
"message-media-preview-image",
|
||||
"message-media-preview-video",
|
||||
);
|
||||
elt
|
||||
.querySelector("video")
|
||||
?.classList.add("media-video-element", "media-image-element");
|
||||
@@ -86,7 +99,10 @@ export function postprocess_content(html: string): string {
|
||||
elt.classList.add("message-embed-title-link");
|
||||
}
|
||||
|
||||
if (elt.parentElement?.classList.contains("message_inline_image")) {
|
||||
if (
|
||||
elt.parentElement?.classList.contains("message-media-preview-image") ||
|
||||
elt.parentElement?.classList.contains("message-media-preview-video")
|
||||
) {
|
||||
// For inline images we want to handle the tooltips explicitly, and disable
|
||||
// the browser's built in handling of the title attribute.
|
||||
const title = elt.getAttribute("title");
|
||||
@@ -210,7 +226,7 @@ export function postprocess_content(html: string): string {
|
||||
}
|
||||
|
||||
for (const inline_img of template.content.querySelectorAll<HTMLImageElement>(
|
||||
"div.message_inline_image > a > img",
|
||||
".message-media-preview-image img",
|
||||
)) {
|
||||
inline_img.setAttribute("loading", "lazy");
|
||||
// We can't just check whether `inline_image.src` starts with
|
||||
@@ -224,7 +240,7 @@ export function postprocess_content(html: string): string {
|
||||
// If the image source URL can't be parsed, likely due to
|
||||
// some historical bug in the Markdown processor, just
|
||||
// drop the invalid image element.
|
||||
inline_img.closest("div.message_inline_image")!.remove();
|
||||
inline_img.closest(".message-media-preview-image")!.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -246,7 +262,7 @@ export function postprocess_content(html: string): string {
|
||||
// If we're showing a still thumbnail, show a play
|
||||
// button so that users that it can be played.
|
||||
inline_img
|
||||
.closest(".message_inline_image")!
|
||||
.closest(".message-media-preview-image")!
|
||||
.classList.add("message_inline_animated_image_still");
|
||||
}
|
||||
}
|
||||
@@ -255,10 +271,10 @@ export function postprocess_content(html: string): string {
|
||||
}
|
||||
|
||||
// After all other processing on images has been done, we look for
|
||||
// adjacent images and tuck them structurally into galleries.
|
||||
// This will also process uploaded video thumbnails, which likewise
|
||||
// take the `.message_inline_image` class
|
||||
for (const elt of template.content.querySelectorAll(".message_inline_image")) {
|
||||
// adjacent images and videos, and tuck them structurally into galleries.
|
||||
for (const elt of template.content.querySelectorAll(
|
||||
".message-media-preview-image, .message-media-preview-video",
|
||||
)) {
|
||||
let gallery_element;
|
||||
|
||||
const is_part_of_open_gallery = elt.previousElementSibling?.classList.contains(
|
||||
|
@@ -505,7 +505,8 @@
|
||||
}
|
||||
|
||||
.twitter-image,
|
||||
.message_inline_image {
|
||||
.message-media-preview-image,
|
||||
.message-media-preview-video {
|
||||
/* Set a background for the image; the background will be visible
|
||||
behind the width of the transparent border. */
|
||||
border: solid 3px transparent;
|
||||
@@ -595,7 +596,7 @@
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.message_inline_image .media-image-element {
|
||||
.media-image-element {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
|
@@ -1330,7 +1330,7 @@ test("predicate_basics", ({override}) => {
|
||||
|
||||
const img_msg = {
|
||||
content:
|
||||
'<p><a href="/user_uploads/randompath/test.jpeg">test.jpeg</a></p><div class="message_inline_image"><a href="/user_uploads/randompath/test.jpeg" title="test.jpeg"><img src="/user_uploads/randompath/test.jpeg"></a></div>',
|
||||
'<p><a href="/user_uploads/randompath/test.jpeg">test.jpeg</a></p><div class="message-media-preview-image"><a href="/user_uploads/randompath/test.jpeg" title="test.jpeg"><img src="/user_uploads/randompath/test.jpeg"></a></div>',
|
||||
};
|
||||
|
||||
const link_msg = {
|
||||
@@ -1403,13 +1403,17 @@ test("predicate_basics", ({override}) => {
|
||||
assert.ok(!has_attachment(no_has_filter_matching_msg));
|
||||
|
||||
const has_image = get_predicate([["has", "image"]]);
|
||||
set_find_results_for_msg_content(img_msg, ".message_inline_image", ["stub"]);
|
||||
set_find_results_for_msg_content(img_msg, ".message-media-preview-image", ["stub"]);
|
||||
assert.ok(has_image(img_msg));
|
||||
set_find_results_for_msg_content(non_img_attachment_msg, ".message_inline_image", false);
|
||||
set_find_results_for_msg_content(non_img_attachment_msg, ".message-media-preview-image", false);
|
||||
assert.ok(!has_image(non_img_attachment_msg));
|
||||
set_find_results_for_msg_content(link_msg, ".message_inline_image", false);
|
||||
set_find_results_for_msg_content(link_msg, ".message-media-preview-image", false);
|
||||
assert.ok(!has_image(link_msg));
|
||||
set_find_results_for_msg_content(no_has_filter_matching_msg, ".message_inline_image", false);
|
||||
set_find_results_for_msg_content(
|
||||
no_has_filter_matching_msg,
|
||||
".message-media-preview-image",
|
||||
false,
|
||||
);
|
||||
assert.ok(!has_image(no_has_filter_matching_msg));
|
||||
|
||||
const has_reaction = get_predicate([["has", "reaction"]]);
|
||||
|
@@ -59,12 +59,12 @@ run_test("postprocess_media_and_embeds", () => {
|
||||
"</div>",
|
||||
),
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image message_inline_video">' +
|
||||
'<div class="message-media-preview-video message_inline_video">' +
|
||||
'<a href="http://zulip.zulipdev.com/user_uploads/w/ha/tever/inline.mp4" target="_blank" rel="noopener noreferrer" class="media-anchor-element">' +
|
||||
'<video src="http://zulip.zulipdev.com/user_uploads/w/ha/tever/inline.mp4" class="media-video-element media-image-element"></video>' +
|
||||
"</a>" +
|
||||
"</div>" +
|
||||
'<div class="youtube-video message_inline_image">' +
|
||||
'<div class="youtube-video message-media-preview-image">' +
|
||||
'<a class="media-anchor-element" href="https://www.youtube.com/watch?v=tyKJueEk0XM" target="_blank" rel="noopener noreferrer">' +
|
||||
'<img src="https://i.ytimg.com/vi/tyKJueEk0XM/mqdefault.jpg" class="media-image-element" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -122,12 +122,12 @@ run_test("inline_image_galleries", ({override}) => {
|
||||
),
|
||||
"<p>Message text</p>" +
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="1000x2000" src="/user_uploads/thumbnail/path/to/image.png/840x560.webp" class="media-image-element portrait-thumbnail" width="1000" height="2000" style="width: 5em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
"</div>" +
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="2000x1000" src="/user_uploads/thumbnail/path/to/image.png/840x560.webp" class="media-image-element landscape-thumbnail" width="2000" height="1000" style="width: 20em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -135,7 +135,7 @@ run_test("inline_image_galleries", ({override}) => {
|
||||
"</div>" +
|
||||
"<p>Message text</p>" +
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="1000x1000" src="/user_uploads/thumbnail/path/to/image.png/840x560.webp" class="media-image-element portrait-thumbnail" width="1000" height="1000" style="width: 10em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -196,7 +196,7 @@ run_test("message_inline_animated_image_still", ({override}) => {
|
||||
"</div>",
|
||||
),
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="3264x2448" src="/user_uploads/thumbnail/path/to/image.png/300x200.webp" class="media-image-element landscape-thumbnail" width="3264" height="2448" style="width: 13.333333333333334em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -214,7 +214,7 @@ run_test("message_inline_animated_image_still", ({override}) => {
|
||||
"</div>",
|
||||
),
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="100x200" src="/user_uploads/thumbnail/path/to/image.png/300x200.webp" class="media-image-element portrait-thumbnail" width="100" height="200" style="width: 5em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -232,7 +232,7 @@ run_test("message_inline_animated_image_still", ({override}) => {
|
||||
"</div>",
|
||||
),
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="1x10" src="/user_uploads/thumbnail/path/to/image.png/300x200.webp" class="media-image-element dinky-thumbnail extreme-aspect-ratio portrait-thumbnail" width="1" height="10" style="width: 1px;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -251,7 +251,7 @@ run_test("message_inline_animated_image_still", ({override}) => {
|
||||
"</div>",
|
||||
),
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="3264x2448" src="/user_uploads/thumbnail/path/to/image.png/300x200-anim.webp" data-animated="true" class="media-image-element landscape-thumbnail" width="3264" height="2448" style="width: 13.333333333333334em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -270,7 +270,7 @@ run_test("message_inline_animated_image_still", ({override}) => {
|
||||
"</div>",
|
||||
),
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image message_inline_animated_image_still">' +
|
||||
'<div class="message-media-preview-image message_inline_animated_image_still">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="3264x2448" src="/user_uploads/thumbnail/path/to/image.png/300x200.webp" data-animated="true" class="media-image-element landscape-thumbnail" width="3264" height="2448" style="width: 13.333333333333334em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -288,7 +288,7 @@ run_test("message_inline_animated_image_still", ({override}) => {
|
||||
"</div>",
|
||||
),
|
||||
'<div class="message-thumbnail-gallery">' +
|
||||
'<div class="message_inline_image message_inline_animated_image_still">' +
|
||||
'<div class="message-media-preview-image message_inline_animated_image_still">' +
|
||||
'<a href="/user_uploads/path/to/image.png" target="_blank" rel="noopener noreferrer" class="media-anchor-element" aria-label="image.png">' +
|
||||
'<img data-original-dimensions="3264x2448" src="/user_uploads/thumbnail/path/to/image.png/300x200.webp" data-animated="true" class="media-image-element landscape-thumbnail" width="3264" height="2448" style="width: 13.333333333333334em;" loading="lazy">' +
|
||||
"</a>" +
|
||||
@@ -301,7 +301,7 @@ run_test("message_inline_animated_image_still", ({override}) => {
|
||||
// history.
|
||||
assert.equal(
|
||||
postprocess_content(
|
||||
'<div class="message_inline_image">' +
|
||||
'<div class="message-media-preview-image">' +
|
||||
'<a href="https://zulip.%20[Click%20to%20join%20video%20call](https://meeting.example.com/abcd1234)%20example.com/user_uploads/2/ab/abcd1234/image.png" target="_blank" title="image.png">' +
|
||||
'<img src="https://zulip.%20[Click%20to%20join%20video%20call](https://meeting.example.com/abcd1234)%20example.com/user_uploads/2/ab/abcd1234/image.png">' +
|
||||
"</a>" +
|
||||
|
Reference in New Issue
Block a user