mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 15:15:24 +00:00
v26.10.1 (#1599)
* feat: AI translations at release, 7 new languages and regional fallback * fix: proper plural forms for count strings and full translations * fix: plural forms for selected, hidden and active counts * fix: synced plugin updates failing on desktop and server-only plugins shown as stopped * fix: restore rounded corners on app icons and favicon * feat: desktop app auto updates with automatic, ask first or never modes * feat: community and custom plugin registries * feat: plugin guide for AI tools in the SDK with a lint check * fix: keep the terminal WebSocket open past nginx's 60s default (#1588) * chore: update changelog * feat: show plugin download counts only and stop CI builds inflating them * feat: hide installed plugins in the browse tab by default * chore: pin bundled plugins to latest releases * chore: update translations * fix: focusing a saved password field and saving no longer erases it * fix: tell desktop users when their 2.8 data needs 2.9 first * fix: point windows update info at the x64 installer * fix: keep desktop client tunnel sockets alive behind proxies * chore: pin bundled plugins to latest releases * fix: cover client tunnel keepalive in the c2s runtime tests * fix: typing after opening a host no longer goes to the host search * fix: accept tab and = separators in SSH config import (#1598) * chore: update changelog * chore: drop plugin versions from core changelog * chore: update translations * chore: lint, format, and bump version to 26.10.1 --------- Co-authored-by: Darnel Hunter <68697450+innotelinc@users.noreply.github.com> Co-authored-by: Iain <Iain1970@protonmail.com>
This commit is contained in:
174 files changed
+94334
-39995
No files matched your search
@@ -489,10 +489,6 @@ export function CredentialEditorView({
|
||||
? ""
|
||||
: credForm.passphrase
|
||||
}
|
||||
onFocus={() => {
|
||||
if (credForm.passphrase === "existing_key_password")
|
||||
setCredField("passphrase", "");
|
||||
}}
|
||||
onChange={(e) => setCredField("passphrase", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1094,10 +1094,6 @@ export function HostEditor({
|
||||
? ""
|
||||
: form.password
|
||||
}
|
||||
onFocus={() => {
|
||||
if (form.password === "existing_password")
|
||||
setField("password", "");
|
||||
}}
|
||||
onChange={(e) => setField("password", e.target.value)}
|
||||
/>
|
||||
<PluginComponent
|
||||
@@ -1211,10 +1207,6 @@ export function HostEditor({
|
||||
? ""
|
||||
: form.keyPassword
|
||||
}
|
||||
onFocus={() => {
|
||||
if (form.keyPassword === "existing_key_password")
|
||||
setField("keyPassword", "");
|
||||
}}
|
||||
onChange={(e) =>
|
||||
setField("keyPassword", e.target.value)
|
||||
}
|
||||
@@ -1236,10 +1228,6 @@ export function HostEditor({
|
||||
? ""
|
||||
: form.password
|
||||
}
|
||||
onFocus={() => {
|
||||
if (form.password === "existing_password")
|
||||
setField("password", "");
|
||||
}}
|
||||
onChange={(e) =>
|
||||
setField("password", e.target.value)
|
||||
}
|
||||
@@ -1377,10 +1365,6 @@ export function HostEditor({
|
||||
? ""
|
||||
: form.password
|
||||
}
|
||||
onFocus={() => {
|
||||
if (form.password === "existing_password")
|
||||
setField("password", "");
|
||||
}}
|
||||
onChange={(e) =>
|
||||
setField("password", e.target.value)
|
||||
}
|
||||
@@ -1506,10 +1490,6 @@ export function HostEditor({
|
||||
? ""
|
||||
: form.sudoPassword
|
||||
}
|
||||
onFocus={() => {
|
||||
if (form.sudoPassword === "existing_sudo_password")
|
||||
setField("sudoPassword", "");
|
||||
}}
|
||||
onChange={(e) =>
|
||||
setField("sudoPassword", e.target.value)
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ import type { FontSizeId, ThemeId, UiFontId } from "@/types/ui-types";
|
||||
import { toast } from "sonner";
|
||||
import { changeAppLanguage, normalizeLanguageCode } from "@/i18n/i18n";
|
||||
import { Select2 } from "@/components/select2";
|
||||
import { LANGUAGES, THEMES } from "@/settings/appearance/appearance-controls";
|
||||
import { THEMES } from "@/settings/appearance/appearance-controls";
|
||||
import { LANGUAGES } from "@/i18n/languages";
|
||||
import { clearLocalAdaptivePreferences } from "@/lib/local-adaptive-preferences";
|
||||
import { reportBetaFeedbackUrl } from "@/lib/issue-url";
|
||||
import { isPrerelease } from "@/plugins/plugin-model";
|
||||
|
||||
@@ -79,7 +79,7 @@ import { useSidebarDragState } from "./hooks/useSidebarDragState";
|
||||
|
||||
export function SidebarTree({
|
||||
children,
|
||||
onOpenTab,
|
||||
onOpenTab: openTab,
|
||||
onEditHost,
|
||||
onShareHost,
|
||||
query: externalQuery = "",
|
||||
@@ -125,6 +125,16 @@ export function SidebarTree({
|
||||
rowFields?: HostRowFields;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
// Focus left on the clicked row sends the next keys to the host speed
|
||||
// search instead of the session that just opened.
|
||||
const onOpenTab: typeof openTab = (...args) => {
|
||||
const active = document.activeElement;
|
||||
if (active instanceof HTMLElement && rootRef.current?.contains(active)) {
|
||||
active.blur();
|
||||
}
|
||||
openTab(...args);
|
||||
};
|
||||
const hostSettingPlugins = usePluginHostSections();
|
||||
const hostSwitchPlugins = hostSettingPlugins.filter(
|
||||
(plugin) => !!plugin.contributes?.settings?.host?.enableKey,
|
||||
@@ -939,6 +949,7 @@ export function SidebarTree({
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={rootRef}
|
||||
className="relative flex flex-col flex-1 min-h-0"
|
||||
onKeyDown={(event) => {
|
||||
if (selectionMode || arrangeMode) return;
|
||||
@@ -1413,7 +1424,6 @@ export function SidebarTree({
|
||||
setConfirmDialog({
|
||||
message: t("hosts.deleteHostsConfirm", {
|
||||
count: selectedHostIds.size,
|
||||
plural: selectedHostIds.size !== 1 ? "s" : "",
|
||||
}),
|
||||
onConfirm: async () => {
|
||||
const ids = Array.from(selectedHostIds);
|
||||
|
||||
Reference in new issue
Block a user