feat: collapse long notes
This commit is contained in:
@@ -9,7 +9,6 @@ import Content from '../Content'
|
|||||||
import { FormattedTimestamp } from '../FormattedTimestamp'
|
import { FormattedTimestamp } from '../FormattedTimestamp'
|
||||||
import ImageGallery from '../ImageGallery'
|
import ImageGallery from '../ImageGallery'
|
||||||
import NoteOptions from '../NoteOptions'
|
import NoteOptions from '../NoteOptions'
|
||||||
import NoteStats from '../NoteStats'
|
|
||||||
import ParentNotePreview from '../ParentNotePreview'
|
import ParentNotePreview from '../ParentNotePreview'
|
||||||
import UserAvatar from '../UserAvatar'
|
import UserAvatar from '../UserAvatar'
|
||||||
import Username from '../Username'
|
import Username from '../Username'
|
||||||
@@ -18,16 +17,12 @@ export default function Note({
|
|||||||
event,
|
event,
|
||||||
size = 'normal',
|
size = 'normal',
|
||||||
className,
|
className,
|
||||||
hideParentNotePreview = false,
|
hideParentNotePreview = false
|
||||||
hideStats = false,
|
|
||||||
fetchNoteStats = false
|
|
||||||
}: {
|
}: {
|
||||||
event: Event
|
event: Event
|
||||||
size?: 'normal' | 'small'
|
size?: 'normal' | 'small'
|
||||||
className?: string
|
className?: string
|
||||||
hideParentNotePreview?: boolean
|
hideParentNotePreview?: boolean
|
||||||
hideStats?: boolean
|
|
||||||
fetchNoteStats?: boolean
|
|
||||||
}) {
|
}) {
|
||||||
const { push } = useSecondaryPage()
|
const { push } = useSecondaryPage()
|
||||||
const parentEventId = useMemo(
|
const parentEventId = useMemo(
|
||||||
@@ -78,9 +73,6 @@ export default function Note({
|
|||||||
{event.kind === ExtendedKind.PICTURE && imageInfos.length > 0 && (
|
{event.kind === ExtendedKind.PICTURE && imageInfos.length > 0 && (
|
||||||
<ImageGallery images={imageInfos} />
|
<ImageGallery images={imageInfos} />
|
||||||
)}
|
)}
|
||||||
{!hideStats && (
|
|
||||||
<NoteStats className="mt-3" event={event} fetchIfNotExisting={fetchNoteStats} />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
import { Button } from '@/components/ui/button'
|
||||||
import { Separator } from '@/components/ui/separator'
|
import { Separator } from '@/components/ui/separator'
|
||||||
import { toNote } from '@/lib/link'
|
import { toNote } from '@/lib/link'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
import { useSecondaryPage } from '@/PageManager'
|
import { useSecondaryPage } from '@/PageManager'
|
||||||
import { Event } from 'nostr-tools'
|
import { Event } from 'nostr-tools'
|
||||||
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import Note from '../Note'
|
import Note from '../Note'
|
||||||
|
import NoteStats from '../NoteStats'
|
||||||
import RepostDescription from './RepostDescription'
|
import RepostDescription from './RepostDescription'
|
||||||
|
|
||||||
export default function MainNoteCard({
|
export default function MainNoteCard({
|
||||||
@@ -16,20 +21,77 @@ export default function MainNoteCard({
|
|||||||
reposter?: string
|
reposter?: string
|
||||||
embedded?: boolean
|
embedded?: boolean
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
const { push } = useSecondaryPage()
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
|
ref={containerRef}
|
||||||
className={className}
|
className={className}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
push(toNote(event))
|
push(toNote(event))
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div className={`clickable ${embedded ? 'p-2 sm:p-3 border rounded-lg' : 'py-3'}`}>
|
||||||
<div
|
<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} />
|
<RepostDescription className={embedded ? '' : 'px-4'} reposter={reposter} />
|
||||||
<Note size={embedded ? 'small' : 'normal'} event={event} hideStats={embedded} />
|
<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>
|
</div>
|
||||||
{!embedded && <Separator />}
|
{!embedded && <Separator />}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ export default function NormalPostContent({
|
|||||||
{parentEvent && (
|
{parentEvent && (
|
||||||
<ScrollArea className="flex max-h-48 flex-col overflow-y-auto rounded-lg border bg-muted/40">
|
<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">
|
<div className="p-2 sm:p-3 pointer-events-none">
|
||||||
<Note size="small" event={parentEvent} hideStats hideParentNotePreview />
|
<Note size="small" event={parentEvent} hideParentNotePreview />
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -223,6 +223,7 @@ export default {
|
|||||||
'Remove bookmark': 'إزالة الإشارة',
|
'Remove bookmark': 'إزالة الإشارة',
|
||||||
'no bookmarks found': 'لم يتم العثور على إشارات',
|
'no bookmarks found': 'لم يتم العثور على إشارات',
|
||||||
'no more bookmarks': 'لا مزيد من الإشارات',
|
'no more bookmarks': 'لا مزيد من الإشارات',
|
||||||
Bookmarks: 'الإشارات المرجعية'
|
Bookmarks: 'الإشارات المرجعية',
|
||||||
|
'Show more': 'عرض المزيد'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ export default {
|
|||||||
'Remove bookmark': 'Lesezeichen entfernen',
|
'Remove bookmark': 'Lesezeichen entfernen',
|
||||||
'no bookmarks found': 'Keine Lesezeichen gefunden',
|
'no bookmarks found': 'Keine Lesezeichen gefunden',
|
||||||
'no more bookmarks': 'Keine weiteren Lesezeichen',
|
'no more bookmarks': 'Keine weiteren Lesezeichen',
|
||||||
Bookmarks: 'Lesezeichen'
|
Bookmarks: 'Lesezeichen',
|
||||||
|
'Show more': 'Mehr anzeigen'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,6 +223,7 @@ export default {
|
|||||||
'Remove bookmark': 'Remove bookmark',
|
'Remove bookmark': 'Remove bookmark',
|
||||||
'no bookmarks found': 'no bookmarks found',
|
'no bookmarks found': 'no bookmarks found',
|
||||||
'no more bookmarks': 'no more bookmarks',
|
'no more bookmarks': 'no more bookmarks',
|
||||||
Bookmarks: 'Bookmarks'
|
Bookmarks: 'Bookmarks',
|
||||||
|
'Show more': 'Show more'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ export default {
|
|||||||
'Remove bookmark': 'Quitar marcador',
|
'Remove bookmark': 'Quitar marcador',
|
||||||
'no bookmarks found': 'No se encontraron marcadores',
|
'no bookmarks found': 'No se encontraron marcadores',
|
||||||
'no more bookmarks': 'No hay más marcadores',
|
'no more bookmarks': 'No hay más marcadores',
|
||||||
Bookmarks: 'Marcadores'
|
Bookmarks: 'Marcadores',
|
||||||
|
'Show more': 'Mostrar más'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ export default {
|
|||||||
'Remove bookmark': 'Retirer le favori',
|
'Remove bookmark': 'Retirer le favori',
|
||||||
'no bookmarks found': 'Aucun favori trouvé',
|
'no bookmarks found': 'Aucun favori trouvé',
|
||||||
'no more bookmarks': 'Plus de favoris',
|
'no more bookmarks': 'Plus de favoris',
|
||||||
Bookmarks: 'Favoris'
|
Bookmarks: 'Favoris',
|
||||||
|
'Show more': 'Afficher plus'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ export default {
|
|||||||
'Remove bookmark': 'Rimuovi segnalibro',
|
'Remove bookmark': 'Rimuovi segnalibro',
|
||||||
'no bookmarks found': 'Nessun segnalibro trovato',
|
'no bookmarks found': 'Nessun segnalibro trovato',
|
||||||
'no more bookmarks': 'Nessun altro segnalibro',
|
'no more bookmarks': 'Nessun altro segnalibro',
|
||||||
Bookmarks: 'Segnalibri'
|
Bookmarks: 'Segnalibri',
|
||||||
|
'Show more': 'Mostra di più'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ export default {
|
|||||||
'Remove bookmark': 'ブックマークを削除',
|
'Remove bookmark': 'ブックマークを削除',
|
||||||
'no bookmarks found': 'ブックマークが見つかりません',
|
'no bookmarks found': 'ブックマークが見つかりません',
|
||||||
'no more bookmarks': 'これ以上ブックマークはありません',
|
'no more bookmarks': 'これ以上ブックマークはありません',
|
||||||
Bookmarks: 'ブックマーク一覧'
|
Bookmarks: 'ブックマーク一覧',
|
||||||
|
'Show more': 'もっと見る'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,6 +225,7 @@ export default {
|
|||||||
'Remove bookmark': 'Usuń zakładkę',
|
'Remove bookmark': 'Usuń zakładkę',
|
||||||
'no bookmarks found': 'Nie znaleziono zakładek',
|
'no bookmarks found': 'Nie znaleziono zakładek',
|
||||||
'no more bookmarks': 'Koniec zakładek',
|
'no more bookmarks': 'Koniec zakładek',
|
||||||
Bookmarks: 'Zakładki'
|
Bookmarks: 'Zakładki',
|
||||||
|
'Show more': 'Pokaż więcej'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,6 +225,7 @@ export default {
|
|||||||
'Remove bookmark': 'Remover favorito',
|
'Remove bookmark': 'Remover favorito',
|
||||||
'no bookmarks found': 'Nenhum favorito encontrado',
|
'no bookmarks found': 'Nenhum favorito encontrado',
|
||||||
'no more bookmarks': 'Sem mais favoritos',
|
'no more bookmarks': 'Sem mais favoritos',
|
||||||
Bookmarks: 'Favoritos'
|
Bookmarks: 'Favoritos',
|
||||||
|
'Show more': 'Mostrar mais'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ export default {
|
|||||||
'Remove bookmark': 'Remover favorito',
|
'Remove bookmark': 'Remover favorito',
|
||||||
'no bookmarks found': 'Nenhum favorito encontrado',
|
'no bookmarks found': 'Nenhum favorito encontrado',
|
||||||
'no more bookmarks': 'Sem mais favoritos',
|
'no more bookmarks': 'Sem mais favoritos',
|
||||||
Bookmarks: 'Favoritos'
|
Bookmarks: 'Favoritos',
|
||||||
|
'Show more': 'Mostrar mais'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ export default {
|
|||||||
'Remove bookmark': 'Удалить закладку',
|
'Remove bookmark': 'Удалить закладку',
|
||||||
'no bookmarks found': 'Закладки не найдены',
|
'no bookmarks found': 'Закладки не найдены',
|
||||||
'no more bookmarks': 'Больше нет закладок',
|
'no more bookmarks': 'Больше нет закладок',
|
||||||
Bookmarks: 'Закладки'
|
Bookmarks: 'Закладки',
|
||||||
|
'Show more': 'Показать больше'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ export default {
|
|||||||
'Remove bookmark': '取消收藏',
|
'Remove bookmark': '取消收藏',
|
||||||
'no bookmarks found': '暂无收藏',
|
'no bookmarks found': '暂无收藏',
|
||||||
'no more bookmarks': '到底了',
|
'no more bookmarks': '到底了',
|
||||||
Bookmarks: '收藏'
|
Bookmarks: '收藏',
|
||||||
|
'Show more': '显示更多'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useSecondaryPage } from '@/PageManager'
|
|||||||
import ContentPreview from '@/components/ContentPreview'
|
import ContentPreview from '@/components/ContentPreview'
|
||||||
import Nip22ReplyNoteList from '@/components/Nip22ReplyNoteList'
|
import Nip22ReplyNoteList from '@/components/Nip22ReplyNoteList'
|
||||||
import Note from '@/components/Note'
|
import Note from '@/components/Note'
|
||||||
|
import NoteStats from '@/components/NoteStats'
|
||||||
import PictureNote from '@/components/PictureNote'
|
import PictureNote from '@/components/PictureNote'
|
||||||
import ReplyNoteList from '@/components/ReplyNoteList'
|
import ReplyNoteList from '@/components/ReplyNoteList'
|
||||||
import UserAvatar from '@/components/UserAvatar'
|
import UserAvatar from '@/components/UserAvatar'
|
||||||
@@ -74,9 +75,9 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
|
|||||||
key={`note-${event.id}`}
|
key={`note-${event.id}`}
|
||||||
event={event}
|
event={event}
|
||||||
className="select-text"
|
className="select-text"
|
||||||
fetchNoteStats
|
|
||||||
hideParentNotePreview
|
hideParentNotePreview
|
||||||
/>
|
/>
|
||||||
|
<NoteStats className="mt-3" event={event} fetchIfNotExisting />
|
||||||
</div>
|
</div>
|
||||||
<Separator className="mt-4" />
|
<Separator className="mt-4" />
|
||||||
{event.kind === kinds.ShortTextNote ? (
|
{event.kind === kinds.ShortTextNote ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user