From 82075b554ada476f2fac186a84bcc749adb6a159 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Thu, 26 Feb 2026 13:40:39 +0100 Subject: [PATCH] refactor the refactor Nostr-Signature: 62aafbdadfd37b20f1b16742a297e2b17d59dd3d6930e64e75d0d1b6a2f04bd6 573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc 050eaca1703b73443b51fd160932a2edfa04fc0a5efd3b5bb0a1e4c8b944caa60d444b2148c07b74f4ff4a589984fa524a7109a2a89c3eddf6c937b23b18c69b --- nostr/commit-signatures.jsonl | 1 + src/routes/repos/[npub]/[repo]/+page.svelte | 367 ++---------------- .../[repo]/services/branch-operations.ts | 101 +++++ .../[npub]/[repo]/services/file-operations.ts | 255 ++++++++++++ 4 files changed, 388 insertions(+), 336 deletions(-) create mode 100644 src/routes/repos/[npub]/[repo]/services/branch-operations.ts create mode 100644 src/routes/repos/[npub]/[repo]/services/file-operations.ts diff --git a/nostr/commit-signatures.jsonl b/nostr/commit-signatures.jsonl index b33ea56..0fc925a 100644 --- a/nostr/commit-signatures.jsonl +++ b/nostr/commit-signatures.jsonl @@ -95,3 +95,4 @@ {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772105581,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fdix build"]],"content":"Signed commit: fdix build","id":"aa457cd97e3af5c7e7e6f8938d159f62de2eee27afcf9a9a415192a8b39cd038","sig":"1959bae547fefff3b3fd72e23071e989724ab71f2042bad9cb5a969133045119a068b529df17ded13db96b54372f662760df79a34f1b6072dcabf5d2f003000b"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772106804,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","refactor 3"]],"content":"Signed commit: refactor 3","id":"a761c789227ef2368eff89f7062fa7889820c4846701667360978cfdad08c3d2","sig":"9d229200ab66d3f4a0a2a21112c9100ee14d0a5d9f8409a35fef36f195f5f73c8ac2344aa1175cc476f650336a5a10ea6ac0076c8ec2cb229fea7d600c5d4399"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772107667,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix build"]],"content":"Signed commit: fix build","id":"2a8db19aff5126547a397f7daf9121f711a3d61efcced642b496687d9afc48dc","sig":"7e0558fac1764e185b3f52450f5a34805b04342bdb0821b4d459b1627d057d7e2af397b3263a8831e9be2e615556ef09094bce808c22f6049261273004da74bc"} +{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772108817,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix build"]],"content":"Signed commit: fix build","id":"a37754536125d75a5c55f6af3b5521f89839e797ad1bffb69e3d313939cb7b65","sig":"6bcca1a025e4478ae330d3664dd2b9cff55f4bec82065ab2afb5bfb92031f7dde3264657dd892fe844396990117048b19247b0ef7423139f89d4cbf46b47f828"} diff --git a/src/routes/repos/[npub]/[repo]/+page.svelte b/src/routes/repos/[npub]/[repo]/+page.svelte index bbc0849..41ae2f5 100644 --- a/src/routes/repos/[npub]/[repo]/+page.svelte +++ b/src/routes/repos/[npub]/[repo]/+page.svelte @@ -77,6 +77,15 @@ getUserEmail as getUserEmailUtil, getUserName as getUserNameUtil } from './utils/user-profile.js'; + import { + saveFile as saveFileService, + createFile as createFileService, + deleteFile as deleteFileService + } from './services/file-operations.js'; + import { + createBranch as createBranchService, + deleteBranch as deleteBranchService + } from './services/branch-operations.js'; // Consolidated state - all state variables in one object let state = $state(createRepoState()); @@ -3013,88 +3022,12 @@ } async function saveFile() { - if (!state.files.currentFile || !state.forms.commit.message.trim()) { - alert('Please enter a commit message'); - return; - } - - if (!state.user.pubkey) { - alert('Please connect your NIP-07 extension to save state.files.list'); - return; - } - - // Validate branch selection - if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') { - alert('Please select a branch before state.saving the file'); - return; - } - - state.saving = true; - state.error = null; - - try { - // Get user email and name (from profile or prompt) - const authorEmail = await getUserEmail(); - const authorName = await getUserName(); - - // Sign commit with NIP-07 (client-side) - let commitSignatureEvent: NostrEvent | null = null; - if (isNIP07Available()) { - try { - const { KIND } = await import('$lib/types/nostr.js'); - const timestamp = Math.floor(Date.now() / 1000); - const eventTemplate: Omit = { - kind: KIND.COMMIT_SIGNATURE, - pubkey: '', // Will be filled by NIP-07 - created_at: timestamp, - tags: [ - ['author', authorName, authorEmail], - ['message', state.forms.commit.message.trim()] - ], - content: `Signed commit: ${state.forms.commit.message.trim()}` - }; - commitSignatureEvent = await signEventWithNIP07(eventTemplate); - } catch (err) { - console.warn('Failed to sign commit with NIP-07:', err); - // Continue without signature if signing fails - } - } - - const response = await fetch(`/api/repos/${state.npub}/${state.repo}/file`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...buildApiHeaders() - }, - body: JSON.stringify({ - path: state.files.currentFile, - content: state.files.editedContent, - message: state.forms.commit.message.trim(), - authorName: authorName, - authorEmail: authorEmail, - branch: state.git.currentBranch, - userPubkey: state.user.pubkey, - commitSignatureEvent: commitSignatureEvent // Send the signed event to server - }) - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({ message: response.statusText })); - const errorMessage = errorData.message || errorData.state.error || 'Failed to save file'; - throw new Error(errorMessage); - } - - // Reload file to get updated content - await loadFile(state.files.currentFile); - state.forms.commit.message = ''; - state.openDialog = null; - alert('File saved successfully!'); - } catch (err) { - state.error = err instanceof Error ? err.message : 'Failed to save file'; - console.error('Error state.saving file:', err); - } finally { - state.saving = false; - } + await saveFileService(state, { + getUserEmail, + getUserName, + loadFiles, + loadFile + }); } function handleBranchChangeDirect(branch: string) { @@ -3142,269 +3075,31 @@ } async function createFile() { - if (!state.forms.file.fileName.trim()) { - alert('Please enter a file name'); - return; - } - - if (!state.user.pubkey) { - alert('Please connect your NIP-07 extension'); - return; - } - - // Validate branch selection - if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') { - alert('Please select a branch before creating the file'); - return; - } - - state.saving = true; - state.error = null; - - try { - // Get user email and name (from profile or prompt) - const authorEmail = await getUserEmail(); - const authorName = await getUserName(); - const filePath = state.files.currentPath ? `${state.files.currentPath}/${state.forms.file.fileName}` : state.forms.file.fileName; - const commitMsg = `Create ${state.forms.file.fileName}`; - - // Sign commit with NIP-07 (client-side) - let commitSignatureEvent: NostrEvent | null = null; - if (isNIP07Available()) { - try { - const { KIND } = await import('$lib/types/nostr.js'); - const timestamp = Math.floor(Date.now() / 1000); - const eventTemplate: Omit = { - kind: KIND.COMMIT_SIGNATURE, - pubkey: '', // Will be filled by NIP-07 - created_at: timestamp, - tags: [ - ['author', authorName, authorEmail], - ['message', commitMsg] - ], - content: `Signed commit: ${commitMsg}` - }; - commitSignatureEvent = await signEventWithNIP07(eventTemplate); - } catch (err) { - console.warn('Failed to sign commit with NIP-07:', err); - // Continue without signature if signing fails - } - } - - const response = await fetch(`/api/repos/${state.npub}/${state.repo}/file`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...buildApiHeaders() - }, - body: JSON.stringify({ - path: filePath, - content: state.forms.file.content, - message: commitMsg, - authorName: authorName, - authorEmail: authorEmail, - branch: state.git.currentBranch, - action: 'create', - userPubkey: state.user.pubkey, - commitSignatureEvent: commitSignatureEvent // Send the signed event to server - }) - }); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.message || 'Failed to create file'); - } - - state.openDialog = null; - state.forms.file.fileName = ''; - state.forms.file.content = ''; - await loadFiles(state.files.currentPath); - alert('File created successfully!'); - } catch (err) { - state.error = err instanceof Error ? err.message : 'Failed to create file'; - } finally { - state.saving = false; - } + await createFileService(state, { + getUserEmail, + getUserName, + loadFiles + }); } async function deleteFile(filePath: string) { - if (!confirm(`Are you sure you want to delete "${filePath}"?\n\nThis will permanently delete the file from the repository. This action cannot be undone.\n\nClick OK to delete, or Cancel to abort.`)) { - return; - } - - if (!state.user.pubkey) { - alert('Please connect your NIP-07 extension'); - return; - } - - // Validate branch selection - if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') { - alert('Please select a branch before deleting the file'); - return; - } - - state.saving = true; - state.error = null; - - try { - // Get user email and name (from profile or prompt) - const authorEmail = await getUserEmail(); - const authorName = await getUserName(); - const commitMsg = `Delete ${filePath}`; - - // Sign commit with NIP-07 (client-side) - let commitSignatureEvent: NostrEvent | null = null; - if (isNIP07Available()) { - try { - const { KIND } = await import('$lib/types/nostr.js'); - const timestamp = Math.floor(Date.now() / 1000); - const eventTemplate: Omit = { - kind: KIND.COMMIT_SIGNATURE, - pubkey: '', // Will be filled by NIP-07 - created_at: timestamp, - tags: [ - ['author', authorName, authorEmail], - ['message', commitMsg] - ], - content: `Signed commit: ${commitMsg}` - }; - commitSignatureEvent = await signEventWithNIP07(eventTemplate); - } catch (err) { - console.warn('Failed to sign commit with NIP-07:', err); - // Continue without signature if signing fails - } - } - - const response = await fetch(`/api/repos/${state.npub}/${state.repo}/file`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...buildApiHeaders() - }, - body: JSON.stringify({ - path: filePath, - message: commitMsg, - authorName: authorName, - authorEmail: authorEmail, - branch: state.git.currentBranch, - action: 'delete', - userPubkey: state.user.pubkey, - commitSignatureEvent: commitSignatureEvent // Send the signed event to server - }) - }); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.message || 'Failed to delete file'); - } - - if (state.files.currentFile === filePath) { - state.files.currentFile = null; - } - await loadFiles(state.files.currentPath); - alert('File deleted successfully!'); - } catch (err) { - state.error = err instanceof Error ? err.message : 'Failed to delete file'; - } finally { - state.saving = false; - } + await deleteFileService(filePath, state, { + getUserEmail, + getUserName, + loadFiles + }); } async function createBranch() { - if (!state.forms.branch.name.trim()) { - alert('Please enter a branch name'); - return; - } - - state.saving = true; - state.error = null; - - try { - // If no state.git.branches exist, don't pass fromBranch (will use --orphan) - // Otherwise, use the selected branch or current branch - let fromBranch: string | undefined = state.forms.branch.from || state.git.currentBranch || undefined; - - // Include announcement if available (for empty repos) - const requestBody: { branchName: string; fromBranch?: string; announcement?: NostrEvent } = { - branchName: state.forms.branch.name - }; - if (state.git.branches.length > 0 && fromBranch) { - requestBody.fromBranch = fromBranch; - } - // Pass announcement if available (especially useful for empty repos) - if (repoAnnouncement) { - requestBody.announcement = repoAnnouncement; - } - - const response = await fetch(`/api/repos/${state.npub}/${state.repo}/branches`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - ...buildApiHeaders() - }, - body: JSON.stringify(requestBody) - }); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.message || 'Failed to create branch'); - } - - state.openDialog = null; - state.forms.branch.name = ''; - await loadBranches(); - alert('Branch created successfully!'); - } catch (err) { - state.error = err instanceof Error ? err.message : 'Failed to create branch'; - } finally { - state.saving = false; - } + await createBranchService(state, repoAnnouncement, { + loadBranches + }); } async function deleteBranch(branchName: string) { - if (!confirm(`Are you sure you want to delete the branch "${branchName}"?\n\nThis will permanently delete the branch from the repository. This action CANNOT be undone.\n\nClick OK to delete, or Cancel to abort.`)) { - return; - } - - if (!state.user.pubkey) { - alert('Please connect your NIP-07 extension'); - return; - } - - // Prevent deleting the current branch - if (branchName === state.git.currentBranch) { - alert('Cannot delete the currently selected branch. Please switch to a different branch first.'); - return; - } - - state.saving = true; - state.error = null; - - try { - const response = await fetch(`/api/repos/${state.npub}/${state.repo}/branches`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - ...buildApiHeaders() - }, - body: JSON.stringify({ - branchName: branchName - }) - }); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.message || 'Failed to delete branch'); - } - - await loadBranches(); - alert('Branch deleted successfully!'); - } catch (err) { - state.error = err instanceof Error ? err.message : 'Failed to delete branch'; - alert(state.error); - } finally { - state.saving = false; - } + await deleteBranchService(branchName, state, { + loadBranches + }); } async function loadCommitHistory() { diff --git a/src/routes/repos/[npub]/[repo]/services/branch-operations.ts b/src/routes/repos/[npub]/[repo]/services/branch-operations.ts new file mode 100644 index 0000000..391234b --- /dev/null +++ b/src/routes/repos/[npub]/[repo]/services/branch-operations.ts @@ -0,0 +1,101 @@ +/** + * Branch operations service + * Handles branch creation and deletion + */ + +import type { NostrEvent } from '$lib/types/nostr.js'; +import type { RepoState } from '../stores/repo-state.js'; +import { apiPost, apiRequest } from '../utils/api-client.js'; + +interface BranchOperationsCallbacks { + loadBranches: () => Promise; +} + +/** + * Create a new branch + */ +export async function createBranch( + state: RepoState, + repoAnnouncement: NostrEvent | null | undefined, + callbacks: BranchOperationsCallbacks +): Promise { + if (!state.forms.branch.name.trim()) { + alert('Please enter a branch name'); + return; + } + + state.saving = true; + state.error = null; + + try { + // If no branches exist, don't pass fromBranch (will use --orphan) + // Otherwise, use the selected branch or current branch + let fromBranch: string | undefined = state.forms.branch.from || state.git.currentBranch || undefined; + + // Include announcement if available (for empty repos) + const requestBody: { branchName: string; fromBranch?: string; announcement?: NostrEvent } = { + branchName: state.forms.branch.name + }; + if (state.git.branches.length > 0 && fromBranch) { + requestBody.fromBranch = fromBranch; + } + // Pass announcement if available (especially useful for empty repos) + if (repoAnnouncement) { + requestBody.announcement = repoAnnouncement; + } + + await apiPost(`/api/repos/${state.npub}/${state.repo}/branches`, requestBody); + + state.openDialog = null; + state.forms.branch.name = ''; + await callbacks.loadBranches(); + alert('Branch created successfully!'); + } catch (err) { + state.error = err instanceof Error ? err.message : 'Failed to create branch'; + } finally { + state.saving = false; + } +} + +/** + * Delete a branch + */ +export async function deleteBranch( + branchName: string, + state: RepoState, + callbacks: BranchOperationsCallbacks +): Promise { + if (!confirm(`Are you sure you want to delete the branch "${branchName}"?\n\nThis will permanently delete the branch from the repository. This action CANNOT be undone.\n\nClick OK to delete, or Cancel to abort.`)) { + return; + } + + if (!state.user.pubkey) { + alert('Please connect your NIP-07 extension'); + return; + } + + // Prevent deleting the current branch + if (branchName === state.git.currentBranch) { + alert('Cannot delete the currently selected branch. Please switch to a different branch first.'); + return; + } + + state.saving = true; + state.error = null; + + try { + // Note: DELETE endpoint expects branchName in body, not query string + await apiRequest(`/api/repos/${state.npub}/${state.repo}/branches`, { + method: 'DELETE', + body: JSON.stringify({ branchName }) + }); + + await callbacks.loadBranches(); + alert('Branch deleted successfully!'); + } catch (err) { + state.error = err instanceof Error ? err.message : 'Failed to delete branch'; + alert(state.error); + } finally { + state.saving = false; + } +} diff --git a/src/routes/repos/[npub]/[repo]/services/file-operations.ts b/src/routes/repos/[npub]/[repo]/services/file-operations.ts new file mode 100644 index 0000000..7def54d --- /dev/null +++ b/src/routes/repos/[npub]/[repo]/services/file-operations.ts @@ -0,0 +1,255 @@ +/** + * File operations service + * Handles file saving, creating, and deleting + * Note: loadFile and loadFiles remain in component due to complex state dependencies + */ + +import type { NostrEvent } from '$lib/types/nostr.js'; +import type { RepoState } from '../stores/repo-state.js'; +import { isNIP07Available, signEventWithNIP07 } from '$lib/services/nostr/nip07-signer.js'; +import { apiPost } from '../utils/api-client.js'; + +interface FileOperationsCallbacks { + getUserEmail: () => Promise; + getUserName: () => Promise; + loadFiles: (path: string) => Promise; + loadFile?: (path: string) => Promise; +} + +/** + * Save a file to the repository + */ +export async function saveFile( + state: RepoState, + callbacks: FileOperationsCallbacks +): Promise { + if (!state.files.currentFile || !state.forms.commit.message.trim()) { + alert('Please enter a commit message'); + return; + } + + if (!state.user.pubkey) { + alert('Please connect your NIP-07 extension to save files'); + return; + } + + if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') { + alert('Please select a branch before saving the file'); + return; + } + + state.saving = true; + state.error = null; + + try { + const authorEmail = await callbacks.getUserEmail(); + const authorName = await callbacks.getUserName(); + + // Sign commit with NIP-07 (client-side) + let commitSignatureEvent: NostrEvent | null = null; + if (isNIP07Available()) { + try { + const { KIND } = await import('$lib/types/nostr.js'); + const timestamp = Math.floor(Date.now() / 1000); + const eventTemplate: Omit = { + kind: KIND.COMMIT_SIGNATURE, + pubkey: '', + created_at: timestamp, + tags: [ + ['author', authorName, authorEmail], + ['message', state.forms.commit.message.trim()] + ], + content: `Signed commit: ${state.forms.commit.message.trim()}` + }; + commitSignatureEvent = await signEventWithNIP07(eventTemplate); + } catch (err) { + console.warn('Failed to sign commit with NIP-07:', err); + } + } + + await apiPost(`/api/repos/${state.npub}/${state.repo}/file`, { + path: state.files.currentFile, + content: state.files.editedContent, + message: state.forms.commit.message.trim(), + authorName: authorName, + authorEmail: authorEmail, + branch: state.git.currentBranch, + userPubkey: state.user.pubkey, + commitSignatureEvent: commitSignatureEvent + }); + + if (callbacks.loadFile) { + await callbacks.loadFile(state.files.currentFile); + } + state.forms.commit.message = ''; + state.openDialog = null; + alert('File saved successfully!'); + } catch (err) { + state.error = err instanceof Error ? err.message : 'Failed to save file'; + console.error('Error saving file:', err); + } finally { + state.saving = false; + } +} + +/** + * Create a new file in the repository + */ +export async function createFile( + state: RepoState, + callbacks: FileOperationsCallbacks +): Promise { + if (!state.forms.file.fileName.trim()) { + alert('Please enter a file name'); + return; + } + + if (!state.user.pubkey) { + alert('Please connect your NIP-07 extension'); + return; + } + + if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') { + alert('Please select a branch before creating the file'); + return; + } + + state.saving = true; + state.error = null; + + try { + const authorEmail = await callbacks.getUserEmail(); + const authorName = await callbacks.getUserName(); + const filePath = state.files.currentPath ? `${state.files.currentPath}/${state.forms.file.fileName}` : state.forms.file.fileName; + const commitMsg = `Create ${state.forms.file.fileName}`; + + // Sign commit with NIP-07 (client-side) + let commitSignatureEvent: NostrEvent | null = null; + if (isNIP07Available()) { + try { + const { KIND } = await import('$lib/types/nostr.js'); + const timestamp = Math.floor(Date.now() / 1000); + const eventTemplate: Omit = { + kind: KIND.COMMIT_SIGNATURE, + pubkey: '', + created_at: timestamp, + tags: [ + ['author', authorName, authorEmail], + ['message', commitMsg] + ], + content: `Signed commit: ${commitMsg}` + }; + commitSignatureEvent = await signEventWithNIP07(eventTemplate); + } catch (err) { + console.warn('Failed to sign commit with NIP-07:', err); + } + } + + await apiPost(`/api/repos/${state.npub}/${state.repo}/file`, { + path: filePath, + content: state.forms.file.content, + message: commitMsg, + authorName: authorName, + authorEmail: authorEmail, + branch: state.git.currentBranch, + action: 'create', + userPubkey: state.user.pubkey, + commitSignatureEvent: commitSignatureEvent + }); + + // Clear form + state.forms.file.fileName = ''; + state.forms.file.content = ''; + state.openDialog = null; + + // Reload file list + await callbacks.loadFiles(state.files.currentPath); + + alert('File created successfully!'); + } catch (err) { + state.error = err instanceof Error ? err.message : 'Failed to create file'; + console.error('Error creating file:', err); + } finally { + state.saving = false; + } +} + +/** + * Delete a file from the repository + */ +export async function deleteFile( + filePath: string, + state: RepoState, + callbacks: FileOperationsCallbacks +): Promise { + if (!confirm(`Are you sure you want to delete "${filePath}"?\n\nThis will permanently delete the file from the repository. This action cannot be undone.\n\nClick OK to delete, or Cancel to abort.`)) { + return; + } + + if (!state.user.pubkey) { + alert('Please connect your NIP-07 extension'); + return; + } + + if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') { + alert('Please select a branch before deleting the file'); + return; + } + + state.saving = true; + state.error = null; + + try { + const authorEmail = await callbacks.getUserEmail(); + const authorName = await callbacks.getUserName(); + const commitMsg = `Delete ${filePath}`; + + // Sign commit with NIP-07 (client-side) + let commitSignatureEvent: NostrEvent | null = null; + if (isNIP07Available()) { + try { + const { KIND } = await import('$lib/types/nostr.js'); + const timestamp = Math.floor(Date.now() / 1000); + const eventTemplate: Omit = { + kind: KIND.COMMIT_SIGNATURE, + pubkey: '', + created_at: timestamp, + tags: [ + ['author', authorName, authorEmail], + ['message', commitMsg] + ], + content: `Signed commit: ${commitMsg}` + }; + commitSignatureEvent = await signEventWithNIP07(eventTemplate); + } catch (err) { + console.warn('Failed to sign commit with NIP-07:', err); + } + } + + await apiPost(`/api/repos/${state.npub}/${state.repo}/file`, { + path: filePath, + message: commitMsg, + authorName: authorName, + authorEmail: authorEmail, + branch: state.git.currentBranch, + action: 'delete', + userPubkey: state.user.pubkey, + commitSignatureEvent: commitSignatureEvent + }); + + // Clear current file if it was deleted + if (state.files.currentFile === filePath) { + state.files.currentFile = null; + } + + // Reload file list + await callbacks.loadFiles(state.files.currentPath); + + alert('File deleted successfully!'); + } catch (err) { + state.error = err instanceof Error ? err.message : 'Failed to delete file'; + console.error('Error deleting file:', err); + } finally { + state.saving = false; + } +}