Browse Source

render markup in discussions and bugfix relay selection and updating

imwald
Silberengel 5 months ago
parent
commit
cb23c7954f
  1. 47
      src/components/Note/DiscussionContent/index.tsx
  2. 3
      src/components/Note/index.tsx
  3. 5
      src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx
  4. 75
      src/pages/primary/DiscussionsPage/index.tsx
  5. 5
      src/services/client.service.ts

47
src/components/Note/DiscussionContent/index.tsx

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
import Markdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { Event } from 'nostr-tools'
import { useMemo } from 'react'
import NostrNode from '../LongFormArticle/NostrNode'
import { remarkNostr } from '../LongFormArticle/remarkNostr'
import { Components } from '../LongFormArticle/types'
export default function DiscussionContent({
event,
className
}: {
event: Event
className?: string
}) {
const components = useMemo(
() =>
({
nostr: (props) => (
<NostrNode
rawText={props.rawText}
bech32Id={props.bech32Id}
/>
),
}) as Components,
[]
)
return (
<div
className={`prose prose-zinc max-w-none dark:prose-invert break-words overflow-wrap-anywhere ${className || ''}`}
>
<Markdown
remarkPlugins={[remarkGfm, remarkNostr]}
urlTransform={(url) => {
if (url.startsWith('nostr:')) {
return url.slice(6) // Remove 'nostr:' prefix for rendering
}
return url
}}
components={components}
>
{event.content}
</Markdown>
</div>
)
}

3
src/components/Note/index.tsx

@ -19,6 +19,7 @@ import UserAvatar from '../UserAvatar' @@ -19,6 +19,7 @@ import UserAvatar from '../UserAvatar'
import Username from '../Username'
import { MessageSquare } from 'lucide-react'
import CommunityDefinition from './CommunityDefinition'
import DiscussionContent from './DiscussionContent'
import GroupMetadata from './GroupMetadata'
import Highlight from './Highlight'
import IValue from './IValue'
@ -97,7 +98,7 @@ export default function Note({ @@ -97,7 +98,7 @@ export default function Note({
content = (
<>
<h3 className="mt-2 text-lg font-semibold leading-tight break-words">{title}</h3>
<Content className="mt-2" event={event} />
<DiscussionContent className="mt-2" event={event} />
</>
)
} else if (event.kind === ExtendedKind.POLL) {

5
src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx

@ -12,6 +12,7 @@ import { useState } from 'react' @@ -12,6 +12,7 @@ import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNostr } from '@/providers/NostrProvider'
import { TDraftEvent } from '@/types'
import { NostrEvent } from 'nostr-tools'
import { prefixNostrAddresses } from '@/lib/nostr-address'
import { showPublishingError } from '@/lib/publishing-feedback'
import dayjs from 'dayjs'
@ -41,7 +42,7 @@ interface CreateThreadDialogProps { @@ -41,7 +42,7 @@ interface CreateThreadDialogProps {
availableRelays: string[]
selectedRelay?: string | null
onClose: () => void
onThreadCreated: () => void
onThreadCreated: (publishedEvent?: NostrEvent) => void
}
export const DISCUSSION_TOPICS = [
@ -206,7 +207,7 @@ export default function CreateThreadDialog({ @@ -206,7 +207,7 @@ export default function CreateThreadDialog({
if (publishedEvent) {
onThreadCreated()
onThreadCreated(publishedEvent)
onClose()
} else {
throw new Error(t('Failed to publish thread'))

75
src/pages/primary/DiscussionsPage/index.tsx

@ -18,6 +18,7 @@ import TopicSubscribeButton from '@/components/TopicSubscribeButton' @@ -18,6 +18,7 @@ import TopicSubscribeButton from '@/components/TopicSubscribeButton'
import { NostrEvent } from 'nostr-tools'
import client from '@/services/client.service'
import noteStatsService from '@/services/note-stats.service'
import storage from '@/services/local-storage.service'
import { useSecondaryPage } from '@/PageManager'
import { toNote } from '@/lib/link'
import { kinds } from 'nostr-tools'
@ -60,20 +61,56 @@ const DiscussionsPage = forwardRef((_, ref) => { @@ -60,20 +61,56 @@ const DiscussionsPage = forwardRef((_, ref) => {
[pubkey, favoriteRelays]
)
// Memoize relay URLs with deduplication
const relayUrls = useMemo(() => {
// State for relay URLs
const [relayUrls, setRelayUrls] = useState<string[]>([])
// Update relay URLs when dependencies change
useEffect(() => {
const updateRelayUrls = async () => {
if (selectedRelay) {
// Check if it's a relay set
const relaySet = relaySets.find(set => set.id === selectedRelay)
if (relaySet) {
return relaySet.relayUrls
setRelayUrls(relaySet.relayUrls)
return
}
// It's an individual relay
return [selectedRelay]
setRelayUrls([selectedRelay])
return
}
// For "All Relays", include user's write relays and stored relay sets too
let userWriteRelays: string[] = []
let storedRelaySetRelays: string[] = []
if (pubkey) {
try {
// Get user's write relays
const relayList = await client.fetchRelayList(pubkey)
userWriteRelays = relayList?.write || []
// Get relays from stored relay sets (additional safety check)
// Note: favoriteRelays should already include these, but let's be thorough
const storedRelaySets = storage.getRelaySets()
storedRelaySetRelays = storedRelaySets.flatMap(set => set.relayUrls)
} catch (error) {
console.warn('Failed to fetch user relay list:', error)
}
// Deduplicate and combine relays
return Array.from(new Set([...availableRelays, ...FAST_READ_RELAY_URLS]))
}, [selectedRelay, availableRelays, relaySets])
}
// Deduplicate and combine all relays: favorite relays, user write relays, stored relay sets, and fast read relays
const allRelays = Array.from(new Set([
...availableRelays,
...userWriteRelays,
...storedRelaySetRelays,
...FAST_READ_RELAY_URLS
]))
setRelayUrls(allRelays)
}
updateRelayUrls()
}, [selectedRelay, availableRelays, relaySets, pubkey, favoriteRelays])
// Available topic IDs for matching
const availableTopicIds = useMemo(() =>
@ -451,9 +488,29 @@ const DiscussionsPage = forwardRef((_, ref) => { @@ -451,9 +488,29 @@ const DiscussionsPage = forwardRef((_, ref) => {
setShowCreateThread(true)
}
const handleThreadCreated = () => {
const handleThreadCreated = (publishedEvent?: NostrEvent) => {
setShowCreateThread(false)
fetchAllThreads() // Refresh all threads
if (publishedEvent) {
// Optimistically add the new thread to the local state
setAllThreads(prev => {
// Check if the thread is already in the list (avoid duplicates)
if (prev.some(thread => thread.id === publishedEvent.id)) {
return prev
}
// Add relay source info
const eventHints = client.getEventHints(publishedEvent.id)
const relaySource = eventHints.length > 0 ? eventHints[0] : 'unknown'
const newThread = { ...publishedEvent, _relaySource: relaySource }
// Add the new thread at the beginning (newest first)
return [newThread, ...prev]
})
} else {
// Fallback: refresh all threads if no published event provided
fetchAllThreads()
}
}
return (

5
src/services/client.service.ts

@ -1768,8 +1768,9 @@ class ClientService extends EventTarget { @@ -1768,8 +1768,9 @@ class ClientService extends EventTarget {
}
})
// Limit to 3 relays to prevent "too many concurrent REQs" errors
return validRelays.slice(0, 3)
// Limit to 8 relays to prevent "too many concurrent REQs" errors
// Increased from 3 to 8 for discussions to include more relay sources
return validRelays.slice(0, 8)
}
// ================= Utils =================

Loading…
Cancel
Save