diff --git a/web/src/components/UpdateVersionBanner.tsx b/web/src/components/UpdateVersionBanner.tsx new file mode 100644 index 00000000..83c854c7 --- /dev/null +++ b/web/src/components/UpdateVersionBanner.tsx @@ -0,0 +1,42 @@ +import { useEffect, useState } from "react"; +import * as api from "../helpers/api"; +import Icon from "./Icon"; +import "../less/about-site-dialog.less"; + +interface State { + latestVersion: string; +} + +const UpdateVersionBanner: React.FC = () => { + const [state, setState] = useState({ + latestVersion: "", + }); + + useEffect(() => { + try { + api.getRepoLatestTag().then((latestTag) => { + setState({ + latestVersion: latestTag, + }); + }); + } catch (error) { + // do nth + } + }, []); + + return ( +
+ + + New Update {state.latestVersion} + +
+ ); +}; + +export default UpdateVersionBanner; diff --git a/web/src/helpers/api.ts b/web/src/helpers/api.ts index 966fb487..7b576af2 100644 --- a/web/src/helpers/api.ts +++ b/web/src/helpers/api.ts @@ -189,3 +189,13 @@ export async function getRepoStarCount() { }); return data.stargazers_count as number; } + +export async function getRepoLatestTag() { + const { data } = await axios.get(`https://api.github.com/repos/usememos/memos/tags`, { + headers: { + Accept: "application/vnd.github.v3.star+json", + Authorization: "", + }, + }); + return data[0].name as string; +} diff --git a/web/src/less/home.less b/web/src/less/home.less index 8b599194..78a9d2e9 100644 --- a/web/src/less/home.less +++ b/web/src/less/home.less @@ -4,6 +4,10 @@ @apply relative top-0 w-full h-screen overflow-y-auto overflow-x-hidden; background-color: #f6f5f4; + > .banner-wrapper { + @apply w-full flex flex-col justify-start items-center; + } + > .page-container { @apply relative w-full min-h-screen mx-auto flex flex-row justify-start sm:justify-center items-start; diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx index e3fa02e7..4dc7af01 100644 --- a/web/src/pages/Home.tsx +++ b/web/src/pages/Home.tsx @@ -1,6 +1,7 @@ -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useLocation } from "react-router-dom"; +import * as api from "../helpers/api"; import { globalService, userService } from "../services"; import { useAppSelector } from "../store"; import toastHelper from "../components/Toast"; @@ -9,12 +10,45 @@ import MemosHeader from "../components/MemosHeader"; import MemoEditor from "../components/MemoEditor"; import MemoFilter from "../components/MemoFilter"; import MemoList from "../components/MemoList"; +import UpdateVersionBanner from "../components/UpdateVersionBanner"; import "../less/home.less"; +interface State { + shouldShowUpdateVersionBanner: boolean; +} + function Home() { const { t } = useTranslation(); const location = useLocation(); const user = useAppSelector((state) => state.user.user); + const [state, setState] = useState({ + shouldShowUpdateVersionBanner: false, + }); + + useEffect(() => { + Promise.all([api.getRepoLatestTag(), api.getSystemStatus()]) + .then( + ([ + latestTag, + { + data: { + data: { profile }, + }, + }, + ]) => { + const latestVersion = latestTag.slice(1) || "0.0.0"; + const currentVersion = profile.version; + if (latestVersion > currentVersion) { + setState({ + shouldShowUpdateVersionBanner: true, + }); + } + } + ) + .catch(() => { + // do nth + }); + }, []); useEffect(() => { const { owner } = userService.getState(); @@ -34,6 +68,7 @@ function Home() { return (
+
{state.shouldShowUpdateVersionBanner && }