/** * Notification context — provides a `push()` helper that surfaces * toast-style notifications via `react-native-toast-message`. * * Mount `` somewhere above the components that * consume `useNotificationContext()`. The `` component itself * must be rendered separately in the app root (see * `react-native-toast-message` docs). * * The vault notification provider also bridged a WebSocket service into * this context to dispatch server-pushed toasts; that piece is * app-specific and not included here. Consumers that need it can build * a thin wrapper around this provider. */ import React, { createContext, useCallback, useContext, useMemo } from "react"; import Toast from "react-native-toast-message"; export type NotificationLevel = "success" | "error" | "warning" | "info"; export interface ToastOptions { level: NotificationLevel; title: string; message?: string; /** Milliseconds before auto-dismiss. Defaults to 4000. */ ttl_ms?: number; } interface NotificationContextValue { push: (options: ToastOptions) => void; } const NotificationContext = createContext(null); const LEVEL_TO_TOAST_TYPE: Record = { success: "success", error: "error", // react-native-toast-message only ships success/error/info — warnings // map onto error so they show with the warning-coloured icon. warning: "error", info: "info", }; export function NotificationProvider({ children }: { children: React.ReactNode }) { const push = useCallback((options: ToastOptions) => { Toast.show({ type: LEVEL_TO_TOAST_TYPE[options.level], text1: options.title, text2: options.message, visibilityTime: options.ttl_ms ?? 4000, }); }, []); // Memoize the context value so an inline-object identity churn // doesn't re-render every consumer on each NotificationProvider // render. `push` is already `useCallback`-stable, so the memo // effectively pins the value across the provider's lifetime. const value = useMemo(() => ({ push }), [push]); return {children}; } export function useNotificationContext(): NotificationContextValue { const ctx = useContext(NotificationContext); if (!ctx) { throw new Error("useNotificationContext must be used inside "); } return ctx; }