Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show more videos and consolidate media logic #791

Closed
wants to merge 16 commits into from
Closed
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/features/comment/links/LinkPreview.tsx
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ import {
import { css } from "@emotion/react";
import { getImageSrc } from "../../../services/lemmy";
import { ReactNode, useMemo } from "react";
import { isUrlImage } from "../../../helpers/lemmy";
import useLemmyUrlHandler from "../../shared/useLemmyUrlHandler";
import { isUrlImage } from "../../../helpers/url";

const shared = css`
width: 30px;
11 changes: 10 additions & 1 deletion src/features/gallery/GalleryImg.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { FocusEvent, KeyboardEvent, useContext, useRef } from "react";
import React, {
FocusEvent,
KeyboardEvent,
ReactEventHandler,
useContext,
useRef,
} from "react";
import "photoswipe/dist/photoswipe.css";
import { PostView } from "lemmy-js-client";
import { GalleryContext } from "./GalleryProvider";
@@ -10,6 +16,7 @@ export interface GalleryImgProps {
className?: string;
post?: PostView;
animationType?: PreparedPhotoSwipeOptions["showHideAnimationType"];
onError?: ReactEventHandler<HTMLImageElement> | undefined;
}

/**
@@ -28,6 +35,7 @@ export function GalleryImg({
className,
post,
animationType,
onError,
}: GalleryImgProps) {
const loaded = useRef(false);
const imgRef = useRef<HTMLImageElement>(null);
@@ -53,6 +61,7 @@ export function GalleryImg({

loaded.current = true;
}}
onError={onError}
/>
);
}
14 changes: 10 additions & 4 deletions src/features/gallery/PostGalleryImg.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import { PostView } from "lemmy-js-client";
import { isUrlImage } from "../../helpers/lemmy";
import { findLoneImage } from "../../helpers/markdown";
import { GalleryImg, GalleryImgProps } from "./GalleryImg";
import { isUrlImage } from "../../helpers/url";

export interface PostGalleryImgProps extends Omit<GalleryImgProps, "src"> {
post: PostView;
thumbnail?: boolean;
}

export default function PostGalleryImg({
post,
thumbnail = false,
...props
}: PostGalleryImgProps) {
return <GalleryImg {...props} src={getPostImage(post)} post={post} />;
return (
<GalleryImg {...props} src={getPostImage(post, thumbnail)} post={post} />
);
}

function getPostImage(post: PostView): string | undefined {
if (post.post.thumbnail_url) return post.post.thumbnail_url;
function getPostImage(post: PostView, thumbnail: boolean): string | undefined {
if (thumbnail && post.post.thumbnail_url) {
return post.post.thumbnail_url;
}

if (post.post.url && isUrlImage(post.post.url)) return post.post.url;

51 changes: 16 additions & 35 deletions src/features/post/detail/PostDetail.tsx
Original file line number Diff line number Diff line change
@@ -16,25 +16,23 @@ import {
} from "react";
import { findLoneImage } from "../../../helpers/markdown";
import { setPostRead } from "../postSlice";
import { isUrlImage, isUrlVideo } from "../../../helpers/lemmy";
import { maxWidthCss } from "../../shared/AppContent";
import PersonLink from "../../labels/links/PersonLink";
import { CommentSortType, PostView } from "lemmy-js-client";
import ViewAllComments from "./ViewAllComments";
import InlineMarkdown from "../../shared/InlineMarkdown";
import { megaphone } from "ionicons/icons";
import CommunityLink from "../../labels/links/CommunityLink";
import Video from "../../shared/Video";
import { css } from "@emotion/react";
import Nsfw, { isNsfw } from "../../labels/Nsfw";
import { PageContext } from "../../auth/PageContext";
import PostGalleryImg from "../../gallery/PostGalleryImg";
import { scrollIntoView } from "../../../helpers/dom";
import JumpFab from "../../comment/JumpFab";
import { OTapToCollapseType } from "../../../services/db";
import Locked from "./Locked";
import useAppToast from "../../../helpers/useAppToast";
import { postLocked } from "../../../helpers/toastMessages";
import Media from "../../shared/Media";
import { isUrlMedia } from "../../../helpers/url";

const BorderlessIonItem = styled(IonItem)`
--padding-start: 0;
@@ -57,19 +55,6 @@ const Container = styled.div`
width: 100%;
`;

const lightboxCss = css`
width: 100%;
max-height: 50vh;
object-fit: contain;
background: var(--lightroom-bg);
`;

const LightboxImg = styled(PostGalleryImg)`
-webkit-touch-callout: default;

${lightboxCss}
`;

const StyledMarkdown = styled(Markdown)`
margin: 16px 0;

@@ -127,6 +112,7 @@ export default function PostDetail({
sort,
}: PostDetailProps) {
const [collapsed, setCollapsed] = useState(false);
const [hasMediaError, setHasMediaError] = useState(false);
const dispatch = useAppDispatch();
const markdownLoneImage = useMemo(
() => (post?.post.body ? findLoneImage(post.post.body) : undefined),
@@ -170,37 +156,23 @@ export default function PostDetail({
[],
);

function renderImage() {
if (!post) return;

if (post.post.url) {
if (isUrlImage(post.post.url)) return <LightboxImg post={post} />;

if (isUrlVideo(post.post.url))
return <Video src={post.post.url} css={lightboxCss} controls />;
}

if (markdownLoneImage) return <LightboxImg post={post} />;
}

function renderText() {
if (!post) return;

if (post.post.body && !markdownLoneImage) {
return (
<>
{post.post.url &&
!isUrlImage(post.post.url) &&
!isUrlVideo(post.post.url) && <Embed post={post} />}
(!isUrlMedia(post.post.embed_video_url || post.post.url) ||
hasMediaError) && <Embed post={post} />}
<StyledMarkdown>{post.post.body}</StyledMarkdown>
</>
);
}

if (
post.post.url &&
!isUrlImage(post.post.url) &&
!isUrlVideo(post.post.url)
(!isUrlMedia(post.post.embed_video_url || post.post.url) || hasMediaError)
) {
return <StyledEmbed post={post} />;
}
@@ -224,7 +196,16 @@ export default function PostDetail({
}}
>
<Container>
<div onClick={(e) => e.stopPropagation()}>{renderImage()}</div>
{!hasMediaError && (
<div onClick={(e) => e.stopPropagation()}>
<Media
post={post}
detail={true}
blur={false}
onError={() => setHasMediaError(true)}
/>
</div>
)}
<PostDeets>
<Title ref={titleRef}>
<InlineMarkdown>{post.post.name}</InlineMarkdown>{" "}
4 changes: 2 additions & 2 deletions src/features/post/inFeed/compact/Thumbnail.tsx
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@ import { IonIcon } from "@ionic/react";
import { link, linkOutline } from "ionicons/icons";
import { PostView } from "lemmy-js-client";
import { MouseEvent, useCallback, useMemo } from "react";
import { isUrlImage } from "../../../../helpers/lemmy";
import { findLoneImage } from "../../../../helpers/markdown";
import { useAppDispatch, useAppSelector } from "../../../../store";
import PostGalleryImg from "../../../gallery/PostGalleryImg";
@@ -17,6 +16,7 @@ import {
OCompactThumbnailSizeType,
} from "../../../../services/db";
import { setPostRead } from "../../postSlice";
import { isUrlImage } from "../../../../helpers/url";

function getWidthForSize(size: CompactThumbnailSizeType): number {
switch (size) {
@@ -162,7 +162,7 @@ export default function Thumbnail({ post }: ImgProps) {
}

if (postImageSrc) {
return <StyledPostGallery post={post} blur={nsfw} />;
return <StyledPostGallery post={post} blur={nsfw} thumbnail />;
}

return <SelfSvg />;
68 changes: 14 additions & 54 deletions src/features/post/inFeed/large/LargePost.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { useState } from "react";
import styled from "@emotion/styled";
import { css } from "@emotion/react";
import { megaphone } from "ionicons/icons";
import PreviewStats from "../PreviewStats";
import Embed from "../../shared/Embed";
import { useMemo } from "react";
import { findLoneImage } from "../../../../helpers/markdown";
import { isUrlImage, isUrlVideo } from "../../../../helpers/lemmy";
import { maxWidthCss } from "../../../shared/AppContent";
import Nsfw, { isNsfw, isNsfwBlurred } from "../../../labels/Nsfw";
import { VoteButton } from "../../shared/VoteButton";
@@ -14,11 +12,11 @@ import PersonLink from "../../../labels/links/PersonLink";
import InlineMarkdown from "../../../shared/InlineMarkdown";
import { AnnouncementIcon } from "../../../../pages/posts/PostPage";
import CommunityLink from "../../../labels/links/CommunityLink";
import Video from "../../../shared/Video";
import { PostProps } from "../Post";
import Save from "../../../labels/Save";
import { Image } from "./Image";
import { useAppSelector } from "../../../../store";
import Media from "../../../shared/Media";
import { isUrlMedia } from "../../../../helpers/url";

const Container = styled.div`
display: flex;
@@ -98,63 +96,16 @@ const PostBody = styled.div<{ isRead: boolean }>`
overflow: hidden;
`;

const ImageContainer = styled.div`
overflow: hidden;
margin: 0 -0.75rem;
`;

export default function LargePost({ post, communityMode }: PostProps) {
const hasBeenRead: boolean =
useAppSelector((state) => state.post.postReadById[post.post.id]) ||
post.read;
const markdownLoneImage = useMemo(
() => (post.post.body ? findLoneImage(post.post.body) : undefined),
[post],
);
const blurNsfw = useAppSelector(
(state) => state.settings.appearance.posts.blurNsfw,
);
const [hasMediaError, setHasMediaError] = useState(false);

function renderPostBody() {
if (post.post.url) {
if (isUrlImage(post.post.url)) {
return (
<ImageContainer>
<Image
blur={isNsfwBlurred(post, blurNsfw)}
post={post}
animationType="zoom"
/>
</ImageContainer>
);
}
if (isUrlVideo(post.post.url)) {
return (
<ImageContainer>
<Video src={post.post.url} blur={isNsfwBlurred(post, blurNsfw)} />
</ImageContainer>
);
}
}

if (markdownLoneImage)
return (
<ImageContainer>
<Image
blur={isNsfwBlurred(post, blurNsfw)}
post={post}
animationType="zoom"
/>
</ImageContainer>
);

/**
* Embedded video, image with a thumbanil
*/
if (post.post.thumbnail_url && post.post.url) {
return <Embed post={post} />;
}

/**
* text image with captions
*/
@@ -182,7 +133,16 @@ export default function LargePost({ post, communityMode }: PostProps) {
{isNsfw(post) && <Nsfw />}
</Title>

{renderPostBody()}
{!hasMediaError &&
isUrlMedia(post.post.embed_video_url || post.post.url || "") ? (
<Media
post={post}
blur={isNsfwBlurred(post, blurNsfw)}
onError={() => setHasMediaError(true)}
/>
) : (
renderPostBody()
)}

<Details>
<LeftDetails isRead={hasBeenRead}>
4 changes: 2 additions & 2 deletions src/features/post/new/PostEditorRoot.tsx
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ import { Centered, Spinner } from "../../auth/Login";
import { jwtSelector, urlSelector } from "../../auth/authSlice";
import { startCase } from "lodash";
import { css } from "@emotion/react";
import { getHandle, getRemoteHandle, isUrlImage } from "../../../helpers/lemmy";
import { getHandle, getRemoteHandle } from "../../../helpers/lemmy";
import { cameraOutline } from "ionicons/icons";
import { PostEditorProps } from "./PostEditor";
import NewPostText from "./NewPostText";
@@ -34,7 +34,7 @@ import PhotoPreview from "./PhotoPreview";
import { uploadImage } from "../../../services/lemmy";
import { receivedPosts } from "../postSlice";
import useAppToast from "../../../helpers/useAppToast";
import { isValidUrl } from "../../../helpers/url";
import { isValidUrl, isUrlImage } from "../../../helpers/url";
import { problemFetchingTitle } from "../../../helpers/toastMessages";

const Container = styled.div`
Loading