diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 1c9dc413c..9c7b7e6f1 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -2,28 +2,29 @@ name: Upstream Sync on: schedule: - - cron: '0 */12 * * *' # every 12 hours - workflow_dispatch: # on button click + - cron: "0 */6 * * *" # every 6 hours + workflow_dispatch: jobs: sync_latest_from_upstream: name: Sync latest commits from upstream repo runs-on: ubuntu-latest + if: ${{ github.event.repository.fork }} steps: - # Step 1: run a standard checkout action, provided by github - - name: Checkout target repo - uses: actions/checkout@v3 + # Step 1: run a standard checkout action, provided by github + - name: Checkout target repo + uses: actions/checkout@v3 - # Step 2: run the sync action - - name: Sync upstream changes - id: sync - uses: aormsby/Fork-Sync-With-Upstream-action@v3.4 - with: - upstream_sync_repo: Yidadaa/ChatGPT-Next-Web - upstream_sync_branch: main - target_sync_branch: main - target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set - - # Set test_mode true to run tests instead of the true action!! - test_mode: false + # Step 2: run the sync action + - name: Sync upstream changes + id: sync + uses: aormsby/Fork-Sync-With-Upstream-action@v3.4 + with: + upstream_sync_repo: Yidadaa/ChatGPT-Next-Web + upstream_sync_branch: main + target_sync_branch: main + target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set + + # Set test_mode true to run tests instead of the true action!! + test_mode: false diff --git a/README.md b/README.md index 23c3d0b84..815aba1af 100644 --- a/README.md +++ b/README.md @@ -182,16 +182,8 @@ docker run -d -p 3000:3000 -e OPENAI_API_KEY="" -e CODE="" yidadaa/chatgpt-next- ![更多展示 More](./static/more.png) -## 捐赠 Donate USDT - -> BNB Smart Chain (BEP 20) - -``` -0x67cD02c7EB62641De576a1fA3EdB32eA0c3ffD89 -``` ## 鸣谢 Special Thanks - ### 捐赠者 Sponsor [@mushan0x0](https://github.com/mushan0x0) diff --git a/app/api/chat-stream/route.ts b/app/api/chat-stream/route.ts index e7bdfc5fb..f33175543 100644 --- a/app/api/chat-stream/route.ts +++ b/app/api/chat-stream/route.ts @@ -8,6 +8,15 @@ async function createStream(req: NextRequest) { const res = await requestOpenai(req); + const contentType = res.headers.get("Content-Type") ?? ""; + if (!contentType.includes("stream")) { + const content = await ( + await res.text() + ).replace(/provided:.*. You/, "provided: ***. You"); + console.log("[Stream] error ", content); + return "```json\n" + content + "```"; + } + const stream = new ReadableStream({ async start(controller) { function onParse(event: any) { diff --git a/app/components/chat.tsx b/app/components/chat.tsx index f94cee9a0..94ae484ce 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -452,7 +452,7 @@ export function Chat(props: {}) { role: "user", content: userInput, date: new Date().toLocaleString(), - preview: false, + preview: true, }, ] : [], @@ -460,6 +460,12 @@ export function Chat(props: {}) { const [showPromptModal, setShowPromptModal] = useState(false); + // Auto focus + useEffect(() => { + if (sidebarCollapse && isMobileScreen()) return; + inputRef.current?.focus(); + }, [sidebarCollapse]); + return (
@@ -525,6 +531,7 @@ export function Chat(props: {}) { className={styles["chat-body"]} ref={scrollRef} onScroll={(e) => onChatBodyScroll(e.currentTarget)} + onTouchStart={() => inputRef.current?.blur()} > {messages.map((message, i) => { const isUser = message.role === "user"; @@ -545,10 +552,7 @@ export function Chat(props: {}) { {Locale.Chat.Typing}
)} -
inputRef.current?.blur()} - > +
{!isUser && !(message.preview || message.content.length === 0) && (
@@ -588,6 +592,7 @@ export function Chat(props: {}) { if (!isMobileScreen()) return; setUserInput(message.content); }} + onMouseOver={() => inputRef.current?.blur()} >
@@ -622,6 +627,9 @@ export function Chat(props: {}) { setAutoScroll(false); setTimeout(() => setPromptHints([]), 500); }} + onMouseOver={() => { + inputRef.current?.focus(); + }} autoFocus={sidebarCollapse} /> { return isValidModel(x as string); }, max_tokens(x) { - return isValidNumber(x as number, 100, 4000); + return isValidNumber(x as number, 100, 32000); }, presence_penalty(x) { return isValidNumber(x as number, -2, 2); diff --git a/app/styles/globals.scss b/app/styles/globals.scss index ff2cf1e54..a723495f4 100644 --- a/app/styles/globals.scss +++ b/app/styles/globals.scss @@ -190,7 +190,7 @@ input[type="text"] { appearance: none; border-radius: 10px; border: var(--border-in-light); - height: 36px; + min-height: 36px; box-sizing: border-box; background: var(--white); color: var(--black); diff --git a/app/styles/highlight.scss b/app/styles/highlight.scss index f1314a263..8aee8b6c6 100644 --- a/app/styles/highlight.scss +++ b/app/styles/highlight.scss @@ -8,16 +8,22 @@ font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; } - pre code.hljs { + pre code { display: block; overflow-x: auto; padding: 1em; } - code.hljs { + code { padding: 3px 5px; } + .hljs, + pre { + background: #1a1b26; + color: #cbd2ea; + } + /*! Theme: Tokyo-night-Dark origin: https://github.com/enkia/tokyo-night-vscode-theme @@ -99,11 +105,6 @@ color: #c0caf5; } - .hljs { - background: #1a1b26; - color: #9aa5ce; - } - .hljs-emphasis { font-style: italic; } diff --git a/app/utils.ts b/app/utils.ts index 1fb3d3166..5fe277c63 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -5,15 +5,19 @@ export function trimTopic(topic: string) { return topic.replace(/[,。!?、,.!?]*$/, ""); } -export function copyToClipboard(text: string) { - navigator.clipboard - .writeText(text) - .then((res) => { - showToast(Locale.Copy.Success); - }) - .catch((err) => { - showToast(Locale.Copy.Failed); - }); +export async function copyToClipboard(text: string) { + try { + await navigator.clipboard.writeText(text); + } catch (error) { + const textarea = document.createElement("textarea"); + textarea.value = text; + document.body.appendChild(textarea); + textarea.select(); + document.execCommand("copy"); + document.body.removeChild(textarea); + } finally { + showToast(Locale.Copy.Success); + } } export function downloadAs(text: string, filename: string) {