mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	refactor: #6 check update over one hour and debound scroll
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
				
			|||||||
"use client";
 | 
					"use client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useState, useRef, useEffect } from "react";
 | 
					import { useState, useRef, useEffect, useLayoutEffect } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { IconButton } from "./button";
 | 
					import { IconButton } from "./button";
 | 
				
			||||||
import styles from "./home.module.scss";
 | 
					import styles from "./home.module.scss";
 | 
				
			||||||
@@ -192,14 +192,16 @@ export function Chat(props: { showSideBar?: () => void }) {
 | 
				
			|||||||
        : []
 | 
					        : []
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					  useLayoutEffect(() => {
 | 
				
			||||||
    const dom = latestMessageRef.current;
 | 
					    setTimeout(() => {
 | 
				
			||||||
    if (dom && !isIOS()) {
 | 
					      const dom = latestMessageRef.current;
 | 
				
			||||||
      dom.scrollIntoView({
 | 
					      if (dom && !isIOS()) {
 | 
				
			||||||
        behavior: "smooth",
 | 
					        dom.scrollIntoView({
 | 
				
			||||||
        block: "end",
 | 
					          behavior: "smooth",
 | 
				
			||||||
      });
 | 
					          block: "end",
 | 
				
			||||||
    }
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }, 500);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
@@ -296,9 +298,9 @@ export function Chat(props: { showSideBar?: () => void }) {
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
        })}
 | 
					        })}
 | 
				
			||||||
        <span ref={latestMessageRef} style={{ opacity: 0 }}>
 | 
					        <div ref={latestMessageRef} style={{ opacity: 0, height: "2em" }}>
 | 
				
			||||||
          -
 | 
					          -
 | 
				
			||||||
        </span>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className={styles["chat-input-panel"]}>
 | 
					      <div className={styles["chat-input-panel"]}>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,11 +11,17 @@ import ClearIcon from "../icons/clear.svg";
 | 
				
			|||||||
import { List, ListItem, Popover } from "./ui-lib";
 | 
					import { List, ListItem, Popover } from "./ui-lib";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { IconButton } from "./button";
 | 
					import { IconButton } from "./button";
 | 
				
			||||||
import { SubmitKey, useChatStore, Theme, ALL_MODELS } from "../store";
 | 
					import {
 | 
				
			||||||
 | 
					  SubmitKey,
 | 
				
			||||||
 | 
					  useChatStore,
 | 
				
			||||||
 | 
					  Theme,
 | 
				
			||||||
 | 
					  ALL_MODELS,
 | 
				
			||||||
 | 
					  useUpdateStore,
 | 
				
			||||||
 | 
					} from "../store";
 | 
				
			||||||
import { Avatar } from "./home";
 | 
					import { Avatar } from "./home";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Locale, { changeLang, getLang } from "../locales";
 | 
					import Locale, { changeLang, getLang } from "../locales";
 | 
				
			||||||
import { checkUpstreamLatestCommitId, getCurrentCommitId } from "../utils";
 | 
					import { getCurrentCommitId } from "../utils";
 | 
				
			||||||
import Link from "next/link";
 | 
					import Link from "next/link";
 | 
				
			||||||
import { UPDATE_URL } from "../constant";
 | 
					import { UPDATE_URL } from "../constant";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,15 +54,15 @@ export function Settings(props: { closeSettings: () => void }) {
 | 
				
			|||||||
    ]
 | 
					    ]
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const currentId = getCurrentCommitId();
 | 
					  const updateStore = useUpdateStore();
 | 
				
			||||||
  const [checkingUpdate, setCheckingUpdate] = useState(false);
 | 
					  const [checkingUpdate, setCheckingUpdate] = useState(false);
 | 
				
			||||||
  const [remoteId, setRemoteId] = useState<string>();
 | 
					  const currentId = getCurrentCommitId();
 | 
				
			||||||
 | 
					  const remoteId = updateStore.remoteId;
 | 
				
			||||||
  const hasNewVersion = currentId !== remoteId;
 | 
					  const hasNewVersion = currentId !== remoteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function checkUpdate(force = false) {
 | 
					  function checkUpdate(force = false) {
 | 
				
			||||||
    setCheckingUpdate(true);
 | 
					    setCheckingUpdate(true);
 | 
				
			||||||
    checkUpstreamLatestCommitId(force).then((id) => {
 | 
					    updateStore.getLatestCommitId(force).then(() => {
 | 
				
			||||||
      setRemoteId(id);
 | 
					 | 
				
			||||||
      setCheckingUpdate(false);
 | 
					      setCheckingUpdate(false);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
export const REPO_URL = "https://github.com/Yidadaa/ChatGPT-Next-Web";
 | 
					export const OWNER = "Yidadaa";
 | 
				
			||||||
export const UPDATE_URL =
 | 
					export const REPO = "ChatGPT-Next-Web";
 | 
				
			||||||
  "https://github.com/Yidadaa/ChatGPT-Next-Web#%E4%BF%9D%E6%8C%81%E6%9B%B4%E6%96%B0-keep-updated";
 | 
					export const REPO_URL = `https://github.com/${OWNER}/${REPO}`;
 | 
				
			||||||
 | 
					export const UPDATE_URL = `${REPO_URL}#%E4%BF%9D%E6%8C%81%E6%9B%B4%E6%96%B0-keep-updated`;
 | 
				
			||||||
 | 
					export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
import type { ChatRequest, ChatReponse } from "./api/chat/typing";
 | 
					import type { ChatRequest, ChatReponse } from "./api/chat/typing";
 | 
				
			||||||
import { filterConfig, isValidModel, Message, ModelConfig } from "./store";
 | 
					import { filterConfig, Message, ModelConfig } from "./store";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TIME_OUT_MS = 30000;
 | 
					const TIME_OUT_MS = 30000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,10 +2,10 @@ import { create } from "zustand";
 | 
				
			|||||||
import { persist } from "zustand/middleware";
 | 
					import { persist } from "zustand/middleware";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { type ChatCompletionResponseMessage } from "openai";
 | 
					import { type ChatCompletionResponseMessage } from "openai";
 | 
				
			||||||
import { requestChatStream, requestWithPrompt } from "./requests";
 | 
					import { requestChatStream, requestWithPrompt } from "../requests";
 | 
				
			||||||
import { trimTopic } from "./utils";
 | 
					import { trimTopic } from "../utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Locale from "./locales";
 | 
					import Locale from "../locales";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type Message = ChatCompletionResponseMessage & {
 | 
					export type Message = ChatCompletionResponseMessage & {
 | 
				
			||||||
  date: string;
 | 
					  date: string;
 | 
				
			||||||
							
								
								
									
										2
									
								
								app/store/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/store/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					export * from "./app";
 | 
				
			||||||
 | 
					export * from "./update";
 | 
				
			||||||
							
								
								
									
										49
									
								
								app/store/update.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/store/update.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					import { create } from "zustand";
 | 
				
			||||||
 | 
					import { persist } from "zustand/middleware";
 | 
				
			||||||
 | 
					import { FETCH_COMMIT_URL } from "../constant";
 | 
				
			||||||
 | 
					import { getCurrentCommitId } from "../utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface UpdateStore {
 | 
				
			||||||
 | 
					  lastUpdate: number;
 | 
				
			||||||
 | 
					  remoteId: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getLatestCommitId: (force: boolean) => Promise<string>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const UPDATE_KEY = "chat-update";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useUpdateStore = create<UpdateStore>()(
 | 
				
			||||||
 | 
					  persist(
 | 
				
			||||||
 | 
					    (set, get) => ({
 | 
				
			||||||
 | 
					      lastUpdate: 0,
 | 
				
			||||||
 | 
					      remoteId: "",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      async getLatestCommitId(force = false) {
 | 
				
			||||||
 | 
					        const overOneHour = Date.now() - get().lastUpdate > 3600 * 1000;
 | 
				
			||||||
 | 
					        const shouldFetch = force || overOneHour;
 | 
				
			||||||
 | 
					        if (!shouldFetch) {
 | 
				
			||||||
 | 
					          return getCurrentCommitId();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          const data = await (await fetch(FETCH_COMMIT_URL)).json();
 | 
				
			||||||
 | 
					          const sha = data[0].sha as string;
 | 
				
			||||||
 | 
					          const remoteId = sha.substring(0, 7);
 | 
				
			||||||
 | 
					          set(() => ({
 | 
				
			||||||
 | 
					            lastUpdate: Date.now(),
 | 
				
			||||||
 | 
					            remoteId,
 | 
				
			||||||
 | 
					          }));
 | 
				
			||||||
 | 
					          console.log("[Got Upstream] ", remoteId);
 | 
				
			||||||
 | 
					          return remoteId;
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					          console.error("[Fetch Upstream Commit Id]", error);
 | 
				
			||||||
 | 
					          return getCurrentCommitId();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name: UPDATE_KEY,
 | 
				
			||||||
 | 
					      version: 1,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@@ -199,7 +199,6 @@ div.math {
 | 
				
			|||||||
  font-size: 12px;
 | 
					  font-size: 12px;
 | 
				
			||||||
  color: var(--primary);
 | 
					  color: var(--primary);
 | 
				
			||||||
  text-decoration: none;
 | 
					  text-decoration: none;
 | 
				
			||||||
  padding: 5px 10px;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &:hover {
 | 
					  &:hover {
 | 
				
			||||||
    text-decoration: underline;
 | 
					    text-decoration: underline;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								app/utils.ts
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								app/utils.ts
									
									
									
									
									
								
							@@ -74,24 +74,3 @@ export function getCurrentCommitId() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return currentId;
 | 
					  return currentId;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
let remoteId: string;
 | 
					 | 
				
			||||||
export async function checkUpstreamLatestCommitId(force = false) {
 | 
					 | 
				
			||||||
  if (!force && remoteId) {
 | 
					 | 
				
			||||||
    return remoteId;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const owner = "Yidadaa";
 | 
					 | 
				
			||||||
  const repo = "ChatGPT-Next-Web";
 | 
					 | 
				
			||||||
  const url = `https://api.github.com/repos/${owner}/${repo}/commits?per_page=1`;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const data = await (await fetch(url)).json();
 | 
					 | 
				
			||||||
    const sha = data[0].sha as string;
 | 
					 | 
				
			||||||
    remoteId = sha.substring(0, 7);
 | 
					 | 
				
			||||||
    return remoteId;
 | 
					 | 
				
			||||||
  } catch (error) {
 | 
					 | 
				
			||||||
    console.error("[Fetch Upstream Commit Id]", error);
 | 
					 | 
				
			||||||
    return getCurrentCommitId();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user