refactor: new notes button
This commit is contained in:
@@ -1,84 +1,68 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import UserAvatar from '@/components/UserAvatar'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { SimpleUserAvatar } from '@/components/UserAvatar'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
||||
import { useDeepBrowsing } from '@/providers/DeepBrowsingProvider'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export type User = {
|
||||
pubkey: string
|
||||
}
|
||||
|
||||
interface NewNotesButtonProps {
|
||||
users?: User[]
|
||||
eventCount?: number
|
||||
onShowEvents?: () => void
|
||||
}
|
||||
|
||||
const NewNotesButton: React.FC<NewNotesButtonProps> = ({
|
||||
users = [],
|
||||
eventCount: initialEventCount = 0,
|
||||
onShowEvents
|
||||
}) => {
|
||||
const [newNotesCount, setNewNotesCount] = useState(initialEventCount)
|
||||
export default function NewNotesButton({
|
||||
newEvents = [],
|
||||
onClick
|
||||
}: {
|
||||
newEvents?: Event[]
|
||||
onClick?: () => void
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const { isSmallScreen } = useScreenSize()
|
||||
const { deepBrowsing } = useDeepBrowsing()
|
||||
|
||||
useEffect(() => {
|
||||
setNewNotesCount(initialEventCount)
|
||||
}, [initialEventCount])
|
||||
|
||||
const handleClick = () => {
|
||||
if (onShowEvents) {
|
||||
onShowEvents()
|
||||
} else {
|
||||
console.log('Showing new notes...')
|
||||
const pubkeys = useMemo(() => {
|
||||
const arr: string[] = []
|
||||
for (const event of newEvents) {
|
||||
if (!arr.includes(event.pubkey)) {
|
||||
arr.push(event.pubkey)
|
||||
}
|
||||
if (arr.length >= 3) break
|
||||
}
|
||||
setNewNotesCount(0)
|
||||
}
|
||||
|
||||
const getDesktopPosition = () => {
|
||||
return deepBrowsing
|
||||
? 'absolute left-0 right-0 top-[3.5rem] w-full flex justify-center z-50'
|
||||
: 'absolute left-0 right-0 top-[6.5rem] w-full flex justify-center z-50'
|
||||
}
|
||||
return arr
|
||||
}, [newEvents])
|
||||
|
||||
return (
|
||||
<>
|
||||
{newNotesCount > 0 && (
|
||||
{newEvents.length > 0 && (
|
||||
<div
|
||||
className={
|
||||
isSmallScreen
|
||||
? 'fixed left-0 right-0 w-full flex justify-center z-[9999]'
|
||||
: getDesktopPosition()
|
||||
}
|
||||
className={cn(
|
||||
'w-full flex justify-center z-40',
|
||||
isSmallScreen ? 'fixed' : 'absolute bottom-4'
|
||||
)}
|
||||
style={isSmallScreen ? { bottom: 'calc(4rem + env(safe-area-inset-bottom))' } : undefined}
|
||||
>
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="flex items-center bg-purple-600 hover:bg-purple-700 text-white px-3 py-2 rounded-full text-sm font-medium shadow-lg"
|
||||
<Button
|
||||
onClick={onClick}
|
||||
className="group rounded-full h-fit pl-2 pr-3 hover:bg-primary-hover"
|
||||
>
|
||||
{users && users.length > 0 && (
|
||||
<div className="flex items-center mr-1">
|
||||
{users.slice(0, 3).map((user, index) => (
|
||||
{pubkeys.length > 0 && (
|
||||
<div className="flex items-center">
|
||||
{pubkeys.map((pubkey, index) => (
|
||||
<div
|
||||
key={user.pubkey}
|
||||
key={pubkey}
|
||||
className="relative -mr-2.5 last:mr-0"
|
||||
style={{ zIndex: 3 - index }}
|
||||
>
|
||||
<div className="w-7 h-7 rounded-full border-2 border-purple-600 overflow-hidden flex items-center justify-center bg-background">
|
||||
<UserAvatar userId={user.pubkey} size="small" />
|
||||
</div>
|
||||
<SimpleUserAvatar
|
||||
userId={pubkey}
|
||||
size="small"
|
||||
className="border-primary border-2 group-hover:border-primary-hover"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<span className="whitespace-nowrap ml-1">
|
||||
Show {newNotesCount > 99 ? '99+' : newNotesCount} new events
|
||||
</span>
|
||||
</button>
|
||||
<div className="text-md font-medium">
|
||||
{t('Show n new notes', { n: newEvents.length > 99 ? '99+' : newEvents.length })}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default NewNotesButton
|
||||
|
||||
@@ -59,6 +59,14 @@ export default function NoteList({
|
||||
}
|
||||
}, [JSON.stringify(filter), isPictures])
|
||||
const topRef = useRef<HTMLDivElement | null>(null)
|
||||
const filteredNewEvents = useMemo(() => {
|
||||
return newEvents.filter((event: Event) => {
|
||||
return (
|
||||
(!filterMutedNotes || !mutePubkeys.includes(event.pubkey)) &&
|
||||
(listMode !== 'posts' || !isReplyNoteEvent(event))
|
||||
)
|
||||
})
|
||||
}, [newEvents, listMode, filterMutedNotes, mutePubkeys])
|
||||
|
||||
useEffect(() => {
|
||||
if (relayUrls.length === 0 && !noteFilter.authors?.length) return
|
||||
@@ -168,29 +176,6 @@ export default function NoteList({
|
||||
setNewEvents([])
|
||||
}
|
||||
|
||||
const newUsers = useMemo(() => {
|
||||
return newEvents
|
||||
.filter((event: Event) => {
|
||||
return (
|
||||
(!filterMutedNotes || !mutePubkeys.includes(event.pubkey)) &&
|
||||
(listMode !== 'posts' || !isReplyNoteEvent(event))
|
||||
)
|
||||
})
|
||||
.slice(0, 3)
|
||||
.map((event) => {
|
||||
return {
|
||||
pubkey: event.pubkey
|
||||
}
|
||||
})
|
||||
}, [newEvents, filterMutedNotes, mutePubkeys, listMode])
|
||||
|
||||
const filteredNewEventsCount = newEvents.filter((event: Event) => {
|
||||
return (
|
||||
(!filterMutedNotes || !mutePubkeys.includes(event.pubkey)) &&
|
||||
(listMode !== 'posts' || !isReplyNoteEvent(event))
|
||||
)
|
||||
}).length
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<ListModeSwitch
|
||||
@@ -203,12 +188,8 @@ export default function NoteList({
|
||||
}}
|
||||
/>
|
||||
<div ref={topRef} />
|
||||
{filteredNewEventsCount > 0 && (
|
||||
<NewNotesButton
|
||||
users={newUsers}
|
||||
eventCount={filteredNewEventsCount}
|
||||
onShowEvents={showNewEvents}
|
||||
/>
|
||||
{filteredNewEvents.length > 0 && (
|
||||
<NewNotesButton newEvents={filteredNewEvents} onClick={showNewEvents} />
|
||||
)}
|
||||
<PullToRefresh
|
||||
onRefresh={async () => {
|
||||
|
||||
@@ -216,6 +216,7 @@ export default {
|
||||
'Media upload service': 'خدمة تحميل الوسائط',
|
||||
'Choose a relay': 'اختر ريلاي',
|
||||
'no relays found': 'لم يتم العثور على ريلايات',
|
||||
video: 'فيديو'
|
||||
video: 'فيديو',
|
||||
'Show n new notes': 'عرض {{n}} ملاحظات جديدة'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ export default {
|
||||
'Media upload service': 'Medien-Upload-Service',
|
||||
'Choose a relay': 'Wähle ein Relay',
|
||||
'no relays found': 'Keine Relays gefunden',
|
||||
video: 'Video'
|
||||
video: 'Video',
|
||||
'Show n new notes': 'Zeige {{n}} neue Notizen'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +216,7 @@ export default {
|
||||
'Media upload service': 'Media upload service',
|
||||
'Choose a relay': 'Choose a relay',
|
||||
'no relays found': 'no relays found',
|
||||
video: 'video'
|
||||
video: 'video',
|
||||
'Show n new notes': 'Show {{n}} new notes'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ export default {
|
||||
'Media upload service': 'Servicio de carga de medios',
|
||||
'Choose a relay': 'Selecciona un relé',
|
||||
'no relays found': 'no se encontraron relés',
|
||||
video: 'video'
|
||||
video: 'video',
|
||||
'Show n new notes': 'Mostrar {{n}} nuevas notas'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@ export default {
|
||||
'Media upload service': 'Service de téléchargement de médias',
|
||||
'Choose a relay': 'Choisir un relais',
|
||||
'no relays found': 'aucun relais trouvé',
|
||||
video: 'vidéo'
|
||||
video: 'vidéo',
|
||||
'Show n new notes': 'Afficher {{n}} nouvelles notes'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@ export default {
|
||||
'Media upload service': 'Servizio di caricamento media',
|
||||
'Choose a relay': 'Scegli un relay',
|
||||
'no relays found': 'Nessun relay trovato',
|
||||
video: 'video'
|
||||
video: 'video',
|
||||
'Show n new notes': 'Mostra {{n}} nuove note'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ export default {
|
||||
'Media upload service': 'メディアアップロードサービス',
|
||||
'Choose a relay': 'リレイを選択',
|
||||
'no relays found': 'リレイが見つかりません',
|
||||
video: 'ビデオ'
|
||||
video: 'ビデオ',
|
||||
'Show n new notes': '新しいノートを{{n}}件表示'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +218,7 @@ export default {
|
||||
'Media upload service': 'Usługa przesyłania mediów',
|
||||
'Choose a relay': 'Wybierz transmiter',
|
||||
'no relays found': 'Nie znaleziono transmiterów',
|
||||
video: 'wideo'
|
||||
video: 'wideo',
|
||||
'Show n new notes': 'Pokaż {{n}} nowych wpisów'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +218,7 @@ export default {
|
||||
'Media upload service': 'Serviço de upload de mídia',
|
||||
'Choose a relay': 'Escolher um relé',
|
||||
'no relays found': 'nenhum relé encontrado',
|
||||
video: 'vídeo'
|
||||
video: 'vídeo',
|
||||
'Show n new notes': 'Mostrar {{n}} novas notas'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@ export default {
|
||||
'Media upload service': 'Serviço de Upload de Mídia',
|
||||
'Choose a relay': 'Escolher um Relé',
|
||||
'no relays found': 'nenhum relé encontrado',
|
||||
video: 'vídeo'
|
||||
video: 'vídeo',
|
||||
'Show n new notes': 'Mostrar {{n}} novas notas'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ export default {
|
||||
'Media upload service': 'Служба загрузки медиафайлов',
|
||||
'Choose a relay': 'Выберите ретранслятор',
|
||||
'no relays found': 'ретрансляторы не найдены',
|
||||
video: 'видео'
|
||||
video: 'видео',
|
||||
'Show n new notes': 'Показать {{n}} новых заметок'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ export default {
|
||||
'Media upload service': '媒体上传服务',
|
||||
'Choose a relay': '选择一个服务器',
|
||||
'no relays found': '未找到服务器',
|
||||
video: '视频'
|
||||
video: '视频',
|
||||
'Show n new notes': '显示 {{n}} 条新笔记'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--primary: 259 43% 56%;
|
||||
--primary-hover: 259 43% 65%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
@@ -83,6 +84,7 @@
|
||||
--popover: 240 10% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 259 43% 56%;
|
||||
--primary-hover: 259 43% 65%;
|
||||
--primary-foreground: 240 5.9% 10%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
|
||||
Reference in New Issue
Block a user