Browse Source

remove poll note

fix poll previews
imwald
Silberengel 4 months ago
parent
commit
9f5c607252
  1. 52
      src/components/ContentPreview/PollPreview.tsx
  2. 14
      src/components/PostEditor/PollEditor.tsx
  3. 1
      src/components/PostEditor/PostContent.tsx
  4. 49
      src/components/PostEditor/PostTextarea/Preview.tsx
  5. 6
      src/components/PostEditor/PostTextarea/index.tsx

52
src/components/ContentPreview/PollPreview.tsx

@ -1,4 +1,6 @@
import { POLL_TYPE } from '@/constants'
import { useTranslatedEvent } from '@/hooks' import { useTranslatedEvent } from '@/hooks'
import { getPollMetadataFromEvent } from '@/lib/event-metadata'
import { getEmojiInfosFromEmojiTags } from '@/lib/tag' import { getEmojiInfosFromEmojiTags } from '@/lib/tag'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Event } from 'nostr-tools' import { Event } from 'nostr-tools'
@ -10,15 +12,53 @@ export default function PollPreview({ event, className }: { event: Event; classN
const { t } = useTranslation() const { t } = useTranslation()
const translatedEvent = useTranslatedEvent(event.id) const translatedEvent = useTranslatedEvent(event.id)
const emojiInfos = useMemo(() => getEmojiInfosFromEmojiTags(event.tags), [event]) const emojiInfos = useMemo(() => getEmojiInfosFromEmojiTags(event.tags), [event])
const poll = useMemo(
() => getPollMetadataFromEvent(translatedEvent ?? event),
[event, translatedEvent]
)
const content = (translatedEvent?.content ?? event.content)?.trim()
return ( return (
<div className={cn('pointer-events-none', className)}> <div className={cn('pointer-events-none', className)}>
[{t('Poll')}]{' '} <div className="flex items-center gap-1 mb-1">
<Content <span className="text-muted-foreground">[{t('Poll')}]</span>
content={translatedEvent?.content ?? event.content} {poll?.pollType === POLL_TYPE.MULTIPLE_CHOICE && (
emojiInfos={emojiInfos} <span className="text-xs text-muted-foreground">({t('Multiple choice')})</span>
className="italic pr-0.5" )}
/> </div>
{content ? (
<div className="mb-1">
<Content
content={content}
emojiInfos={emojiInfos}
className="italic pr-0.5"
/>
</div>
) : null}
{poll && poll.options.length > 0 ? (
<div className="grid gap-2">
{poll.options.map((option) => (
<div
key={option.id}
className="relative w-full px-4 py-3 rounded-lg border border-border bg-background flex items-center gap-2 overflow-hidden"
>
<div className="flex items-center gap-2 flex-1 w-0 z-10">
<div className="line-clamp-2 text-left text-sm">
{option.label || t('Option')}
</div>
</div>
</div>
))}
</div>
) : poll ? (
<div className="text-sm text-muted-foreground italic">
{t('Poll with no options')}
</div>
) : (
<div className="text-sm text-muted-foreground italic">
{content || t('Poll')}
</div>
)}
</div> </div>
) )
} }

14
src/components/PostEditor/PollEditor.tsx

@ -8,7 +8,6 @@ import dayjs from 'dayjs'
import { Eraser, X } from 'lucide-react' import { Eraser, X } from 'lucide-react'
import { Dispatch, SetStateAction, useEffect, useState } from 'react' import { Dispatch, SetStateAction, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import AlertCard from '../AlertCard'
export default function PollEditor({ export default function PollEditor({
pollCreateData, pollCreateData,
@ -123,19 +122,6 @@ export default function PollEditor({
placeholder="wss://relay1.com, wss://relay2.com" placeholder="wss://relay1.com, wss://relay2.com"
/> />
</div> </div>
<div className="grid gap-2">
<AlertCard
title={t('This is a poll note.')}
content={t(
'Unlike regular notes, polls are not widely supported and may not display on other clients.'
)}
/>
<Button variant="ghost-destructive" className="w-full" onClick={() => setIsPoll(false)}>
{t('Remove poll')}
</Button>
</div>
</div> </div>
) )
} }

1
src/components/PostEditor/PostContent.tsx

@ -491,6 +491,7 @@ export default function PostContent({
onUploadEnd={handleUploadEnd} onUploadEnd={handleUploadEnd}
kind={isHighlight ? kinds.Highlights : isPublicMessage ? ExtendedKind.PUBLIC_MESSAGE : isPoll ? ExtendedKind.POLL : kinds.ShortTextNote} kind={isHighlight ? kinds.Highlights : isPublicMessage ? ExtendedKind.PUBLIC_MESSAGE : isPoll ? ExtendedKind.POLL : kinds.ShortTextNote}
highlightData={isHighlight ? highlightData : undefined} highlightData={isHighlight ? highlightData : undefined}
pollCreateData={isPoll ? pollCreateData : undefined}
/> />
{isPoll && ( {isPoll && (
<PollEditor <PollEditor

49
src/components/PostEditor/PostTextarea/Preview.tsx

@ -1,10 +1,14 @@
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import { ExtendedKind, POLL_TYPE } from '@/constants'
import { transformCustomEmojisInContent } from '@/lib/draft-event' import { transformCustomEmojisInContent } from '@/lib/draft-event'
import { createFakeEvent } from '@/lib/event' import { createFakeEvent } from '@/lib/event'
import { randomString } from '@/lib/random'
import { cleanUrl } from '@/lib/url' import { cleanUrl } from '@/lib/url'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { TPollCreateData } from '@/types'
import { kinds, nip19 } from 'nostr-tools' import { kinds, nip19 } from 'nostr-tools'
import { useMemo } from 'react' import { useMemo } from 'react'
import ContentPreview from '../../ContentPreview'
import Content from '../../Content' import Content from '../../Content'
import Highlight from '../../Note/Highlight' import Highlight from '../../Note/Highlight'
import { HighlightData } from '../HighlightEditor' import { HighlightData } from '../HighlightEditor'
@ -13,14 +17,16 @@ export default function Preview({
content, content,
className, className,
kind = 1, kind = 1,
highlightData highlightData,
pollCreateData
}: { }: {
content: string content: string
className?: string className?: string
kind?: number kind?: number
highlightData?: HighlightData highlightData?: HighlightData
pollCreateData?: TPollCreateData
}) { }) {
const { content: processedContent, emojiTags, highlightTags } = useMemo( const { content: processedContent, emojiTags, highlightTags, pollTags } = useMemo(
() => { () => {
// Clean tracking parameters from URLs in the preview // Clean tracking parameters from URLs in the preview
const cleanedContent = content.replace( const cleanedContent = content.replace(
@ -70,19 +76,36 @@ export default function Preview({
} }
} }
// Build poll tags if this is a poll
let pollTags: string[][] = []
if (kind === ExtendedKind.POLL && pollCreateData) {
const validOptions = pollCreateData.options.filter((opt) => opt.trim())
pollTags.push(...validOptions.map((option) => ['option', randomString(9), option.trim()]))
pollTags.push(['polltype', pollCreateData.isMultipleChoice ? POLL_TYPE.MULTIPLE_CHOICE : POLL_TYPE.SINGLE_CHOICE])
if (pollCreateData.endsAt) {
pollTags.push(['endsAt', pollCreateData.endsAt.toString()])
}
if (pollCreateData.relays.length > 0) {
pollCreateData.relays.forEach((relay) => {
pollTags.push(['relay', relay])
})
}
}
return { return {
content: processed, content: processed,
emojiTags: tags, emojiTags: tags,
highlightTags highlightTags,
pollTags
} }
}, },
[content, kind, highlightData] [content, kind, highlightData, pollCreateData]
) )
// Combine emoji tags and highlight tags // Combine emoji tags, highlight tags, and poll tags
const allTags = useMemo(() => { const allTags = useMemo(() => {
return [...emojiTags, ...highlightTags] return [...emojiTags, ...highlightTags, ...pollTags]
}, [emojiTags, highlightTags]) }, [emojiTags, highlightTags, pollTags])
const fakeEvent = useMemo(() => { const fakeEvent = useMemo(() => {
return createFakeEvent({ return createFakeEvent({
@ -92,6 +115,18 @@ export default function Preview({
}) })
}, [processedContent, allTags, kind]) }, [processedContent, allTags, kind])
// For polls, use ContentPreview to show poll properly
if (kind === ExtendedKind.POLL) {
return (
<Card className={cn('p-3', className)}>
<ContentPreview
event={fakeEvent}
className="pointer-events-none"
/>
</Card>
)
}
// For highlights, use the Highlight component for proper formatting // For highlights, use the Highlight component for proper formatting
if (kind === kinds.Highlights) { if (kind === kinds.Highlights) {
return ( return (

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

@ -43,6 +43,7 @@ const PostTextarea = forwardRef<
onUploadEnd?: (file: File) => void onUploadEnd?: (file: File) => void
kind?: number kind?: number
highlightData?: HighlightData highlightData?: HighlightData
pollCreateData?: import('@/types').TPollCreateData
} }
>( >(
( (
@ -57,7 +58,8 @@ const PostTextarea = forwardRef<
onUploadProgress, onUploadProgress,
onUploadEnd, onUploadEnd,
kind = 1, kind = 1,
highlightData highlightData,
pollCreateData
}, },
ref ref
) => { ) => {
@ -173,7 +175,7 @@ const PostTextarea = forwardRef<
<EditorContent className="tiptap" editor={editor} /> <EditorContent className="tiptap" editor={editor} />
</TabsContent> </TabsContent>
<TabsContent value="preview"> <TabsContent value="preview">
<Preview content={text} className={className} kind={kind} highlightData={highlightData} /> <Preview content={text} className={className} kind={kind} highlightData={highlightData} pollCreateData={pollCreateData} />
</TabsContent> </TabsContent>
</Tabs> </Tabs>
) )

Loading…
Cancel
Save