Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/desktop/src/main/host-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { serve } from "@hono/node-server";
import {
createApp,
installProcessSafetyNet,
JwtApiAuthProvider,
LocalGitCredentialProvider,
LocalModelProvider,
Expand Down Expand Up @@ -53,6 +54,10 @@ async function main(): Promise<void> {
const server = serve(
{ fetch: app.fetch, port: env.HOST_SERVICE_PORT, hostname: "127.0.0.1" },
(info: { port: number }) => {
// Install only after the server is listening so startup throws still
// reach `main().catch(...)` and exit with a non-zero code.
installProcessSafetyNet();

if (env.ORGANIZATION_ID) {
try {
writeManifest({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,43 @@ interface FileTreeState {
loadingDirectories: Set<string>;
}

interface LoadDirectoryOptions {
force?: boolean;
}

function applyDirectoryEntries(
current: FileTreeState,
absolutePath: string,
entries: FsEntry[],
): FileTreeState {
const nextEntries = new Map(current.entriesByPath);
const nextChildren = new Map(current.childPathsByDirectory);
const nextLoaded = new Set(current.loadedDirectories);
const nextInvalidated = new Set(current.invalidatedDirectories);
const nextLoading = new Set(current.loadingDirectories);
nextLoading.delete(absolutePath);
nextLoaded.add(absolutePath);
nextInvalidated.delete(absolutePath);

for (const entry of entries) {
nextEntries.set(entry.absolutePath, entry);
}

nextChildren.set(
absolutePath,
entries.map((entry) => entry.absolutePath),
);

return {
...current,
childPathsByDirectory: nextChildren,
entriesByPath: nextEntries,
invalidatedDirectories: nextInvalidated,
loadedDirectories: nextLoaded,
loadingDirectories: nextLoading,
};
}

function createInitialState(): FileTreeState {
return {
childPathsByDirectory: new Map<string, string[]>(),
Expand Down Expand Up @@ -187,16 +224,15 @@ export function useFileTree({
);

const loadDirectory = useCallback(
async (absolutePath: string, force = false): Promise<void> => {
if (!workspaceId || !absolutePath) {
return;
}
async (
absolutePath: string,
options: LoadDirectoryOptions = {},
): Promise<void> => {
const { force = false } = options;
if (!workspaceId || !absolutePath) return;

const currentState = stateRef.current;
if (currentState.loadingDirectories.has(absolutePath)) {
return;
}

if (currentState.loadingDirectories.has(absolutePath)) return;
if (
!force &&
currentState.loadedDirectories.has(absolutePath) &&
Expand All @@ -205,65 +241,38 @@ export function useFileTree({
return;
}

updateState((current) => {
const nextLoading = new Set(current.loadingDirectories);
nextLoading.add(absolutePath);
return {
...current,
loadingDirectories: nextLoading,
};
});
const input = { workspaceId, absolutePath };
const cachedResult = utils.filesystem.listDirectory.getData(input);
if (cachedResult) {
updateState((current) =>
applyDirectoryEntries(current, absolutePath, cachedResult.entries),
);
if (!force) return;
Comment thread
MocA-Love marked this conversation as resolved.
}

try {
const result = await utils.filesystem.listDirectory.fetch({
workspaceId,
updateState((current) => ({
...current,
loadingDirectories: new Set(current.loadingDirectories).add(
absolutePath,
});

updateState((current) => {
const nextEntries = new Map(current.entriesByPath);
const nextChildren = new Map(current.childPathsByDirectory);
const nextLoaded = new Set(current.loadedDirectories);
const nextInvalidated = new Set(current.invalidatedDirectories);
const nextLoading = new Set(current.loadingDirectories);
nextLoading.delete(absolutePath);
nextLoaded.add(absolutePath);
nextInvalidated.delete(absolutePath);

for (const entry of result.entries) {
nextEntries.set(entry.absolutePath, entry);
}

nextChildren.set(
absolutePath,
result.entries.map((entry) => entry.absolutePath),
);
),
}));

return {
...current,
childPathsByDirectory: nextChildren,
entriesByPath: nextEntries,
invalidatedDirectories: nextInvalidated,
loadedDirectories: nextLoaded,
loadingDirectories: nextLoading,
};
});
try {
// Server-side timeout + React Query's TIMEOUT-aware retry handle
// hung host-service IPC; we just await the fetch and apply results.
const result = await utils.filesystem.listDirectory.fetch(input);
updateState((current) =>
applyDirectoryEntries(current, absolutePath, result.entries),
);
} catch (error) {
console.error(
"[workspace-client/useFileTree] Failed to load directory:",
{
absolutePath,
error,
},
{ absolutePath, error },
);

updateState((current) => {
const nextLoading = new Set(current.loadingDirectories);
nextLoading.delete(absolutePath);
return {
...current,
loadingDirectories: nextLoading,
};
return { ...current, loadingDirectories: nextLoading };
});
}
},
Expand All @@ -272,7 +281,7 @@ export function useFileTree({

const refreshPath = useCallback(
async (absolutePath: string): Promise<void> => {
await loadDirectory(absolutePath, true);
await loadDirectory(absolutePath, { force: true });
},
[loadDirectory],
);
Expand All @@ -288,10 +297,10 @@ export function useFileTree({
(left, right) => left.split(/[/\\]/).length - right.split(/[/\\]/).length,
);

await loadDirectory(rootPath, true);
await loadDirectory(rootPath, { force: true });
for (const absolutePath of expandedDirectories) {
if (absolutePath !== rootPath) {
await loadDirectory(absolutePath, true);
await loadDirectory(absolutePath, { force: true });
}
}
}, [loadDirectory, rootPath]);
Expand Down Expand Up @@ -347,11 +356,8 @@ export function useFileTree({

useEffect(() => {
updateState(() => createInitialState());
if (!rootPath) {
return;
}

void loadDirectory(rootPath, true);
if (!rootPath) return;
void loadDirectory(rootPath, { force: true });
}, [loadDirectory, rootPath, updateState]);

useWorkspaceEvent(
Expand Down Expand Up @@ -404,16 +410,16 @@ export function useFileTree({
});

if (stateRef.current.loadedDirectories.has(oldParentPath)) {
void loadDirectory(oldParentPath, true);
void loadDirectory(oldParentPath, { force: true });
}
if (stateRef.current.loadedDirectories.has(newParentPath)) {
void loadDirectory(newParentPath, true);
void loadDirectory(newParentPath, { force: true });
}
if (
event.isDirectory &&
stateRef.current.expandedDirectories.has(event.absolutePath)
) {
void loadDirectory(event.absolutePath, true);
void loadDirectory(event.absolutePath, { force: true });
}
return;
}
Expand All @@ -438,7 +444,7 @@ export function useFileTree({
});

if (stateRef.current.loadedDirectories.has(parentPath)) {
void loadDirectory(parentPath, true);
void loadDirectory(parentPath, { force: true });
}
},
Boolean(workspaceId && rootPath),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ interface WorkspaceSidebarProps {
selectedFilePath?: string;
pendingReveal?: PendingReveal | null;
workspaceId: string;
workspaceName?: string;
}

function IconButton({
Expand Down Expand Up @@ -82,7 +81,6 @@ export function WorkspaceSidebar({
selectedFilePath,
pendingReveal,
workspaceId,
workspaceName,
}: WorkspaceSidebarProps) {
const collections = useCollections();
// FORK NOTE: keep reactive `useLiveQuery` against
Expand Down Expand Up @@ -155,7 +153,6 @@ export function WorkspaceSidebar({
selectedFilePath={selectedFilePath}
pendingReveal={pendingReveal}
workspaceId={workspaceId}
workspaceName={workspaceName}
gitStatus={gitStatus.data}
/>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { toast } from "@superset/ui/sonner";
import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip";
import { workspaceTrpc } from "@superset/workspace-client";
import type { inferRouterOutputs } from "@trpc/server";
import { FilePlus, FolderPlus, FoldVertical, RefreshCw } from "lucide-react";
import {
FilePlus,
FolderPlus,
FoldVertical,
Loader2,
RefreshCw,
} from "lucide-react";
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
import {
type FileTreeNode,
Expand Down Expand Up @@ -39,7 +45,6 @@ interface FilesTabProps {
isDirectory: boolean;
} | null;
workspaceId: string;
workspaceName?: string;
gitStatus: GitStatusData | undefined;
}

Expand Down Expand Up @@ -209,7 +214,6 @@ export function FilesTab({
selectedFilePath,
pendingReveal,
workspaceId,
workspaceName,
gitStatus,
}: FilesTabProps) {
const [_isRefreshing, setIsRefreshing] = useState(false);
Expand Down Expand Up @@ -462,10 +466,17 @@ export function FilesTab({
[workspaceId, deletePath],
);

if (!workspaceQuery.data?.worktreePath) {
if (!rootPath) {
return (
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
Workspace worktree not available
<div className="flex h-full items-center justify-center gap-2 text-sm text-muted-foreground">
{workspaceQuery.isLoading ? (
<>
<Loader2 className="size-3.5 animate-spin" />
<span>Loading files...</span>
</>
) : (
"Workspace worktree not available"
)}
</div>
);
}
Expand Down Expand Up @@ -503,7 +514,7 @@ export function FilesTab({
zIndex: 20,
}}
>
<span className="truncate">{workspaceName ?? "Explorer"}</span>
<span className="truncate">Explorer</span>
<div className="flex items-center gap-0.5">
<Tooltip>
<TooltipTrigger asChild>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ function V2WorkspacePage() {
<WorkspaceContent
projectId={workspace.projectId}
workspaceId={workspace.id}
workspaceName={workspace.name}
terminalId={terminalId}
chatSessionId={chatSessionId}
focusRequestId={focusRequestId}
Expand Down Expand Up @@ -223,7 +222,6 @@ function useClearActivePaneAttention({
function WorkspaceContent({
projectId,
workspaceId,
workspaceName,
terminalId,
chatSessionId,
focusRequestId,
Expand All @@ -233,7 +231,6 @@ function WorkspaceContent({
}: {
projectId: string;
workspaceId: string;
workspaceName: string;
terminalId?: string;
chatSessionId?: string;
focusRequestId?: string;
Expand Down Expand Up @@ -870,7 +867,6 @@ function WorkspaceContent({
>
<WorkspaceSidebar
workspaceId={workspaceId}
workspaceName={workspaceName}
onSelectFile={openSidebarFilePane}
onSelectDiffFile={openDiffPane}
onOpenComment={openCommentPane}
Expand Down Expand Up @@ -900,7 +896,6 @@ function WorkspaceContent({
recentlyViewedFiles={recentFiles}
scope={commandPalette.scope}
searchResults={commandPalette.searchResults}
workspaceName={workspaceName}
includeIgnored={commandPalette.includeIgnored}
onToggleIncludeIgnored={commandPalette.toggleIncludeIgnored}
/>
Expand Down
Loading
Loading