feat: collapse long notes

This commit is contained in:
codytseng
2025-04-28 22:32:52 +08:00
parent 3ffad2ed49
commit 3a98629617
16 changed files with 95 additions and 28 deletions

View File

@@ -9,7 +9,6 @@ import Content from '../Content'
import { FormattedTimestamp } from '../FormattedTimestamp'
import ImageGallery from '../ImageGallery'
import NoteOptions from '../NoteOptions'
import NoteStats from '../NoteStats'
import ParentNotePreview from '../ParentNotePreview'
import UserAvatar from '../UserAvatar'
import Username from '../Username'
@@ -18,16 +17,12 @@ export default function Note({
event,
size = 'normal',
className,
hideParentNotePreview = false,
hideStats = false,
fetchNoteStats = false
hideParentNotePreview = false
}: {
event: Event
size?: 'normal' | 'small'
className?: string
hideParentNotePreview?: boolean
hideStats?: boolean
fetchNoteStats?: boolean
}) {
const { push } = useSecondaryPage()
const parentEventId = useMemo(
@@ -78,9 +73,6 @@ export default function Note({
{event.kind === ExtendedKind.PICTURE && imageInfos.length > 0 && (
<ImageGallery images={imageInfos} />
)}
{!hideStats && (
<NoteStats className="mt-3" event={event} fetchIfNotExisting={fetchNoteStats} />
)}
</div>
)
}

View File

@@ -1,8 +1,13 @@
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import { toNote } from '@/lib/link'
import { cn } from '@/lib/utils'
import { useSecondaryPage } from '@/PageManager'
import { Event } from 'nostr-tools'
import { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Note from '../Note'
import NoteStats from '../NoteStats'
import RepostDescription from './RepostDescription'
export default function MainNoteCard({
@@ -16,20 +21,77 @@ export default function MainNoteCard({
reposter?: string
embedded?: boolean
}) {
const { t } = useTranslation()
const { push } = useSecondaryPage()
const containerRef = useRef<HTMLDivElement>(null)
const [expanded, setExpanded] = useState(false)
const [shouldCollapse, setShouldCollapse] = useState(false)
useEffect(() => {
if (embedded || shouldCollapse) return
const contentEl = containerRef.current
if (!contentEl) return
const checkHeight = () => {
const fullHeight = contentEl.scrollHeight
if (fullHeight > 900) {
setShouldCollapse(true)
}
}
checkHeight()
const observer = new ResizeObserver(() => {
checkHeight()
})
observer.observe(contentEl)
return () => {
observer.disconnect()
}
}, [embedded, shouldCollapse])
return (
<div
ref={containerRef}
className={className}
onClick={(e) => {
e.stopPropagation()
push(toNote(event))
}}
>
<div className={`clickable ${embedded ? 'p-2 sm:p-3 border rounded-lg' : 'py-3'}`}>
<div
className={`clickable text-left ${embedded ? 'p-2 sm:p-3 border rounded-lg' : 'px-4 py-3'}`}
className="relative text-left overflow-hidden"
style={{
maxHeight: !shouldCollapse || expanded ? 'none' : '600px'
}}
>
<RepostDescription reposter={reposter} />
<Note size={embedded ? 'small' : 'normal'} event={event} hideStats={embedded} />
<RepostDescription className={embedded ? '' : 'px-4'} reposter={reposter} />
<Note
className={embedded ? '' : 'px-4'}
size={embedded ? 'small' : 'normal'}
event={event}
/>
{shouldCollapse && !expanded && (
<div className="absolute bottom-0 h-20 w-full bg-gradient-to-b from-transparent to-muted flex items-center justify-center">
<div className="bg-background rounded-md">
<Button
className="bg-foreground hover:bg-foreground/80"
onClick={(e) => {
e.stopPropagation()
setExpanded(!expanded)
}}
>
{t('Show more')}
</Button>
</div>
</div>
)}
</div>
{!embedded && <NoteStats className={cn('mt-3', embedded ? '' : 'px-4')} event={event} />}
</div>
{!embedded && <Separator />}
</div>

View File

@@ -119,7 +119,7 @@ export default function NormalPostContent({
{parentEvent && (
<ScrollArea className="flex 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} hideStats hideParentNotePreview />
<Note size="small" event={parentEvent} hideParentNotePreview />
</div>
</ScrollArea>
)}

View File

@@ -223,6 +223,7 @@ export default {
'Remove bookmark': 'إزالة الإشارة',
'no bookmarks found': 'لم يتم العثور على إشارات',
'no more bookmarks': 'لا مزيد من الإشارات',
Bookmarks: 'الإشارات المرجعية'
Bookmarks: 'الإشارات المرجعية',
'Show more': 'عرض المزيد'
}
}

View File

@@ -227,6 +227,7 @@ export default {
'Remove bookmark': 'Lesezeichen entfernen',
'no bookmarks found': 'Keine Lesezeichen gefunden',
'no more bookmarks': 'Keine weiteren Lesezeichen',
Bookmarks: 'Lesezeichen'
Bookmarks: 'Lesezeichen',
'Show more': 'Mehr anzeigen'
}
}

View File

@@ -223,6 +223,7 @@ export default {
'Remove bookmark': 'Remove bookmark',
'no bookmarks found': 'no bookmarks found',
'no more bookmarks': 'no more bookmarks',
Bookmarks: 'Bookmarks'
Bookmarks: 'Bookmarks',
'Show more': 'Show more'
}
}

View File

@@ -227,6 +227,7 @@ export default {
'Remove bookmark': 'Quitar marcador',
'no bookmarks found': 'No se encontraron marcadores',
'no more bookmarks': 'No hay más marcadores',
Bookmarks: 'Marcadores'
Bookmarks: 'Marcadores',
'Show more': 'Mostrar más'
}
}

View File

@@ -226,6 +226,7 @@ export default {
'Remove bookmark': 'Retirer le favori',
'no bookmarks found': 'Aucun favori trouvé',
'no more bookmarks': 'Plus de favoris',
Bookmarks: 'Favoris'
Bookmarks: 'Favoris',
'Show more': 'Afficher plus'
}
}

View File

@@ -226,6 +226,7 @@ export default {
'Remove bookmark': 'Rimuovi segnalibro',
'no bookmarks found': 'Nessun segnalibro trovato',
'no more bookmarks': 'Nessun altro segnalibro',
Bookmarks: 'Segnalibri'
Bookmarks: 'Segnalibri',
'Show more': 'Mostra di più'
}
}

View File

@@ -224,6 +224,7 @@ export default {
'Remove bookmark': 'ブックマークを削除',
'no bookmarks found': 'ブックマークが見つかりません',
'no more bookmarks': 'これ以上ブックマークはありません',
Bookmarks: 'ブックマーク一覧'
Bookmarks: 'ブックマーク一覧',
'Show more': 'もっと見る'
}
}

View File

@@ -225,6 +225,7 @@ export default {
'Remove bookmark': 'Usuń zakładkę',
'no bookmarks found': 'Nie znaleziono zakładek',
'no more bookmarks': 'Koniec zakładek',
Bookmarks: 'Zakładki'
Bookmarks: 'Zakładki',
'Show more': 'Pokaż więcej'
}
}

View File

@@ -225,6 +225,7 @@ export default {
'Remove bookmark': 'Remover favorito',
'no bookmarks found': 'Nenhum favorito encontrado',
'no more bookmarks': 'Sem mais favoritos',
Bookmarks: 'Favoritos'
Bookmarks: 'Favoritos',
'Show more': 'Mostrar mais'
}
}

View File

@@ -226,6 +226,7 @@ export default {
'Remove bookmark': 'Remover favorito',
'no bookmarks found': 'Nenhum favorito encontrado',
'no more bookmarks': 'Sem mais favoritos',
Bookmarks: 'Favoritos'
Bookmarks: 'Favoritos',
'Show more': 'Mostrar mais'
}
}

View File

@@ -227,6 +227,7 @@ export default {
'Remove bookmark': 'Удалить закладку',
'no bookmarks found': 'Закладки не найдены',
'no more bookmarks': 'Больше нет закладок',
Bookmarks: 'Закладки'
Bookmarks: 'Закладки',
'Show more': 'Показать больше'
}
}

View File

@@ -224,6 +224,7 @@ export default {
'Remove bookmark': '取消收藏',
'no bookmarks found': '暂无收藏',
'no more bookmarks': '到底了',
Bookmarks: '收藏'
Bookmarks: '收藏',
'Show more': '显示更多'
}
}

View File

@@ -2,6 +2,7 @@ import { useSecondaryPage } from '@/PageManager'
import ContentPreview from '@/components/ContentPreview'
import Nip22ReplyNoteList from '@/components/Nip22ReplyNoteList'
import Note from '@/components/Note'
import NoteStats from '@/components/NoteStats'
import PictureNote from '@/components/PictureNote'
import ReplyNoteList from '@/components/ReplyNoteList'
import UserAvatar from '@/components/UserAvatar'
@@ -74,9 +75,9 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
key={`note-${event.id}`}
event={event}
className="select-text"
fetchNoteStats
hideParentNotePreview
/>
<NoteStats className="mt-3" event={event} fetchIfNotExisting />
</div>
<Separator className="mt-4" />
{event.kind === kinds.ShortTextNote ? (