story-research-zapwall/components/keyManagement/useKeyManagementManager.ts
2026-01-13 14:49:19 +01:00

141 lines
4.4 KiB
TypeScript

import { useEffect, useMemo, useState } from 'react'
import {
INITIAL_KEY_MANAGEMENT_STATE,
confirmReplace,
copyToClipboard,
handleImport,
loadKeys,
type KeyManagementManagerState,
type PatchState,
} from './keyManagementController'
export interface KeyManagementManagerActions {
onChangeImportKey: (value: string) => void
onShowImportForm: () => void
onCancelImport: () => void
onImport: () => void
onDismissReplaceWarning: () => void
onConfirmReplace: () => void
onCopyNpub: () => void
onCopyPublicKey: () => void
onCopyRecoveryPhrase: () => void
onDoneRecovery: () => void
}
export interface UseKeyManagementManagerResult {
state: KeyManagementManagerState
actions: KeyManagementManagerActions
}
export function useKeyManagementManager(): UseKeyManagementManagerResult {
const [state, setState] = useState<KeyManagementManagerState>(INITIAL_KEY_MANAGEMENT_STATE)
const patchState = useMemo((): PatchState => createPatchState(setState), [])
useEffect(() => {
void loadKeys({ patchState })
}, [patchState])
const actions = useMemo((): KeyManagementManagerActions => createActions({ state, patchState }), [state, patchState])
return { state, actions }
}
function createPatchState(setState: React.Dispatch<React.SetStateAction<KeyManagementManagerState>>): PatchState {
return (patch: Partial<KeyManagementManagerState>): void => {
setState((previous) => ({ ...previous, ...patch }))
}
}
function createActions(params: { state: KeyManagementManagerState; patchState: PatchState }): KeyManagementManagerActions {
return {
onChangeImportKey: (value: string): void => {
params.patchState({ importKey: value, error: null })
},
onShowImportForm: (): void => {
params.patchState({ showImportForm: true, error: null })
},
onCancelImport: (): void => {
params.patchState({ showImportForm: false, importKey: '', error: null, showReplaceWarning: false })
},
onImport: (): void => {
void handleImport({ state: params.state, patchState: params.patchState })
},
onDismissReplaceWarning: (): void => {
params.patchState({ showReplaceWarning: false })
},
onConfirmReplace: (): void => {
void confirmReplace({ state: params.state, patchState: params.patchState })
},
onCopyNpub: (): void => {
void copyNpub({ state: params.state, patchState: params.patchState })
},
onCopyPublicKey: (): void => {
void copyPublicKey({ state: params.state, patchState: params.patchState })
},
onCopyRecoveryPhrase: (): void => {
void copyRecoveryPhrase({ state: params.state, patchState: params.patchState })
},
onDoneRecovery: (): void => {
params.patchState({ recoveryPhrase: null, newNpub: null })
void loadKeys({ patchState: params.patchState })
},
}
}
async function copyNpub(params: { state: KeyManagementManagerState; patchState: PatchState }): Promise<void> {
const npub = params.state.publicKeys?.npub
if (!npub) {
return
}
await copyToClipboard({
text: npub,
onCopied: () => {
params.patchState({ copiedNpub: true })
scheduleResetCopiedFlag(() => params.patchState({ copiedNpub: false }))
},
onCopyFailed: (e) => {
console.error('[KeyManagement] Error copying npub:', e)
},
})
}
async function copyPublicKey(params: { state: KeyManagementManagerState; patchState: PatchState }): Promise<void> {
const publicKey = params.state.publicKeys?.publicKey
if (!publicKey) {
return
}
await copyToClipboard({
text: publicKey,
onCopied: () => {
params.patchState({ copiedPublicKey: true })
scheduleResetCopiedFlag(() => params.patchState({ copiedPublicKey: false }))
},
onCopyFailed: (e) => {
console.error('[KeyManagement] Error copying public key:', e)
},
})
}
async function copyRecoveryPhrase(params: { state: KeyManagementManagerState; patchState: PatchState }): Promise<void> {
const {recoveryPhrase} = params.state
if (!recoveryPhrase) {
return
}
await copyToClipboard({
text: recoveryPhrase.join(' '),
onCopied: () => {
params.patchState({ copiedRecoveryPhrase: true })
scheduleResetCopiedFlag(() => params.patchState({ copiedRecoveryPhrase: false }))
},
onCopyFailed: (e) => {
console.error('[KeyManagement] Error copying recovery phrase:', e)
},
})
}
function scheduleResetCopiedFlag(reset: () => void): void {
setTimeout(() => {
reset()
}, 2000)
}