Browse Source

fix janky reply form

imwald
Silberengel 2 weeks ago
parent
commit
55ce27d272
  1. 30
      src/components/PostEditor/PostContent.tsx
  2. 16
      src/components/PostEditor/PostTextarea/index.tsx
  3. 18
      src/components/PostEditor/index.tsx

30
src/components/PostEditor/PostContent.tsx

@ -47,6 +47,7 @@ import { @@ -47,6 +47,7 @@ import {
} from '@/constants'
import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useReplyIngress } from '@/hooks/useReplyIngress'
import { canonicalizeRssArticleUrl, getArticleUrlFromCommentITags } from '@/lib/rss-article'
import { cleanUrl, isBlossomBudBlobUrl, rewritePlainTextHttpUrls } from '@/lib/url'
@ -200,6 +201,7 @@ export default function PostContent({ @@ -200,6 +201,7 @@ export default function PostContent({
}) {
const { t, i18n } = useTranslation()
const { pubkey, publish, checkLogin, canSignEvents } = useNostr()
const { isSmallScreen } = useScreenSize()
const { addReplies } = useReplyIngress()
const mergePublishedReplyIntoThread = useCallback(
@ -2519,7 +2521,19 @@ export default function PostContent({ @@ -2519,7 +2521,19 @@ export default function PostContent({
}
return (
<div className="space-y-2 min-w-0">
<div
className={cn(
'min-w-0',
isSmallScreen ? 'flex min-h-0 flex-1 flex-col' : 'space-y-2'
)}
>
<NeventPickerProvider>
<div
className={cn(
'space-y-2 min-w-0',
isSmallScreen && 'min-h-0 flex-1 overflow-y-auto overscroll-y-contain'
)}
>
{/* Dynamic Title based on mode */}
<div className="text-lg font-semibold">
{(() => {
@ -2569,7 +2583,7 @@ export default function PostContent({ @@ -2569,7 +2583,7 @@ export default function PostContent({
</div>
{parentEvent && (
<ScrollArea className="flex max-h-48 flex-col overflow-y-auto rounded-lg border bg-muted/40">
<ScrollArea className="flex max-h-32 sm:max-h-48 flex-col overflow-y-auto rounded-lg border bg-muted/40">
<div className="p-2 sm:p-3 pointer-events-none">
<Note size="small" event={parentEvent} hideParentNotePreview />
</div>
@ -3355,7 +3369,6 @@ export default function PostContent({ @@ -3355,7 +3369,6 @@ export default function PostContent({
</div>
)}
<NeventPickerProvider>
<PostTextarea
ref={textareaRef}
text={text}
@ -3364,7 +3377,7 @@ export default function PostContent({ @@ -3364,7 +3377,7 @@ export default function PostContent({
parentEvent={isDiscussionThread && !parentEvent ? THREAD_POST_EDITOR_PARENT : parentEvent}
onSubmit={() => post()}
className={cn(
isPoll ? 'min-h-20' : 'min-h-52',
isPoll ? 'min-h-20' : isSmallScreen ? 'min-h-36' : 'min-h-52',
isDiscussionThread && threadErrors.content && 'border-destructive'
)}
onUploadStart={handleUploadStart}
@ -3718,6 +3731,14 @@ export default function PostContent({ @@ -3718,6 +3731,14 @@ export default function PostContent({
<button ref={mediaUploaderBtnRef} type="button" aria-hidden="true" tabIndex={-1} />
</Uploader>
)}
</div>
<div
className={cn(
'space-y-2 min-w-0',
isSmallScreen &&
'sticky bottom-0 z-10 shrink-0 border-t border-border bg-background pt-2 pb-[max(0.5rem,env(safe-area-inset-bottom,0px))]'
)}
>
<div className="flex min-w-0 w-full items-center gap-1.5">
<div className="min-w-0 flex-1 overflow-x-auto overscroll-x-contain">
<PostEditorFormatToolbar
@ -3873,6 +3894,7 @@ export default function PostContent({ @@ -3873,6 +3894,7 @@ export default function PostContent({
inComposer
/>
) : null}
</div>
{/* Media Kind Selection Dialog */}
<Dialog open={showMediaKindDialog} onOpenChange={setShowMediaKindDialog}>

16
src/components/PostEditor/PostTextarea/index.tsx

@ -13,10 +13,12 @@ import Text from '@tiptap/extension-text' @@ -13,10 +13,12 @@ import Text from '@tiptap/extension-text'
import { TextSelection } from '@tiptap/pm/state'
import { Editor, EditorContent, useEditor } from '@tiptap/react'
import { Event } from 'nostr-tools'
import { useScreenSizeOptional } from '@/providers/ScreenSizeProvider'
import {
Dispatch,
forwardRef,
SetStateAction,
useEffect,
useImperativeHandle,
useMemo,
useRef,
@ -122,6 +124,7 @@ const PostTextarea = forwardRef< @@ -122,6 +124,7 @@ const PostTextarea = forwardRef<
ref
) => {
const { t } = useTranslation()
const isSmallScreen = useScreenSizeOptional()?.isSmallScreen ?? false
const onUploadSuccessRef = useRef(onUploadSuccess)
onUploadSuccessRef.current = onUploadSuccess
const onUploadCompressPhaseRef = useRef(onUploadCompressPhase)
@ -197,6 +200,19 @@ const PostTextarea = forwardRef< @@ -197,6 +200,19 @@ const PostTextarea = forwardRef<
editorRef.current = editor
useEffect(() => {
if (!editor || !isSmallScreen) return
const scrollEditorIntoView = () => {
requestAnimationFrame(() => {
editor.view.dom.scrollIntoView({ block: 'nearest', inline: 'nearest' })
})
}
editor.on('focus', scrollEditorIntoView)
return () => {
editor.off('focus', scrollEditorIntoView)
}
}, [editor, isSmallScreen])
useImperativeHandle(ref, () => ({
appendText: (text: string, addNewline = false) => {
const ed = editorRef.current

18
src/components/PostEditor/index.tsx

@ -98,7 +98,7 @@ export default function PostEditor({ @@ -98,7 +98,7 @@ export default function PostEditor({
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetContent
className="h-full w-full max-w-full p-0 border-none overflow-hidden"
className="flex h-[var(--vh,100dvh)] max-h-[var(--vh,100dvh)] w-full max-w-full flex-col p-0 border-none overflow-hidden data-[state=open]:duration-200 data-[state=closed]:duration-200"
side="bottom"
hideClose
onInteractOutside={(e) => {
@ -114,15 +114,13 @@ export default function PostEditor({ @@ -114,15 +114,13 @@ export default function PostEditor({
}
}}
>
<ScrollArea className="px-4 h-full max-h-screen min-w-0 overflow-x-auto" scrollBarClassName="opacity-100">
<div className="space-y-4 px-2 pr-4 py-6 min-w-0">
<SheetHeader className="sr-only">
<SheetTitle>Post Editor</SheetTitle>
<SheetDescription>Create a new post or reply</SheetDescription>
</SheetHeader>
{content}
</div>
</ScrollArea>
<div className="flex min-h-0 flex-1 flex-col px-4 pt-4 pb-2 min-w-0">
<SheetHeader className="sr-only">
<SheetTitle>Post Editor</SheetTitle>
<SheetDescription>Create a new post or reply</SheetDescription>
</SheetHeader>
{content}
</div>
</SheetContent>
</Sheet>
)

Loading…
Cancel
Save