170 lines
5.5 KiB
TypeScript
170 lines
5.5 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { nanoid } from "nanoid";
|
|
import { Prompt, SearchService, usePromptStore } from "@/app/store/prompt";
|
|
import { Input as Textarea, Modal } from "@/app/components/ui-lib";
|
|
import Locale from "@/app/locales";
|
|
import { IconButton } from "@/app/components/button";
|
|
|
|
import AddIcon from "@/app/icons/add.svg";
|
|
import CopyIcon from "@/app/icons/copy.svg";
|
|
import ClearIcon from "@/app/icons/clear.svg";
|
|
import EditIcon from "@/app/icons/edit.svg";
|
|
import EyeIcon from "@/app/icons/eye.svg";
|
|
|
|
import styles from "../index.module.scss";
|
|
import { copyToClipboard } from "@/app/utils";
|
|
import Input from "@/app/components/Input";
|
|
|
|
function EditPromptModal(props: { id: string; onClose: () => void }) {
|
|
const promptStore = usePromptStore();
|
|
const prompt = promptStore.get(props.id);
|
|
|
|
return prompt ? (
|
|
<div className="modal-mask">
|
|
<Modal
|
|
title={Locale.Settings.Prompt.EditModal.Title}
|
|
onClose={props.onClose}
|
|
actions={[
|
|
<IconButton
|
|
key=""
|
|
onClick={props.onClose}
|
|
text={Locale.UI.Confirm}
|
|
bordered
|
|
/>,
|
|
]}
|
|
// className="!bg-modal-mask"
|
|
>
|
|
<div className={styles["edit-prompt-modal"]}>
|
|
<Input
|
|
type="text"
|
|
value={prompt.title}
|
|
readOnly={!prompt.isUser}
|
|
className={styles["edit-prompt-title"]}
|
|
onChange={(e) =>
|
|
promptStore.updatePrompt(props.id, (prompt) => (prompt.title = e))
|
|
}
|
|
></Input>
|
|
<Textarea
|
|
value={prompt.content}
|
|
readOnly={!prompt.isUser}
|
|
className={styles["edit-prompt-content"]}
|
|
rows={10}
|
|
onInput={(e) =>
|
|
promptStore.updatePrompt(
|
|
props.id,
|
|
(prompt) => (prompt.content = e.currentTarget.value),
|
|
)
|
|
}
|
|
></Textarea>
|
|
</div>
|
|
</Modal>
|
|
</div>
|
|
) : null;
|
|
}
|
|
|
|
export default function UserPromptModal(props: { onClose?: () => void }) {
|
|
const promptStore = usePromptStore();
|
|
const userPrompts = promptStore.getUserPrompts();
|
|
const builtinPrompts = SearchService.builtinPrompts;
|
|
const allPrompts = userPrompts.concat(builtinPrompts);
|
|
const [searchInput, setSearchInput] = useState("");
|
|
const [searchPrompts, setSearchPrompts] = useState<Prompt[]>([]);
|
|
const prompts = searchInput.length > 0 ? searchPrompts : allPrompts;
|
|
|
|
const [editingPromptId, setEditingPromptId] = useState<string>();
|
|
|
|
useEffect(() => {
|
|
if (searchInput.length > 0) {
|
|
const searchResult = SearchService.search(searchInput);
|
|
setSearchPrompts(searchResult);
|
|
} else {
|
|
setSearchPrompts([]);
|
|
}
|
|
}, [searchInput]);
|
|
|
|
return (
|
|
<div className="modal-mask">
|
|
<Modal
|
|
title={Locale.Settings.Prompt.Modal.Title}
|
|
onClose={() => props.onClose?.()}
|
|
actions={[
|
|
<IconButton
|
|
key="add"
|
|
onClick={() => {
|
|
const promptId = promptStore.add({
|
|
id: nanoid(),
|
|
createdAt: Date.now(),
|
|
title: "Empty Prompt",
|
|
content: "Empty Prompt Content",
|
|
});
|
|
setEditingPromptId(promptId);
|
|
}}
|
|
icon={<AddIcon />}
|
|
bordered
|
|
text={Locale.Settings.Prompt.Modal.Add}
|
|
/>,
|
|
]}
|
|
// className="!bg-modal-mask"
|
|
>
|
|
<div className={styles["user-prompt-modal"]}>
|
|
<Input
|
|
type="text"
|
|
className={styles["user-prompt-search"]}
|
|
placeholder={Locale.Settings.Prompt.Modal.Search}
|
|
value={searchInput}
|
|
onChange={(e) => setSearchInput(e)}
|
|
></Input>
|
|
|
|
<div className={styles["user-prompt-list"]}>
|
|
{prompts.map((v, _) => (
|
|
<div className={styles["user-prompt-item"]} key={v.id ?? v.title}>
|
|
<div className={styles["user-prompt-header"]}>
|
|
<div className={styles["user-prompt-title"]}>{v.title}</div>
|
|
<div className={styles["user-prompt-content"] + " one-line"}>
|
|
{v.content}
|
|
</div>
|
|
</div>
|
|
|
|
<div className={styles["user-prompt-buttons"]}>
|
|
{v.isUser && (
|
|
<IconButton
|
|
icon={<ClearIcon />}
|
|
className={styles["user-prompt-button"]}
|
|
onClick={() => promptStore.remove(v.id!)}
|
|
/>
|
|
)}
|
|
{v.isUser ? (
|
|
<IconButton
|
|
icon={<EditIcon />}
|
|
className={styles["user-prompt-button"]}
|
|
onClick={() => setEditingPromptId(v.id)}
|
|
/>
|
|
) : (
|
|
<IconButton
|
|
icon={<EyeIcon />}
|
|
className={styles["user-prompt-button"]}
|
|
onClick={() => setEditingPromptId(v.id)}
|
|
/>
|
|
)}
|
|
<IconButton
|
|
icon={<CopyIcon />}
|
|
className={styles["user-prompt-button"]}
|
|
onClick={() => copyToClipboard(v.content)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</Modal>
|
|
|
|
{editingPromptId !== undefined && (
|
|
<EditPromptModal
|
|
id={editingPromptId!}
|
|
onClose={() => setEditingPromptId(undefined)}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|