Skip to content

Commit

Permalink
Merge pull request #2193 from Yidadaa/bugfix-0629
Browse files Browse the repository at this point in the history
feat: improve ux & auto updater
  • Loading branch information
Yidadaa committed Jun 29, 2023
2 parents 3adca26 + 1e8d476 commit 2388f85
Show file tree
Hide file tree
Showing 13 changed files with 624 additions and 80 deletions.
2 changes: 1 addition & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ BASE_URL=https://chatgpt1.nextweb.fun/api/proxy

1. 安装 nodejs 18 和 yarn,具体细节请询问 ChatGPT;
2. 执行 `yarn install && yarn dev` 即可。⚠️ 注意:此命令仅用于本地开发,不要用于部署!
3. 如果你想本地部署,请使用 `yarn install && yarn start` 命令,你可以配合 pm2 来守护进程,防止被杀死,详情询问 ChatGPT。
3. 如果你想本地部署,请使用 `yarn install && yarn build && yarn start` 命令,你可以配合 pm2 来守护进程,防止被杀死,详情询问 ChatGPT。

## 部署

Expand Down
54 changes: 31 additions & 23 deletions app/components/chat.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,19 @@
&:last-child {
animation: slide-in ease 0.3s;
}

&:hover {
.chat-message-actions {
opacity: 1;
transform: translateY(0px);
max-width: 100%;
height: 40px;
}

.chat-message-action-date {
opacity: 0.2;
}
}
}

.chat-message-user {
Expand Down Expand Up @@ -305,45 +318,40 @@
position: relative;
transition: all ease 0.3s;

&:hover {
.chat-message-actions {
opacity: 1;
transform: translateY(0px);
max-width: 100%;
height: 40px;

.chat-message-action-date {
opacity: 0.3;
}
}
}

.chat-message-actions {
display: flex;
box-sizing: border-box;
font-size: 12px;
align-items: flex-end;
justify-content: space-between;
transition: all ease 0.1s;
transform: translateY(10px);
transition: all ease 0.3s 0.15s;
transform: translateX(-5px) scale(0.9) translateY(30px);
opacity: 0;
height: 0;
max-width: 0;
position: absolute;
left: 0;
z-index: 2;

.chat-input-actions {
display: flex;
flex-wrap: nowrap;
}
}
}

.chat-message-action-date {
white-space: nowrap;
transition: all ease 0.6s;
color: var(--black);
opacity: 0;
text-align: right;
margin-left: 20px;
}
.chat-message-action-date {
font-size: 12px;
opacity: 0.2;
white-space: nowrap;
transition: all ease 0.6s;
color: var(--black);
text-align: right;
width: 100%;
box-sizing: border-box;
padding-right: 10px;
pointer-events: none;
z-index: 1;
}

.chat-message-user > .chat-message-container > .chat-message-item {
Expand Down
10 changes: 6 additions & 4 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -992,13 +992,15 @@ export function Chat() {
</>
)}
</div>

<div className={styles["chat-message-action-date"]}>
{message.date.toLocaleString()}
</div>
</div>
)}
</div>

{showActions && (
<div className={styles["chat-message-action-date"]}>
{message.date.toLocaleString()}
</div>
)}
</div>
</div>
{shouldShowClearContextDivider && <ClearContextDivider />}
Expand Down
32 changes: 7 additions & 25 deletions app/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import Locale, {
} from "../locales";
import { copyToClipboard } from "../utils";
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 { ErrorBoundary } from "./error";
import { InputRange } from "./input-range";
Expand Down Expand Up @@ -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() {
const navigate = useNavigate();
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
Expand All @@ -332,24 +319,19 @@ export function Settings() {

const updateStore = useUpdateStore();
const [checkingUpdate, setCheckingUpdate] = useState(false);
const currentVersion = formatVersionDate(updateStore.version);
const remoteId = formatVersionDate(updateStore.remoteVersion);
const currentVersion = updateStore.formatVersion(updateStore.version);
const remoteId = updateStore.formatVersion(updateStore.remoteVersion);
const hasNewVersion = currentVersion !== remoteId;
const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL;

function checkUpdate(force = false) {
setCheckingUpdate(true);
updateStore.getLatestVersion(force).then(() => {
setCheckingUpdate(false);
});

console.log(
"[Update] local version ",
new Date(+updateStore.version).toLocaleString(),
);
console.log(
"[Update] remote version ",
new Date(+updateStore.remoteVersion).toLocaleString(),
);
console.log("[Update] local version ", updateStore.version);
console.log("[Update] remote version ", updateStore.remoteVersion);
}

const usage = {
Expand Down Expand Up @@ -460,7 +442,7 @@ export function Settings() {
{checkingUpdate ? (
<LoadingIcon />
) : hasNewVersion ? (
<Link href={UPDATE_URL} target="_blank" className="link">
<Link href={updateUrl} target="_blank" className="link">
{Locale.Settings.Update.GoToUpdate}
</Link>
) : (
Expand Down
28 changes: 22 additions & 6 deletions app/config/build.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,43 @@
import tauriConfig from "../../src-tauri/tauri.conf.json";

export const getBuildConfig = () => {
if (typeof process === "undefined") {
throw Error(
"[Server Config] you are importing a nodejs-only module outside of nodejs",
);
}

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 {
const childProcess = require("child_process");
return childProcess
const commitDate: string = childProcess
.execSync('git log -1 --format="%at000" --date=unix')
.toString()
.trim();
const commitHash: string = childProcess
.execSync('git log --pretty=format:"%H" -n 1')
.toString()
.trim();

return { commitDate, commitHash };
} catch (e) {
console.error("[Build Config] No git or not from git repo.");
return "unknown";
return {
commitDate: "unknown",
commitHash: "unknown",
};
}
})();

return {
commitId: COMMIT_ID,
buildMode: process.env.BUILD_MODE ?? "standalone",
isApp: !!process.env.BUILD_APP,
version,
...commitInfo,
buildMode,
isApp,
};
};

Expand Down
1 change: 1 addition & 0 deletions app/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const REPO = "ChatGPT-Next-Web";
export const REPO_URL = `https://github.com/${OWNER}/${REPO}`;
export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`;
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_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`;
export const RUNTIME_CONFIG_DOM = "danger-runtime-config";
Expand Down
66 changes: 57 additions & 9 deletions app/store/update.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,96 @@
import { create } from "zustand";
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 { getClientConfig } from "../config/client";

export interface UpdateStore {
versionType: "date" | "tag";
lastUpdate: number;
version: string;
remoteVersion: string;

used?: number;
subscription?: number;
lastUpdateUsage: number;

version: string;
getLatestVersion: (force?: boolean) => Promise<void>;
updateUsage: (force?: boolean) => Promise<void>;

formatVersion: (version: string) => string;
}

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>()(
persist(
(set, get) => ({
versionType: "tag",
lastUpdate: 0,
version: "unknown",
remoteVersion: "",

lastUpdateUsage: 0,

version: "unknown",
formatVersion(version: string) {
if (get().versionType === "date") {
version = formatVersionDate(version);
}
return version;
},

async getLatestVersion(force = false) {
set(() => ({ version: getClientConfig()?.commitId ?? "unknown" }));
const versionType = get().versionType;
let version =
versionType === "date"
? getClientConfig()?.commitDate
: getClientConfig()?.version;

set(() => ({ version }));

const overTenMins = Date.now() - get().lastUpdate > 10 * ONE_MINUTE;
if (!force && !overTenMins) return;
const shouldCheck =
Date.now() - get().lastUpdate > 24 * 60 * ONE_MINUTE;
if (!force && !shouldCheck) return;

set(() => ({
lastUpdate: Date.now(),
}));

try {
const data = await (await fetch(FETCH_COMMIT_URL)).json();
const remoteCommitTime = data[0].commit.committer.date;
const remoteId = new Date(remoteCommitTime).getTime().toString();
const remoteId = await getVersion(versionType);
set(() => ({
remoteVersion: remoteId,
}));
Expand Down
17 changes: 17 additions & 0 deletions docs/faq-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,23 @@ keepalive_timeout 300; # 设定keep-alive超时时间为65秒

API KEY 有问题。余额不足。

## 使用时遇到 "Error: Loading CSS chunk xxx failed..."

为了减少首屏白屏时间,默认启用了分块编译,技术原理见下:

- https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading
- https://stackoverflow.com/questions/55993890/how-can-i-disable-chunkcode-splitting-with-webpack4
- https://github.com/vercel/next.js/issues/38507
- https://stackoverflow.com/questions/55993890/how-can-i-disable-chunkcode-splitting-with-webpack4

然而 NextJS 的兼容性比较差,在比较老的浏览器上会导致此报错,可以在编译时关闭分块编译。

对于 Vercel 平台,在环境变量中增加 `DISABLE_CHUNK=1`,然后重新部署即可;
对于自行编译部署的项目,在构建时使用 `DISABLE_CHUNK=1 yarn build` 构建即可;
对于 Docker 用户,由于 Docker 打包时已经构建完毕,所以暂不支持关闭此特性。

注意,关闭此特性后,用户会在第一次访问网站时加载所有资源,如果用户网络状况较差,可能会引起较长时间的白屏,从而影响用户使用体验,所以自行考虑。

# 网络服务相关问题

## Cloudflare 是什么?
Expand Down

0 comments on commit 2388f85

Please sign in to comment.