Remove pinned launchers from workspace rows
This commit is contained in:
@@ -19,10 +19,6 @@ export function tabRowPin(page: Page, target: PinnedTabTarget) {
|
||||
return page.getByTestId(`workspace-pinned-target-${pinnedTargetKey(target)}`);
|
||||
}
|
||||
|
||||
export function sidebarPin(page: Page, target: PinnedTabTarget) {
|
||||
return page.getByTestId(`sidebar-pinned-target-${pinnedTargetKey(target)}`);
|
||||
}
|
||||
|
||||
export async function openNewTabMenu(page: Page): Promise<void> {
|
||||
const trigger = page
|
||||
.getByTestId("workspace-new-tab-menu-trigger")
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { test, expect } from "./fixtures";
|
||||
import { gotoWorkspace } from "./helpers/launcher";
|
||||
import { gotoAppShell } from "./helpers/app";
|
||||
import { getServerId } from "./helpers/server-id";
|
||||
import { seedWorkspace, type SeededWorkspace } from "./helpers/seed-client";
|
||||
import { togglePinFromMenu, tabRowPin, sidebarPin } from "./helpers/pins";
|
||||
import { togglePinFromMenu, tabRowPin } from "./helpers/pins";
|
||||
import { expectTerminalTabOpen } from "./helpers/workspace-tabs";
|
||||
import type { PinnedTabTarget } from "../src/workspace-pins/target";
|
||||
|
||||
@@ -45,23 +43,4 @@ test.describe("Pinned tab targets", () => {
|
||||
|
||||
await expectTerminalTabOpen(page);
|
||||
});
|
||||
|
||||
test("the pinned button is mirrored in the sidebar workspace row and launches a terminal in that workspace", async ({
|
||||
page,
|
||||
}) => {
|
||||
test.setTimeout(45_000);
|
||||
await gotoWorkspace(page, workspace.workspaceId);
|
||||
await togglePinFromMenu(page, TERMINAL_TARGET);
|
||||
|
||||
await gotoAppShell(page);
|
||||
const row = page.getByTestId(`sidebar-workspace-row-${getServerId()}:${workspace.workspaceId}`);
|
||||
await expect(row).toBeVisible({ timeout: 30_000 });
|
||||
await row.hover();
|
||||
|
||||
await expect(sidebarPin(page, TERMINAL_TARGET)).toBeVisible({ timeout: 10_000 });
|
||||
await sidebarPin(page, TERMINAL_TARGET).click();
|
||||
|
||||
await expect(page).toHaveURL(/\/workspace\//, { timeout: 30_000 });
|
||||
await expectTerminalTabOpen(page);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -70,11 +70,6 @@ import {
|
||||
type SidebarWorkspaceEntry,
|
||||
} from "@/hooks/use-sidebar-workspaces-list";
|
||||
import { useSidebarOrderStore } from "@/stores/sidebar-order-store";
|
||||
import { buildWorkspaceTabPersistenceKey } from "@/stores/workspace-tabs-store/state";
|
||||
import { usePinnedLaunchers } from "@/workspace-pins/launch";
|
||||
import { useLaunchIntentStore } from "@/workspace-pins/launch-intent-store";
|
||||
import { PinnedTargetsRow } from "@/workspace-pins/pinned-targets-row";
|
||||
import type { PinnedTabTarget } from "@/workspace-pins/target";
|
||||
import { useShowShortcutBadges } from "@/hooks/use-show-shortcut-badges";
|
||||
import { ContextMenuTrigger, useContextMenu } from "@/components/ui/context-menu";
|
||||
import {
|
||||
@@ -667,40 +662,16 @@ function WorkspaceRowRightGroup({
|
||||
onRename?: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const isMobileBreakpoint = useIsCompactFormFactor();
|
||||
const showShortcut = showShortcutBadge && shortcutNumber !== null;
|
||||
const showKebab = Boolean(onArchive && (isHovered || isTouchPlatform));
|
||||
const showKebabInSlot = showKebab && !showShortcut;
|
||||
const shouldRenderActionSlot = Boolean(onArchive || workspace.diffStat);
|
||||
const showPinnedTargets = (isHovered || platformIsNative || isMobileBreakpoint) && !showShortcut;
|
||||
|
||||
const onLaunch = useCallback(
|
||||
(target: PinnedTabTarget) => {
|
||||
const workspaceKey = buildWorkspaceTabPersistenceKey({
|
||||
serverId: workspace.serverId,
|
||||
workspaceId: workspace.workspaceId,
|
||||
});
|
||||
if (!workspaceKey) return;
|
||||
navigateToWorkspace(workspace.serverId, workspace.workspaceId);
|
||||
useLaunchIntentStore.getState().request({ workspaceKey, target });
|
||||
},
|
||||
[workspace.serverId, workspace.workspaceId],
|
||||
);
|
||||
const launchers = usePinnedLaunchers({ serverId: workspace.serverId, onLaunch });
|
||||
|
||||
return (
|
||||
<>
|
||||
{isCreating ? (
|
||||
<Text style={styles.workspaceCreatingText}>{t("sidebar.workspace.status.creating")}</Text>
|
||||
) : null}
|
||||
{launchers.length > 0 ? (
|
||||
<View
|
||||
style={showPinnedTargets ? undefined : styles.pinnedTargetsHidden}
|
||||
pointerEvents={showPinnedTargets ? "auto" : "none"}
|
||||
>
|
||||
<PinnedTargetsRow launchers={launchers} testIdPrefix="sidebar-pinned-target" />
|
||||
</View>
|
||||
) : null}
|
||||
{shouldRenderActionSlot ? (
|
||||
<SidebarWorkspaceTrailingActionSlot>
|
||||
<SidebarWorkspaceTrailingActionBase
|
||||
@@ -2719,9 +2690,6 @@ const styles = StyleSheet.create((theme) => ({
|
||||
fontSize: theme.fontSize.xs,
|
||||
flexShrink: 0,
|
||||
},
|
||||
pinnedTargetsHidden: {
|
||||
opacity: 0,
|
||||
},
|
||||
kebabButton: {
|
||||
padding: 2,
|
||||
borderRadius: 4,
|
||||
|
||||
@@ -185,8 +185,6 @@ import {
|
||||
resolveTerminalProfiles,
|
||||
} from "@getpaseo/protocol/terminal-profiles";
|
||||
import { getProviderIcon } from "@/components/provider-icons";
|
||||
import { useLaunchIntentStore } from "@/workspace-pins/launch-intent-store";
|
||||
import { runPinnedTabTarget, type TabTargetHandlers } from "@/workspace-pins/run";
|
||||
import {
|
||||
createWorkspaceFileTabTarget,
|
||||
normalizeWorkspaceFileLocation,
|
||||
@@ -1720,37 +1718,6 @@ function useWorkspaceCheckoutStatus(input: {
|
||||
return { checkoutQuery, isCheckoutStatusLoading };
|
||||
}
|
||||
|
||||
interface PinnedTabLaunchConsumerInput {
|
||||
serverId: string;
|
||||
persistenceKey: string | null;
|
||||
isRouteFocused: boolean;
|
||||
handlers: TabTargetHandlers;
|
||||
}
|
||||
|
||||
function usePinnedTabLaunchConsumer({
|
||||
serverId,
|
||||
persistenceKey,
|
||||
isRouteFocused,
|
||||
handlers,
|
||||
}: PinnedTabLaunchConsumerInput) {
|
||||
const { config } = useDaemonConfig(serverId);
|
||||
const profiles = useMemo(
|
||||
() => resolveTerminalProfiles(config?.terminalProfiles),
|
||||
[config?.terminalProfiles],
|
||||
);
|
||||
const pending = useLaunchIntentStore((state) => state.pending);
|
||||
|
||||
useEffect(() => {
|
||||
if (!persistenceKey || !isRouteFocused || pending?.workspaceKey !== persistenceKey) {
|
||||
return;
|
||||
}
|
||||
const target = useLaunchIntentStore.getState().consume(persistenceKey);
|
||||
if (target) {
|
||||
runPinnedTabTarget(target, profiles, handlers);
|
||||
}
|
||||
}, [handlers, isRouteFocused, pending, persistenceKey, profiles]);
|
||||
}
|
||||
|
||||
function WorkspaceScreenContent({
|
||||
serverId,
|
||||
workspaceId,
|
||||
@@ -2597,28 +2564,6 @@ function WorkspaceScreenContent({
|
||||
[openWorkspaceTabFocused, persistenceKey],
|
||||
);
|
||||
|
||||
const pinnedTabHandlers = useMemo<TabTargetHandlers>(
|
||||
() => ({
|
||||
createDraft: handleCreateDraftTab,
|
||||
createTerminal: handleCreateTerminal,
|
||||
createBrowser: handleCreateBrowserTab,
|
||||
createTerminalWithProfile: handleCreateTerminalWithProfile,
|
||||
}),
|
||||
[
|
||||
handleCreateBrowserTab,
|
||||
handleCreateDraftTab,
|
||||
handleCreateTerminal,
|
||||
handleCreateTerminalWithProfile,
|
||||
],
|
||||
);
|
||||
|
||||
usePinnedTabLaunchConsumer({
|
||||
serverId: normalizedServerId,
|
||||
persistenceKey,
|
||||
isRouteFocused,
|
||||
handlers: pinnedTabHandlers,
|
||||
});
|
||||
|
||||
useDesktopBrowserNewTabRequests({
|
||||
enabled: Boolean(persistenceKey),
|
||||
workspaceLayout,
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { useLaunchIntentStore } from "./launch-intent-store";
|
||||
|
||||
beforeEach(() => {
|
||||
useLaunchIntentStore.setState({ pending: null });
|
||||
});
|
||||
|
||||
describe("launch intent store", () => {
|
||||
it("returns the requested target when the workspace key matches", () => {
|
||||
useLaunchIntentStore.getState().request({ workspaceKey: "ws-1", target: { kind: "terminal" } });
|
||||
expect(useLaunchIntentStore.getState().consume("ws-1")).toEqual({ kind: "terminal" });
|
||||
});
|
||||
|
||||
it("clears the pending intent once consumed", () => {
|
||||
useLaunchIntentStore.getState().request({ workspaceKey: "ws-1", target: { kind: "draft" } });
|
||||
useLaunchIntentStore.getState().consume("ws-1");
|
||||
expect(useLaunchIntentStore.getState().pending).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null and keeps the intent when the workspace key does not match", () => {
|
||||
useLaunchIntentStore.getState().request({ workspaceKey: "ws-1", target: { kind: "browser" } });
|
||||
expect(useLaunchIntentStore.getState().consume("ws-2")).toBeNull();
|
||||
expect(useLaunchIntentStore.getState().pending).toEqual({
|
||||
workspaceKey: "ws-1",
|
||||
target: { kind: "browser" },
|
||||
});
|
||||
});
|
||||
|
||||
it("returns null when there is no pending intent", () => {
|
||||
expect(useLaunchIntentStore.getState().consume("ws-1")).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
import { create } from "zustand";
|
||||
import type { PinnedTabTarget } from "@/workspace-pins/target";
|
||||
|
||||
export interface PendingTabLaunch {
|
||||
workspaceKey: string;
|
||||
target: PinnedTabTarget;
|
||||
}
|
||||
|
||||
interface LaunchIntentState {
|
||||
pending: PendingTabLaunch | null;
|
||||
request: (intent: PendingTabLaunch) => void;
|
||||
consume: (workspaceKey: string) => PinnedTabTarget | null;
|
||||
}
|
||||
|
||||
export const useLaunchIntentStore = create<LaunchIntentState>((set, get) => ({
|
||||
pending: null,
|
||||
request: (intent) => set({ pending: intent }),
|
||||
consume: (workspaceKey) => {
|
||||
const { pending } = get();
|
||||
if (!pending || pending.workspaceKey !== workspaceKey) {
|
||||
return null;
|
||||
}
|
||||
set({ pending: null });
|
||||
return pending.target;
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user