feat: add check update

This commit is contained in:
Yifei Zhang
2023-03-23 16:01:00 +00:00
parent e55520e93c
commit 29de957395
13 changed files with 201 additions and 5257 deletions

View File

@@ -26,6 +26,7 @@ import { copyToClipboard, downloadAs, isIOS, selectOrCopy } from "../utils";
import Locale from "../locales";
import dynamic from "next/dynamic";
import { REPO_URL } from "../constant";
export function Loading(props: { noLogo?: boolean }) {
return (
@@ -466,10 +467,7 @@ export function Home() {
/>
</div>
<div className={styles["sidebar-action"]}>
<a
href="https://github.com/Yidadaa/ChatGPT-Next-Web"
target="_blank"
>
<a href={REPO_URL} target="_blank">
<IconButton icon={<GithubIcon />} />
</a>
</div>

View File

@@ -1,4 +1,4 @@
import { useState } from "react";
import { useState, useEffect } from "react";
import EmojiPicker, { Theme as EmojiTheme } from "emoji-picker-react";
@@ -15,6 +15,9 @@ import { SubmitKey, useChatStore, Theme, ALL_MODELS } from "../store";
import { Avatar } from "./home";
import Locale, { changeLang, getLang } from "../locales";
import { checkUpstreamLatestCommitId, getCurrentCommitId } from "../utils";
import Link from "next/link";
import { UPDATE_URL } from "../constant";
function SettingItem(props: {
title: string;
@@ -45,6 +48,23 @@ export function Settings(props: { closeSettings: () => void }) {
]
);
const currentId = getCurrentCommitId();
const [checkingUpdate, setCheckingUpdate] = useState(false);
const [remoteId, setRemoteId] = useState<string>();
const hasNewVersion = currentId !== remoteId;
function checkUpdate(force = false) {
setCheckingUpdate(true);
checkUpstreamLatestCommitId(force).then((id) => {
setRemoteId(id);
setCheckingUpdate(false);
});
}
useEffect(() => {
checkUpdate();
}, []);
return (
<>
<div className={styles["window-header"]}>
@@ -109,6 +129,31 @@ export function Settings(props: { closeSettings: () => void }) {
</Popover>
</SettingItem>
<SettingItem
title={Locale.Settings.Update.Version(currentId)}
subTitle={
checkingUpdate
? Locale.Settings.Update.IsChecking
: hasNewVersion
? Locale.Settings.Update.FoundUpdate(remoteId ?? "ERROR")
: Locale.Settings.Update.IsLatest
}
>
{checkingUpdate ? (
<div />
) : hasNewVersion ? (
<Link href={UPDATE_URL} target="_blank" className="link">
{Locale.Settings.Update.GoToUpdate}
</Link>
) : (
<IconButton
icon={<ResetIcon></ResetIcon>}
text={Locale.Settings.Update.CheckUpdate}
onClick={() => checkUpdate(true)}
/>
)}
</SettingItem>
<SettingItem title={Locale.Settings.SendKey}>
<select
value={config.submitKey}

3
app/constant.ts Normal file
View File

@@ -0,0 +1,3 @@
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";

View File

@@ -4,9 +4,11 @@ import "./styles/prism.scss";
export const metadata = {
title: "ChatGPT Next Web",
description: "Your personal ChatGPT Chat Bot.",
description: "Your personal ChatGPT Chat Bot."
};
const COMMIT_ID = process.env.COMMIT_ID
export default function RootLayout({
children,
}: {
@@ -19,7 +21,14 @@ export default function RootLayout({
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<meta name="version" content={COMMIT_ID} />
<link rel="manifest" href="/site.webmanifest"></link>
<link rel="preconnect" href="https://fonts.googleapis.com"></link>
<link rel="preconnect" href="https://fonts.gstatic.com"></link>
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;700;900&display=swap"
rel="stylesheet"
></link>
</head>
<body>{children}</body>
</html>

View File

@@ -43,6 +43,14 @@ const cn = {
},
},
Avatar: "头像",
Update: {
Version: (x: string) => `当前版本:${x}`,
IsLatest: "已是最新版本",
CheckUpdate: "检查更新",
IsChecking: "正在检查更新...",
FoundUpdate: (x: string) => `发现新版本:${x}`,
GoToUpdate: "前往更新",
},
SendKey: "发送键",
Theme: "主题",
TightBorder: "紧凑边框",

View File

@@ -46,6 +46,14 @@ const en: LocaleType = {
},
},
Avatar: "Avatar",
Update: {
Version: (x: string) => `Version: ${x}`,
IsLatest: "Latest version",
CheckUpdate: "Check Update",
IsChecking: "Checking update...",
FoundUpdate: (x: string) => `Found new version: ${x}`,
GoToUpdate: "Update",
},
SendKey: "Send Key",
Theme: "Theme",
TightBorder: "Tight Border",

View File

@@ -83,6 +83,8 @@ body {
justify-content: center;
align-items: center;
user-select: none;
font-family: "Noto Sans SC", "SF Pro SC", "SF Pro Text", "SF Pro Icons",
"PingFang SC", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
::-webkit-scrollbar {
@@ -192,3 +194,14 @@ div.math {
align-items: center;
justify-content: center;
}
.link {
font-size: 12px;
color: var(--primary);
text-decoration: none;
padding: 5px 10px;
&:hover {
text-decoration: underline;
}
}

View File

@@ -96,8 +96,6 @@
margin: 0;
color: var(--color-fg-default);
background-color: var(--color-canvas-default);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
font-size: 14px;
line-height: 1.5;
word-wrap: break-word;
@@ -319,7 +317,7 @@
cursor: pointer;
}
.markdown-body details:not([open])>*:not(summary) {
.markdown-body details:not([open]) > *:not(summary) {
display: none !important;
}
@@ -489,11 +487,11 @@
content: "";
}
.markdown-body>*:first-child {
.markdown-body > *:first-child {
margin-top: 0 !important;
}
.markdown-body>*:last-child {
.markdown-body > *:last-child {
margin-bottom: 0 !important;
}
@@ -529,11 +527,11 @@
margin-bottom: 16px;
}
.markdown-body blockquote> :first-child {
.markdown-body blockquote > :first-child {
margin-top: 0;
}
.markdown-body blockquote> :last-child {
.markdown-body blockquote > :last-child {
margin-bottom: 0;
}
@@ -632,7 +630,7 @@
list-style-type: decimal;
}
.markdown-body div>ol:not([type]) {
.markdown-body div > ol:not([type]) {
list-style-type: decimal;
}
@@ -644,11 +642,11 @@
margin-bottom: 0;
}
.markdown-body li>p {
.markdown-body li > p {
margin-top: 16px;
}
.markdown-body li+li {
.markdown-body li + li {
margin-top: 0.25em;
}
@@ -711,7 +709,7 @@
overflow: hidden;
}
.markdown-body span.frame>span {
.markdown-body span.frame > span {
display: block;
float: left;
width: auto;
@@ -739,7 +737,7 @@
clear: both;
}
.markdown-body span.align-center>span {
.markdown-body span.align-center > span {
display: block;
margin: 13px auto 0;
overflow: hidden;
@@ -757,7 +755,7 @@
clear: both;
}
.markdown-body span.align-right>span {
.markdown-body span.align-right > span {
display: block;
margin: 13px 0 0;
overflow: hidden;
@@ -787,7 +785,7 @@
overflow: hidden;
}
.markdown-body span.float-right>span {
.markdown-body span.float-right > span {
display: block;
margin: 13px auto 0;
overflow: hidden;
@@ -821,7 +819,7 @@
font-size: 100%;
}
.markdown-body pre>code {
.markdown-body pre > code {
padding: 0;
margin: 0;
word-break: normal;
@@ -1085,7 +1083,7 @@
cursor: pointer;
}
.markdown-body .task-list-item+.task-list-item {
.markdown-body .task-list-item + .task-list-item {
margin-top: 4px;
}
@@ -1107,7 +1105,9 @@
}
.markdown-body .contains-task-list:hover .task-list-item-convert-container,
.markdown-body .contains-task-list:focus-within .task-list-item-convert-container {
.markdown-body
.contains-task-list:focus-within
.task-list-item-convert-container {
display: block;
width: auto;
height: 24px;
@@ -1117,4 +1117,4 @@
.markdown-body ::-webkit-calendar-picker-indicator {
filter: invert(50%);
}
}

View File

@@ -56,3 +56,42 @@ export function selectOrCopy(el: HTMLElement, content: string) {
return true;
}
let currentId: string;
export function getCurrentCommitId() {
if (currentId) {
return currentId;
}
if (document) {
const meta = document.head.querySelector(
"meta[name='version']"
) as HTMLMetaElement;
currentId = meta?.content ?? "";
} else {
currentId = process.env.COMMIT_ID ?? "";
}
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();
}
}