mirror of
https://github.com/dergigi/boris.git
synced 2025-12-31 05:24:36 +01:00
feat: add debug buttons for highlight loading and Web of Trust
- Add three quick-load buttons: Load My Highlights, Load Friends Highlights, Load Nostrverse Highlights - Add Web of Trust section with Load Friends button to display followed npubs - Stream highlights with dedupe and timing metrics - Display friends count and scrollable list of npubs - All buttons respect loading states and account requirements
This commit is contained in:
@@ -8,6 +8,7 @@ import { Accounts } from 'applesauce-accounts'
|
||||
import { NostrConnectSigner } from 'applesauce-signers'
|
||||
import { RelayPool } from 'applesauce-relay'
|
||||
import { Helpers } from 'applesauce-core'
|
||||
import { nip19 } from 'nostr-tools'
|
||||
import { getDefaultBunkerPermissions } from '../services/nostrConnect'
|
||||
import { DebugBus, type DebugLogEntry } from '../utils/debugBus'
|
||||
import ThreePaneLayout from './ThreePaneLayout'
|
||||
@@ -16,6 +17,9 @@ import type { NostrEvent } from '../services/bookmarkHelpers'
|
||||
import { Bookmark } from '../types/bookmarks'
|
||||
import { useBookmarksUI } from '../hooks/useBookmarksUI'
|
||||
import { useSettings } from '../hooks/useSettings'
|
||||
import { fetchHighlights, fetchHighlightsFromAuthors } from '../services/highlightService'
|
||||
import { fetchNostrverseHighlights } from '../services/nostrverseService'
|
||||
import { fetchContacts } from '../services/contactService'
|
||||
|
||||
const defaultPayload = 'The quick brown fox jumps over the lazy dog.'
|
||||
|
||||
@@ -99,6 +103,10 @@ const Debug: React.FC<DebugProps> = ({
|
||||
decryptBookmarks?: { startTime: number }
|
||||
loadHighlights?: { startTime: number }
|
||||
}>({})
|
||||
|
||||
// Web of Trust state
|
||||
const [friendsPubkeys, setFriendsPubkeys] = useState<Set<string>>(new Set())
|
||||
const [friendsLoading, setFriendsLoading] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
return DebugBus.subscribe((e) => setLogs(prev => [...prev, e].slice(-300)))
|
||||
@@ -420,6 +428,119 @@ const Debug: React.FC<DebugProps> = ({
|
||||
DebugBus.info('debug', 'Cleared highlight data')
|
||||
}
|
||||
|
||||
const handleLoadMyHighlights = async () => {
|
||||
if (!relayPool || !activeAccount?.pubkey) {
|
||||
DebugBus.warn('debug', 'Please log in to load your highlights')
|
||||
return
|
||||
}
|
||||
const start = performance.now()
|
||||
setHighlightEvents([])
|
||||
setIsLoadingHighlights(true)
|
||||
setTLoadHighlights(null)
|
||||
setTFirstHighlight(null)
|
||||
DebugBus.info('debug', 'Loading my highlights...')
|
||||
try {
|
||||
let firstEventTime: number | null = null
|
||||
await fetchHighlights(relayPool, activeAccount.pubkey, (h) => {
|
||||
if (firstEventTime === null) {
|
||||
firstEventTime = performance.now() - start
|
||||
setTFirstHighlight(Math.round(firstEventTime))
|
||||
}
|
||||
setHighlightEvents(prev => {
|
||||
if (prev.some(x => x.id === h.id)) return prev
|
||||
const next = [...prev, { ...h, pubkey: h.pubkey, created_at: h.created_at, id: h.id, kind: 9802, tags: [], content: h.content, sig: '' } as NostrEvent]
|
||||
return next.sort((a, b) => b.created_at - a.created_at)
|
||||
})
|
||||
}, settings)
|
||||
} finally {
|
||||
setIsLoadingHighlights(false)
|
||||
const elapsed = Math.round(performance.now() - start)
|
||||
setTLoadHighlights(elapsed)
|
||||
DebugBus.info('debug', `Loaded my highlights in ${elapsed}ms`)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoadFriendsHighlights = async () => {
|
||||
if (!relayPool || !activeAccount?.pubkey) {
|
||||
DebugBus.warn('debug', 'Please log in to load friends highlights')
|
||||
return
|
||||
}
|
||||
const start = performance.now()
|
||||
setHighlightEvents([])
|
||||
setIsLoadingHighlights(true)
|
||||
setTLoadHighlights(null)
|
||||
setTFirstHighlight(null)
|
||||
DebugBus.info('debug', 'Loading friends highlights...')
|
||||
try {
|
||||
const contacts = await fetchContacts(relayPool, activeAccount.pubkey)
|
||||
DebugBus.info('debug', `Found ${contacts.size} friends`)
|
||||
let firstEventTime: number | null = null
|
||||
await fetchHighlightsFromAuthors(relayPool, Array.from(contacts), (h) => {
|
||||
if (firstEventTime === null) {
|
||||
firstEventTime = performance.now() - start
|
||||
setTFirstHighlight(Math.round(firstEventTime))
|
||||
}
|
||||
setHighlightEvents(prev => {
|
||||
if (prev.some(x => x.id === h.id)) return prev
|
||||
const next = [...prev, { ...h, pubkey: h.pubkey, created_at: h.created_at, id: h.id, kind: 9802, tags: [], content: h.content, sig: '' } as NostrEvent]
|
||||
return next.sort((a, b) => b.created_at - a.created_at)
|
||||
})
|
||||
})
|
||||
} finally {
|
||||
setIsLoadingHighlights(false)
|
||||
const elapsed = Math.round(performance.now() - start)
|
||||
setTLoadHighlights(elapsed)
|
||||
DebugBus.info('debug', `Loaded friends highlights in ${elapsed}ms`)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoadNostrverseHighlights = async () => {
|
||||
if (!relayPool) {
|
||||
DebugBus.warn('debug', 'Relay pool not available')
|
||||
return
|
||||
}
|
||||
const start = performance.now()
|
||||
setHighlightEvents([])
|
||||
setIsLoadingHighlights(true)
|
||||
setTLoadHighlights(null)
|
||||
setTFirstHighlight(null)
|
||||
DebugBus.info('debug', 'Loading nostrverse highlights...')
|
||||
try {
|
||||
const all = await fetchNostrverseHighlights(relayPool, 100)
|
||||
setHighlightEvents(all.map(h => ({ ...h, pubkey: h.pubkey, created_at: h.created_at, id: h.id, kind: 9802, tags: [], content: h.content, sig: '' } as NostrEvent)))
|
||||
} finally {
|
||||
setIsLoadingHighlights(false)
|
||||
const elapsed = Math.round(performance.now() - start)
|
||||
setTLoadHighlights(elapsed)
|
||||
DebugBus.info('debug', `Loaded nostrverse highlights in ${elapsed}ms`)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoadFriendsList = async () => {
|
||||
if (!relayPool || !activeAccount?.pubkey) {
|
||||
DebugBus.warn('debug', 'Please log in to load friends list')
|
||||
return
|
||||
}
|
||||
setFriendsLoading(true)
|
||||
setFriendsPubkeys(new Set())
|
||||
DebugBus.info('debug', 'Loading friends list...')
|
||||
try {
|
||||
const final = await fetchContacts(
|
||||
relayPool,
|
||||
activeAccount.pubkey,
|
||||
(partial) => setFriendsPubkeys(new Set(partial))
|
||||
)
|
||||
setFriendsPubkeys(new Set(final))
|
||||
DebugBus.info('debug', `Loaded ${final.size} friends`)
|
||||
} finally {
|
||||
setFriendsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const friendsNpubs = useMemo(() => {
|
||||
return Array.from(friendsPubkeys).map(pk => nip19.npubEncode(pk))
|
||||
}, [friendsPubkeys])
|
||||
|
||||
const handleBunkerLogin = async () => {
|
||||
if (!bunkerUri.trim()) {
|
||||
setBunkerError('Please enter a bunker URI')
|
||||
@@ -845,6 +966,31 @@ const Debug: React.FC<DebugProps> = ({
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="mb-3 text-sm opacity-70">Quick load options:</div>
|
||||
<div className="flex gap-2 mb-3 flex-wrap">
|
||||
<button
|
||||
className="btn btn-secondary text-sm"
|
||||
onClick={handleLoadMyHighlights}
|
||||
disabled={isLoadingHighlights || !relayPool || !activeAccount}
|
||||
>
|
||||
Load My Highlights
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-secondary text-sm"
|
||||
onClick={handleLoadFriendsHighlights}
|
||||
disabled={isLoadingHighlights || !relayPool || !activeAccount}
|
||||
>
|
||||
Load Friends Highlights
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-secondary text-sm"
|
||||
onClick={handleLoadNostrverseHighlights}
|
||||
disabled={isLoadingHighlights || !relayPool}
|
||||
>
|
||||
Load Nostrverse Highlights
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="mb-3 flex gap-2 flex-wrap">
|
||||
<Stat label="total" value={tLoadHighlights} bookmarkOp="loadHighlights" />
|
||||
<Stat label="first event" value={tFirstHighlight} />
|
||||
@@ -890,6 +1036,42 @@ const Debug: React.FC<DebugProps> = ({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Web of Trust Section */}
|
||||
<div className="settings-section">
|
||||
<h3 className="section-title">Web of Trust</h3>
|
||||
<div className="text-sm opacity-70 mb-3">Load your followed contacts (friends) for highlight fetching:</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={handleLoadFriendsList}
|
||||
disabled={friendsLoading || !relayPool || !activeAccount}
|
||||
>
|
||||
{friendsLoading ? (
|
||||
<>
|
||||
<FontAwesomeIcon icon={faSpinner} className="animate-spin mr-2" />
|
||||
Loading...
|
||||
</>
|
||||
) : (
|
||||
'Load Friends'
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{friendsPubkeys.size > 0 && (
|
||||
<div className="mb-3">
|
||||
<div className="text-sm opacity-70 mb-2">Friends Count: {friendsNpubs.length}</div>
|
||||
<div className="font-mono text-xs max-h-48 overflow-y-auto bg-gray-100 dark:bg-gray-800 p-3 rounded space-y-1">
|
||||
{friendsNpubs.map(npub => (
|
||||
<div key={npub} title={npub} className="truncate hover:text-clip hover:whitespace-normal cursor-pointer">
|
||||
{npub}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Debug Logs Section */}
|
||||
<div className="settings-section">
|
||||
<h3 className="section-title">Debug Logs</h3>
|
||||
|
||||
Reference in New Issue
Block a user