Browse Source

fix relay selector for discussions

imwald
Silberengel 5 months ago
parent
commit
9f2e5f1e1f
  1. 44
      src/components/PostEditor/PostRelaySelector.tsx
  2. 54
      src/services/client.service.ts

44
src/components/PostEditor/PostRelaySelector.tsx

@ -8,6 +8,9 @@ import {
DropdownMenuTrigger DropdownMenuTrigger
} from '@/components/ui/dropdown-menu' } from '@/components/ui/dropdown-menu'
import { Separator } from '@/components/ui/separator' import { Separator } from '@/components/ui/separator'
import { ExtendedKind } from '@/constants'
import client from '@/services/client.service'
import { isWebsocketUrl, normalizeUrl } from '@/lib/url'
import { simplifyUrl } from '@/lib/url' import { simplifyUrl } from '@/lib/url'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider' import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider' import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
@ -92,9 +95,46 @@ export default function PostRelaySelector({
setPostTargetItems(Array.from(new Set(openFrom)).map((url) => ({ type: 'relay', url }))) setPostTargetItems(Array.from(new Set(openFrom)).map((url) => ({ type: 'relay', url })))
return return
} }
// Privacy: Default to write relays, never parent event's relays
// Check if we're replying to a discussion or comment that requires specific relay routing
if (_parentEvent && (_parentEvent.kind === ExtendedKind.DISCUSSION || _parentEvent.kind === ExtendedKind.COMMENT)) {
let relayHint: string | undefined
if (_parentEvent.kind === ExtendedKind.COMMENT) {
// For kind 1111 (COMMENT): look for 'E' tag which points to the root event
const ETag = _parentEvent.tags.find(tag => tag[0] === 'E')
if (ETag && ETag[2]) {
relayHint = ETag[2] // Relay hint is the 3rd element
}
// If no 'E' tag, check lowercase 'e' tag for parent event
if (!relayHint) {
const eTag = _parentEvent.tags.find(tag => tag[0] === 'e')
if (eTag && eTag[2]) {
relayHint = eTag[2]
}
}
} else if (_parentEvent.kind === ExtendedKind.DISCUSSION) {
// For kind 11 (DISCUSSION): get relay hint from where it was found
const eventHints = client.getEventHints(_parentEvent.id)
if (eventHints.length > 0) {
relayHint = eventHints[0]
}
}
// If we found a valid relay hint, use it instead of write relays
if (relayHint && isWebsocketUrl(relayHint)) {
const normalizedRelayHint = normalizeUrl(relayHint)
if (normalizedRelayHint) {
setPostTargetItems([{ type: 'relay', url: normalizedRelayHint }])
return
}
}
}
// Default to write relays for all other cases
setPostTargetItems([{ type: 'writeRelays' }]) setPostTargetItems([{ type: 'writeRelays' }])
}, [openFrom]) }, [openFrom, _parentEvent])
useEffect(() => { useEffect(() => {
const isProtectedEvent = postTargetItems.every((item) => item.type !== 'writeRelays') const isProtectedEvent = postTargetItems.every((item) => item.type !== 'writeRelays')

54
src/services/client.service.ts

@ -97,7 +97,59 @@ class ClientService extends EventTarget {
// Check if this is a discussion thread or reply to a discussion // Check if this is a discussion thread or reply to a discussion
const isDiscussionRelated = event.kind === ExtendedKind.DISCUSSION || const isDiscussionRelated = event.kind === ExtendedKind.DISCUSSION ||
event.tags.some(tag => tag[0] === 'k' && tag[1] === '11') event.tags.some(tag => tag[0] === 'k' && tag[1] === String(ExtendedKind.DISCUSSION))
// Special handling for kind 11 (DISCUSSION) and kind 1111 (COMMENT/NIP-22)
// These should only be published to the relay where the original event was found
// or to the relay hint specified in the event tags
if (event.kind === ExtendedKind.DISCUSSION || event.kind === ExtendedKind.COMMENT) {
let rootEventId: string | undefined
let relayHint: string | undefined
if (event.kind === ExtendedKind.COMMENT) {
// Kind 1111 (NIP-22 Comment): look for 'E' tag which points to the root event
// Format: ["E", "<id>", "<relay hint>", "<root pubkey>"]
const ETag = event.tags.find(tag => tag[0] === 'E')
if (ETag) {
rootEventId = ETag[1]
relayHint = ETag[2] // Relay hint is the 3rd element
}
// If no 'E' tag, check lowercase 'e' tag for parent event
// This handles cases where we're replying to a reply
if (!rootEventId) {
const eTag = event.tags.find(tag => tag[0] === 'e')
if (eTag) {
rootEventId = eTag[1]
relayHint = eTag[2]
}
}
} else if (event.kind === ExtendedKind.DISCUSSION) {
// Kind 11 (DISCUSSION): this is the root event itself
// For new root events, we can use the specified relays or fall through to normal handling
// But for replies TO kind 11, we should have caught them as kind 1111 above
rootEventId = event.id
}
// Priority 1: Use relay hint from the tag if present and valid
if (relayHint && isWebsocketUrl(relayHint)) {
const normalizedRelayHint = normalizeUrl(relayHint)
if (normalizedRelayHint) {
relays = [normalizedRelayHint]
return relays
}
}
// Priority 2: Get relay where the root event was found
if (rootEventId) {
const originalEventRelays = this.getEventHints(rootEventId)
if (originalEventRelays.length > 0) {
// Only publish to the relay(s) where the original event was found
relays = originalEventRelays.slice(0, 1) // Use only the first relay for insular discussions
return relays
}
}
}
// Publish to mentioned users' inboxes for all events EXCEPT discussions // Publish to mentioned users' inboxes for all events EXCEPT discussions
if (!isDiscussionRelated) { if (!isDiscussionRelated) {

Loading…
Cancel
Save