Skip to content

Commit

Permalink
Merge pull request ChatGPTNextWeb#1333 from Yidadaa/0508-bugfix
Browse files Browse the repository at this point in the history
feat: ChatGPTNextWeb#1303 and fix ChatGPTNextWeb#1294 1307, new modal style
  • Loading branch information
Yidadaa authored May 8, 2023
2 parents 696e84e + 2223013 commit 8f21e73
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 74 deletions.
28 changes: 28 additions & 0 deletions app/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useSearchParams } from "react-router-dom";

type Command = (param: string) => void;
interface Commands {
fill?: Command;
submit?: Command;
mask?: Command;
}

export function useCommand(commands: Commands = {}) {
const [searchParams, setSearchParams] = useSearchParams();

if (commands === undefined) return;

let shouldUpdate = false;
searchParams.forEach((param, name) => {
const commandName = name as keyof Commands;
if (typeof commands[commandName] === "function") {
commands[commandName]!(param);
searchParams.delete(name);
shouldUpdate = true;
}
});

if (shouldUpdate) {
setSearchParams(searchParams);
}
}
23 changes: 12 additions & 11 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ import {
SubmitKey,
useChatStore,
BOT_HELLO,
ROLES,
createMessage,
useAccessStore,
Theme,
useAppConfig,
ModelConfig,
DEFAULT_TOPIC,
} from "../store";

Expand All @@ -58,11 +56,8 @@ import { useLocation, useNavigate } from "react-router-dom";
import { Path } from "../constant";
import { Avatar } from "./emoji";
import { MaskAvatar, MaskConfig } from "./mask";
import {
DEFAULT_MASK_AVATAR,
DEFAULT_MASK_ID,
useMaskStore,
} from "../store/mask";
import { useMaskStore } from "../store/mask";
import { useCommand } from "../command";

const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
loading: () => <LoadingIcon />,
Expand Down Expand Up @@ -478,8 +473,7 @@ export function Chat() {
}
};

// submit user input
const onUserSubmit = () => {
const doSubmit = (userInput: string) => {
if (userInput.trim() === "") return;
setIsLoading(true);
chatStore.onUserInput(userInput).then(() => setIsLoading(false));
Expand All @@ -504,7 +498,7 @@ export function Chat() {
return;
}
if (shouldSubmit(e)) {
onUserSubmit();
doSubmit(userInput);
e.preventDefault();
}
};
Expand Down Expand Up @@ -618,6 +612,13 @@ export function Chat() {
const isChat = location.pathname === Path.Chat;
const autoFocus = !isMobileScreen || isChat; // only focus in chat page

useCommand({
fill: setUserInput,
submit: (text) => {
doSubmit(text);
},
});

return (
<div className={styles.chat} key={session.id}>
<div className="window-header">
Expand Down Expand Up @@ -816,7 +817,7 @@ export function Chat() {
text={Locale.Chat.Send}
className={styles["chat-input-send"]}
type="primary"
onClick={onUserSubmit}
onClick={() => doSubmit(userInput)}
/>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions app/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from "react-router-dom";
import { SideBar } from "./sidebar";
import { useAppConfig } from "../store/config";
import { useMaskStore } from "../store/mask";

export function Loading(props: { noLogo?: boolean }) {
return (
Expand Down
20 changes: 13 additions & 7 deletions app/components/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@ import mermaid from "mermaid";
import LoadingIcon from "../icons/three-dots.svg";
import React from "react";

export function Mermaid(props: { code: string }) {
export function Mermaid(props: { code: string; onError: () => void }) {
const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
if (props.code && ref.current) {
mermaid.run({
nodes: [ref.current],
});
mermaid
.run({
nodes: [ref.current],
})
.catch((e) => {
props.onError();
console.error("[Mermaid] ", e.message);
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.code]);

function viewSvgInNewWindow() {
Expand All @@ -38,7 +44,7 @@ export function Mermaid(props: { code: string }) {
return (
<div
className="no-dark"
style={{ cursor: "pointer" }}
style={{ cursor: "pointer", overflow: "auto" }}
ref={ref}
onClick={() => viewSvgInNewWindow()}
>
Expand All @@ -60,7 +66,7 @@ export function PreCode(props: { children: any }) {
}, [props.children]);

if (mermaidCode) {
return <Mermaid code={mermaidCode} />;
return <Mermaid code={mermaidCode} onError={() => setMermaidCode("")} />;
}

return (
Expand Down Expand Up @@ -147,7 +153,7 @@ export function Markdown(
}
};

checkInView();
setTimeout(() => checkInView(), 1);

return (
<div
Expand Down
99 changes: 61 additions & 38 deletions app/components/mask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Locale, { AllLangs, Lang } from "../locales";
import { useNavigate } from "react-router-dom";

import chatStyle from "./chat.module.scss";
import { useEffect, useState } from "react";
import { useState } from "react";
import { downloadAs, readFromFile } from "../utils";
import { Updater } from "../api/openai/typing";
import { ModelConfigList } from "./model-config";
Expand Down Expand Up @@ -106,6 +106,59 @@ export function MaskConfig(props: {
);
}

function ContextPromptItem(props: {
prompt: Message;
update: (prompt: Message) => void;
remove: () => void;
}) {
const [focusingInput, setFocusingInput] = useState(false);

return (
<div className={chatStyle["context-prompt-row"]}>
{!focusingInput && (
<select
value={props.prompt.role}
className={chatStyle["context-role"]}
onChange={(e) =>
props.update({
...props.prompt,
role: e.target.value as any,
})
}
>
{ROLES.map((r) => (
<option key={r} value={r}>
{r}
</option>
))}
</select>
)}
<Input
value={props.prompt.content}
type="text"
className={chatStyle["context-content"]}
rows={focusingInput ? 5 : 1}
onFocus={() => setFocusingInput(true)}
onBlur={() => setFocusingInput(false)}
onInput={(e) =>
props.update({
...props.prompt,
content: e.currentTarget.value as any,
})
}
/>
{!focusingInput && (
<IconButton
icon={<DeleteIcon />}
className={chatStyle["context-delete-button"]}
onClick={() => props.remove()}
bordered
/>
)}
</div>
);
}

export function ContextPrompts(props: {
context: Message[];
updateContext: (updater: (context: Message[]) => void) => void;
Expand All @@ -128,42 +181,12 @@ export function ContextPrompts(props: {
<>
<div className={chatStyle["context-prompt"]} style={{ marginBottom: 20 }}>
{context.map((c, i) => (
<div className={chatStyle["context-prompt-row"]} key={i}>
<select
value={c.role}
className={chatStyle["context-role"]}
onChange={(e) =>
updateContextPrompt(i, {
...c,
role: e.target.value as any,
})
}
>
{ROLES.map((r) => (
<option key={r} value={r}>
{r}
</option>
))}
</select>
<Input
value={c.content}
type="text"
className={chatStyle["context-content"]}
rows={1}
onInput={(e) =>
updateContextPrompt(i, {
...c,
content: e.currentTarget.value as any,
})
}
/>
<IconButton
icon={<DeleteIcon />}
className={chatStyle["context-delete-button"]}
onClick={() => removeContextPrompt(i)}
bordered
/>
</div>
<ContextPromptItem
key={i}
prompt={c}
update={(prompt) => updateContextPrompt(i, prompt)}
remove={() => removeContextPrompt(i)}
/>
))}

<div className={chatStyle["context-prompt-row"]}>
Expand All @@ -174,7 +197,7 @@ export function ContextPrompts(props: {
className={chatStyle["context-prompt-button"]}
onClick={() =>
addContextPrompt({
role: "system",
role: "user",
content: "",
date: "",
})
Expand Down
1 change: 0 additions & 1 deletion app/components/model-config.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import styles from "./settings.module.scss";
import { ALL_MODELS, ModalConfigValidator, ModelConfig } from "../store";

import Locale from "../locales";
Expand Down
14 changes: 13 additions & 1 deletion app/components/new-chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Mask, useMaskStore } from "../store/mask";
import Locale from "../locales";
import { useAppConfig, useChatStore } from "../store";
import { MaskAvatar } from "./mask";
import { useCommand } from "../command";

function getIntersectionArea(aRect: DOMRect, bRect: DOMRect) {
const xmin = Math.max(aRect.x, bRect.x);
Expand Down Expand Up @@ -108,9 +109,20 @@ export function NewChat() {

const startChat = (mask?: Mask) => {
chatStore.newSession(mask);
navigate(Path.Chat);
setTimeout(() => navigate(Path.Chat), 1);
};

useCommand({
mask: (id) => {
try {
const mask = maskStore.get(parseInt(id));
startChat(mask ?? undefined);
} catch {
console.error("[New Chat] failed to create chat from mask id=", id);
}
},
});

return (
<div className={styles["new-chat"]}>
<div className={styles["mask-header"]}>
Expand Down
22 changes: 12 additions & 10 deletions app/components/ui-lib.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@
}
}

@media screen and (max-width: 600px) {
.modal-container {
width: 100vw;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;

.modal-content {
max-height: 50vh;
}
}
}

.show {
opacity: 1;
transition: all ease 0.3s;
Expand Down Expand Up @@ -191,13 +203,3 @@
resize: none;
min-width: 50px;
}

@media only screen and (max-width: 600px) {
.modal-container {
width: 90vw;

.modal-content {
max-height: 50vh;
}
}
}
4 changes: 2 additions & 2 deletions app/locales/cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const cn = {
WIP: "该功能仍在开发中……",
Error: {
Unauthorized:
"现在是未授权状态,请点击左下角[设置](/#/settings)按钮输入访问密码。",
"访问密码不正确或为空,请前往[设置](/#/settings)页输入正确的访问密码,或者填入你自己的 OpenAI API Key。",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} 条对话`,
Expand Down Expand Up @@ -149,7 +149,7 @@ const cn = {
},
AccessCode: {
Title: "访问密码",
SubTitle: "已开启加密访问",
SubTitle: "管理员已开启加密访问",
Placeholder: "请输入访问密码",
},
Model: "模型 (model)",
Expand Down
4 changes: 2 additions & 2 deletions app/store/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
requestChatStream,
requestWithPrompt,
} from "../requests";
import { isMobileScreen, trimTopic } from "../utils";
import { trimTopic } from "../utils";

import Locale from "../locales";
import { showToast } from "../components/ui-lib";
import { DEFAULT_CONFIG, ModelConfig, ModelType, useAppConfig } from "./config";
import { ModelType } from "./config";
import { createEmptyMask, Mask } from "./mask";
import { StoreKey } from "../constant";

Expand Down
2 changes: 1 addition & 1 deletion app/store/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const DEFAULT_CONFIG = {

modelConfig: {
model: "gpt-3.5-turbo" as ModelType,
temperature: 1,
temperature: 0.5,
max_tokens: 2000,
presence_penalty: 0,
sendMemory: true,
Expand Down
Loading

0 comments on commit 8f21e73

Please sign in to comment.