mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	feat: close #118 add stop all button
This commit is contained in:
		@@ -19,6 +19,7 @@ import LightIcon from "../icons/light.svg";
 | 
			
		||||
import DarkIcon from "../icons/dark.svg";
 | 
			
		||||
import AutoIcon from "../icons/auto.svg";
 | 
			
		||||
import BottomIcon from "../icons/bottom.svg";
 | 
			
		||||
import StopIcon from "../icons/pause.svg";
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  Message,
 | 
			
		||||
@@ -38,7 +39,6 @@ import {
 | 
			
		||||
  isMobileScreen,
 | 
			
		||||
  selectOrCopy,
 | 
			
		||||
  autoGrowTextArea,
 | 
			
		||||
  getCSSVar,
 | 
			
		||||
} from "../utils";
 | 
			
		||||
 | 
			
		||||
import dynamic from "next/dynamic";
 | 
			
		||||
@@ -355,8 +355,8 @@ export function ChatActions(props: {
 | 
			
		||||
}) {
 | 
			
		||||
  const chatStore = useChatStore();
 | 
			
		||||
 | 
			
		||||
  // switch themes
 | 
			
		||||
  const theme = chatStore.config.theme;
 | 
			
		||||
 | 
			
		||||
  function nextTheme() {
 | 
			
		||||
    const themes = [Theme.Auto, Theme.Light, Theme.Dark];
 | 
			
		||||
    const themeIndex = themes.indexOf(theme);
 | 
			
		||||
@@ -365,8 +365,20 @@ export function ChatActions(props: {
 | 
			
		||||
    chatStore.updateConfig((config) => (config.theme = nextTheme));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // stop all responses
 | 
			
		||||
  const couldStop = ControllerPool.hasPending();
 | 
			
		||||
  const stopAll = () => ControllerPool.stopAll();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={chatStyle["chat-input-actions"]}>
 | 
			
		||||
      {couldStop && (
 | 
			
		||||
        <div
 | 
			
		||||
          className={`${chatStyle["chat-input-action"]} clickable`}
 | 
			
		||||
          onClick={stopAll}
 | 
			
		||||
        >
 | 
			
		||||
          <StopIcon />
 | 
			
		||||
        </div>
 | 
			
		||||
      )}
 | 
			
		||||
      {!props.hitBottom && (
 | 
			
		||||
        <div
 | 
			
		||||
          className={`${chatStyle["chat-input-action"]} clickable`}
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><defs><rect id="path_0" x="0" y="0" width="16" height="16" /></defs><g opacity="1" transform="translate(0 0)  rotate(0 8 8)"><mask id="bg-mask-0" fill="white"><use xlink:href="#path_0"></use></mask><g mask="url(#bg-mask-0)" ><path  id="路径 1" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(8.002766666666666 2)  rotate(0 0 4.649916666666667)" d="M0,9.3L0,0 " /><path  id="路径 2" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(4 7.333333333333333)  rotate(0 4 2)" d="M8,0L4,4L0,0 " /><path  id="路径 3" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(4 14)  rotate(0 4 0)" d="M8,0L0,0 " /></g></g></svg>
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><defs><rect id="path_0" x="0" y="0" width="16" height="16" /></defs><g opacity="1" transform="translate(0 0)  rotate(0 8 8)"><mask id="bg-mask-0" fill="white"><use xlink:href="#path_0"></use></mask><g mask="url(#bg-mask-0)" ><path  id="路径 1" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(4 4)  rotate(0 4 2)" d="M8,0L4,4L0,0 " /><path  id="路径 2" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(4 8)  rotate(0 4 2)" d="M8,0L4,4L0,0 " /></g></g></svg>
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 958 B After Width: | Height: | Size: 736 B  | 
							
								
								
									
										1
									
								
								app/icons/pause.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								app/icons/pause.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><defs><rect id="path_0" x="0" y="0" width="16" height="16" /></defs><g opacity="1" transform="translate(0 0)  rotate(0 8 8)"><mask id="bg-mask-0" fill="white"><use xlink:href="#path_0"></use></mask><g mask="url(#bg-mask-0)" ><path  id="路径 1" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(1.3333333333333333 1.3333333333333333)  rotate(0 6.666666666666666 6.666666666666666)" d="M13.33,6.67C13.33,2.98 10.35,0 6.67,0C2.98,0 0,2.98 0,6.67C0,10.35 2.98,13.33 6.67,13.33C10.35,13.33 13.33,10.35 13.33,6.67Z " /><path  id="路径 2" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(6.333333333333333 6)  rotate(0 0 2)" d="M0,0L0,4 " /><path  id="路径 3" style="stroke:#333333; stroke-width:1.3333333333333333; stroke-opacity:1; stroke-dasharray:0 0" transform="translate(9.666666666666666 6)  rotate(0 0 2)" d="M0,0L0,4 " /></g></g></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
@@ -2,7 +2,7 @@ import type { ChatRequest, ChatResponse } from "./api/openai/typing";
 | 
			
		||||
import { Message, ModelConfig, useAccessStore, useChatStore } from "./store";
 | 
			
		||||
import { showToast } from "./components/ui-lib";
 | 
			
		||||
 | 
			
		||||
const TIME_OUT_MS = 30000;
 | 
			
		||||
const TIME_OUT_MS = 60000;
 | 
			
		||||
 | 
			
		||||
const makeRequestParam = (
 | 
			
		||||
  messages: Message[],
 | 
			
		||||
@@ -167,15 +167,14 @@ export async function requestChatStream(
 | 
			
		||||
      options?.onController?.(controller);
 | 
			
		||||
 | 
			
		||||
      while (true) {
 | 
			
		||||
        // handle time out, will stop if no response in 10 secs
 | 
			
		||||
        const resTimeoutId = setTimeout(() => finish(), TIME_OUT_MS);
 | 
			
		||||
        const content = await reader?.read();
 | 
			
		||||
        clearTimeout(resTimeoutId);
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
        if (!content || !content.value) {
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
        const text = decoder.decode(content.value, { stream: true });
 | 
			
		||||
        responseText += text;
 | 
			
		||||
 | 
			
		||||
@@ -235,6 +234,14 @@ export const ControllerPool = {
 | 
			
		||||
    controller?.abort();
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  stopAll() {
 | 
			
		||||
    Object.values(this.controllers).forEach((v) => v.abort());
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  hasPending() {
 | 
			
		||||
    return Object.values(this.controllers).length > 0;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  remove(sessionIndex: number, messageId: number) {
 | 
			
		||||
    const key = this.key(sessionIndex, messageId);
 | 
			
		||||
    delete this.controllers[key];
 | 
			
		||||
 
 | 
			
		||||
@@ -421,7 +421,7 @@ export const useChatStore = create<ChatStore>()(
 | 
			
		||||
          onError(error, statusCode) {
 | 
			
		||||
            if (statusCode === 401) {
 | 
			
		||||
              botMessage.content = Locale.Error.Unauthorized;
 | 
			
		||||
            } else {
 | 
			
		||||
            } else if (!error.message.includes("aborted")) {
 | 
			
		||||
              botMessage.content += "\n\n" + Locale.Store.Error;
 | 
			
		||||
            }
 | 
			
		||||
            botMessage.streaming = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,8 @@
 | 
			
		||||
    "start": "next start",
 | 
			
		||||
    "lint": "next lint",
 | 
			
		||||
    "fetch": "node ./scripts/fetch-prompts.mjs",
 | 
			
		||||
    "prepare": "husky install"
 | 
			
		||||
    "prepare": "husky install",
 | 
			
		||||
    "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@hello-pangea/dnd": "^16.2.0",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								scripts/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								scripts/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
proxychains.conf
 | 
			
		||||
							
								
								
									
										5
									
								
								scripts/init-proxy.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								scripts/init-proxy.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
dir="$(dirname "$0")"
 | 
			
		||||
config=$dir/proxychains.conf
 | 
			
		||||
host_ip=$(grep nameserver /etc/resolv.conf | sed 's/nameserver //')
 | 
			
		||||
cp $dir/proxychains.template.conf $config 
 | 
			
		||||
sed -i "\$s/.*/http $host_ip 7890/" $config
 | 
			
		||||
							
								
								
									
										12
									
								
								scripts/proxychains.template.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								scripts/proxychains.template.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
strict_chain
 | 
			
		||||
proxy_dns 
 | 
			
		||||
 | 
			
		||||
remote_dns_subnet 224
 | 
			
		||||
 | 
			
		||||
tcp_read_time_out 15000
 | 
			
		||||
tcp_connect_time_out 8000
 | 
			
		||||
 | 
			
		||||
localnet 127.0.0.0/255.0.0.0
 | 
			
		||||
 | 
			
		||||
[ProxyList]
 | 
			
		||||
socks4 	127.0.0.1 9050
 | 
			
		||||
		Reference in New Issue
	
	Block a user