Skip to content

Commit

Permalink
Add compact view (aeharding#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeharding authored Jun 30, 2023
1 parent 3e38384 commit 53e9457
Show file tree
Hide file tree
Showing 18 changed files with 573 additions and 220 deletions.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<link rel="manifest" href="/manifest.json" />

<link rel="shortcut icon" type="image/jpeg" href="/logo.png" />
<link rel="apple-touch-icon" href="/logo.png" />

<meta
name="theme-color"
Expand Down
4 changes: 4 additions & 0 deletions src/TabbedRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { LEMMY_SERVERS } from "./helpers/lemmy";
import AppearancePage from "./pages/settings/AppearancePage";
import CommunitySidebarPage from "./pages/shared/CommunitySidebarPage";
import ApolloMigratePage from "./pages/settings/ApolloMigratePage";
import PostAppearancePage from "./pages/settings/PostAppearancePage";

const Interceptor = styled.div`
position: absolute;
Expand Down Expand Up @@ -334,6 +335,9 @@ export default function TabbedRoutes() {
</Route>
{/* general routes for settings is only for apollo-migrate */}
{...buildGeneralBrowseRoutes("settings")}
<Route exact path="/settings/appearance/posts">
<PostAppearancePage />
</Route>
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton
Expand Down
7 changes: 6 additions & 1 deletion src/features/comment/reply/CommentReply.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,13 @@ export default function CommentReply({ onDismiss, item }: CommentReplyProps) {
auth: jwt,
});
} catch (error) {
const errorDescription =
error === "language_not_allowed"
? "Please select a language in your lemmy profile settings."
: "Please try again.";

present({
message: "Problem posting your comment. Please try again.",
message: `Problem posting your comment. ${errorDescription}`,
duration: 3500,
position: "bottom",
color: "danger",
Expand Down
42 changes: 35 additions & 7 deletions src/features/feed/PostCommentFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { useCallback } from "react";
import Feed, { FeedProps, FetchFn } from "./Feed";
import FeedComment from "../comment/inFeed/FeedComment";
import Post from "../post/inFeed/Post";
import { CommentView, PostView } from "lemmy-js-client";
import { useAppDispatch } from "../../store";
import { useAppDispatch, useAppSelector } from "../../store";
import { css } from "@emotion/react";
import { receivedPosts } from "../post/postSlice";
import { receivedComments } from "../comment/commentSlice";
import Post from "../post/inFeed/Post";
import CommentHr from "../comment/CommentHr";

const itemCss = css`
const thickBorderCss = css`
border-bottom: 8px solid var(--thick-separator-color);
`;

Expand All @@ -33,17 +34,44 @@ export default function PostCommentFeed({
...rest
}: PostCommentFeed) {
const dispatch = useAppDispatch();
const postAppearanceType = useAppSelector(
(state) => state.appearance.posts.type
);

const renderItemContent = useCallback(
const borderCss = (() => {
switch (postAppearanceType) {
case "compact":
return undefined;
case "large":
return thickBorderCss;
}
})();

const renderItem = useCallback(
(item: PostCommentItem) => {
if (isPost(item))
return (
<Post post={item} communityMode={!!communityName} css={itemCss} />
<Post post={item} communityMode={!!communityName} css={borderCss} />
);

return <FeedComment comment={item} css={borderCss} />;
},
[communityName, borderCss]
);

const renderItemContent = useCallback(
(item: PostCommentItem) => {
if (postAppearanceType === "compact")
return (
<>
{renderItem(item)}
<CommentHr depth={0} />
</>
);

return <FeedComment comment={item} css={itemCss} />;
return renderItem(item);
},
[communityName]
[postAppearanceType, renderItem]
);

const fetchFn: FetchFn<PostCommentItem> = useCallback(
Expand Down
1 change: 1 addition & 0 deletions src/features/labels/links/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export const StyledLink = styled(Link)`
text-decoration: none;
color: inherit;
font-weight: 500;
white-space: nowrap;
`;
226 changes: 20 additions & 206 deletions src/features/post/inFeed/Post.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
import styled from "@emotion/styled";
import { IonItem } from "@ionic/react";
import { PostView } from "lemmy-js-client";
import { megaphone } from "ionicons/icons";
import PreviewStats from "./PreviewStats";
import Embed from "../shared/Embed";
import { useEffect, useMemo, useState } from "react";
import { css } from "@emotion/react";
import { findLoneImage } from "../../../helpers/markdown";
import { getHandle, isUrlImage, isUrlVideo } from "../../../helpers/lemmy";
import { maxWidthCss } from "../../shared/AppContent";
import Nsfw, { isNsfw } from "../../labels/Nsfw";
import { VoteButton } from "../shared/VoteButton";
import LargePost from "./large/LargePost";
import { useAppSelector } from "../../../store";
import CompactPost from "./compact/CompactPost";
import SlidingVote from "../../shared/sliding/SlidingPostVote";
import MoreActions from "../shared/MoreActions";
import { IonItem } from "@ionic/react";
import styled from "@emotion/styled";
import { useBuildGeneralBrowseLink } from "../../../helpers/routes";
import PersonLink from "../../labels/links/PersonLink";
import InlineMarkdown from "../../shared/InlineMarkdown";
import { AnnouncementIcon } from "../detail/PostDetail";
import CommunityLink from "../../labels/links/CommunityLink";
import Video from "../../shared/Video";
import { getHandle } from "../../../helpers/lemmy";

const CustomIonItem = styled(IonItem)`
--padding-start: 0;
Expand All @@ -29,77 +17,7 @@ const CustomIonItem = styled(IonItem)`
--background-hover: none;
`;

const Container = styled.div`
display: flex;
flex-direction: column;
width: 100%;
gap: 0.75rem;
padding: 0.75rem;
${maxWidthCss}
`;

const Details = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
font-size: 0.8em;
color: var(--ion-color-medium);
`;

const LeftDetails = styled.div`
display: flex;
flex-direction: column;
gap: 0.5rem;
min-width: 0;
`;

const RightDetails = styled.div`
display: flex;
align-items: center;
font-size: 1.5rem;
> * {
padding: 0.5rem;
}
`;

const CommunityName = styled.span`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;

const PostBody = styled.div`
font-size: 0.88em;
line-height: 1.25;
opacity: 0.6;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
`;

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

const PostImage = styled.img<{ blur: boolean }>`
width: 100%;
max-width: none;
${({ blur }) =>
blur &&
css`
filter: blur(40px);
`}
`;

interface PostProps {
export interface PostProps {
post: PostView;

/**
Expand All @@ -110,136 +28,32 @@ interface PostProps {
className?: string;
}

export default function Post({ post, communityMode, className }: PostProps) {
export default function Post(props: PostProps) {
const buildGeneralBrowseLink = useBuildGeneralBrowseLink();
const markdownLoneImage = useMemo(
() => (post.post.body ? findLoneImage(post.post.body) : undefined),
[post]
const postAppearanceType = useAppSelector(
(state) => state.appearance.posts.type
);
const [blur, setBlur] = useState(isNsfw(post));

useEffect(() => {
setBlur(isNsfw(post));
}, [post]);

function renderPostBody() {
if (post.post.url) {
if (isUrlImage(post.post.url)) {
return (
<ImageContainer>
<PostImage
src={post.post.url}
draggable="false"
blur={blur}
onClick={(e) => {
if (isNsfw(post)) {
e.stopPropagation();
setBlur(!blur);
}
}}
/>
</ImageContainer>
);
}
if (isUrlVideo(post.post.url)) {
return (
<ImageContainer>
<Video src={post.post.url} />
</ImageContainer>
);
}
const postBody = (() => {
switch (postAppearanceType) {
case "large":
return <LargePost {...props} />;
case "compact":
return <CompactPost {...props} />;
}

if (markdownLoneImage)
return (
<ImageContainer>
<PostImage
src={markdownLoneImage.url}
alt={markdownLoneImage.altText}
blur={blur}
onClick={(e) => {
if (isNsfw(post)) {
e.stopPropagation();
setBlur(!blur);
}
}}
/>
</ImageContainer>
);

if (post.post.thumbnail_url && post.post.url) {
return <Embed post={post} />;
}

if (post.post.body) {
return (
<>
{post.post.url && <Embed post={post} />}

<PostBody>
<InlineMarkdown>{post.post.body}</InlineMarkdown>
</PostBody>
</>
);
}

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

return (
<SlidingVote item={post} className={className}>
<SlidingVote item={props.post} className={props.className}>
{/* href=undefined: Prevent drag failure on firefox */}
<CustomIonItem
detail={false}
routerLink={buildGeneralBrowseLink(
`/c/${getHandle(post.community)}/comments/${post.post.id}`
`/c/${getHandle(props.post.community)}/comments/${props.post.post.id}`
)}
href={undefined}
>
<Container>
<div>
<InlineMarkdown>{post.post.name}</InlineMarkdown>{" "}
{isNsfw(post) && <Nsfw />}
</div>

{renderPostBody()}

<Details>
<LeftDetails>
<CommunityName>
{post.counts.featured_community ||
post.counts.featured_local ? (
<AnnouncementIcon icon={megaphone} />
) : undefined}
{communityMode ? (
<PersonLink
person={post.creator}
showInstanceWhenRemote
prefix="by"
/>
) : (
<CommunityLink
community={post.community}
showInstanceWhenRemote
/>
)}
</CommunityName>

<PreviewStats
stats={post.counts}
voteFromServer={post.my_vote}
published={post.post.published}
/>
</LeftDetails>
<RightDetails onClick={(e) => e.stopPropagation()}>
<MoreActions post={post} />
<VoteButton type="up" postId={post.post.id} />
<VoteButton type="down" postId={post.post.id} />
</RightDetails>
</Details>
</Container>
{postBody}
</CustomIonItem>
</SlidingVote>
);
Expand Down
Loading

0 comments on commit 53e9457

Please sign in to comment.