Merge remote-tracking branch 'origin/dev-1.10.1' into dev-1.10.1
This commit is contained in:
@@ -211,7 +211,7 @@ class UserDataImport {
|
||||
newHostData,
|
||||
targetUserId,
|
||||
options.userDataKey,
|
||||
);
|
||||
) as Record<string, unknown>;
|
||||
}
|
||||
|
||||
delete processedHostData.id;
|
||||
@@ -294,7 +294,7 @@ class UserDataImport {
|
||||
newCredentialData,
|
||||
targetUserId,
|
||||
options.userDataKey,
|
||||
);
|
||||
) as Record<string, unknown>;
|
||||
}
|
||||
|
||||
delete processedCredentialData.id;
|
||||
|
||||
@@ -13,6 +13,7 @@ import { AdminSettings } from "@/ui/desktop/apps/admin/AdminSettings.tsx";
|
||||
import { UserProfile } from "@/ui/desktop/user/UserProfile.tsx";
|
||||
import { NetworkGraphView } from "@/ui/desktop/dashboard/network-graph";
|
||||
import { Toaster } from "@/components/ui/sonner.tsx";
|
||||
import { toast } from "sonner";
|
||||
import { CommandPalette } from "@/ui/desktop/apps/command-palette/CommandPalette.tsx";
|
||||
import { getUserInfo, logoutUser, isElectron } from "@/ui/main-axios.ts";
|
||||
import { useTheme } from "@/components/theme-provider";
|
||||
@@ -89,30 +90,44 @@ function AppContent() {
|
||||
|
||||
useEffect(() => {
|
||||
const path = window.location.pathname;
|
||||
const match = path.match(/^\/hosts\/([a-zA-Z0-9_-]+)\/terminal$/);
|
||||
if (match) {
|
||||
const hostId = match[1];
|
||||
|
||||
const openTerminalForHost = async () => {
|
||||
// New format: /terminal/{hostNameOrId}
|
||||
const terminalMatch = path.match(/^\/terminal\/([a-zA-Z0-9_-]+)$/);
|
||||
// Legacy format: /hosts/{id}/terminal (backward compatible)
|
||||
const legacyMatch = path.match(/^\/hosts\/([a-zA-Z0-9_-]+)\/terminal$/);
|
||||
const hostIdentifier = terminalMatch?.[1] || legacyMatch?.[1];
|
||||
|
||||
if (hostIdentifier) {
|
||||
const openTerminal = async () => {
|
||||
try {
|
||||
const { getSSHHostById } = await import("@/ui/main-axios.ts");
|
||||
const host = await getSSHHostById(parseInt(hostId, 10));
|
||||
const { getSSHHostById, getSSHHosts } = await import("@/ui/main-axios.ts");
|
||||
let host = null;
|
||||
|
||||
// Pure numeric → lookup by ID
|
||||
if (/^\d+$/.test(hostIdentifier)) {
|
||||
host = await getSSHHostById(parseInt(hostIdentifier, 10));
|
||||
} else {
|
||||
// Non-numeric → lookup by name (first match)
|
||||
const hosts = await getSSHHosts();
|
||||
host = hosts.find((h: { name?: string }) => h.name === hostIdentifier) || null;
|
||||
}
|
||||
|
||||
if (host) {
|
||||
addTab({
|
||||
type: "terminal",
|
||||
title: host.name || host.ip,
|
||||
data: {
|
||||
host,
|
||||
initialCommand: "",
|
||||
},
|
||||
data: { host, initialCommand: "" },
|
||||
});
|
||||
// Clean URL to prevent re-opening on refresh
|
||||
window.history.replaceState({}, "", "/");
|
||||
} else {
|
||||
toast.error(`Host "${hostIdentifier}" not found`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to open terminal for host:", error);
|
||||
console.error("Failed to open terminal:", error);
|
||||
toast.error("Failed to open terminal for host");
|
||||
}
|
||||
};
|
||||
|
||||
openTerminalForHost();
|
||||
openTerminal();
|
||||
}
|
||||
}, [addTab]);
|
||||
|
||||
|
||||
@@ -1349,6 +1349,24 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ctrl+Alt+<key> → Ctrl+<key> remapping for browser-blocked shortcuts
|
||||
// Browsers intercept Ctrl+W/T/N/Q, so we use Ctrl+Alt as an alternative
|
||||
if (e.ctrlKey && e.altKey && !e.metaKey && !e.shiftKey) {
|
||||
const key = e.key.toLowerCase();
|
||||
const blockedKeys = ["w", "t", "n", "q"];
|
||||
if (blockedKeys.includes(key)) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const ctrlCode = key.charCodeAt(0) - 96;
|
||||
if (webSocketRef.current?.readyState === 1) {
|
||||
webSocketRef.current.send(
|
||||
JSON.stringify({ type: "input", data: String.fromCharCode(ctrlCode) }),
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (showAutocompleteRef.current) {
|
||||
if (e.key === "Escape") {
|
||||
e.preventDefault();
|
||||
|
||||
Reference in New Issue
Block a user