feat: close #2190 improve app auto updater

This commit is contained in:
Yidadaa 2023-06-30 00:26:03 +08:00
parent 3937dad6a6
commit be4834688d
4 changed files with 87 additions and 40 deletions

View File

@ -40,7 +40,7 @@ import Locale, {
} from "../locales"; } from "../locales";
import { copyToClipboard } from "../utils"; import { copyToClipboard } from "../utils";
import Link from "next/link"; import Link from "next/link";
import { Path, UPDATE_URL } from "../constant"; import { Path, RELEASE_URL, UPDATE_URL } from "../constant";
import { Prompt, SearchService, usePromptStore } from "../store/prompt"; import { Prompt, SearchService, usePromptStore } from "../store/prompt";
import { ErrorBoundary } from "./error"; import { ErrorBoundary } from "./error";
import { InputRange } from "./input-range"; import { InputRange } from "./input-range";
@ -310,19 +310,6 @@ function SyncItems() {
); );
} }
function formatVersionDate(t: string) {
const d = new Date(+t);
const year = d.getUTCFullYear();
const month = d.getUTCMonth() + 1;
const day = d.getUTCDate();
return [
year.toString(),
month.toString().padStart(2, "0"),
day.toString().padStart(2, "0"),
].join("");
}
export function Settings() { export function Settings() {
const navigate = useNavigate(); const navigate = useNavigate();
const [showEmojiPicker, setShowEmojiPicker] = useState(false); const [showEmojiPicker, setShowEmojiPicker] = useState(false);
@ -332,9 +319,10 @@ export function Settings() {
const updateStore = useUpdateStore(); const updateStore = useUpdateStore();
const [checkingUpdate, setCheckingUpdate] = useState(false); const [checkingUpdate, setCheckingUpdate] = useState(false);
const currentVersion = formatVersionDate(updateStore.version); const currentVersion = updateStore.formatVersion(updateStore.version);
const remoteId = formatVersionDate(updateStore.remoteVersion); const remoteId = updateStore.formatVersion(updateStore.remoteVersion);
const hasNewVersion = currentVersion !== remoteId; const hasNewVersion = currentVersion !== remoteId;
const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL;
function checkUpdate(force = false) { function checkUpdate(force = false) {
setCheckingUpdate(true); setCheckingUpdate(true);
@ -342,14 +330,8 @@ export function Settings() {
setCheckingUpdate(false); setCheckingUpdate(false);
}); });
console.log( console.log("[Update] local version ", updateStore.version);
"[Update] local version ", console.log("[Update] remote version ", updateStore.remoteVersion);
new Date(+updateStore.version).toLocaleString(),
);
console.log(
"[Update] remote version ",
new Date(+updateStore.remoteVersion).toLocaleString(),
);
} }
const usage = { const usage = {
@ -460,7 +442,7 @@ export function Settings() {
{checkingUpdate ? ( {checkingUpdate ? (
<LoadingIcon /> <LoadingIcon />
) : hasNewVersion ? ( ) : hasNewVersion ? (
<Link href={UPDATE_URL} target="_blank" className="link"> <Link href={updateUrl} target="_blank" className="link">
{Locale.Settings.Update.GoToUpdate} {Locale.Settings.Update.GoToUpdate}
</Link> </Link>
) : ( ) : (

View File

@ -1,3 +1,5 @@
import tauriConfig from "../../src-tauri/tauri.conf.json";
export const getBuildConfig = () => { export const getBuildConfig = () => {
if (typeof process === "undefined") { if (typeof process === "undefined") {
throw Error( throw Error(
@ -5,23 +7,37 @@ export const getBuildConfig = () => {
); );
} }
const COMMIT_ID: string = (() => { const buildMode = process.env.BUILD_MODE ?? "standalone";
const isApp = !!process.env.BUILD_APP;
const version = tauriConfig.package.version;
const commitInfo = (() => {
try { try {
const childProcess = require("child_process"); const childProcess = require("child_process");
return childProcess const commitDate: string = childProcess
.execSync('git log -1 --format="%at000" --date=unix') .execSync('git log -1 --format="%at000" --date=unix')
.toString() .toString()
.trim(); .trim();
const commitHash: string = childProcess
.execSync('git log --pretty=format:"%H" -n 1')
.toString()
.trim();
return { commitDate, commitHash };
} catch (e) { } catch (e) {
console.error("[Build Config] No git or not from git repo."); console.error("[Build Config] No git or not from git repo.");
return "unknown"; return {
commitDate: "unknown",
commitHash: "unknown",
};
} }
})(); })();
return { return {
commitId: COMMIT_ID, version,
buildMode: process.env.BUILD_MODE ?? "standalone", ...commitInfo,
isApp: !!process.env.BUILD_APP, buildMode,
isApp,
}; };
}; };

View File

@ -3,6 +3,7 @@ export const REPO = "ChatGPT-Next-Web";
export const REPO_URL = `https://github.com/${OWNER}/${REPO}`; export const REPO_URL = `https://github.com/${OWNER}/${REPO}`;
export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`; export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`;
export const UPDATE_URL = `${REPO_URL}#keep-updated`; export const UPDATE_URL = `${REPO_URL}#keep-updated`;
export const RELEASE_URL = `${REPO_URL}/releases`;
export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`; export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`;
export const FETCH_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`; export const FETCH_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`;
export const RUNTIME_CONFIG_DOM = "danger-runtime-config"; export const RUNTIME_CONFIG_DOM = "danger-runtime-config";

View File

@ -1,48 +1,96 @@
import { create } from "zustand"; import { create } from "zustand";
import { persist } from "zustand/middleware"; import { persist } from "zustand/middleware";
import { FETCH_COMMIT_URL, StoreKey } from "../constant"; import { FETCH_COMMIT_URL, FETCH_TAG_URL, StoreKey } from "../constant";
import { api } from "../client/api"; import { api } from "../client/api";
import { getClientConfig } from "../config/client"; import { getClientConfig } from "../config/client";
export interface UpdateStore { export interface UpdateStore {
versionType: "date" | "tag";
lastUpdate: number; lastUpdate: number;
version: string;
remoteVersion: string; remoteVersion: string;
used?: number; used?: number;
subscription?: number; subscription?: number;
lastUpdateUsage: number; lastUpdateUsage: number;
version: string;
getLatestVersion: (force?: boolean) => Promise<void>; getLatestVersion: (force?: boolean) => Promise<void>;
updateUsage: (force?: boolean) => Promise<void>; updateUsage: (force?: boolean) => Promise<void>;
formatVersion: (version: string) => string;
} }
const ONE_MINUTE = 60 * 1000; const ONE_MINUTE = 60 * 1000;
function formatVersionDate(t: string) {
const d = new Date(+t);
const year = d.getUTCFullYear();
const month = d.getUTCMonth() + 1;
const day = d.getUTCDate();
return [
year.toString(),
month.toString().padStart(2, "0"),
day.toString().padStart(2, "0"),
].join("");
}
async function getVersion(type: "date" | "tag") {
if (type === "date") {
const data = (await (await fetch(FETCH_COMMIT_URL)).json()) as {
commit: {
author: { name: string; date: string };
};
sha: string;
}[];
const remoteCommitTime = data[0].commit.author.date;
const remoteId = new Date(remoteCommitTime).getTime().toString();
return remoteId;
} else if (type === "tag") {
const data = (await (await fetch(FETCH_TAG_URL)).json()) as {
commit: { sha: string; url: string };
name: string;
}[];
return data.at(0)?.name;
}
}
export const useUpdateStore = create<UpdateStore>()( export const useUpdateStore = create<UpdateStore>()(
persist( persist(
(set, get) => ({ (set, get) => ({
versionType: "tag",
lastUpdate: 0, lastUpdate: 0,
version: "unknown",
remoteVersion: "", remoteVersion: "",
lastUpdateUsage: 0, lastUpdateUsage: 0,
version: "unknown", formatVersion(version: string) {
if (get().versionType === "date") {
version = formatVersionDate(version);
}
return version;
},
async getLatestVersion(force = false) { async getLatestVersion(force = false) {
set(() => ({ version: getClientConfig()?.commitId ?? "unknown" })); const versionType = get().versionType;
let version =
versionType === "date"
? getClientConfig()?.commitDate
: getClientConfig()?.version;
const overTenMins = Date.now() - get().lastUpdate > 10 * ONE_MINUTE; set(() => ({ version }));
if (!force && !overTenMins) return;
const shouldCheck =
Date.now() - get().lastUpdate > 24 * 60 * ONE_MINUTE;
if (!force && !shouldCheck) return;
set(() => ({ set(() => ({
lastUpdate: Date.now(), lastUpdate: Date.now(),
})); }));
try { try {
const data = await (await fetch(FETCH_COMMIT_URL)).json(); const remoteId = await getVersion(versionType);
const remoteCommitTime = data[0].commit.committer.date;
const remoteId = new Date(remoteCommitTime).getTime().toString();
set(() => ({ set(() => ({
remoteVersion: remoteId, remoteVersion: remoteId,
})); }));