fix: remove release update popup

This commit is contained in:
tianma-if committed 2026-08-20 01:54:41 +08:00
1 parent 29d4ec2976
commit 85a691eeaf
4 files changed
+8 -156

No files matched your search

+7 -11
View File
@@ -3,7 +3,6 @@ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Navigate, Route, Routes, useNavigate } from "react-router";
import { useTranslation } from "react-i18next";
import { PwaUpdateNotice } from "@/components/PwaUpdateNotice";
import { ReleaseUpdateNotice } from "@/components/ReleaseUpdateNotice";
import { PwaInstallProvider } from "@/components/PwaInstallContext";
import { PwaIosPrompt } from "@/components/PwaIosPrompt";
import { Button } from "@/components/ui/button";
@@ -199,16 +198,13 @@ const AuthenticatedWorkspace = () => {
return (
<Suspense fallback={<AuthLoadingScreen />}>
<>
<WorkspaceApp
authRequired={session.authRequired}
demoMode={session.demoMode}
isLoggingOut={logoutMutation.isPending}
user={session.user}
onLogout={() => logoutMutation.mutate()}
/>
<ReleaseUpdateNotice />
</>
<WorkspaceApp
authRequired={session.authRequired}
demoMode={session.demoMode}
isLoggingOut={logoutMutation.isPending}
user={session.user}
onLogout={() => logoutMutation.mutate()}
/>
</Suspense>
);
};
+1 -7
View File
@@ -133,7 +133,6 @@ import { copyEditorToWeChat, copyMarkdownToWeChat } from "@/lib/wechat-copy";
import { ThemeBlock } from "./ThemeBlock";
import { SystemInfoDialog } from "./SystemInfoDialog";
import { fetchLatestRelease, isVersionOutdated } from "@/lib/version-check";
import { RELEASE_STATUS_EVENT } from "@/lib/release-notice";
import { downloadMarkdownFile } from "@/lib/note-markdown-export";
import { NOTE_HTML_FULL_STYLES } from "@/lib/note-html-export-assets";
import { downloadNoteHtmlFile, getHtmlImageEmbedNoticeKind } from "@/lib/note-html-export";
@@ -851,12 +850,7 @@ const RichEditorPane = ({
void fetchLatestRelease(controller.signal)
.then((release) => setUpdateAvailable(isVersionOutdated(__EDGEEVER_APP_VERSION__, release.version)))
.catch(() => undefined);
const handleReleaseStatus = () => setUpdateAvailable(true);
window.addEventListener(RELEASE_STATUS_EVENT, handleReleaseStatus);
return () => {
controller.abort();
window.removeEventListener(RELEASE_STATUS_EVENT, handleReleaseStatus);
};
return () => controller.abort();
}, []);
const effectiveReadOnly = readOnly || (isMobileViewport && !mobileEditingActive);
const useMobilePlainTextEditor = isMobileViewport && mobileEditingActive && !readOnly;
@@ -1,119 +0,0 @@
import { useEffect, useState } from "react";
import { ArrowUpCircle, Download, ExternalLink, RefreshCw, X } from "lucide-react";
import { useTranslation } from "react-i18next";
import { fetchLatestRelease, isVersionOutdated, type LatestRelease } from "@/lib/version-check";
import { dismissRelease, getDismissedRelease } from "@/lib/release-notice";
import { UpdateAvailableDescription } from "./UpdateAvailableDescription";
const AUTO_DISMISS_MS = 3_000;
export const ReleaseUpdateNotice = () => {
const { t } = useTranslation();
const [release, setRelease] = useState<LatestRelease | null>(null);
const [dismissed, setDismissed] = useState(false);
const [nativeUpdateState, setNativeUpdateState] = useState<"idle" | "available" | "downloading" | "downloaded" | "error">("idle");
const desktopBridge = window.edgeeverDesktop;
useEffect(() => {
const controller = new AbortController();
void fetchLatestRelease(controller.signal)
.then((latest) => {
if (isVersionOutdated(__EDGEEVER_APP_VERSION__, latest.version)) setRelease(latest);
})
.catch(() => undefined);
return () => controller.abort();
}, []);
useEffect(() => {
if (!desktopBridge?.isAvailable) return;
let active = true;
const readStatus = async () => {
try {
const { state } = await desktopBridge.updateStatus();
if (active && (state === "available" || state === "downloaded")) setNativeUpdateState(state);
} catch {
// The release link remains available when the native updater is unavailable.
}
};
void readStatus();
const timer = window.setInterval(() => void readStatus(), 5_000);
return () => {
active = false;
window.clearInterval(timer);
};
}, [desktopBridge]);
useEffect(() => {
if (!release || nativeUpdateState !== "idle") return;
const timer = window.setTimeout(() => setDismissed(true), AUTO_DISMISS_MS);
return () => window.clearTimeout(timer);
}, [nativeUpdateState, release?.tagName]);
if ((!release && nativeUpdateState === "idle") || dismissed || (release && getDismissedRelease() === release.tagName)) return null;
const handleNativeUpdate = async () => {
if (!desktopBridge?.isAvailable) return;
try {
if (nativeUpdateState === "available") {
setNativeUpdateState("downloading");
await desktopBridge.downloadUpdate();
} else if (nativeUpdateState === "downloaded") {
await desktopBridge.installUpdate();
}
} catch {
setNativeUpdateState("error");
}
};
const isNativeUpdate = nativeUpdateState !== "idle";
return (
<aside
className="fixed right-5 top-5 z-[70] w-[min(22rem,calc(100vw-2rem))] rounded-lg border border-emerald-200 bg-white/95 p-3 text-slate-900 shadow-[0_18px_48px_rgba(15,23,42,0.16)] backdrop-blur"
role="status"
aria-live="polite"
>
<div className="flex items-start gap-3">
<div className="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-emerald-50 text-emerald-600" aria-hidden="true">
<ArrowUpCircle className="h-4 w-4" />
</div>
<div className="min-w-0 flex-1">
<div className="text-sm font-semibold leading-5">{t("systemInfo.updateAvailableTitle")}</div>
<div className="mt-0.5 text-xs leading-5 text-slate-500">
{nativeUpdateState === "downloading"
? t("systemInfo.desktopUpdateDownloading")
: nativeUpdateState === "downloaded"
? t("systemInfo.desktopUpdateReady")
: nativeUpdateState === "error"
? t("systemInfo.desktopUpdateFailed")
: <UpdateAvailableDescription version={release?.version ?? ""} />}
</div>
<div className="mt-2 flex flex-wrap items-center gap-3">
{isNativeUpdate && nativeUpdateState !== "downloading" && nativeUpdateState !== "error" && (
<button className="inline-flex items-center gap-1 text-xs font-semibold text-emerald-700 hover:text-emerald-900" type="button" onClick={() => void handleNativeUpdate()}>
{nativeUpdateState === "downloaded" ? <RefreshCw className="h-3 w-3" /> : <Download className="h-3 w-3" />}
{nativeUpdateState === "downloaded" ? t("systemInfo.desktopUpdateRestart") : t("systemInfo.desktopUpdateDownload")}
</button>
)}
{release && <a className="inline-flex items-center gap-1 text-xs font-semibold text-emerald-700 underline underline-offset-2 hover:text-emerald-900" href={release.url} target="_blank" rel="noreferrer">
{t("systemInfo.viewRelease")}
<ExternalLink className="h-3 w-3" />
</a>}
</div>
</div>
<button
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-slate-400 transition hover:bg-slate-100 hover:text-slate-700"
type="button"
aria-label={t("systemInfo.closeUpdateNotice")}
onClick={() => {
if (release) dismissRelease(release.tagName);
setDismissed(true);
}}
>
<X className="h-4 w-4" />
</button>
</div>
</aside>
);
};
-19
View File
@@ -1,19 +0,0 @@
const DISMISSED_RELEASE_KEY = "edgeever:dismissed-release";
export const RELEASE_STATUS_EVENT = "edgeever:release-status";
export const getDismissedRelease = () => {
try {
return window.localStorage.getItem(DISMISSED_RELEASE_KEY);
} catch {
return null;
}
};
export const dismissRelease = (tagName: string) => {
try {
window.localStorage.setItem(DISMISSED_RELEASE_KEY, tagName);
} catch {
// Storage can be unavailable in restricted browsing modes.
}
window.dispatchEvent(new CustomEvent(RELEASE_STATUS_EVENT, { detail: { tagName, dismissed: true } }));
};