reconstitution ui with daisyui

This commit is contained in:
ecwu
2024-07-16 21:51:58 +08:00
parent 4079ec77f9
commit 0ae53ff954
9 changed files with 3134 additions and 766 deletions

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html data-theme="cupcake" lang="en">
<head>
<meta charset="UTF-8" />
<meta

2268
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
"@heroicons/react": "^2.1.5",
"@types/ungap__structured-clone": "^0.3.1",
"@ungap/structured-clone": "^1.2.0",
"autoprefixer": "^10.4.16",
@@ -21,6 +22,8 @@
},
"devDependencies": {
"@preact/preset-vite": "^2.6.0",
"daisyui": "^4.12.10",
"theme-change": "^2.5.0",
"typescript": "^5.2.2",
"vite": "^4.5.0"
}

View File

@@ -228,7 +228,9 @@ export function App() {
if (oldVersion < 11) {
if (oldVersion < 11 && oldVersion >= 1) {
alert("Start upgrading storage, just a sec... (Click OK to continue)");
alert(
"Start upgrading storage, just a sec... (Click OK to continue)"
);
}
if (
transaction
@@ -401,16 +403,16 @@ export function App() {
}, []);
return (
<div className="flex text-sm h-full bg-slate-200 dark:bg-slate-800 dark:text-white">
<div className="flex flex-col h-full p-2 border-r-indigo-500 border-2 dark:border-slate-800 dark:border-r-indigo-500 dark:text-black">
<div className="flex text-sm h-full">
<div className="flex flex-col h-full p-2 bg-primary">
<div className="grow overflow-scroll">
<button
className="w-full bg-violet-300 p-1 rounded hover:bg-violet-400"
className="btn btn-sm btn-info p-1 my-1 w-full"
onClick={handleNewChatStore}
>
{Tr("NEW")}
</button>
<ul>
<ul class="pt-2">
{(allChatStoreIndexes as number[])
.slice()
.reverse()
@@ -419,8 +421,8 @@ export function App() {
return (
<li>
<button
className={`w-full my-1 p-1 rounded hover:bg-blue-500 ${
i === selectedChatIndex ? "bg-blue-500" : "bg-blue-200"
className={`w-full my-1 p-1 btn btn-sm ${
i === selectedChatIndex ? "btn-accent" : "btn-secondary"
}`}
onClick={() => {
setSelectedChatIndex(i);
@@ -433,52 +435,59 @@ export function App() {
})}
</ul>
</div>
<button
className="rounded bg-rose-400 p-1 my-1 w-full"
onClick={async () => {
if (!confirm("Are you sure you want to delete this chat history?"))
return;
console.log("remove item", `${STORAGE_NAME}-${selectedChatIndex}`);
(await db).delete(STORAGE_NAME, selectedChatIndex);
const newAllChatStoreIndexes = await (
await db
).getAllKeys(STORAGE_NAME);
if (newAllChatStoreIndexes.length === 0) {
handleNewChatStore();
return;
}
// find nex selected chat index
const next =
newAllChatStoreIndexes[newAllChatStoreIndexes.length - 1];
console.log("next is", next);
setSelectedChatIndex(next as number);
setAllChatStoreIndexes(newAllChatStoreIndexes);
}}
>
{Tr("DEL")}
</button>
{chatStore.develop_mode && (
<div>
<button
className="rounded bg-rose-800 p-1 my-1 w-full text-white"
className="btn btn-warning btn-sm p-1 my-1 w-full"
onClick={async () => {
if (
!confirm(
"Are you sure you want to delete **ALL** chat history?"
)
!confirm("Are you sure you want to delete this chat history?")
)
return;
console.log(
"remove item",
`${STORAGE_NAME}-${selectedChatIndex}`
);
(await db).delete(STORAGE_NAME, selectedChatIndex);
const newAllChatStoreIndexes = await (
await db
).getAllKeys(STORAGE_NAME);
await (await db).clear(STORAGE_NAME);
setAllChatStoreIndexes([]);
setSelectedChatIndex(1);
window.location.reload();
if (newAllChatStoreIndexes.length === 0) {
handleNewChatStore();
return;
}
// find nex selected chat index
const next =
newAllChatStoreIndexes[newAllChatStoreIndexes.length - 1];
console.log("next is", next);
setSelectedChatIndex(next as number);
setAllChatStoreIndexes(newAllChatStoreIndexes);
}}
>
{Tr("CLS")}
{Tr("DEL")}
</button>
)}
{chatStore.develop_mode && (
<button
className="btn btn-sm btn-warning p-1 my-1 w-full"
onClick={async () => {
if (
!confirm(
"Are you sure you want to delete **ALL** chat history?"
)
)
return;
await (await db).clear(STORAGE_NAME);
setAllChatStoreIndexes([]);
setSelectedChatIndex(1);
window.location.reload();
}}
>
{Tr("CLS")}
</button>
)}
</div>
</div>
<ChatBOX
db={db}

View File

@@ -34,6 +34,7 @@ import { ListToolsTempaltes } from "./listToolsTemplates";
import { autoHeight } from "./textarea";
import Search from "./search";
import { IDBPDatabase } from "idb";
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
export interface TemplateChatStore extends ChatStore {
name: string;
@@ -434,7 +435,7 @@ export default function ChatBOX(props: {
const userInputRef = createRef();
return (
<div className="grow flex flex-col p-2 dark:text-black">
<div className="grow flex flex-col p-2">
{showSettings && (
<Settings
chatStore={chatStore}
@@ -464,11 +465,11 @@ export default function ChatBOX(props: {
/>
)}
<div
className="relative cursor-pointer rounded bg-cyan-300 dark:text-white p-1 dark:bg-cyan-800"
className="relative cursor-pointer rounded p-2 bg-base-200"
onClick={() => setShowSettings(true)}
>
<button
className="absolute right-1 bg-gray-300 rounded p-1 m-1"
className="absolute right-1 rounded p-1 m-1"
onClick={(event) => {
// stop propagation to parent
event.stopPropagation();
@@ -476,7 +477,7 @@ export default function ChatBOX(props: {
setShowSearch(true);
}}
>
🔍
<MagnifyingGlassIcon class="w-5 h-5" />
</button>
<div>
<button className="underline">
@@ -514,12 +515,12 @@ export default function ChatBOX(props: {
</div>
<div className="grow overflow-scroll">
{!chatStore.apiKey && (
<p className="opacity-60 p-6 rounded bg-white my-3 text-left dark:text-black">
<p className="bg-base-200 p-6 rounded my-3 text-left">
{Tr("Please click above to set")} (OpenAI) API KEY
</p>
)}
{!chatStore.apiEndpoint && (
<p className="opacity-60 p-6 rounded bg-white my-3 text-left dark:text-black">
<p className="bg-base-200 p-6 rounded my-3 text-left">
{Tr("Please click above to set")} API Endpoint
</p>
)}
@@ -581,7 +582,7 @@ export default function ChatBOX(props: {
)}
{chatStore.history.filter((msg) => !msg.example).length == 0 && (
<div className="break-all opacity-80 p-3 rounded bg-white my-3 text-left dark:text-black">
<div className="bg-base-200 break-all p-3 my-3 text-left">
<h2>
<span>{Tr("Saved prompt templates")}</span>
<button
@@ -596,7 +597,7 @@ export default function ChatBOX(props: {
{Tr("Reset Current")}
</button>
</h2>
<hr className="my-2" />
<div class="divider"></div>
<div className="flex flex-wrap">
{templates.map((t, index) => (
<div
@@ -729,7 +730,7 @@ export default function ChatBOX(props: {
<p className="text-center">
{chatStore.history.length > 0 && (
<button
className="disabled:line-through disabled:bg-slate-500 rounded m-2 p-2 border-2 bg-teal-500 hover:bg-teal-600"
className="btn btn-warning disabled:line-through disabled:btn-neutral disabled:text-white m-2 p-2"
disabled={showGenerating}
onClick={async () => {
const messageIndex = chatStore.history.length - 1;
@@ -749,7 +750,7 @@ export default function ChatBOX(props: {
)}
{chatStore.develop_mode && chatStore.history.length > 0 && (
<button
className="disabled:line-through disabled:bg-slate-500 rounded m-2 p-2 border-2 bg-yellow-500 hover:bg-yellow-600"
className="btn btn-warning disabled:line-through disabled:bg-neural m-2 p-2"
disabled={showGenerating}
onClick={async () => {
await complete();
@@ -852,15 +853,16 @@ export default function ChatBOX(props: {
<input type="checkbox" checked={follow} />
</span>
)}
<div className="flex justify-between">
<button
className="disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 bg-cyan-400 hover:bg-cyan-600"
className="btn btn-primary disabled:line-through disabled:text-white disabled:bg-neutral m-1 p-1"
disabled={showGenerating || !chatStore.apiKey}
onClick={() => {
setShowAddImage(!showAddImage);
}}
>
Img
Image
</button>
{showAddImage && (
<AddImage
@@ -891,11 +893,11 @@ export default function ChatBOX(props: {
autoHeight(event.target);
setInputMsg(event.target.value);
}}
className="rounded grow m-1 p-1 border-2 border-gray-400 w-0"
className="textarea textarea-bordered textarea-xs grow m-1 p-1 w-0"
placeholder="Type here..."
></textarea>
<button
className="disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 bg-cyan-400 hover:bg-cyan-600"
className="btn btn-primary disabled:btn-neutral disabled:line-through m-1 p-1"
disabled={showGenerating}
onClick={() => {
send(inputMsg, true);
@@ -909,10 +911,8 @@ export default function ChatBOX(props: {
chatStore.whisper_key &&
(chatStore.whisper_key || chatStore.apiKey) && (
<button
className={`disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 ${
isRecording === "Recording"
? "bg-red-400 hover:bg-red-600"
: "bg-cyan-400 hover:bg-cyan-600"
className={`btn disabled:line-through disabled:btn-neutral disabled:text-white m-1 p-1 ${
isRecording === "Recording" ? "btn-error" : "btn-success"
} ${isRecording !== "Mic" ? "animate-pulse" : ""}`}
disabled={isRecording === "Transcribing"}
ref={mediaRef}
@@ -1027,7 +1027,7 @@ export default function ChatBOX(props: {
)}
{chatStore.develop_mode && (
<button
className="disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 bg-cyan-400 hover:bg-cyan-600"
className="btn disabled:line-through disabled:btn-neutral disabled:text-white m-1 p-1"
disabled={showGenerating || !chatStore.apiKey}
onClick={() => {
chatStore.history.push({
@@ -1051,7 +1051,7 @@ export default function ChatBOX(props: {
)}
{chatStore.develop_mode && (
<button
className="disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 bg-cyan-400 hover:bg-cyan-600"
className="btn disabled:line-through disabled:btn-neutral disabled:text-white m-1 p-1"
disabled={showGenerating || !chatStore.apiKey}
onClick={() => {
send(inputMsg, false);
@@ -1062,7 +1062,7 @@ export default function ChatBOX(props: {
)}
{chatStore.develop_mode && (
<button
className="disabled:line-through disabled:bg-slate-500 rounded m-1 p-1 border-2 bg-cyan-400 hover:bg-cyan-600"
className="btn disabled:line-through disabled:btn-neutral disabled:text-white m-1 p-1"
disabled={showGenerating || !chatStore.apiKey}
onClick={() => {
setShowAddToolMsg(true);

View File

@@ -3,25 +3,28 @@ import { App } from "./app";
import { useState, useEffect } from "preact/hooks";
import { Tr, langCodeContext, LANG_OPTIONS } from "./translate";
import { themeChange } from "theme-change";
function Base() {
const [langCode, _setLangCode] = useState("en-US");
const setLangCode = (langCode: string) => {
_setLangCode(langCode)
if (!localStorage) return
_setLangCode(langCode);
if (!localStorage) return;
localStorage.setItem('chatgpt-api-web-lang', langCode)
}
localStorage.setItem("chatgpt-api-web-lang", langCode);
};
// select language
useEffect(() => {
themeChange(false);
// query localStorage
if (localStorage) {
const lang = localStorage.getItem('chatgpt-api-web-lang')
const lang = localStorage.getItem("chatgpt-api-web-lang");
if (lang) {
console.log(`query langCode ${lang} from localStorage`)
_setLangCode(lang)
return
console.log(`query langCode ${lang} from localStorage`);
_setLangCode(lang);
return;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,42 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
daisyui: {
themes: ["light",
"dark",
"cupcake",
"bumblebee",
"emerald",
"corporate",
"synthwave",
"retro",
"cyberpunk",
"valentine",
"halloween",
"garden",
"forest",
"aqua",
"lofi",
"pastel",
"fantasy",
"wireframe",
"black",
"luxury",
"dracula",
"cmyk",
"autumn",
"business",
"acid",
"lemonade",
"night",
"coffee",
"winter",
"dim",
"nord",
"sunset",],
},
theme: {
extend: {},
},
plugins: [],
plugins: [require('daisyui')],
};

511
yarn.lock

File diff suppressed because it is too large Load Diff