feat: zap details (#731)
Co-authored-by: The Daniel <dmnyc@users.noreply.github.com>
Co-authored-by: The Daniel ⚡️ <dmnycnet@proton.me>
This commit is contained in:
parent
603bd35b4a
commit
7e8f1692ac
21 changed files with 138 additions and 47 deletions
|
|
@ -1,12 +1,14 @@
|
|||
import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area'
|
||||
import { useStuffStatsById } from '@/hooks/useStuffStatsById'
|
||||
import { useStuff } from '@/hooks/useStuff'
|
||||
import { useStuffStatsById } from '@/hooks/useStuffStatsById'
|
||||
import { createFakeEvent } from '@/lib/event'
|
||||
import { formatAmount } from '@/lib/lightning'
|
||||
import { Zap } from 'lucide-react'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { useMemo, useState } from 'react'
|
||||
import ContentPreview from '../ContentPreview'
|
||||
import { SimpleUserAvatar } from '../UserAvatar'
|
||||
import ZapDialog from '../ZapDialog'
|
||||
import ZapDetailDialog from '../ZapDetailDialog'
|
||||
|
||||
export default function TopZaps({ stuff }: { stuff: Event | string }) {
|
||||
const { event, stuffKey } = useStuff(stuff)
|
||||
|
|
@ -22,8 +24,8 @@ export default function TopZaps({ stuff }: { stuff: Event | string }) {
|
|||
<ScrollArea className="pb-2 mb-1">
|
||||
<div className="flex gap-1">
|
||||
{topZaps.map((zap, index) => (
|
||||
<div key={zap.pr}>
|
||||
<div
|
||||
key={zap.pr}
|
||||
className="flex gap-1 py-1 pl-1 pr-2 text-sm max-w-72 rounded-full bg-muted/80 items-center text-yellow-400 border border-yellow-400 hover:bg-yellow-400/20 cursor-pointer"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
|
|
@ -33,9 +35,14 @@ export default function TopZaps({ stuff }: { stuff: Event | string }) {
|
|||
<SimpleUserAvatar userId={zap.pubkey} size="xSmall" />
|
||||
<Zap className="size-3 fill-yellow-400 shrink-0" />
|
||||
<div className="font-semibold">{formatAmount(zap.amount)}</div>
|
||||
<div className="truncate">{zap.comment}</div>
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<ZapDialog
|
||||
<ContentPreview
|
||||
className="truncate"
|
||||
event={createFakeEvent({
|
||||
content: zap.comment
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<ZapDetailDialog
|
||||
open={zapIndex === index}
|
||||
setOpen={(open) => {
|
||||
if (open) {
|
||||
|
|
@ -44,13 +51,9 @@ export default function TopZaps({ stuff }: { stuff: Event | string }) {
|
|||
setZapIndex(-1)
|
||||
}
|
||||
}}
|
||||
pubkey={event.pubkey}
|
||||
event={event}
|
||||
defaultAmount={zap.amount}
|
||||
defaultComment={zap.comment}
|
||||
zap={zap}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<ScrollBar orientation="horizontal" />
|
||||
|
|
|
|||
70
src/components/ZapDetailDialog/index.tsx
Normal file
70
src/components/ZapDetailDialog/index.tsx
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer'
|
||||
import { formatAmount } from '@/lib/lightning'
|
||||
import { Zap } from 'lucide-react'
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
||||
import UserAvatar from '../UserAvatar'
|
||||
import Username from '../Username'
|
||||
import Content from '../Content'
|
||||
import { FormattedTimestamp } from '../FormattedTimestamp'
|
||||
|
||||
interface ZapDetailDialogProps {
|
||||
open: boolean
|
||||
setOpen: Dispatch<SetStateAction<boolean>>
|
||||
zap: {
|
||||
pubkey: string
|
||||
amount: number
|
||||
comment?: string
|
||||
created_at: number
|
||||
}
|
||||
}
|
||||
|
||||
export default function ZapDetailDialog({ open, setOpen, zap }: ZapDetailDialogProps) {
|
||||
const { t } = useTranslation()
|
||||
const { isSmallScreen } = useScreenSize()
|
||||
|
||||
const content = (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<UserAvatar userId={zap.pubkey} size="medium" />
|
||||
<div className="flex-1">
|
||||
<Username userId={zap.pubkey} className="font-semibold" />
|
||||
<div className="flex items-center gap-1 text-sm text-muted-foreground">
|
||||
<FormattedTimestamp timestamp={zap.created_at} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1 text-yellow-400">
|
||||
<Zap className="size-5 fill-yellow-400" />
|
||||
<span className="text-lg font-bold">{formatAmount(zap.amount)}</span>
|
||||
</div>
|
||||
</div>
|
||||
{zap.comment && <Content content={zap.comment} />}
|
||||
</div>
|
||||
)
|
||||
|
||||
if (isSmallScreen) {
|
||||
return (
|
||||
<Drawer open={open} onOpenChange={setOpen}>
|
||||
<DrawerContent className="px-4 pb-4">
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>{t('Zap Details')}</DrawerTitle>
|
||||
</DrawerHeader>
|
||||
{content}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent onClick={(e) => e.stopPropagation()}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t('Zap Details')}</DialogTitle>
|
||||
</DialogHeader>
|
||||
{content}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
|
@ -662,6 +662,7 @@ export default {
|
|||
'تحذير: يرجى عدم تعديل هذه الإعدادات بشكل عشوائي، فقد يؤثر ذلك على تجربتك الأساسية.',
|
||||
'Invalid relay URL': 'عنوان URL للمرحل غير صالح',
|
||||
'Muted words': 'الكلمات المحظورة',
|
||||
'Add muted word': 'إضافة كلمة محظورة'
|
||||
'Add muted word': 'إضافة كلمة محظورة',
|
||||
'Zap Details': 'تفاصيل Zap'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -684,6 +684,7 @@ export default {
|
|||
'Warnung: Ändern Sie diese Einstellungen nicht leichtfertig, da dies Ihre grundlegende Erfahrung beeinträchtigen kann.',
|
||||
'Invalid relay URL': 'Ungültige Relay-URL',
|
||||
'Muted words': 'Stummgeschaltete Wörter',
|
||||
'Add muted word': 'Stummgeschaltetes Wort hinzufügen'
|
||||
'Add muted word': 'Stummgeschaltetes Wort hinzufügen',
|
||||
'Zap Details': 'Zap-Details'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -667,6 +667,7 @@ export default {
|
|||
'Warning: Please do not modify these settings casually, as it may affect your basic experience.',
|
||||
'Invalid relay URL': 'Invalid relay URL',
|
||||
'Muted words': 'Muted words',
|
||||
'Add muted word': 'Add muted word'
|
||||
'Add muted word': 'Add muted word',
|
||||
'Zap Details': 'Zap Details'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,6 +678,7 @@ export default {
|
|||
'Advertencia: No modifiques estas configuraciones a la ligera, ya que puede afectar tu experiencia básica.',
|
||||
'Invalid relay URL': 'URL de relé no válida',
|
||||
'Muted words': 'Palabras silenciadas',
|
||||
'Add muted word': 'Agregar palabra silenciada'
|
||||
'Add muted word': 'Agregar palabra silenciada',
|
||||
'Zap Details': 'Detalles del Zap'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -673,6 +673,7 @@ export default {
|
|||
'هشدار: لطفاً این تنظیمات را به صورت تصادفی تغییر ندهید، ممکن است بر تجربه اولیه شما تأثیر بگذارد.',
|
||||
'Invalid relay URL': 'آدرس URL رله نامعتبر است',
|
||||
'Muted words': 'کلمات بیصدا شده',
|
||||
'Add muted word': 'افزودن کلمه بیصدا'
|
||||
'Add muted word': 'افزودن کلمه بیصدا',
|
||||
'Zap Details': 'جزئیات زپ'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -682,6 +682,7 @@ export default {
|
|||
'Attention : Ne modifiez pas ces paramètres à la légère, car cela pourrait affecter votre expérience de base.',
|
||||
'Invalid relay URL': 'URL de relais non valide',
|
||||
'Muted words': 'Mots masqués',
|
||||
'Add muted word': 'Ajouter un mot masqué'
|
||||
'Add muted word': 'Ajouter un mot masqué',
|
||||
'Zap Details': 'Détails du Zap'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -674,6 +674,7 @@ export default {
|
|||
'चेतावनी: कृपया इन सेटिंग्स को बेतरतीब ढंग से संशोधित न करें, क्योंकि यह आपके बुनियादी अनुभव को प्रभावित कर सकता है।',
|
||||
'Invalid relay URL': 'अमान्य रिले URL',
|
||||
'Muted words': 'म्यूट किए गए शब्द',
|
||||
'Add muted word': 'म्यूट शब्द जोड़ें'
|
||||
'Add muted word': 'म्यूट शब्द जोड़ें',
|
||||
'Zap Details': 'जैप विवरण'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -667,6 +667,7 @@ export default {
|
|||
'Figyelmeztetés: Ne módosítsa ezeket a beállításokat meggondolatlanul, mert ez befolyásolhatja az alapvető élményt.',
|
||||
'Invalid relay URL': 'Érvénytelen továbbító URL',
|
||||
'Muted words': 'Némított szavak',
|
||||
'Add muted word': 'Némított szó hozzáadása'
|
||||
'Add muted word': 'Némított szó hozzáadása',
|
||||
'Zap Details': 'Zap Részletek'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,6 +678,7 @@ export default {
|
|||
"Attenzione: Non modificare queste impostazioni alla leggera, potrebbe influire sull'esperienza di base.",
|
||||
'Invalid relay URL': 'URL relay non valido',
|
||||
'Muted words': 'Parole silenziate',
|
||||
'Add muted word': 'Aggiungi parola silenziata'
|
||||
'Add muted word': 'Aggiungi parola silenziata',
|
||||
'Zap Details': 'Dettagli Zap'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -672,6 +672,7 @@ export default {
|
|||
'警告:これらの設定を無闇に変更しないでください。基本的な体験に影響を与える可能性があります。',
|
||||
'Invalid relay URL': '無効なリレーURL',
|
||||
'Muted words': 'ミュートワード',
|
||||
'Add muted word': 'ミュートワードを追加'
|
||||
'Add muted word': 'ミュートワードを追加',
|
||||
'Zap Details': 'Zapの詳細'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -668,6 +668,7 @@ export default {
|
|||
'경고: 이러한 설정을 임의로 수정하지 마십시오. 기본 경험에 영향을 줄 수 있습니다.',
|
||||
'Invalid relay URL': '유효하지 않은 릴레이 URL',
|
||||
'Muted words': '차단 단어',
|
||||
'Add muted word': '차단 단어 추가'
|
||||
'Add muted word': '차단 단어 추가',
|
||||
'Zap Details': '잽 세부 정보'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -679,6 +679,7 @@ export default {
|
|||
'Ostrzeżenie: Nie modyfikuj tych ustawień pochopnie, może to wpłynąć na podstawowe doświadczenie.',
|
||||
'Invalid relay URL': 'Nieprawidłowy adres URL przekaźnika',
|
||||
'Muted words': 'Wyciszone słowa',
|
||||
'Add muted word': 'Dodaj wyciszone słowo'
|
||||
'Add muted word': 'Dodaj wyciszone słowo',
|
||||
'Zap Details': 'Szczegóły zapu'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -675,6 +675,7 @@ export default {
|
|||
'Aviso: Não modifique essas configurações casualmente, pois pode afetar sua experiência básica.',
|
||||
'Invalid relay URL': 'URL de relé inválida',
|
||||
'Muted words': 'Palavras silenciadas',
|
||||
'Add muted word': 'Adicionar palavra silenciada'
|
||||
'Add muted word': 'Adicionar palavra silenciada',
|
||||
'Zap Details': 'Detalhes do Zap'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,6 +678,7 @@ export default {
|
|||
'Aviso: Não modifique estas configurações casualmente, pois pode afetar a sua experiência básica.',
|
||||
'Invalid relay URL': 'URL de relay inválido',
|
||||
'Muted words': 'Palavras silenciadas',
|
||||
'Add muted word': 'Adicionar palavra silenciada'
|
||||
'Add muted word': 'Adicionar palavra silenciada',
|
||||
'Zap Details': 'Detalhes do Zap'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,6 +678,7 @@ export default {
|
|||
'Предупреждение: Не изменяйте эти настройки без необходимости, это может повлиять на базовый опыт использования.',
|
||||
'Invalid relay URL': 'Неверный URL реле',
|
||||
'Muted words': 'Заблокированные слова',
|
||||
'Add muted word': 'Добавить заблокированное слово'
|
||||
'Add muted word': 'Добавить заблокированное слово',
|
||||
'Zap Details': 'Детали запа'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -663,6 +663,7 @@ export default {
|
|||
'คำเตือน: กรุณาอย่าแก้ไขการตั้งค่าเหล่านี้โดยไม่ระมัดระวัง เพราะอาจส่งผลต่อประสบการณ์พื้นฐานของคุณ',
|
||||
'Invalid relay URL': 'URL รีเลย์ไม่ถูกต้อง',
|
||||
'Muted words': 'คำที่ถูกปิดเสียง',
|
||||
'Add muted word': 'เพิ่มคำที่ถูกปิดเสียง'
|
||||
'Add muted word': 'เพิ่มคำที่ถูกปิดเสียง',
|
||||
'Zap Details': 'รายละเอียดซาตส์'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -646,6 +646,7 @@ export default {
|
|||
'Default relays warning': '警告:請不要隨意修改這些設定,可能會影響基礎體驗。',
|
||||
'Invalid relay URL': '無效的中繼地址',
|
||||
'Muted words': '屏蔽詞',
|
||||
'Add muted word': '添加屏蔽詞'
|
||||
'Add muted word': '添加屏蔽詞',
|
||||
'Zap Details': '打閃詳情'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -651,6 +651,7 @@ export default {
|
|||
'Default relays warning': '警告:请不要随意修改这些设置,可能会影响您的基本体验。',
|
||||
'Invalid relay URL': '无效的中继地址',
|
||||
'Muted words': '屏蔽词',
|
||||
'Add muted word': '添加屏蔽词'
|
||||
'Add muted word': '添加屏蔽词',
|
||||
'Zap Details': '打闪详情'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ class StuffStatsService {
|
|||
const info = getZapInfoFromEvent(evt)
|
||||
if (!info) return
|
||||
const { originalEventId, senderPubkey, invoice, amount, comment } = info
|
||||
if (!originalEventId || !senderPubkey) return
|
||||
if (!originalEventId || !senderPubkey || amount <= 0) return
|
||||
|
||||
return this.addZap(
|
||||
senderPubkey,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue