Browse Source

refactor: #6 check update over one hour and debound scroll

Yifei Zhang 2 years ago
parent
commit
99b88f36fd
9 changed files with 85 additions and 46 deletions
  1. 13 11
      app/components/home.tsx
  2. 12 6
      app/components/settings.tsx
  3. 5 3
      app/constant.ts
  4. 1 1
      app/requests.ts
  5. 3 3
      app/store/app.ts
  6. 2 0
      app/store/index.ts
  7. 49 0
      app/store/update.ts
  8. 0 1
      app/styles/globals.scss
  9. 0 21
      app/utils.ts

+ 13 - 11
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 }) {
             </div>
           );
         })}
-        <span ref={latestMessageRef} style={{ opacity: 0 }}>
+        <div ref={latestMessageRef} style={{ opacity: 0, height: "2em" }}>
           -
-        </span>
+        </div>
       </div>
 
       <div className={styles["chat-input-panel"]}>

+ 12 - 6
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<string>();
+  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);
     });
   }

+ 5 - 3
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`;

+ 1 - 1
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;
 

+ 3 - 3
app/store.ts → 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;

+ 2 - 0
app/store/index.ts

@@ -0,0 +1,2 @@
+export * from "./app";
+export * from "./update";

+ 49 - 0
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<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,
+    }
+  )
+);

+ 0 - 1
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;

+ 0 - 21
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();
-  }
-}