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
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { ServiceStatusIndicators } from "./components/ServiceStatusIndicators";
import { SidebarToggle } from "./components/SidebarToggle";
import { V2WorkspaceOpenInButton } from "./components/V2WorkspaceOpenInButton";
import { V2WorkspaceSearchBarTrigger } from "./components/V2WorkspaceSearchBarTrigger";
import { VersionToggle } from "./components/VersionToggle";
import { WindowControls } from "./components/WindowControls";

export function TopBar() {
Expand All @@ -32,7 +31,7 @@ export function TopBar() {
{ enabled: !!workspaceId && !isV2WorkspaceRoute },
);
const isOnline = useOnlineStatus();
const { isV2CloudEnabled, isRemoteV2Enabled } = useIsV2CloudEnabled();
const { isV2CloudEnabled } = useIsV2CloudEnabled();
// Default to Mac layout while loading to avoid overlap with traffic lights
const isMac = platform === undefined || platform === "darwin";

Expand All @@ -47,7 +46,6 @@ export function TopBar() {
<SidebarToggle />
<NavigationControls />
<ResourceConsumption />
{isRemoteV2Enabled && <VersionToggle />}
</div>

{isV2WorkspaceRoute ? (
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useBrowserShellInteractionPassthrough } from "./useBrowserShellInteractionPassthrough";
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { WorkspaceInteractionState } from "@superset/panes";
import { useCallback, useEffect, useRef } from "react";
import { browserRuntimeRegistry } from "../usePaneRegistry/components/BrowserPane";

interface UseBrowserShellInteractionPassthroughArgs {
sidebarOpen: boolean;
}

export function useBrowserShellInteractionPassthrough({
sidebarOpen,
}: UseBrowserShellInteractionPassthroughArgs) {
const workspaceResizeActiveRef = useRef(false);
const sidebarResizeActiveRef = useRef(false);

const syncBrowserShellInteractionPassthrough = useCallback(() => {
browserRuntimeRegistry.setShellInteractionPassthrough(
workspaceResizeActiveRef.current || sidebarResizeActiveRef.current,
);
}, []);

const onWorkspaceInteractionStateChange = useCallback(
(state: WorkspaceInteractionState) => {
workspaceResizeActiveRef.current = state.resizeActive;
syncBrowserShellInteractionPassthrough();
},
[syncBrowserShellInteractionPassthrough],
);

const onSidebarResizeDragging = useCallback(
(isDragging: boolean) => {
sidebarResizeActiveRef.current = isDragging;
syncBrowserShellInteractionPassthrough();
},
[syncBrowserShellInteractionPassthrough],
);

const clearBrowserShellInteractionPassthrough = useCallback(() => {
workspaceResizeActiveRef.current = false;
sidebarResizeActiveRef.current = false;
browserRuntimeRegistry.setShellInteractionPassthrough(false);
}, []);

useEffect(() => {
window.addEventListener("blur", clearBrowserShellInteractionPassthrough);
return () => {
window.removeEventListener(
"blur",
clearBrowserShellInteractionPassthrough,
);
clearBrowserShellInteractionPassthrough();
};
}, [clearBrowserShellInteractionPassthrough]);

useEffect(() => {
if (sidebarOpen || !sidebarResizeActiveRef.current) return;
sidebarResizeActiveRef.current = false;
syncBrowserShellInteractionPassthrough();
}, [sidebarOpen, syncBrowserShellInteractionPassthrough]);

return {
onSidebarResizeDragging,
onWorkspaceInteractionStateChange,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useClearActivePaneAttention } from "./useClearActivePaneAttention";
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { WorkspaceStore } from "@superset/panes";
import { useEffect } from "react";
import {
getV2NotificationSourcesForPane,
useV2NotificationStore,
useV2PaneNotificationStatus,
} from "renderer/stores/v2-notifications";
import { useStore } from "zustand";
import type { StoreApi } from "zustand/vanilla";
import type { PaneViewerData } from "../../types";

export function useClearActivePaneAttention({
workspaceId,
store,
}: {
workspaceId: string;
store: StoreApi<WorkspaceStore<PaneViewerData>>;
}): void {
const activePane = useStore(store, (state) => {
const tab = state.tabs.find(
(candidate) => candidate.id === state.activeTabId,
);
return tab?.activePaneId ? tab.panes[tab.activePaneId] : undefined;
});
const activePaneStatus = useV2PaneNotificationStatus(workspaceId, activePane);
const clearSourceAttention = useV2NotificationStore(
(state) => state.clearSourceAttention,
);

useEffect(() => {
if (activePaneStatus !== "review") return;
for (const source of getV2NotificationSourcesForPane(activePane)) {
clearSourceAttention(source, workspaceId);
}
}, [activePane, activePaneStatus, clearSourceAttention, workspaceId]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useDefaultPaneActions } from "./useDefaultPaneActions";
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { PaneActionConfig } from "@superset/panes";
import { useMemo } from "react";
import { HiMiniXMark } from "react-icons/hi2";
import { TbLayoutColumns, TbLayoutRows } from "react-icons/tb";
import { HotkeyLabel } from "renderer/hotkeys";
import type { PaneViewerData, TerminalPaneData } from "../../types";

export function useDefaultPaneActions(): PaneActionConfig<PaneViewerData>[] {
return useMemo<PaneActionConfig<PaneViewerData>[]>(
() => [
{
key: "split",
icon: (ctx) =>
ctx.pane.parentDirection === "horizontal" ? (
<TbLayoutRows className="size-3.5" />
) : (
<TbLayoutColumns className="size-3.5" />
),
tooltip: <HotkeyLabel label="Split pane" id="SPLIT_AUTO" />,
onClick: (ctx) => {
const position =
ctx.pane.parentDirection === "horizontal" ? "down" : "right";
ctx.actions.split(position, {
kind: "terminal",
data: {
terminalId: crypto.randomUUID(),
} as TerminalPaneData,
});
},
},
{
key: "close",
icon: <HiMiniXMark className="size-3.5" />,
tooltip: <HotkeyLabel label="Close pane" id="CLOSE_PANE" />,
onClick: (ctx) => ctx.actions.close(),
},
],
[],
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useDirtyTabCloseGuard } from "./useDirtyTabCloseGuard";
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { WorkspaceProps } from "@superset/panes";
import { alert } from "@superset/ui/atoms/Alert";
import { useCallback } from "react";
import { getBaseName } from "renderer/lib/pathBasename";
import { getDocument } from "../../state/fileDocumentStore";
import type { FilePaneData, PaneViewerData } from "../../types";

type OnBeforeCloseTab = NonNullable<
WorkspaceProps<PaneViewerData>["onBeforeCloseTab"]
>;

export function useDirtyTabCloseGuard({
workspaceId,
}: {
workspaceId: string;
}): OnBeforeCloseTab {
return useCallback<OnBeforeCloseTab>(
(tab) => {
const dirtyPanes = Object.values(tab.panes).filter((pane) => {
if (pane.kind !== "file") return false;
const filePath = (pane.data as FilePaneData).filePath;
return getDocument(workspaceId, filePath)?.dirty === true;
});
const dirtyFileNames = dirtyPanes.map((pane) =>
getBaseName((pane.data as FilePaneData).filePath),
);
if (dirtyPanes.length === 0) return true;
const title =
dirtyPanes.length === 1
? `Do you want to save the changes you made to ${dirtyFileNames[0]}?`
: `Do you want to save changes to ${dirtyPanes.length} files?`;
return new Promise<boolean>((resolve) => {
alert({
title,
description: "Your changes will be lost if you don't save them.",
actions: [
{
label: "Save All",
onClick: async () => {
for (const pane of dirtyPanes) {
const filePath = (pane.data as FilePaneData).filePath;
const doc = getDocument(workspaceId, filePath);
if (!doc) continue;
const result = await doc.save();
if (result.status !== "saved") {
resolve(false);
return;
}
}
resolve(true);
},
},
{
label: "Don't Save",
variant: "secondary",
onClick: async () => {
for (const pane of dirtyPanes) {
const filePath = (pane.data as FilePaneData).filePath;
const doc = getDocument(workspaceId, filePath);
if (doc) await doc.reload();
}
resolve(true);
},
},
{
label: "Cancel",
variant: "ghost",
onClick: () => resolve(false),
},
],
});
});
},
[workspaceId],
);
}
Loading
Loading