mirror of
https://github.com/dergigi/boris.git
synced 2025-12-24 01:54:19 +01:00
feat: add bookmark loading and decryption section to debug page
This commit is contained in:
@@ -170,7 +170,7 @@ function AppRoutes({
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route path="/debug" element={<Debug />} />
|
||||
<Route path="/debug" element={<Debug relayPool={relayPool} />} />
|
||||
<Route path="/" element={<Navigate to={`/a/${DEFAULT_ARTICLE}`} replace />} />
|
||||
</Routes>
|
||||
)
|
||||
|
||||
@@ -4,13 +4,22 @@ import { faClock, faSpinner } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Hooks } from 'applesauce-react'
|
||||
import { Accounts } from 'applesauce-accounts'
|
||||
import { NostrConnectSigner } from 'applesauce-signers'
|
||||
import { RelayPool } from 'applesauce-relay'
|
||||
import { getDefaultBunkerPermissions } from '../services/nostrConnect'
|
||||
import { DebugBus, type DebugLogEntry } from '../utils/debugBus'
|
||||
import VersionFooter from './VersionFooter'
|
||||
import { queryEvents } from '../services/dataFetch'
|
||||
import { KINDS } from '../config/kinds'
|
||||
import { collectBookmarksFromEvents } from '../services/bookmarkProcessing'
|
||||
import type { NostrEvent } from '../services/bookmarkHelpers'
|
||||
|
||||
const defaultPayload = 'The quick brown fox jumps over the lazy dog.'
|
||||
|
||||
const Debug: React.FC = () => {
|
||||
interface DebugProps {
|
||||
relayPool?: RelayPool | null
|
||||
}
|
||||
|
||||
const Debug: React.FC<DebugProps> = ({ relayPool }) => {
|
||||
const activeAccount = Hooks.useActiveAccount()
|
||||
const accountManager = Hooks.useAccountManager()
|
||||
const [payload, setPayload] = useState<string>(defaultPayload)
|
||||
@@ -30,6 +39,12 @@ const Debug: React.FC = () => {
|
||||
const [isBunkerLoading, setIsBunkerLoading] = useState<boolean>(false)
|
||||
const [bunkerError, setBunkerError] = useState<string | null>(null)
|
||||
|
||||
// Bookmark loading state
|
||||
const [bookmarkEvents, setBookmarkEvents] = useState<NostrEvent[]>([])
|
||||
const [isLoadingBookmarks, setIsLoadingBookmarks] = useState(false)
|
||||
const [isDecryptingBookmarks, setIsDecryptingBookmarks] = useState(false)
|
||||
const [bookmarkStats, setBookmarkStats] = useState<{ public: number; private: number } | null>(null)
|
||||
|
||||
// Live timing state
|
||||
const [liveTiming, setLiveTiming] = useState<{
|
||||
nip44?: { type: 'encrypt' | 'decrypt'; startTime: number }
|
||||
@@ -123,6 +138,70 @@ const Debug: React.FC = () => {
|
||||
else localStorage.removeItem('debug')
|
||||
}
|
||||
|
||||
const handleLoadBookmarks = async () => {
|
||||
if (!relayPool || !activeAccount) {
|
||||
DebugBus.warn('debug', 'Cannot load bookmarks: missing relayPool or activeAccount')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setIsLoadingBookmarks(true)
|
||||
setBookmarkStats(null)
|
||||
DebugBus.info('debug', 'Loading bookmark events...')
|
||||
|
||||
const rawEvents = await queryEvents(
|
||||
relayPool,
|
||||
{ kinds: [KINDS.ListSimple, KINDS.ListReplaceable, KINDS.List, KINDS.WebBookmark], authors: [activeAccount.pubkey] },
|
||||
{}
|
||||
)
|
||||
|
||||
setBookmarkEvents(rawEvents)
|
||||
DebugBus.info('debug', `Loaded ${rawEvents.length} bookmark events`, {
|
||||
kinds: rawEvents.map(e => e.kind).join(', ')
|
||||
})
|
||||
} catch (error) {
|
||||
DebugBus.error('debug', 'Failed to load bookmarks', error instanceof Error ? error.message : String(error))
|
||||
} finally {
|
||||
setIsLoadingBookmarks(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDecryptBookmarks = async () => {
|
||||
if (!activeAccount || bookmarkEvents.length === 0) {
|
||||
DebugBus.warn('debug', 'Cannot decrypt: missing activeAccount or no bookmark events loaded')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setIsDecryptingBookmarks(true)
|
||||
DebugBus.info('debug', 'Decrypting bookmark events...')
|
||||
|
||||
const fullAccount = accountManager.getActive()
|
||||
const signerCandidate = fullAccount || activeAccount
|
||||
|
||||
const { publicItemsAll, privateItemsAll } = await collectBookmarksFromEvents(
|
||||
bookmarkEvents,
|
||||
activeAccount,
|
||||
signerCandidate
|
||||
)
|
||||
|
||||
setBookmarkStats({
|
||||
public: publicItemsAll.length,
|
||||
private: privateItemsAll.length
|
||||
})
|
||||
|
||||
DebugBus.info('debug', `Decryption complete`, {
|
||||
public: publicItemsAll.length,
|
||||
private: privateItemsAll.length,
|
||||
total: publicItemsAll.length + privateItemsAll.length
|
||||
})
|
||||
} catch (error) {
|
||||
DebugBus.error('debug', 'Failed to decrypt bookmarks', error instanceof Error ? error.message : String(error))
|
||||
} finally {
|
||||
setIsDecryptingBookmarks(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleBunkerLogin = async () => {
|
||||
if (!bunkerUri.trim()) {
|
||||
setBunkerError('Please enter a bunker URI')
|
||||
@@ -350,6 +429,68 @@ const Debug: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bookmark Loading Section */}
|
||||
<div className="settings-section">
|
||||
<h3 className="section-title">Bookmark Loading</h3>
|
||||
<div className="text-sm opacity-70 mb-3">Test bookmark loading and decryption (kinds: 10003, 30003, 30001, 39701)</div>
|
||||
|
||||
<div className="flex gap-2 mb-3">
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={handleLoadBookmarks}
|
||||
disabled={isLoadingBookmarks || !relayPool || !activeAccount}
|
||||
>
|
||||
{isLoadingBookmarks ? (
|
||||
<>
|
||||
<FontAwesomeIcon icon={faSpinner} className="animate-spin mr-2" />
|
||||
Loading...
|
||||
</>
|
||||
) : (
|
||||
'Load Bookmarks'
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={handleDecryptBookmarks}
|
||||
disabled={isDecryptingBookmarks || bookmarkEvents.length === 0}
|
||||
>
|
||||
{isDecryptingBookmarks ? (
|
||||
<>
|
||||
<FontAwesomeIcon icon={faSpinner} className="animate-spin mr-2" />
|
||||
Decrypting...
|
||||
</>
|
||||
) : (
|
||||
'Decrypt'
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{bookmarkEvents.length > 0 && (
|
||||
<div className="mb-3">
|
||||
<div className="text-sm opacity-70 mb-2">Loaded Events:</div>
|
||||
<div className="font-mono text-xs p-2 bg-gray-100 dark:bg-gray-800 rounded">
|
||||
{bookmarkEvents.length} event{bookmarkEvents.length !== 1 ? 's' : ''} found
|
||||
{bookmarkEvents.length > 0 && (
|
||||
<div className="mt-1">
|
||||
Kinds: {Array.from(new Set(bookmarkEvents.map(e => e.kind))).join(', ')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bookmarkStats && (
|
||||
<div className="mb-3">
|
||||
<div className="text-sm opacity-70 mb-2">Decrypted Bookmarks:</div>
|
||||
<div className="font-mono text-xs p-2 bg-gray-100 dark:bg-gray-800 rounded">
|
||||
<div>Public: {bookmarkStats.public}</div>
|
||||
<div>Private: {bookmarkStats.private}</div>
|
||||
<div className="font-semibold mt-1">Total: {bookmarkStats.public + bookmarkStats.private}</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