diff --git a/app/components/home.tsx b/app/components/home.tsx index 28f39e74..5087f5c7 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useRef, useEffect } from "react"; +import { useState, useRef, useEffect, useLayoutEffect } from "react"; import { IconButton } from "./button"; import styles from "./home.module.scss"; @@ -192,14 +192,16 @@ export function Chat(props: { showSideBar?: () => void }) { : [] ); - useEffect(() => { - const dom = latestMessageRef.current; - if (dom && !isIOS()) { - dom.scrollIntoView({ - behavior: "smooth", - block: "end", - }); - } + useLayoutEffect(() => { + setTimeout(() => { + const dom = latestMessageRef.current; + if (dom && !isIOS()) { + dom.scrollIntoView({ + behavior: "smooth", + block: "end", + }); + } + }, 500); }); return ( @@ -296,9 +298,9 @@ export function Chat(props: { showSideBar?: () => void }) { ); })} - +
- - +
diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 4966e9c4..9623c3f9 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -11,11 +11,17 @@ import ClearIcon from "../icons/clear.svg"; import { List, ListItem, Popover } from "./ui-lib"; 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 Locale, { changeLang, getLang } from "../locales"; -import { checkUpstreamLatestCommitId, getCurrentCommitId } from "../utils"; +import { getCurrentCommitId } from "../utils"; import Link from "next/link"; 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 [remoteId, setRemoteId] = useState(); + const currentId = getCurrentCommitId(); + const remoteId = updateStore.remoteId; const hasNewVersion = currentId !== remoteId; function checkUpdate(force = false) { setCheckingUpdate(true); - checkUpstreamLatestCommitId(force).then((id) => { - setRemoteId(id); + updateStore.getLatestCommitId(force).then(() => { setCheckingUpdate(false); }); } diff --git a/app/constant.ts b/app/constant.ts index a5cadb14..818ef1fb 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -1,3 +1,5 @@ -export const REPO_URL = "https://github.com/Yidadaa/ChatGPT-Next-Web"; -export const UPDATE_URL = - "https://github.com/Yidadaa/ChatGPT-Next-Web#%E4%BF%9D%E6%8C%81%E6%9B%B4%E6%96%B0-keep-updated"; +export const OWNER = "Yidadaa"; +export const REPO = "ChatGPT-Next-Web"; +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`; diff --git a/app/requests.ts b/app/requests.ts index 87f780b3..d502dc15 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -1,5 +1,5 @@ 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; diff --git a/app/store.ts b/app/store/app.ts similarity index 98% rename from app/store.ts rename to app/store/app.ts index 4df62733..91abb2c8 100644 --- a/app/store.ts +++ b/app/store/app.ts @@ -2,10 +2,10 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; import { type ChatCompletionResponseMessage } from "openai"; -import { requestChatStream, requestWithPrompt } from "./requests"; -import { trimTopic } from "./utils"; +import { requestChatStream, requestWithPrompt } from "../requests"; +import { trimTopic } from "../utils"; -import Locale from "./locales"; +import Locale from "../locales"; export type Message = ChatCompletionResponseMessage & { date: string; diff --git a/app/store/index.ts b/app/store/index.ts new file mode 100644 index 00000000..b247a7cd --- /dev/null +++ b/app/store/index.ts @@ -0,0 +1,2 @@ +export * from "./app"; +export * from "./update"; diff --git a/app/store/update.ts b/app/store/update.ts new file mode 100644 index 00000000..118ea3ce --- /dev/null +++ b/app/store/update.ts @@ -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; +} + +export const UPDATE_KEY = "chat-update"; + +export const useUpdateStore = create()( + 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, + } + ) +); diff --git a/app/styles/globals.scss b/app/styles/globals.scss index c14491cb..fde2239a 100644 --- a/app/styles/globals.scss +++ b/app/styles/globals.scss @@ -199,7 +199,6 @@ div.math { font-size: 12px; color: var(--primary); text-decoration: none; - padding: 5px 10px; &:hover { text-decoration: underline; diff --git a/app/utils.ts b/app/utils.ts index a1b1f10b..bcf45d9c 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -74,24 +74,3 @@ export function getCurrentCommitId() { 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(); - } -}