mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 14:15:24 +00:00
fix: keep plugins loaded after signing in from the login screen
This commit is contained in:
1 parent
8043d6dbdd
commit
4423c4c8ef
3 files changed
+48
-12
No files matched your search
+1
-10
@@ -134,10 +134,6 @@ function App() {
|
||||
const [authUsername, setAuthUsername] = useState(stored?.username ?? "");
|
||||
const [verifyRetryCount, setVerifyRetryCount] = useState(0);
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
// Track whether fading-in came from a fresh login (vs. session verification on page load).
|
||||
// When session-verified, Auth must not mount during the transition — it would trigger
|
||||
// silent OIDC redirect and cause an infinite refresh loop.
|
||||
const fadingInFromLoginRef = useRef(false);
|
||||
// Dedupes concurrent handleLogout() calls within the same tick -- see
|
||||
// handleLogout for why phase state alone isn't sufficient for this.
|
||||
const loggingOutRef = useRef(false);
|
||||
@@ -175,7 +171,6 @@ function App() {
|
||||
// Non-fatal: WebSocket connections will fall back to cookie auth
|
||||
}
|
||||
}
|
||||
fadingInFromLoginRef.current = false;
|
||||
setPhase("loading-app");
|
||||
await Promise.all([
|
||||
startPluginRuntime()
|
||||
@@ -241,7 +236,6 @@ function App() {
|
||||
loggingOutRef.current = false;
|
||||
clearDesktopManualLogout();
|
||||
setAuthUsername(u);
|
||||
fadingInFromLoginRef.current = true;
|
||||
setPhase("loading-app");
|
||||
void (async () => {
|
||||
await Promise.all([
|
||||
@@ -299,10 +293,7 @@ function App() {
|
||||
|
||||
const showApp =
|
||||
phase === "idle-app" || phase === "fading-in" || phase === "fading-out";
|
||||
const showAuth =
|
||||
phase === "idle-auth" ||
|
||||
(phase === "fading-in" && fadingInFromLoginRef.current) ||
|
||||
phase === "fading-out";
|
||||
const showAuth = phase === "idle-auth" || phase === "fading-out";
|
||||
const appOpacity = phase === "idle-app" ? 1 : 0;
|
||||
const authOpacity = phase === "idle-auth" ? 1 : 0;
|
||||
|
||||
|
||||
@@ -442,13 +442,20 @@ export async function startPreLoginPlugins(): Promise<void> {
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
if (list.length === 0) return;
|
||||
if (list.length === 0 || started) return;
|
||||
setPluginLocaleResolver((namespace, _language, file) => {
|
||||
const summary = getPluginRecord(namespace)?.summary;
|
||||
if (!summary) return Promise.resolve(null);
|
||||
return currentDeps().loadLocale(summary, file);
|
||||
});
|
||||
await syncPlugins(list);
|
||||
await enqueue(async () => {
|
||||
// Once signed in the full sync owns the list, and reconciling this
|
||||
// subset would unload everything else. Auth remounts during the
|
||||
// post-login fade, so this runs after sign-in every time.
|
||||
if (started) return;
|
||||
await reconcile(list);
|
||||
markPluginsSettled();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
isPluginFrontendActive,
|
||||
orderForActivation,
|
||||
resetPluginLoader,
|
||||
startPluginRuntime,
|
||||
startPreLoginPlugins,
|
||||
syncPlugins,
|
||||
} from "@/plugin-host/loader";
|
||||
import {
|
||||
@@ -208,6 +210,42 @@ describe("plugin loader", () => {
|
||||
expect(railIds()).not.toContain("headless-panel");
|
||||
});
|
||||
|
||||
it("keeps every plugin when the pre-login list lands after sign-in", async () => {
|
||||
modules.login = railPlugin("login");
|
||||
modules.alpha = railPlugin("alpha");
|
||||
plugins = [summary("login"), summary("alpha")];
|
||||
|
||||
let releasePreLogin: (value: Response) => void = () => {};
|
||||
vi.spyOn(globalThis, "fetch").mockImplementation(
|
||||
() =>
|
||||
new Promise<Response>((resolve) => {
|
||||
releasePreLogin = resolve;
|
||||
}),
|
||||
);
|
||||
|
||||
const preLogin = startPreLoginPlugins();
|
||||
await startPluginRuntime();
|
||||
releasePreLogin(new Response(JSON.stringify([summary("login")])));
|
||||
await preLogin;
|
||||
|
||||
expect(isPluginFrontendActive("login")).toBe(true);
|
||||
expect(isPluginFrontendActive("alpha")).toBe(true);
|
||||
});
|
||||
|
||||
it("ignores a pre-login load started after sign-in", async () => {
|
||||
modules.login = railPlugin("login");
|
||||
modules.alpha = railPlugin("alpha");
|
||||
plugins = [summary("login"), summary("alpha")];
|
||||
vi.spyOn(globalThis, "fetch").mockImplementation(
|
||||
async () => new Response(JSON.stringify([summary("login")])),
|
||||
);
|
||||
|
||||
await startPluginRuntime();
|
||||
await startPreLoginPlugins();
|
||||
|
||||
expect(isPluginFrontendActive("alpha")).toBe(true);
|
||||
});
|
||||
|
||||
it("settles even when the plugin list cannot be fetched", async () => {
|
||||
vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
configurePluginLoader({
|
||||
|
||||
Reference in new issue
Block a user