Initial Commit
This commit is contained in:
183
src/tui/hooks/useAppContext.tsx
Normal file
183
src/tui/hooks/useAppContext.tsx
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* App context hook for accessing controllers and app-level functions.
|
||||
*/
|
||||
|
||||
import React, { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
|
||||
import type { WalletController } from '../../controllers/wallet-controller.js';
|
||||
import type { InvitationController } from '../../controllers/invitation-controller.js';
|
||||
import type { AppContextType, DialogState } from '../types.js';
|
||||
|
||||
/**
|
||||
* App context.
|
||||
*/
|
||||
const AppContext = createContext<AppContextType | null>(null);
|
||||
|
||||
/**
|
||||
* Dialog context for managing modal dialogs.
|
||||
*/
|
||||
interface DialogContextType {
|
||||
dialog: DialogState | null;
|
||||
setDialog: (dialog: DialogState | null) => void;
|
||||
}
|
||||
|
||||
const DialogContext = createContext<DialogContextType | null>(null);
|
||||
|
||||
/**
|
||||
* Status context for managing status bar.
|
||||
*/
|
||||
interface StatusContextType {
|
||||
status: string;
|
||||
setStatus: (status: string) => void;
|
||||
}
|
||||
|
||||
const StatusContext = createContext<StatusContextType | null>(null);
|
||||
|
||||
/**
|
||||
* App provider props.
|
||||
*/
|
||||
interface AppProviderProps {
|
||||
children: ReactNode;
|
||||
walletController: WalletController;
|
||||
invitationController: InvitationController;
|
||||
onExit: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* App provider component.
|
||||
* Provides controllers, dialog management, and app-level functions to children.
|
||||
*/
|
||||
export function AppProvider({
|
||||
children,
|
||||
walletController,
|
||||
invitationController,
|
||||
onExit,
|
||||
}: AppProviderProps): React.ReactElement {
|
||||
const [dialog, setDialog] = useState<DialogState | null>(null);
|
||||
const [status, setStatusState] = useState<string>('Ready');
|
||||
const [isWalletInitialized, setWalletInitialized] = useState(false);
|
||||
|
||||
// Promise resolver for confirm dialogs
|
||||
const [confirmResolver, setConfirmResolver] = useState<((value: boolean) => void) | null>(null);
|
||||
|
||||
/**
|
||||
* Show an error dialog.
|
||||
*/
|
||||
const showError = useCallback((message: string) => {
|
||||
setDialog({
|
||||
visible: true,
|
||||
type: 'error',
|
||||
message,
|
||||
onCancel: () => setDialog(null),
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Show an info dialog.
|
||||
*/
|
||||
const showInfo = useCallback((message: string) => {
|
||||
setDialog({
|
||||
visible: true,
|
||||
type: 'info',
|
||||
message,
|
||||
onCancel: () => setDialog(null),
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Show a confirmation dialog and wait for user response.
|
||||
*/
|
||||
const confirm = useCallback((message: string): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
setConfirmResolver(() => resolve);
|
||||
setDialog({
|
||||
visible: true,
|
||||
type: 'confirm',
|
||||
message,
|
||||
onConfirm: () => {
|
||||
setDialog(null);
|
||||
resolve(true);
|
||||
},
|
||||
onCancel: () => {
|
||||
setDialog(null);
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Update status bar message.
|
||||
*/
|
||||
const setStatus = useCallback((message: string) => {
|
||||
setStatusState(message);
|
||||
}, []);
|
||||
|
||||
const appValue: AppContextType = {
|
||||
walletController,
|
||||
invitationController,
|
||||
showError,
|
||||
showInfo,
|
||||
confirm,
|
||||
exit: onExit,
|
||||
setStatus,
|
||||
isWalletInitialized,
|
||||
setWalletInitialized,
|
||||
};
|
||||
|
||||
const dialogValue: DialogContextType = {
|
||||
dialog,
|
||||
setDialog,
|
||||
};
|
||||
|
||||
const statusValue: StatusContextType = {
|
||||
status,
|
||||
setStatus,
|
||||
};
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={appValue}>
|
||||
<DialogContext.Provider value={dialogValue}>
|
||||
<StatusContext.Provider value={statusValue}>
|
||||
{children}
|
||||
</StatusContext.Provider>
|
||||
</DialogContext.Provider>
|
||||
</AppContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to access app context.
|
||||
* @returns App context
|
||||
* @throws Error if used outside AppProvider
|
||||
*/
|
||||
export function useAppContext(): AppContextType {
|
||||
const context = useContext(AppContext);
|
||||
if (!context) {
|
||||
throw new Error('useAppContext must be used within an AppProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to access dialog context.
|
||||
* @returns Dialog context
|
||||
*/
|
||||
export function useDialog(): DialogContextType {
|
||||
const context = useContext(DialogContext);
|
||||
if (!context) {
|
||||
throw new Error('useDialog must be used within an AppProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to access status context.
|
||||
* @returns Status context
|
||||
*/
|
||||
export function useStatus(): StatusContextType {
|
||||
const context = useContext(StatusContext);
|
||||
if (!context) {
|
||||
throw new Error('useStatus must be used within an AppProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user