Skip to content

Commit

Permalink
Fix media with query parameters showing as link (#1179)
Browse files Browse the repository at this point in the history
Also add support for jxl extension
  • Loading branch information
aeharding committed Jan 24, 2024
1 parent 952eac6 commit ede7a24
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 27 deletions.
4 changes: 3 additions & 1 deletion src/features/comment/links/LinkPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export default function LinkPreview({ link }: LinkPreviewProps): ReactNode {
}
}, [link.url, determineObjectTypeFromUrl]);

if (link.type === "image" || isUrlImage(link.url))
const isImage = useMemo(() => isUrlImage(link.url), [link.url]);

if (link.type === "image" || isImage)
return (
<LinkImage src={getImageSrc(link.url, { size: 30 })} alt={link.text} />
);
Expand Down
15 changes: 10 additions & 5 deletions src/features/gallery/PostMedia.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { findLoneImage } from "../../helpers/markdown";
import GalleryImg, { GalleryImgProps } from "./GalleryImg";
import { isUrlMedia, isUrlVideo } from "../../helpers/url";
import Video, { VideoProps } from "../shared/Video";
import { RefObject, forwardRef, memo } from "react";
import { RefObject, forwardRef, memo, useMemo } from "react";

export interface PostGalleryImgProps
extends Omit<GalleryImgProps & VideoProps, "src"> {
Expand All @@ -14,11 +14,12 @@ const PostMedia = forwardRef<
HTMLVideoElement | HTMLImageElement,
PostGalleryImgProps
>(function PostMedia({ post, ...props }, ref) {
const src = getPostMedia(post);
const src = useMemo(() => getPostMedia(post), [post]);
const isVideo = useMemo(() => src && isUrlVideo(src), [src]);

if (src && isUrlVideo(src))
if (isVideo)
return (
<Video ref={ref as RefObject<HTMLVideoElement>} src={src} {...props} />
<Video ref={ref as RefObject<HTMLVideoElement>} src={src!} {...props} />
);

return (
Expand All @@ -34,7 +35,11 @@ const PostMedia = forwardRef<
export default memo(PostMedia);

export function getPostMedia(post: PostView): string | undefined {
if (post.post.url && isUrlMedia(post.post.url)) return post.post.url;
if (post.post.url && isUrlMedia(post.post.url)) {
if (post.post.thumbnail_url) return post.post.thumbnail_url;

return post.post.url;
}

if (post.post.thumbnail_url) return post.post.thumbnail_url;

Expand Down
18 changes: 11 additions & 7 deletions src/features/post/detail/PostHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,15 @@ function PostHeader({
[post],
);

const urlIsMedia = useMemo(
() => post.post.url && isUrlMedia(post.post.url),
[post],
);

const renderMedia = useCallback(() => {
if (!post) return;

if ((post.post.url && isUrlMedia(post.post.url)) || markdownLoneImage) {
if (urlIsMedia || markdownLoneImage) {
return (
<LightboxPostMedia
post={post}
Expand All @@ -170,7 +175,7 @@ function PostHeader({
/>
);
}
}, [markdownLoneImage, post, constrainHeight]);
}, [post, urlIsMedia, markdownLoneImage, constrainHeight]);

const renderText = useCallback(() => {
if (!post) return;
Expand All @@ -179,22 +184,21 @@ function PostHeader({
return <StyledCrosspost post={post} url={crosspostUrl} />;
}

const usedLoneImage =
markdownLoneImage && (!post.post.url || !isUrlMedia(post.post.url));
const usedLoneImage = markdownLoneImage && !urlIsMedia;

if (post.post.body && !usedLoneImage) {
return (
<>
{post.post.url && !isUrlMedia(post.post.url) && <Embed post={post} />}
{post.post.url && !urlIsMedia && <Embed post={post} />}
<StyledMarkdown>{post.post.body}</StyledMarkdown>
</>
);
}

if (post.post.url && !isUrlMedia(post.post.url)) {
if (post.post.url && !urlIsMedia) {
return <StyledEmbed post={post} />;
}
}, [markdownLoneImage, post, crosspostUrl]);
}, [post, crosspostUrl, markdownLoneImage, urlIsMedia]);

return (
<ModeratableItem itemView={post}>
Expand Down
5 changes: 3 additions & 2 deletions src/features/post/inFeed/compact/Thumbnail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,12 @@ export default function Thumbnail({ post }: ImgProps) {
[post],
);

const postImageSrc = (() => {
const postImageSrc = useMemo(() => {
if (post.post.url && isUrlImage(post.post.url)) return post.post.url;

if (markdownLoneImage) return markdownLoneImage.url;
})();
}, [markdownLoneImage, post.post.url]);

const blurNsfw = useAppSelector(
(state) => state.settings.appearance.posts.blurNsfw,
);
Expand Down
7 changes: 6 additions & 1 deletion src/features/post/inFeed/large/LargePostContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ export default function LargePostContents({ post }: LargePostContentsProps) {
(state) => state.settings.appearance.posts.blurNsfw,
);

if ((post.post.url && isUrlMedia(post.post.url)) || markdownLoneImage) {
const urlIsMedia = useMemo(
() => post.post.url && isUrlMedia(post.post.url),
[post],
);

if (urlIsMedia || markdownLoneImage) {
return (
<ImageContainer>
<Media
Expand Down
12 changes: 7 additions & 5 deletions src/features/post/new/PostEditorRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
IonNavLink,
IonToggle,
} from "@ionic/react";
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import useClient from "../../../helpers/useClient";
import { useAppDispatch, useAppSelector } from "../../../store";
import { Centered, Spinner } from "../../auth/login/LoginNav";
Expand Down Expand Up @@ -97,12 +97,14 @@ export default function PostEditorRoot({

const existingPost = "existingPost" in props ? props.existingPost : undefined;

const isImage = useMemo(
() => existingPost?.post.url && isUrlImage(existingPost.post.url),
[existingPost],
);

const dispatch = useAppDispatch();

const initialImage =
existingPost?.post.url && isUrlImage(existingPost.post.url)
? existingPost.post.url
: undefined;
const initialImage = isImage ? existingPost!.post.url : undefined;

const initialPostType = (() => {
if (!existingPost) return "photo";
Expand Down
10 changes: 7 additions & 3 deletions src/features/shared/MarkdownImg.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HTMLProps } from "react";
import { HTMLProps, useMemo } from "react";
import { isUrlVideo } from "../../helpers/url";
import GalleryImg, { GalleryImgProps } from "../gallery/GalleryImg";
import Video from "./Video";
Expand All @@ -19,11 +19,15 @@ interface MarkdownImgProps

export default function MarkdownImg({ small, ...props }: MarkdownImgProps) {
const sharedStyles = small ? smallStyles : undefined;
const isVideo = useMemo(
() => props.src && isUrlVideo(props.src),
[props.src],
);

if (props.src && isUrlVideo(props.src))
if (isVideo)
return (
<Video
src={props.src}
src={props.src!}
progress={false}
css={sharedStyles}
controls={!small}
Expand Down
26 changes: 23 additions & 3 deletions src/helpers/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,36 @@ export function isValidUrl(
return url.protocol === "http:" || url.protocol === "https:";
}

const imageExtensions = ["jpeg", "png", "gif", "jpg", "webp"];
function getPathname(url: string): string | undefined {
try {
return new URL(url).pathname;
} catch {
return;
}
}

const imageExtensions = ["jpeg", "png", "gif", "jpg", "webp", "jxl"];

export function isUrlImage(url: string): boolean {
return imageExtensions.some((extension) => url.endsWith(`.${extension}`));
const pathname = getPathname(url);

if (!pathname) return false;

return imageExtensions.some((extension) =>
pathname.endsWith(`.${extension}`),
);
}

const videoExtensions = ["mp4", "webm"];

export function isUrlVideo(url: string): boolean {
return videoExtensions.some((extension) => url.endsWith(`.${extension}`));
const pathname = getPathname(url);

if (!pathname) return false;

return videoExtensions.some((extension) =>
pathname.endsWith(`.${extension}`),
);
}

export function isUrlMedia(url: string): boolean {
Expand Down

0 comments on commit ede7a24

Please sign in to comment.