From 64457460eb35d1dd96717cf01c02a37cc386b8c5 Mon Sep 17 00:00:00 2001 From: syui Date: Thu, 15 Jan 2026 17:28:04 +0900 Subject: [PATCH] add delete --- src/components/atbrowser.ts | 41 ++++++++++++++++++++++++++++++++++--- src/lib/auth.ts | 16 +++++++++++++++ src/main.ts | 3 ++- src/styles/main.css | 27 ++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/src/components/atbrowser.ts b/src/components/atbrowser.ts index 1723a17..c950e1e 100644 --- a/src/components/atbrowser.ts +++ b/src/components/atbrowser.ts @@ -1,4 +1,5 @@ import { describeRepo, listRecordsRaw, getRecordRaw, fetchLexicon, resolveHandle, getServiceInfo } from '../lib/api.js' +import { deleteRecord } from '../lib/auth.js' function extractRkey(uri: string): string { const parts = uri.split('/') @@ -82,7 +83,7 @@ async function renderRecordList(did: string, handle: string, collection: string) ` } -async function renderRecordDetail(did: string, handle: string, collection: string, rkey: string): Promise { +async function renderRecordDetail(did: string, handle: string, collection: string, rkey: string, canDelete: boolean): Promise { const record = await getRecordRaw(did, collection, rkey) if (!record) { @@ -94,6 +95,10 @@ async function renderRecordDetail(did: string, handle: string, collection: strin const schemaLabel = lexicon ? '✓ Schema' : '○ No schema' const json = JSON.stringify(record, null, 2) + const deleteBtn = canDelete + ? `` + : '' + return `
@@ -101,6 +106,7 @@ async function renderRecordDetail(did: string, handle: string, collection: strin

${record.uri}

CID: ${record.cid}

${schemaLabel} + ${deleteBtn}
${escapeHtml(json)}
@@ -113,19 +119,21 @@ export async function mountAtBrowser( container: HTMLElement, handle: string, collection: string | null, - rkey: string | null + rkey: string | null, + loginDid: string | null = null ): Promise { container.innerHTML = '

Loading...

' try { const did = handle.startsWith('did:') ? handle : await resolveHandle(handle) + const canDelete = loginDid !== null && loginDid === did let content: string let nav = '' if (collection && rkey) { nav = `← Back` - content = await renderRecordDetail(did, handle, collection, rkey) + content = await renderRecordDetail(did, handle, collection, rkey, canDelete) } else if (collection) { nav = `← Collections` content = await renderRecordList(did, handle, collection) @@ -134,6 +142,33 @@ export async function mountAtBrowser( } container.innerHTML = nav + content + + // Add delete button handler + const deleteBtn = container.querySelector('.delete-btn') + if (deleteBtn) { + deleteBtn.addEventListener('click', async (e) => { + e.preventDefault() + const btn = e.target as HTMLButtonElement + const col = btn.dataset.collection + const rk = btn.dataset.rkey + + if (!col || !rk) return + + if (!confirm('Delete this record?')) return + + try { + btn.disabled = true + btn.textContent = 'Deleting...' + await deleteRecord(col, rk) + // Go back to collection + window.location.href = `?mode=browser&handle=${handle}&collection=${encodeURIComponent(col)}` + } catch (err) { + alert('Delete failed: ' + err) + btn.disabled = false + btn.textContent = 'Delete' + } + }) + } } catch (err) { container.innerHTML = `

Failed to load: ${err}

` } diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 7c4342f..e80d91c 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -145,3 +145,19 @@ export async function createPost(collection: string, title: string, content: str throw err } } + +export async function deleteRecord(collection: string, rkey: string): Promise { + if (!agent) return false + + try { + await agent.com.atproto.repo.deleteRecord({ + repo: agent.assertDid, + collection, + rkey, + }) + return true + } catch (err) { + console.error('Delete record error:', err) + throw err + } +} diff --git a/src/main.ts b/src/main.ts index 8881432..5b4d1ed 100644 --- a/src/main.ts +++ b/src/main.ts @@ -125,7 +125,8 @@ async function init(): Promise { // AT Browser mode if (mode === 'browser') { profileEl.innerHTML = renderTabs(handle, mode, isLoggedIn) - await mountAtBrowser(contentEl, handle, collection, rkey) + const loginDid = authSession?.did || null + await mountAtBrowser(contentEl, handle, collection, rkey, loginDid) return } diff --git a/src/styles/main.css b/src/styles/main.css index 974f718..9027347 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -475,6 +475,27 @@ body { color: #666; } +.delete-btn { + display: inline-block; + padding: 6px 12px; + background: #dc3545; + color: #fff; + border: none; + border-radius: 4px; + font-size: 12px; + cursor: pointer; + margin-left: 8px; +} + +.delete-btn:hover { + background: #c82333; +} + +.delete-btn:disabled { + background: #999; + cursor: not-allowed; +} + /* JSON View */ .json-view { background: #f5f5f5; @@ -554,4 +575,10 @@ body { background: #2a2a2a; color: #888; } + .delete-btn { + background: #dc3545; + } + .delete-btn:hover { + background: #c82333; + } }