mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 22:55:24 +00:00
v26.10.3 (#1692)
* feat: shell controller, TabStage, layout and theme plugins with repair view * feat: move the classic layout into its own bundled plugin * feat: move color themes into a bundled themes plugin * fix: plugin tests and type checks work with a linked sdk * fix: home tab, layout switch and missing layout fallbacks for looks * chore: add classic layout and themes to the readme * chore: drop example plugin links from the plugin guide * feat: plugin filters by type, paged browse, hide plugins needing newer termix * feat: move desktop, status, import, audit and branding features into plugins * feat: host lock api so a plugin can load hosts from a config file (#1581) * chore: add hosts config to the plugin table * feat: login policy hook for plugins and optional https redirect (#1584) * chore: add login security to the plugin table * feat: api key socket tickets so a master can open remote sessions (#1654) * feat: sync moves to a plugin, desktop gets multiple accounts (#1580, #1654) * chore: add sync to the plugin table * feat: move the sync screens and wizard out of core into the plugin (#1580) * fix: add a neutral linked desktop hook for plugins (#1580) * fix: show the linked account's name and admin flag in the app (#1580) * feat: ssh transport providers, core ssh relay and plugin folders api * feat: support FIDO2 security keys through ssh agent * feat: add companion panels beside host tabs * feat: mTLS client certificates for desktop server links * feat: native web view for plugins in the desktop app * fix: detect the desktop link window by Electron's default user agent Fixes #1675 * fix: changelog for desktop link fix * fix: keep text primary keys in the plugin data export * fix: ship sharp binaries for Windows arm64 builds * feat: client cert on the sync link types (sdk 1.0.18) * chore: update translations * feat: themed title bar for the desktop app (#1690) * chore: changelog for the themed title bar * fix: draw the title bar in the sidebar color * feat: per host layout for the terminal panel bar * chore: sdk 1.0.19 for the panel bar layout * chore: bundle all 43 plugins for 26.10.3 * chore: update translations --------- Co-authored-by: SirHephaistos <60616553+SirHephaistos@users.noreply.github.com> Co-authored-by: Giovanny Aranda <garanda21@gmail.com>
This commit is contained in:
577 files changed
+76479
-101831
No files matched your search
+38
-6
@@ -1,5 +1,10 @@
|
||||
/* eslint-disable react-refresh/only-export-components */
|
||||
import { prepareClientCacheVersion } from "@/lib/client-cache-version";
|
||||
import {
|
||||
TitleBar,
|
||||
TITLE_BAR_OFFSET,
|
||||
useTitleBarOverlayColors,
|
||||
} from "@/shell/TitleBar";
|
||||
import { StrictMode, Suspense, lazy, useState, useRef, useEffect } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./ui/index.css";
|
||||
@@ -14,6 +19,7 @@ import {
|
||||
Auth,
|
||||
getStoredAuth,
|
||||
clearStoredAuth,
|
||||
storeAuth,
|
||||
markDesktopManualLogout,
|
||||
clearDesktopManualLogout,
|
||||
} from "@/auth/Auth";
|
||||
@@ -32,6 +38,9 @@ import {
|
||||
} from "@/plugin-host/loader";
|
||||
import { settledPromise } from "@/plugin-host/plugin-store";
|
||||
import { resetShellBridge } from "@/plugin-host/shell-bridge";
|
||||
import { loadLook, resetLook } from "@/look/look-store";
|
||||
import { resetPluginThemes } from "@/look/theme-registry";
|
||||
import { resetPluginLayouts } from "@/look/layout-registry";
|
||||
import { preloadPermissions } from "@/hooks/use-permissions";
|
||||
import { getUserPreferences } from "@/api/open-tabs-api";
|
||||
import { standaloneViewFor } from "@/shell/tab-registry";
|
||||
@@ -156,6 +165,8 @@ function FullscreenAppGate() {
|
||||
}
|
||||
|
||||
function App() {
|
||||
// Keeps the window controls the system draws in the colors of the theme.
|
||||
useTitleBarOverlayColors();
|
||||
const stored = getStoredAuth();
|
||||
const [phase, setPhase] = useState<Phase>(
|
||||
stored?.loggedIn ? "verifying" : "idle-auth",
|
||||
@@ -192,7 +203,12 @@ function App() {
|
||||
if (phase !== "verifying") return;
|
||||
appReadyPromise
|
||||
.then(() => getUserInfo())
|
||||
.then(async () => {
|
||||
.then(async (info) => {
|
||||
// The stored name can be an earlier account, after a switch or rename.
|
||||
if (info.username) {
|
||||
setAuthUsername(info.username);
|
||||
storeAuth(info.username);
|
||||
}
|
||||
if (isElectron()) {
|
||||
try {
|
||||
const token = await getCurrentToken();
|
||||
@@ -209,6 +225,7 @@ function App() {
|
||||
.then(() => settledPromise()),
|
||||
preloadPermissions(),
|
||||
getUserPreferences().catch(() => undefined),
|
||||
loadLook(),
|
||||
]);
|
||||
await enterApp();
|
||||
})
|
||||
@@ -296,12 +313,10 @@ function App() {
|
||||
.then(() => settledPromise()),
|
||||
preloadPermissions(),
|
||||
getUserPreferences().catch(() => undefined),
|
||||
loadLook(),
|
||||
]);
|
||||
await enterApp();
|
||||
})();
|
||||
if (isElectron()) {
|
||||
window.electronAPI?.startC2SAutoStartTunnels?.().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
function handleLogout(options?: LogoutOptions) {
|
||||
@@ -321,6 +336,9 @@ function App() {
|
||||
// should survive into the next session.
|
||||
void stopPluginRuntime();
|
||||
resetShellBridge();
|
||||
resetLook();
|
||||
resetPluginThemes();
|
||||
resetPluginLayouts();
|
||||
clearStoredAuth();
|
||||
localStorage.removeItem("jwt");
|
||||
if (isElectron() && options?.manual) {
|
||||
@@ -359,10 +377,17 @@ function App() {
|
||||
|
||||
const { t } = useTranslation();
|
||||
const isTransitioning = phase === "fading-in" || phase === "fading-out";
|
||||
// The desktop app draws a title bar on top of the window, so everything
|
||||
// below it starts lower. The bar sets the offset only while it shows.
|
||||
const titleBarOffset = TITLE_BAR_OFFSET;
|
||||
|
||||
if (phase === "verifying" || phase === "loading-app") {
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-background">
|
||||
<div
|
||||
className="fixed inset-0 flex items-center justify-center bg-background"
|
||||
style={{ paddingTop: titleBarOffset }}
|
||||
>
|
||||
<TitleBar />
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="w-5 h-5 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">{t("common.loading")}</p>
|
||||
@@ -373,8 +398,13 @@ function App() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<TitleBar />
|
||||
|
||||
{isTransitioning && (
|
||||
<div className="fixed inset-0 z-0 flex items-center justify-center bg-background">
|
||||
<div
|
||||
className="fixed inset-0 z-0 flex items-center justify-center bg-background"
|
||||
style={{ paddingTop: titleBarOffset }}
|
||||
>
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="w-5 h-5 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">
|
||||
@@ -405,6 +435,7 @@ function App() {
|
||||
style={{
|
||||
opacity: appOpacity,
|
||||
pointerEvents: phase === "idle-app" ? "auto" : "none",
|
||||
paddingTop: titleBarOffset,
|
||||
}}
|
||||
>
|
||||
<Suspense fallback={null}>
|
||||
@@ -421,6 +452,7 @@ function App() {
|
||||
style={{
|
||||
opacity: authOpacity,
|
||||
pointerEvents: phase === "idle-auth" ? "auto" : "none",
|
||||
paddingTop: titleBarOffset,
|
||||
}}
|
||||
>
|
||||
<Auth onLogin={handleLogin} />
|
||||
|
||||
Reference in new issue
Block a user