mirror of
https://github.com/ikawrakow/ik_llama.cpp.git
synced 2026-02-23 22:54:10 +00:00
* Webui: add Rename/Upload conversation in header and sidebar webui: don't change modified date when renaming conversation * webui: add a preset feature to the settings #14649 * webui: Add editing assistant messages #13522 Webui: keep the following message while editing assistance response. webui: change icon to edit message * webui: DB import and export #14347 * webui: Wrap long numbers instead of infinite horizontal scroll (#14062) fix sidebar being covered by main content #14082 --------- Co-authored-by: firecoperana <firecoperana>
152 lines
4.4 KiB
TypeScript
152 lines
4.4 KiB
TypeScript
import React, { createContext, useState, useContext } from 'react';
|
|
|
|
type ModalContextType = {
|
|
showConfirm: (message: string) => Promise<boolean>;
|
|
showPrompt: (
|
|
message: string,
|
|
defaultValue?: string
|
|
) => Promise<string | undefined>;
|
|
showAlert: (message: string) => Promise<void>;
|
|
};
|
|
const ModalContext = createContext<ModalContextType>(null!);
|
|
|
|
interface ModalState<T> {
|
|
isOpen: boolean;
|
|
message: string;
|
|
defaultValue?: string;
|
|
resolve: ((value: T) => void) | null;
|
|
}
|
|
|
|
export function ModalProvider({ children }: { children: React.ReactNode }) {
|
|
const [confirmState, setConfirmState] = useState<ModalState<boolean>>({
|
|
isOpen: false,
|
|
message: '',
|
|
resolve: null,
|
|
});
|
|
const [promptState, setPromptState] = useState<
|
|
ModalState<string | undefined>
|
|
>({ isOpen: false, message: '', resolve: null });
|
|
const [alertState, setAlertState] = useState<ModalState<void>>({
|
|
isOpen: false,
|
|
message: '',
|
|
resolve: null,
|
|
});
|
|
const inputRef = React.useRef<HTMLInputElement>(null);
|
|
|
|
const showConfirm = (message: string): Promise<boolean> => {
|
|
return new Promise((resolve) => {
|
|
setConfirmState({ isOpen: true, message, resolve });
|
|
});
|
|
};
|
|
|
|
const showPrompt = (
|
|
message: string,
|
|
defaultValue?: string
|
|
): Promise<string | undefined> => {
|
|
return new Promise((resolve) => {
|
|
setPromptState({ isOpen: true, message, defaultValue, resolve });
|
|
});
|
|
};
|
|
|
|
const showAlert = (message: string): Promise<void> => {
|
|
return new Promise((resolve) => {
|
|
setAlertState({ isOpen: true, message, resolve });
|
|
});
|
|
};
|
|
|
|
const handleConfirm = (result: boolean) => {
|
|
confirmState.resolve?.(result);
|
|
setConfirmState({ isOpen: false, message: '', resolve: null });
|
|
};
|
|
|
|
const handlePrompt = (result?: string) => {
|
|
promptState.resolve?.(result);
|
|
setPromptState({ isOpen: false, message: '', resolve: null });
|
|
};
|
|
|
|
const handleAlertClose = () => {
|
|
alertState.resolve?.();
|
|
setAlertState({ isOpen: false, message: '', resolve: null });
|
|
};
|
|
|
|
return (
|
|
<ModalContext.Provider value={{ showConfirm, showPrompt, showAlert }}>
|
|
{children}
|
|
|
|
{/* Confirm Modal */}
|
|
{confirmState.isOpen && (
|
|
<dialog className="modal modal-open z-[1100]">
|
|
<div className="modal-box">
|
|
<h3 className="font-bold text-lg">{confirmState.message}</h3>
|
|
<div className="modal-action">
|
|
<button
|
|
className="btn btn-ghost"
|
|
onClick={() => handleConfirm(false)}
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
className="btn btn-error"
|
|
onClick={() => handleConfirm(true)}
|
|
>
|
|
Confirm
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
)}
|
|
|
|
{/* Prompt Modal */}
|
|
{promptState.isOpen && (
|
|
<dialog className="modal modal-open z-[1100]">
|
|
<div className="modal-box">
|
|
<h3 className="font-bold text-lg">{promptState.message}</h3>
|
|
<input
|
|
type="text"
|
|
className="input input-bordered w-full mt-2"
|
|
defaultValue={promptState.defaultValue}
|
|
ref={inputRef}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
handlePrompt((e.target as HTMLInputElement).value);
|
|
}
|
|
}}
|
|
/>
|
|
<div className="modal-action">
|
|
<button className="btn btn-ghost" onClick={() => handlePrompt()}>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
className="btn btn-primary"
|
|
onClick={() => handlePrompt(inputRef.current?.value)}
|
|
>
|
|
Submit
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
)}
|
|
|
|
{/* Alert Modal */}
|
|
{alertState.isOpen && (
|
|
<dialog className="modal modal-open z-[1100]">
|
|
<div className="modal-box">
|
|
<h3 className="font-bold text-lg">{alertState.message}</h3>
|
|
<div className="modal-action">
|
|
<button className="btn" onClick={handleAlertClose}>
|
|
OK
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
)}
|
|
</ModalContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useModals() {
|
|
const context = useContext(ModalContext);
|
|
if (!context) throw new Error('useModals must be used within ModalProvider');
|
|
return context;
|
|
}
|