diff --git a/src/components/ContentPreview/index.tsx b/src/components/ContentPreview/index.tsx
index 9da3db9..2c90fac 100644
--- a/src/components/ContentPreview/index.tsx
+++ b/src/components/ContentPreview/index.tsx
@@ -15,6 +15,7 @@ import NormalContentPreview from './NormalContentPreview'
import PictureNotePreview from './PictureNotePreview'
import PollPreview from './PollPreview'
import VideoNotePreview from './VideoNotePreview'
+import DiscussionNote from '../DiscussionNote'
export default function ContentPreview({
event,
@@ -69,6 +70,10 @@ export default function ContentPreview({
return
}
+ if (event.kind === ExtendedKind.DISCUSSION) {
+ return
+ }
+
if (event.kind === kinds.Highlights) {
return
}
diff --git a/src/components/Note/index.tsx b/src/components/Note/index.tsx
index 5cf7c2c..3e870ec 100644
--- a/src/components/Note/index.tsx
+++ b/src/components/Note/index.tsx
@@ -87,6 +87,8 @@ export default function Note({
content =
} else if (event.kind === kinds.CommunityDefinition) {
content =
+ } else if (event.kind === ExtendedKind.DISCUSSION) {
+ content =
} else if (event.kind === ExtendedKind.POLL) {
content = (
<>
diff --git a/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx b/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx
index 1a01b7b..8056d00 100644
--- a/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx
+++ b/src/pages/primary/DiscussionsPage/CreateThreadDialog.tsx
@@ -151,12 +151,22 @@ export default function CreateThreadDialog({
created_at: dayjs().unix()
}
+ console.log('Creating kind 11 thread event:', {
+ kind: threadEvent.kind,
+ content: threadEvent.content.substring(0, 50) + '...',
+ tags: threadEvent.tags,
+ selectedRelay,
+ minPow
+ })
+
// Publish to the selected relay only
const publishedEvent = await publish(threadEvent, {
specifiedRelayUrls: [selectedRelay],
minPow
})
+ console.log('Published event result:', publishedEvent)
+
if (publishedEvent) {
onThreadCreated()
onClose()
@@ -165,7 +175,26 @@ export default function CreateThreadDialog({
}
} catch (error) {
console.error('Error creating thread:', error)
- alert(t('Failed to create thread. Please try again.'))
+ console.error('Error details:', {
+ name: error instanceof Error ? error.name : 'Unknown',
+ message: error instanceof Error ? error.message : String(error),
+ stack: error instanceof Error ? error.stack : undefined
+ })
+
+ let errorMessage = t('Failed to create thread')
+ if (error instanceof Error) {
+ if (error.message.includes('auth-required') || error.message.includes('auth required')) {
+ errorMessage = t('Relay requires authentication for write access. Please try a different relay or contact the relay operator.')
+ } else if (error.message.includes('blocked')) {
+ errorMessage = t('Your account is blocked from posting to this relay.')
+ } else if (error.message.includes('rate limit')) {
+ errorMessage = t('Rate limited. Please wait before trying again.')
+ } else {
+ errorMessage = `${t('Failed to create thread')}: ${error.message}`
+ }
+ }
+
+ alert(errorMessage)
} finally {
setIsSubmitting(false)
}
diff --git a/src/pages/primary/DiscussionsPage/ThreadCard.tsx b/src/pages/primary/DiscussionsPage/ThreadCard.tsx
index 5fea21c..727592a 100644
--- a/src/pages/primary/DiscussionsPage/ThreadCard.tsx
+++ b/src/pages/primary/DiscussionsPage/ThreadCard.tsx
@@ -8,6 +8,7 @@ import { useTranslation } from 'react-i18next'
import { cn } from '@/lib/utils'
import { truncateText } from '@/lib/utils'
import { DISCUSSION_TOPICS } from './CreateThreadDialog'
+import Username from '@/components/Username'
interface ThreadWithRelaySource extends NostrEvent {
_relaySource?: string
@@ -105,9 +106,11 @@ export default function ThreadCard({ thread, onThreadClick, className }: ThreadC
-
- {thread.pubkey.slice(0, 8)}...{thread.pubkey.slice(-8)}
-
+
{t('Read more')}
diff --git a/src/pages/primary/DiscussionsPage/TopicFilter.tsx b/src/pages/primary/DiscussionsPage/TopicFilter.tsx
index 6213052..9c57414 100644
--- a/src/pages/primary/DiscussionsPage/TopicFilter.tsx
+++ b/src/pages/primary/DiscussionsPage/TopicFilter.tsx
@@ -1,8 +1,9 @@
import { Button } from '@/components/ui/button'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
-import { ChevronDown } from 'lucide-react'
+import { ChevronDown, Grid3X3 } from 'lucide-react'
import { NostrEvent } from 'nostr-tools'
import { useMemo } from 'react'
+import { useTranslation } from 'react-i18next'
interface Topic {
id: string
@@ -19,6 +20,8 @@ interface TopicFilterProps {
}
export default function TopicFilter({ topics, selectedTopic, onTopicChange, threads, replies }: TopicFilterProps) {
+ const { t } = useTranslation()
+
// Sort topics by activity (most recent kind 11 or kind 1111 events first)
const sortedTopics = useMemo(() => {
const allEvents = [...threads, ...replies]
@@ -47,7 +50,12 @@ export default function TopicFilter({ topics, selectedTopic, onTopicChange, thre
})
}, [topics, threads, replies])
- const selectedTopicInfo = sortedTopics.find(topic => topic.id === selectedTopic) || sortedTopics[0]
+ // Create all topics option
+ const allTopicsOption = { id: 'all', label: t('All Topics'), icon: Grid3X3 }
+
+ const selectedTopicInfo = selectedTopic === 'all'
+ ? allTopicsOption
+ : sortedTopics.find(topic => topic.id === selectedTopic) || sortedTopics[0]
return (
@@ -57,11 +65,22 @@ export default function TopicFilter({ topics, selectedTopic, onTopicChange, thre
className="flex items-center gap-2 h-10 px-3 min-w-44"
>
- {selectedTopicInfo.id}
+ {selectedTopicInfo.label}
+ onTopicChange('all')}
+ className="flex items-center gap-2"
+ >
+
+ {t('All Topics')}
+ {selectedTopic === 'all' && (
+ ✓
+ )}
+
{sortedTopics.map(topic => (
{
const relayUrls = selectedRelay ? [selectedRelay] : availableRelays
// Fetch all kind 11 events (limit 100, newest first) with relay source tracking
+ console.log('Fetching kind 11 events from relays:', relayUrls)
const events = await client.fetchEvents(relayUrls, [
{
kinds: [11], // Thread events
- '#-': ['-'], // Must have the "-" tag for relay privacy
limit: 100
}
])
+ console.log('Fetched kind 11 events:', events.length, events.map(e => ({ id: e.id, title: e.tags.find(t => t[0] === 'title')?.[1], pubkey: e.pubkey })))
// Filter and sort threads, adding relay source information
const validThreads = events
@@ -99,14 +100,20 @@ const DiscussionsPage = forwardRef((_, ref) => {
}
})
- // Filter threads for the selected topic
- const threadsForTopic = categorizedThreads
- .filter(thread => thread._categorizedTopic === selectedTopic)
- .map(thread => {
- // Remove the temporary categorization property but keep relay source
- const { _categorizedTopic, ...cleanThread } = thread
- return cleanThread
- })
+ // Filter threads for the selected topic (or show all if "all" is selected)
+ const threadsForTopic = selectedTopic === 'all'
+ ? categorizedThreads.map(thread => {
+ // Remove the temporary categorization property but keep relay source
+ const { _categorizedTopic, ...cleanThread } = thread
+ return cleanThread
+ })
+ : categorizedThreads
+ .filter(thread => thread._categorizedTopic === selectedTopic)
+ .map(thread => {
+ // Remove the temporary categorization property but keep relay source
+ const { _categorizedTopic, ...cleanThread } = thread
+ return cleanThread
+ })
setThreads(threadsForTopic)
}
@@ -166,7 +173,7 @@ const DiscussionsPage = forwardRef((_, ref) => {
- {t('Discussions')} - {DISCUSSION_TOPICS.find(t => t.id === selectedTopic)?.label}
+ {t('Discussions')} - {selectedTopic === 'all' ? t('All Topics') : DISCUSSION_TOPICS.find(t => t.id === selectedTopic)?.label}
@@ -180,12 +187,20 @@ const DiscussionsPage = forwardRef((_, ref) => {
{t('No threads yet')}
- {t('Be the first to start a discussion in this topic!')}
+ {selectedTopic === 'all'
+ ? t('No discussion threads found. Try refreshing or check your relay connection.')
+ : t('Be the first to start a discussion in this topic!')
+ }
-
-
- {t('Create Thread')}
-
+
+
+
+ {t('Create Thread')}
+
+
+ {t('Refresh')}
+
+
) : (