mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-04 03:21:04 +08:00
124 lines
2.9 KiB
TypeScript
124 lines
2.9 KiB
TypeScript
import React, {
|
|
createContext,
|
|
useContext,
|
|
useState,
|
|
useCallback,
|
|
useEffect,
|
|
} from 'react'
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogTitle,
|
|
} from './ui/alert-dialog'
|
|
import { setGlobalConfirm } from '../lib/notify'
|
|
|
|
interface ConfirmOptions {
|
|
title?: string
|
|
message: string
|
|
okText?: string
|
|
cancelText?: string
|
|
}
|
|
|
|
interface ConfirmDialogContextType {
|
|
confirm: (options: ConfirmOptions) => Promise<boolean>
|
|
}
|
|
|
|
const ConfirmDialogContext = createContext<
|
|
ConfirmDialogContextType | undefined
|
|
>(undefined)
|
|
|
|
export function useConfirmDialog() {
|
|
const context = useContext(ConfirmDialogContext)
|
|
if (!context) {
|
|
throw new Error(
|
|
'useConfirmDialog must be used within ConfirmDialogProvider'
|
|
)
|
|
}
|
|
return context
|
|
}
|
|
|
|
interface ConfirmState {
|
|
isOpen: boolean
|
|
title?: string
|
|
message: string
|
|
okText: string
|
|
cancelText: string
|
|
resolve?: (value: boolean) => void
|
|
}
|
|
|
|
export function ConfirmDialogProvider({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
const [state, setState] = useState<ConfirmState>({
|
|
isOpen: false,
|
|
message: '',
|
|
okText: '确认',
|
|
cancelText: '取消',
|
|
})
|
|
|
|
const confirm = useCallback((options: ConfirmOptions): Promise<boolean> => {
|
|
return new Promise((resolve) => {
|
|
setState({
|
|
isOpen: true,
|
|
title: options.title,
|
|
message: options.message,
|
|
okText: options.okText || '确认',
|
|
cancelText: options.cancelText || '取消',
|
|
resolve,
|
|
})
|
|
})
|
|
}, [])
|
|
|
|
// 注册全局 confirm 函数
|
|
useEffect(() => {
|
|
setGlobalConfirm(confirm)
|
|
}, [confirm])
|
|
|
|
const handleClose = useCallback((result: boolean) => {
|
|
setState((prev) => {
|
|
prev.resolve?.(result)
|
|
return {
|
|
...prev,
|
|
isOpen: false,
|
|
}
|
|
})
|
|
}, [])
|
|
|
|
return (
|
|
<ConfirmDialogContext.Provider value={{ confirm }}>
|
|
{children}
|
|
<AlertDialog
|
|
open={state.isOpen}
|
|
onOpenChange={(open) => !open && handleClose(false)}
|
|
>
|
|
<AlertDialogContent>
|
|
<div className="flex flex-col gap-5 text-center">
|
|
{state.title && (
|
|
<AlertDialogTitle className="text-xl">
|
|
{state.title}
|
|
</AlertDialogTitle>
|
|
)}
|
|
<AlertDialogDescription className="text-[var(--text-primary)] text-base font-medium">
|
|
{state.message}
|
|
</AlertDialogDescription>
|
|
</div>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel onClick={() => handleClose(false)}>
|
|
{state.cancelText}
|
|
</AlertDialogCancel>
|
|
<AlertDialogAction onClick={() => handleClose(true)}>
|
|
{state.okText}
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</ConfirmDialogContext.Provider>
|
|
)
|
|
}
|