fix: replace explicit any types with proper TypeScript types
- Replace 'any' with 'unknown' in catch blocks and add type assertions - Create explicit interfaces for complex objects (HostConfig, TabData, TerminalHandle) - Fix window/document object type extensions - Update Electron API type definitions - Improve type safety in database routes and utilities - Add proper types to Terminal components (Desktop & Mobile) - Fix navigation component types (TopNavbar, LeftSidebar, AppView) Reduces TypeScript lint errors from 394 to 358 (-36 errors) Fixes 45 @typescript-eslint/no-explicit-any violations
This commit is contained in:
@@ -107,7 +107,8 @@ export function AdminSettings({
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isElectron()) {
|
||||
const serverUrl = (window as any).configuredServerUrl;
|
||||
const serverUrl = (window as { configuredServerUrl?: string })
|
||||
.configuredServerUrl;
|
||||
if (!serverUrl) {
|
||||
return;
|
||||
}
|
||||
@@ -127,7 +128,8 @@ export function AdminSettings({
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isElectron()) {
|
||||
const serverUrl = (window as any).configuredServerUrl;
|
||||
const serverUrl = (window as { configuredServerUrl?: string })
|
||||
.configuredServerUrl;
|
||||
if (!serverUrl) {
|
||||
return;
|
||||
}
|
||||
@@ -148,7 +150,8 @@ export function AdminSettings({
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isElectron()) {
|
||||
const serverUrl = (window as any).configuredServerUrl;
|
||||
const serverUrl = (window as { configuredServerUrl?: string })
|
||||
.configuredServerUrl;
|
||||
if (!serverUrl) {
|
||||
return;
|
||||
}
|
||||
@@ -169,7 +172,8 @@ export function AdminSettings({
|
||||
|
||||
const fetchUsers = async () => {
|
||||
if (isElectron()) {
|
||||
const serverUrl = (window as any).configuredServerUrl;
|
||||
const serverUrl = (window as { configuredServerUrl?: string })
|
||||
.configuredServerUrl;
|
||||
if (!serverUrl) {
|
||||
return;
|
||||
}
|
||||
@@ -234,9 +238,10 @@ export function AdminSettings({
|
||||
try {
|
||||
await updateOIDCConfig(oidcConfig);
|
||||
toast.success(t("admin.oidcConfigurationUpdated"));
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
setOidcError(
|
||||
err?.response?.data?.error || t("admin.failedToUpdateOidcConfig"),
|
||||
(err as { response?: { data?: { error?: string } } })?.response?.data
|
||||
?.error || t("admin.failedToUpdateOidcConfig"),
|
||||
);
|
||||
} finally {
|
||||
setOidcLoading(false);
|
||||
@@ -257,9 +262,10 @@ export function AdminSettings({
|
||||
toast.success(t("admin.userIsNowAdmin", { username: newAdminUsername }));
|
||||
setNewAdminUsername("");
|
||||
fetchUsers();
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
setMakeAdminError(
|
||||
err?.response?.data?.error || t("admin.failedToMakeUserAdmin"),
|
||||
(err as { response?: { data?: { error?: string } } })?.response?.data
|
||||
?.error || t("admin.failedToMakeUserAdmin"),
|
||||
);
|
||||
} finally {
|
||||
setMakeAdminLoading(false);
|
||||
@@ -272,7 +278,7 @@ export function AdminSettings({
|
||||
await removeAdminStatus(username);
|
||||
toast.success(t("admin.adminStatusRemoved", { username }));
|
||||
fetchUsers();
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
toast.error(t("admin.failedToRemoveAdminStatus"));
|
||||
}
|
||||
});
|
||||
@@ -286,7 +292,7 @@ export function AdminSettings({
|
||||
await deleteUser(username);
|
||||
toast.success(t("admin.userDeletedSuccessfully", { username }));
|
||||
fetchUsers();
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
toast.error(t("admin.failedToDeleteUser"));
|
||||
}
|
||||
},
|
||||
@@ -316,7 +322,7 @@ export function AdminSettings({
|
||||
window.location.hostname === "127.0.0.1");
|
||||
|
||||
const apiUrl = isElectron()
|
||||
? `${(window as any).configuredServerUrl}/database/export`
|
||||
? `${(window as { configuredServerUrl?: string }).configuredServerUrl}/database/export`
|
||||
: isDev
|
||||
? `http://localhost:30001/database/export`
|
||||
: `${window.location.protocol}//${window.location.host}/database/export`;
|
||||
@@ -386,7 +392,7 @@ export function AdminSettings({
|
||||
window.location.hostname === "127.0.0.1");
|
||||
|
||||
const apiUrl = isElectron()
|
||||
? `${(window as any).configuredServerUrl}/database/import`
|
||||
? `${(window as { configuredServerUrl?: string }).configuredServerUrl}/database/import`
|
||||
: isDev
|
||||
? `http://localhost:30001/database/import`
|
||||
: `${window.location.protocol}//${window.location.host}/database/import`;
|
||||
@@ -713,9 +719,13 @@ export function AdminSettings({
|
||||
try {
|
||||
await disableOIDCConfig();
|
||||
toast.success(t("admin.oidcConfigurationDisabled"));
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
setOidcError(
|
||||
err?.response?.data?.error ||
|
||||
(
|
||||
err as {
|
||||
response?: { data?: { error?: string } };
|
||||
}
|
||||
)?.response?.data?.error ||
|
||||
t("admin.failedToDisableOidcConfig"),
|
||||
);
|
||||
} finally {
|
||||
|
||||
@@ -311,10 +311,10 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
setFiles(files);
|
||||
clearSelection();
|
||||
initialLoadDoneRef.current = true;
|
||||
} catch (dirError: any) {
|
||||
} catch (dirError: unknown) {
|
||||
console.error("Failed to load initial directory:", dirError);
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error("SSH connection failed:", error);
|
||||
handleCloseWithError(
|
||||
t("fileManager.failedToConnect") + ": " + (error.message || error),
|
||||
@@ -353,7 +353,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
|
||||
setFiles(files);
|
||||
clearSelection();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (currentLoadingPathRef.current === path) {
|
||||
console.error("Failed to load directory:", error);
|
||||
|
||||
@@ -535,7 +535,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
t("fileManager.fileUploadedSuccessfully", { name: file.name }),
|
||||
);
|
||||
handleRefreshDirectory();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
toast.dismiss(progressToast);
|
||||
|
||||
if (
|
||||
@@ -584,7 +584,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
t("fileManager.fileDownloadedSuccessfully", { name: file.name }),
|
||||
);
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (
|
||||
error.message?.includes("connection") ||
|
||||
error.message?.includes("established")
|
||||
@@ -665,7 +665,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
);
|
||||
handleRefreshDirectory();
|
||||
clearSelection();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
if (
|
||||
error.message?.includes("connection") ||
|
||||
error.message?.includes("established")
|
||||
@@ -775,7 +775,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
component: createWindowComponent,
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
toast.error(
|
||||
error?.response?.data?.error ||
|
||||
error?.message ||
|
||||
@@ -914,7 +914,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
successCount++;
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error(`Failed to ${operation} file ${file.name}:`, error);
|
||||
toast.error(
|
||||
t("fileManager.operationFailed", {
|
||||
@@ -1015,7 +1015,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
if (operation === "cut") {
|
||||
setClipboard(null);
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
toast.error(
|
||||
`${t("fileManager.pasteFailed")}: ${error.message || t("fileManager.unknownError")}`,
|
||||
);
|
||||
@@ -1050,7 +1050,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
currentHost?.userId?.toString(),
|
||||
);
|
||||
successCount++;
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error(
|
||||
`Failed to delete copied file ${copiedFile.targetName}:`,
|
||||
error,
|
||||
@@ -1092,7 +1092,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
currentHost?.userId?.toString(),
|
||||
);
|
||||
successCount++;
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error(
|
||||
`Failed to move back file ${movedFile.targetName}:`,
|
||||
error,
|
||||
@@ -1132,7 +1132,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
}
|
||||
|
||||
handleRefreshDirectory();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
toast.error(
|
||||
`${t("fileManager.undoOperationFailed")}: ${error.message || t("fileManager.unknownError")}`,
|
||||
);
|
||||
@@ -1204,7 +1204,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
|
||||
setCreateIntent(null);
|
||||
handleRefreshDirectory();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error("Create failed:", error);
|
||||
toast.error(t("fileManager.failedToCreateItem"));
|
||||
}
|
||||
@@ -1233,7 +1233,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
);
|
||||
setEditingFile(null);
|
||||
handleRefreshDirectory();
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error("Rename failed:", error);
|
||||
toast.error(t("fileManager.failedToRenameItem"));
|
||||
}
|
||||
@@ -1269,11 +1269,11 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
clearSelection();
|
||||
initialLoadDoneRef.current = true;
|
||||
toast.success(t("fileManager.connectedSuccessfully"));
|
||||
} catch (dirError: any) {
|
||||
} catch (dirError: unknown) {
|
||||
console.error("Failed to load initial directory:", dirError);
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error("TOTP verification failed:", error);
|
||||
toast.error(t("fileManager.totpVerificationFailed"));
|
||||
} finally {
|
||||
@@ -1340,7 +1340,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
movedItems.push(file.name);
|
||||
successCount++;
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error(`Failed to move file ${file.name}:`, error);
|
||||
toast.error(
|
||||
t("fileManager.moveFileFailed", { name: file.name }) +
|
||||
@@ -1388,7 +1388,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
handleRefreshDirectory();
|
||||
clearSelection();
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error("Drag move operation failed:", error);
|
||||
toast.error(t("fileManager.moveOperationFailed") + ": " + error.message);
|
||||
}
|
||||
@@ -1459,7 +1459,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
await dragToDesktop.dragFilesToDesktop(files);
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
console.error("Drag to desktop failed:", error);
|
||||
toast.error(
|
||||
t("fileManager.dragFailed") +
|
||||
@@ -1554,7 +1554,9 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
|
||||
|
||||
try {
|
||||
const pinnedData = await getPinnedFiles(currentHost.id);
|
||||
const pinnedPaths = new Set(pinnedData.map((item: any) => item.path));
|
||||
const pinnedPaths = new Set(
|
||||
pinnedData.map((item: Record<string, unknown>) => item.path),
|
||||
);
|
||||
setPinnedFiles(pinnedPaths);
|
||||
} catch (error) {
|
||||
console.error("Failed to load pinned files:", error);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,21 @@ import {
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/components/ui/button.tsx";
|
||||
|
||||
interface TabData {
|
||||
id: number;
|
||||
type: string;
|
||||
title: string;
|
||||
terminalRef?: {
|
||||
current?: {
|
||||
fit?: () => void;
|
||||
notifyResize?: () => void;
|
||||
refresh?: () => void;
|
||||
};
|
||||
};
|
||||
hostConfig?: unknown;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface TerminalViewProps {
|
||||
isTopbarOpen?: boolean;
|
||||
}
|
||||
@@ -25,11 +40,16 @@ interface TerminalViewProps {
|
||||
export function AppView({
|
||||
isTopbarOpen = true,
|
||||
}: TerminalViewProps): React.ReactElement {
|
||||
const { tabs, currentTab, allSplitScreenTab, removeTab } = useTabs() as any;
|
||||
const { tabs, currentTab, allSplitScreenTab, removeTab } = useTabs() as {
|
||||
tabs: TabData[];
|
||||
currentTab: number;
|
||||
allSplitScreenTab: number[];
|
||||
removeTab: (id: number) => void;
|
||||
};
|
||||
const { state: sidebarState } = useSidebar();
|
||||
|
||||
const terminalTabs = tabs.filter(
|
||||
(tab: any) =>
|
||||
(tab: TabData) =>
|
||||
tab.type === "terminal" ||
|
||||
tab.type === "server" ||
|
||||
tab.type === "file_manager",
|
||||
@@ -59,7 +79,7 @@ export function AppView({
|
||||
const splitIds = allSplitScreenTab as number[];
|
||||
visibleIds.push(currentTab, ...splitIds.filter((i) => i !== currentTab));
|
||||
}
|
||||
terminalTabs.forEach((t: any) => {
|
||||
terminalTabs.forEach((t: TabData) => {
|
||||
if (visibleIds.includes(t.id)) {
|
||||
const ref = t.terminalRef?.current;
|
||||
if (ref?.fit) ref.fit();
|
||||
@@ -125,16 +145,16 @@ export function AppView({
|
||||
|
||||
const renderTerminalsLayer = () => {
|
||||
const styles: Record<number, React.CSSProperties> = {};
|
||||
const splitTabs = terminalTabs.filter((tab: any) =>
|
||||
const splitTabs = terminalTabs.filter((tab: TabData) =>
|
||||
allSplitScreenTab.includes(tab.id),
|
||||
);
|
||||
const mainTab = terminalTabs.find((tab: any) => tab.id === currentTab);
|
||||
const mainTab = terminalTabs.find((tab: TabData) => tab.id === currentTab);
|
||||
const layoutTabs = [
|
||||
mainTab,
|
||||
...splitTabs.filter(
|
||||
(t: any) => t && t.id !== (mainTab && (mainTab as any).id),
|
||||
(t: TabData) => t && t.id !== (mainTab && (mainTab as TabData).id),
|
||||
),
|
||||
].filter(Boolean) as any[];
|
||||
].filter((t): t is TabData => t !== null && t !== undefined);
|
||||
|
||||
if (allSplitScreenTab.length === 0 && mainTab) {
|
||||
const isFileManagerTab = mainTab.type === "file_manager";
|
||||
@@ -150,7 +170,7 @@ export function AppView({
|
||||
opacity: ready ? 1 : 0,
|
||||
};
|
||||
} else {
|
||||
layoutTabs.forEach((t: any) => {
|
||||
layoutTabs.forEach((t: TabData) => {
|
||||
const rect = panelRects[String(t.id)];
|
||||
const parentRect = containerRef.current?.getBoundingClientRect();
|
||||
if (rect && parentRect) {
|
||||
@@ -171,7 +191,7 @@ export function AppView({
|
||||
|
||||
return (
|
||||
<div className="absolute inset-0 z-[1]">
|
||||
{terminalTabs.map((t: any) => {
|
||||
{terminalTabs.map((t: TabData) => {
|
||||
const hasStyle = !!styles[t.id];
|
||||
const isVisible =
|
||||
hasStyle || (allSplitScreenTab.length === 0 && t.id === currentTab);
|
||||
@@ -241,16 +261,16 @@ export function AppView({
|
||||
};
|
||||
|
||||
const renderSplitOverlays = () => {
|
||||
const splitTabs = terminalTabs.filter((tab: any) =>
|
||||
const splitTabs = terminalTabs.filter((tab: TabData) =>
|
||||
allSplitScreenTab.includes(tab.id),
|
||||
);
|
||||
const mainTab = terminalTabs.find((tab: any) => tab.id === currentTab);
|
||||
const mainTab = terminalTabs.find((tab: TabData) => tab.id === currentTab);
|
||||
const layoutTabs = [
|
||||
mainTab,
|
||||
...splitTabs.filter(
|
||||
(t: any) => t && t.id !== (mainTab && (mainTab as any).id),
|
||||
(t: TabData) => t && t.id !== (mainTab && (mainTab as TabData).id),
|
||||
),
|
||||
].filter(Boolean) as any[];
|
||||
].filter((t): t is TabData => t !== null && t !== undefined);
|
||||
if (allSplitScreenTab.length === 0) return null;
|
||||
|
||||
const handleStyle = {
|
||||
@@ -258,13 +278,16 @@ export function AppView({
|
||||
zIndex: 12,
|
||||
background: "var(--color-dark-border)",
|
||||
} as React.CSSProperties;
|
||||
const commonGroupProps = {
|
||||
const commonGroupProps: {
|
||||
onLayout: () => void;
|
||||
onResize: () => void;
|
||||
} = {
|
||||
onLayout: scheduleMeasureAndFit,
|
||||
onResize: scheduleMeasureAndFit,
|
||||
} as any;
|
||||
};
|
||||
|
||||
if (layoutTabs.length === 2) {
|
||||
const [a, b] = layoutTabs as any[];
|
||||
const [a, b] = layoutTabs;
|
||||
return (
|
||||
<div className="absolute inset-0 z-[10] pointer-events-none">
|
||||
<ResizablePrimitive.PanelGroup
|
||||
@@ -316,7 +339,7 @@ export function AppView({
|
||||
);
|
||||
}
|
||||
if (layoutTabs.length === 3) {
|
||||
const [a, b, c] = layoutTabs as any[];
|
||||
const [a, b, c] = layoutTabs;
|
||||
return (
|
||||
<div className="absolute inset-0 z-[10] pointer-events-none">
|
||||
<ResizablePrimitive.PanelGroup
|
||||
@@ -404,7 +427,7 @@ export function AppView({
|
||||
);
|
||||
}
|
||||
if (layoutTabs.length === 4) {
|
||||
const [a, b, c, d] = layoutTabs as any[];
|
||||
const [a, b, c, d] = layoutTabs;
|
||||
return (
|
||||
<div className="absolute inset-0 z-[10] pointer-events-none">
|
||||
<ResizablePrimitive.PanelGroup
|
||||
@@ -529,7 +552,7 @@ export function AppView({
|
||||
return null;
|
||||
};
|
||||
|
||||
const currentTabData = tabs.find((tab: any) => tab.id === currentTab);
|
||||
const currentTabData = tabs.find((tab: TabData) => tab.id === currentTab);
|
||||
const isFileManager = currentTabData?.type === "file_manager";
|
||||
const isSplitScreen = allSplitScreenTab.length > 0;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ interface SSHHost {
|
||||
enableTunnel: boolean;
|
||||
enableFileManager: boolean;
|
||||
defaultPath: string;
|
||||
tunnelConnections: any[];
|
||||
tunnelConnections: unknown[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -112,13 +112,19 @@ export function LeftSidebar({
|
||||
setCurrentTab,
|
||||
allSplitScreenTab,
|
||||
updateHostConfig,
|
||||
} = useTabs() as any;
|
||||
} = useTabs() as {
|
||||
tabs: Array<{ id: number; type: string; [key: string]: unknown }>;
|
||||
addTab: (tab: { type: string; [key: string]: unknown }) => number;
|
||||
setCurrentTab: (id: number) => void;
|
||||
allSplitScreenTab: number[];
|
||||
updateHostConfig: (id: number, config: unknown) => void;
|
||||
};
|
||||
const isSplitScreenActive =
|
||||
Array.isArray(allSplitScreenTab) && allSplitScreenTab.length > 0;
|
||||
const sshManagerTab = tabList.find((t) => t.type === "ssh_manager");
|
||||
const openSshManagerTab = () => {
|
||||
if (sshManagerTab || isSplitScreenActive) return;
|
||||
const id = addTab({ type: "ssh_manager" } as any);
|
||||
const id = addTab({ type: "ssh_manager" });
|
||||
setCurrentTab(id);
|
||||
};
|
||||
const adminTab = tabList.find((t) => t.type === "admin");
|
||||
@@ -128,7 +134,7 @@ export function LeftSidebar({
|
||||
setCurrentTab(adminTab.id);
|
||||
return;
|
||||
}
|
||||
const id = addTab({ type: "admin" } as any);
|
||||
const id = addTab({ type: "admin" });
|
||||
setCurrentTab(id);
|
||||
};
|
||||
const userProfileTab = tabList.find((t) => t.type === "user_profile");
|
||||
@@ -138,7 +144,7 @@ export function LeftSidebar({
|
||||
setCurrentTab(userProfileTab.id);
|
||||
return;
|
||||
}
|
||||
const id = addTab({ type: "user_profile" } as any);
|
||||
const id = addTab({ type: "user_profile" });
|
||||
setCurrentTab(id);
|
||||
};
|
||||
|
||||
@@ -206,7 +212,7 @@ export function LeftSidebar({
|
||||
});
|
||||
}, 50);
|
||||
}
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
setHostsError(t("leftSidebar.failedToLoadHosts"));
|
||||
}
|
||||
}, [updateHostConfig]);
|
||||
@@ -319,9 +325,10 @@ export function LeftSidebar({
|
||||
await deleteAccount(deletePassword);
|
||||
|
||||
handleLogout();
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
setDeleteError(
|
||||
err?.response?.data?.error || t("leftSidebar.failedToDeleteAccount"),
|
||||
(err as { response?: { data?: { error?: string } } })?.response?.data
|
||||
?.error || t("leftSidebar.failedToDeleteAccount"),
|
||||
);
|
||||
setDeleteLoading(false);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,18 @@ import { TabDropdown } from "@/ui/Desktop/Navigation/Tabs/TabDropdown.tsx";
|
||||
import { getCookie, setCookie } from "@/ui/main-axios.ts";
|
||||
import { SnippetsSidebar } from "@/ui/Desktop/Apps/Terminal/SnippetsSidebar.tsx";
|
||||
|
||||
interface TabData {
|
||||
id: number;
|
||||
type: string;
|
||||
title: string;
|
||||
terminalRef?: {
|
||||
current?: {
|
||||
sendInput?: (data: string) => void;
|
||||
};
|
||||
};
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface TopNavbarProps {
|
||||
isTopbarOpen: boolean;
|
||||
setIsTopbarOpen: (open: boolean) => void;
|
||||
@@ -35,7 +47,14 @@ export function TopNavbar({
|
||||
setSplitScreenTab,
|
||||
removeTab,
|
||||
allSplitScreenTab,
|
||||
} = useTabs() as any;
|
||||
} = useTabs() as {
|
||||
tabs: TabData[];
|
||||
currentTab: number;
|
||||
setCurrentTab: (id: number) => void;
|
||||
setSplitScreenTab: (id: number) => void;
|
||||
removeTab: (id: number) => void;
|
||||
allSplitScreenTab: number[];
|
||||
};
|
||||
const leftPosition = state === "collapsed" ? "26px" : "264px";
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -192,7 +211,7 @@ export function TopNavbar({
|
||||
|
||||
if (commandToSend) {
|
||||
selectedTabIds.forEach((tabId) => {
|
||||
const tab = tabs.find((t: any) => t.id === tabId);
|
||||
const tab = tabs.find((t: TabData) => t.id === tabId);
|
||||
if (tab?.terminalRef?.current?.sendInput) {
|
||||
tab.terminalRef.current.sendInput(commandToSend);
|
||||
}
|
||||
@@ -206,7 +225,7 @@ export function TopNavbar({
|
||||
if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
|
||||
const char = e.key;
|
||||
selectedTabIds.forEach((tabId) => {
|
||||
const tab = tabs.find((t: any) => t.id === tabId);
|
||||
const tab = tabs.find((t: TabData) => t.id === tabId);
|
||||
if (tab?.terminalRef?.current?.sendInput) {
|
||||
tab.terminalRef.current.sendInput(char);
|
||||
}
|
||||
@@ -215,7 +234,7 @@ export function TopNavbar({
|
||||
};
|
||||
|
||||
const handleSnippetExecute = (content: string) => {
|
||||
const tab = tabs.find((t: any) => t.id === currentTab);
|
||||
const tab = tabs.find((t: TabData) => t.id === currentTab);
|
||||
if (tab?.terminalRef?.current?.sendInput) {
|
||||
tab.terminalRef.current.sendInput(content + "\n");
|
||||
}
|
||||
@@ -223,13 +242,13 @@ export function TopNavbar({
|
||||
|
||||
const isSplitScreenActive =
|
||||
Array.isArray(allSplitScreenTab) && allSplitScreenTab.length > 0;
|
||||
const currentTabObj = tabs.find((t: any) => t.id === currentTab);
|
||||
const currentTabObj = tabs.find((t: TabData) => t.id === currentTab);
|
||||
const currentTabIsHome = currentTabObj?.type === "home";
|
||||
const currentTabIsSshManager = currentTabObj?.type === "ssh_manager";
|
||||
const currentTabIsAdmin = currentTabObj?.type === "admin";
|
||||
const currentTabIsUserProfile = currentTabObj?.type === "user_profile";
|
||||
|
||||
const terminalTabs = tabs.filter((tab: any) => tab.type === "terminal");
|
||||
const terminalTabs = tabs.filter((tab: TabData) => tab.type === "terminal");
|
||||
|
||||
const updateRightClickCopyPaste = (checked: boolean) => {
|
||||
setCookie("rightClickCopyPaste", checked.toString());
|
||||
@@ -246,7 +265,7 @@ export function TopNavbar({
|
||||
}}
|
||||
>
|
||||
<div className="h-full p-1 pr-2 border-r-2 border-dark-border w-[calc(100%-6rem)] flex items-center overflow-x-auto overflow-y-hidden gap-2 thin-scrollbar">
|
||||
{tabs.map((tab: any) => {
|
||||
{tabs.map((tab: TabData) => {
|
||||
const isActive = tab.id === currentTab;
|
||||
const isSplit =
|
||||
Array.isArray(allSplitScreenTab) &&
|
||||
|
||||
Reference in New Issue
Block a user