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

feat: show more on reply content[6.7] #3723

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions src/components/Compose/DraftList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const DraftListItem = memo<DraftListItemProps>(function DraftListItem({ draft, h
export const DraftList = memo(function DraftList() {
const currentProfileAll = useCurrentProfileAll();
const { drafts, removeDraft } = useComposeDraftStateStore();
const { updateChars, apply, currentDraftId, clear } = useComposeStateStore();
const { updateChars, apply, focused, currentDraftId, clear } = useComposeStateStore();
const { updateScheduleTime } = useComposeScheduleStateStore();
const setEditorContent = useSetEditorContent();

Expand Down Expand Up @@ -191,6 +191,7 @@ export const DraftList = memo(function DraftList() {
);
apply({
...draft,
focused,
posts: draft.posts.map((x) => ({
...x,
...(full
Expand All @@ -211,7 +212,7 @@ export const DraftList = memo(function DraftList() {
if (draft.scheduleTime) updateScheduleTime(draft.scheduleTime);
router.history.push('/');
},
[apply, router, setEditorContent, updateChars, updateScheduleTime, currentProfileAll],
[apply, router, setEditorContent, updateChars, updateScheduleTime, currentProfileAll, focused],
);

if (!drafts.length) {
Expand Down
4 changes: 3 additions & 1 deletion src/components/Compose/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ interface EditorProps {
}

export const Editor = memo(function Editor({ post, replying }: EditorProps) {
const { type, posts, updateChars, loadComponentsFromChars } = useComposeStateStore();
const { type, posts, updateChars, updateFocused, loadComponentsFromChars } = useComposeStateStore();
const [, startTransition] = useTransition();

const { chars } = post;
Expand Down Expand Up @@ -103,6 +103,8 @@ export const Editor = memo(function Editor({ post, replying }: EditorProps) {
contentEditable={
<ContentEditable
key="editable"
onFocus={() => updateFocused(true)}
onBlur={() => updateFocused(false)}
className="flex-1 flex-shrink-0 cursor-text resize-none appearance-none border-none bg-transparent p-0 pb-2 text-left text-[16px] leading-6 text-main outline-none outline-0 focus:ring-0"
/>
}
Expand Down
46 changes: 4 additions & 42 deletions src/components/Posts/PostBodyContent.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
'use client';

import { t } from '@lingui/core/macro';
import { Select, Trans } from '@lingui/react/macro';
import { Trans } from '@lingui/react/macro';
import { useForkRef } from '@mui/material';
import { compact } from 'lodash-es';
import { usePathname, useRouter } from 'next/navigation.js';
import { forwardRef, type HTMLProps, useMemo, useState } from 'react';
import { forwardRef, useMemo, useState } from 'react';
import { useAsync } from 'react-use';

import { TwitterArticleBody } from '@/components/Article/TwitterArticleBody.js';
Expand All @@ -17,18 +16,17 @@ import { PollCard } from '@/components/Poll/PollCard.js';
import { Attachments } from '@/components/Posts/Attachment.js';
import { CollapsedContent } from '@/components/Posts/CollapsedContent.js';
import { ContentTranslator } from '@/components/Posts/ContentTranslator.js';
import { PostBodyReplyContent } from '@/components/Posts/PostBodyReplyContent.js';
import { PostLinks } from '@/components/Posts/PostLinks.js';
import { Quote } from '@/components/Posts/Quote.js';
import { RedPacketInspector } from '@/components/RedPacket/RedPacketInspector.js';
import { IS_APPLE, IS_SAFARI } from '@/constants/bowser.js';
import { PageRoute, Source } from '@/constants/enum.js';
import { EMPTY_LIST, RP_HASH_TAG } from '@/constants/index.js';
import { classNames } from '@/helpers/classNames.js';
import { formatUrl } from '@/helpers/formatUrl.js';
import { getEncryptedPayloadFromImageAttachment, getEncryptedPayloadFromText } from '@/helpers/getEncryptedPayload.js';
import { getPostUrl } from '@/helpers/getPostUrl.js';
import { isRoutePathname } from '@/helpers/isRoutePathname.js';
import { isValidUrl } from '@/helpers/isValidUrl.js';
import { resolveOembedUrl } from '@/helpers/resolveOembedUrl.js';
import { resolvePostArticleUrl } from '@/helpers/resolvePostArticleUrl.js';
import { trimify } from '@/helpers/trimify.js';
Expand All @@ -50,12 +48,6 @@ export interface PostBodyContentProps {
showTranslate?: boolean;
}

const overrideComponents = {
a: function Anchor({ title }: HTMLProps<HTMLAnchorElement>) {
return <span>{title && isValidUrl(title) ? formatUrl(title, 30) : title}</span>;
},
};

function canSkipWaitingForPayload(post: Post) {
const content = post.metadata.content?.content;

Expand Down Expand Up @@ -181,37 +173,7 @@ export const PostBodyContent = forwardRef<HTMLDivElement, PostBodyContentProps>(
);
}

if (isReply) {
return (
<div>
<NakedMarkup
post={post}
className={classNames(
'single-post line-clamp-3 w-full self-stretch break-words text-base text-main',
{
'max-h-[7.8rem]': IS_SAFARI && IS_APPLE,
},
)}
components={overrideComponents}
>
{liteRawContent}
</NakedMarkup>
<div className="flex flex-col text-base text-main">
{post.metadata.content?.asset?.type ? (
<Select
value={post.metadata.content.asset.type}
_Image="[Image]"
_Video="[Video]"
_Audio="[Audio]"
_Poll="[Poll]"
other=""
/>
) : null}
{post.quoteOn ? <span>{t`[Quote]`}</span> : null}
</div>
</div>
);
}
if (isReply) return <PostBodyReplyContent post={post} />;

return (
<article
Expand Down
74 changes: 74 additions & 0 deletions src/components/Posts/PostBodyReplyContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { t } from '@lingui/core/macro';
import { Select, Trans } from '@lingui/react/macro';
import { type HTMLProps, memo, useCallback, useEffect, useState } from 'react';

import { ClickableButton } from '@/components/ClickableButton.js';
import { NakedMarkup } from '@/components/Markup/NakedMarkup.js';
import { IS_APPLE, IS_SAFARI } from '@/constants/bowser.js';
import { classNames } from '@/helpers/classNames.js';
import { formatUrl } from '@/helpers/formatUrl.js';
import { isValidUrl } from '@/helpers/isValidUrl.js';
import { useDetectOverflow } from '@/hooks/useDetectOverflow.js';
import type { Post } from '@/providers/types/SocialMedia.js';
import { useComposeStateStore } from '@/store/useComposeStore.js';

interface PostBodyReplyContentProps {
post: Post;
}

const overrideComponents = {
a: function Anchor({ title }: HTMLProps<HTMLAnchorElement>) {
return <span>{title && isValidUrl(title) ? formatUrl(title, 30) : title}</span>;
},
};

export const PostBodyReplyContent = memo<PostBodyReplyContentProps>(function PostBodyReplyContent({ post }) {
const liteRawContent = post.metadata.content?.content;
const [overflow, ref] = useDetectOverflow<HTMLDivElement>();
const [multiple, setMultiple] = useState(1);
const { focused } = useComposeStateStore();

const toggleShowMore = useCallback(() => {
setMultiple((prev) => (overflow ? prev + 1 : 1));
}, [overflow]);

useEffect(() => {
if (focused) {
setMultiple(1);
}
}, [focused]);

return (
<div>
<div
ref={ref}
className={classNames('single-post line-clamp-3 w-full self-stretch break-words text-base text-main', {
'max-h-[7.8rem]': IS_SAFARI && IS_APPLE,
})}
style={{ WebkitLineClamp: multiple * 3 }}
>
<NakedMarkup post={post} components={overrideComponents}>
{liteRawContent}
</NakedMarkup>
</div>
<div className="flex flex-col text-base text-main">
{overflow || multiple > 1 ? (
<ClickableButton className="inline-flex text-highlight" onClick={toggleShowMore}>
{overflow ? <Trans>Show more</Trans> : <Trans>Show less</Trans>}
</ClickableButton>
) : null}
{post.metadata.content?.asset?.type ? (
<Select
value={post.metadata.content.asset.type}
_Image="[Image]"
_Video="[Video]"
_Audio="[Audio]"
_Poll="[Poll]"
other=""
/>
) : null}
{post.quoteOn ? <span>{t`[Quote]`}</span> : null}
</div>
</div>
);
});
11 changes: 11 additions & 0 deletions src/store/useComposeStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ export interface ComposeBaseState {
cursor: Cursor;
// tracking the current applied draft id
currentDraftId?: string;

// editor focus state
focused: boolean;
}

interface ComposeState extends ComposeBaseState {
Expand Down Expand Up @@ -134,6 +137,8 @@ interface ComposeState extends ComposeBaseState {
// reset the editor
apply: (state: ComposeBaseState) => void;
clear: () => void;

updateFocused: (focused: boolean) => void;
}

export function createInitPostState(): Record<SocialSource, null> {
Expand Down Expand Up @@ -183,6 +188,7 @@ const useComposeStateBase = create<ComposeState, [['zustand/immer', unknown]]>(
immer((set, get) => ({
type: 'compose',
cursor: initialPostCursor,
focused: false,
posts: [createInitSinglePostState(initialPostCursor)],
computed: {
get nextAvailablePost() {
Expand Down Expand Up @@ -623,11 +629,16 @@ const useComposeStateBase = create<ComposeState, [['zustand/immer', unknown]]>(
type: state.type,
cursor: id,
currentDraftId: undefined,
focused: false,
posts: [createInitSinglePostState(id)],
} satisfies ComposeBaseState;

Object.assign(state, nextState);
}),
updateFocused: (focused) =>
set((state) => {
state.focused = focused;
}),
})),
);

Expand Down
Loading