mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Move tab row pins and default-pin terminal and browser
This commit is contained in:
@@ -5,6 +5,7 @@ import { togglePinFromMenu, tabRowPin } from "./helpers/pins";
|
|||||||
import { expectTerminalTabOpen } from "./helpers/workspace-tabs";
|
import { expectTerminalTabOpen } from "./helpers/workspace-tabs";
|
||||||
import type { PinnedTabTarget } from "../src/workspace-pins/target";
|
import type { PinnedTabTarget } from "../src/workspace-pins/target";
|
||||||
|
|
||||||
|
const DRAFT_TARGET: PinnedTabTarget = { kind: "draft" };
|
||||||
const TERMINAL_TARGET: PinnedTabTarget = { kind: "terminal" };
|
const TERMINAL_TARGET: PinnedTabTarget = { kind: "terminal" };
|
||||||
|
|
||||||
let workspace: SeededWorkspace;
|
let workspace: SeededWorkspace;
|
||||||
@@ -23,13 +24,13 @@ test.describe("Pinned tab targets", () => {
|
|||||||
}) => {
|
}) => {
|
||||||
await gotoWorkspace(page, workspace.workspaceId);
|
await gotoWorkspace(page, workspace.workspaceId);
|
||||||
|
|
||||||
await expect(tabRowPin(page, TERMINAL_TARGET)).toHaveCount(0);
|
await expect(tabRowPin(page, DRAFT_TARGET)).toHaveCount(0);
|
||||||
|
|
||||||
await togglePinFromMenu(page, TERMINAL_TARGET);
|
await togglePinFromMenu(page, DRAFT_TARGET);
|
||||||
await expect(tabRowPin(page, TERMINAL_TARGET)).toBeVisible({ timeout: 10_000 });
|
await expect(tabRowPin(page, DRAFT_TARGET)).toBeVisible({ timeout: 10_000 });
|
||||||
|
|
||||||
await togglePinFromMenu(page, TERMINAL_TARGET);
|
await togglePinFromMenu(page, DRAFT_TARGET);
|
||||||
await expect(tabRowPin(page, TERMINAL_TARGET)).toHaveCount(0, { timeout: 10_000 });
|
await expect(tabRowPin(page, DRAFT_TARGET)).toHaveCount(0, { timeout: 10_000 });
|
||||||
});
|
});
|
||||||
|
|
||||||
test("clicking the pinned quick-launch button in the tab row opens a terminal tab", async ({
|
test("clicking the pinned quick-launch button in the tab row opens a terminal tab", async ({
|
||||||
@@ -38,7 +39,7 @@ test.describe("Pinned tab targets", () => {
|
|||||||
test.setTimeout(45_000);
|
test.setTimeout(45_000);
|
||||||
await gotoWorkspace(page, workspace.workspaceId);
|
await gotoWorkspace(page, workspace.workspaceId);
|
||||||
|
|
||||||
await togglePinFromMenu(page, TERMINAL_TARGET);
|
await expect(tabRowPin(page, TERMINAL_TARGET)).toBeVisible({ timeout: 10_000 });
|
||||||
await tabRowPin(page, TERMINAL_TARGET).click();
|
await tabRowPin(page, TERMINAL_TARGET).click();
|
||||||
|
|
||||||
await expectTerminalTabOpen(page);
|
await expectTerminalTabOpen(page);
|
||||||
|
|||||||
@@ -171,6 +171,44 @@ function PinnableProfileMenuItem({ profile, disabled, onLaunch }: PinnableProfil
|
|||||||
|
|
||||||
interface WorkspaceInlineAddTabButtonProps {
|
interface WorkspaceInlineAddTabButtonProps {
|
||||||
shortcutKeys: ShortcutKey[][] | null;
|
shortcutKeys: ShortcutKey[][] | null;
|
||||||
|
onCreateAgentTab: () => void;
|
||||||
|
onLayout: (event: LayoutChangeEvent) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function WorkspaceInlineAddTabButton({
|
||||||
|
shortcutKeys,
|
||||||
|
onCreateAgentTab,
|
||||||
|
onLayout,
|
||||||
|
}: WorkspaceInlineAddTabButtonProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const tooltipText = t("workspace.tabs.actions.newAgent");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.inlineAddButton} onLayout={onLayout}>
|
||||||
|
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
|
||||||
|
<TooltipTrigger
|
||||||
|
testID="workspace-new-agent-tab-inline"
|
||||||
|
onPress={onCreateAgentTab}
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel={tooltipText}
|
||||||
|
style={inlineAddActionButtonStyle}
|
||||||
|
>
|
||||||
|
<ThemedPlus size={14} uniProps={mutedColorMapping} />
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="bottom" align="center" offset={8}>
|
||||||
|
<View style={styles.newTabTooltipRow}>
|
||||||
|
<Text style={styles.newTabTooltipText}>{tooltipText}</Text>
|
||||||
|
{shortcutKeys ? (
|
||||||
|
<Shortcut chord={shortcutKeys} style={styles.newTabTooltipShortcut} />
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WorkspaceTabRowExtrasProps {
|
||||||
onCreateAgentTab: () => void;
|
onCreateAgentTab: () => void;
|
||||||
onCreateTerminal: () => void;
|
onCreateTerminal: () => void;
|
||||||
onCreateBrowser: () => void;
|
onCreateBrowser: () => void;
|
||||||
@@ -179,11 +217,9 @@ interface WorkspaceInlineAddTabButtonProps {
|
|||||||
normalizedServerId: string;
|
normalizedServerId: string;
|
||||||
showCreateBrowserTab: boolean;
|
showCreateBrowserTab: boolean;
|
||||||
terminalDisabled: boolean;
|
terminalDisabled: boolean;
|
||||||
onLayout: (event: LayoutChangeEvent) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function WorkspaceInlineAddTabButton({
|
function WorkspaceTabRowExtras({
|
||||||
shortcutKeys,
|
|
||||||
onCreateAgentTab,
|
onCreateAgentTab,
|
||||||
onCreateTerminal,
|
onCreateTerminal,
|
||||||
onCreateBrowser,
|
onCreateBrowser,
|
||||||
@@ -192,8 +228,7 @@ function WorkspaceInlineAddTabButton({
|
|||||||
normalizedServerId,
|
normalizedServerId,
|
||||||
showCreateBrowserTab,
|
showCreateBrowserTab,
|
||||||
terminalDisabled,
|
terminalDisabled,
|
||||||
onLayout,
|
}: WorkspaceTabRowExtrasProps) {
|
||||||
}: WorkspaceInlineAddTabButtonProps) {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { config } = useDaemonConfig(normalizedServerId);
|
const { config } = useDaemonConfig(normalizedServerId);
|
||||||
const profiles = useMemo(
|
const profiles = useMemo(
|
||||||
@@ -220,30 +255,8 @@ function WorkspaceInlineAddTabButton({
|
|||||||
|
|
||||||
const launchers = usePinnedLaunchers({ serverId: normalizedServerId, onLaunch });
|
const launchers = usePinnedLaunchers({ serverId: normalizedServerId, onLaunch });
|
||||||
|
|
||||||
const tooltipText = t("workspace.tabs.actions.newAgent");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.inlineAddButton} onLayout={onLayout}>
|
<>
|
||||||
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
|
|
||||||
<TooltipTrigger
|
|
||||||
testID="workspace-new-agent-tab-inline"
|
|
||||||
onPress={onCreateAgentTab}
|
|
||||||
accessibilityRole="button"
|
|
||||||
accessibilityLabel={tooltipText}
|
|
||||||
style={inlineAddActionButtonStyle}
|
|
||||||
>
|
|
||||||
<ThemedPlus size={14} uniProps={mutedColorMapping} />
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent side="bottom" align="center" offset={8}>
|
|
||||||
<View style={styles.newTabTooltipRow}>
|
|
||||||
<Text style={styles.newTabTooltipText}>{tooltipText}</Text>
|
|
||||||
{shortcutKeys ? (
|
|
||||||
<Shortcut chord={shortcutKeys} style={styles.newTabTooltipShortcut} />
|
|
||||||
) : null}
|
|
||||||
</View>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<PinnedTargetsRow launchers={launchers} testIdPrefix="workspace-pinned-target" />
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
|
<Tooltip delayDuration={0} enabledOnDesktop enabledOnMobile={false}>
|
||||||
<TooltipTrigger asChild triggerRefProp="triggerRef">
|
<TooltipTrigger asChild triggerRefProp="triggerRef">
|
||||||
@@ -251,7 +264,7 @@ function WorkspaceInlineAddTabButton({
|
|||||||
testID="workspace-new-tab-menu-trigger"
|
testID="workspace-new-tab-menu-trigger"
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={t("workspace.tabs.actions.moreActions")}
|
accessibilityLabel={t("workspace.tabs.actions.moreActions")}
|
||||||
style={inlineAddActionButtonStyle}
|
style={newTabActionButtonStyle}
|
||||||
>
|
>
|
||||||
<ThemedChevronDown size={14} uniProps={mutedColorMapping} />
|
<ThemedChevronDown size={14} uniProps={mutedColorMapping} />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
@@ -301,7 +314,8 @@ function WorkspaceInlineAddTabButton({
|
|||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</View>
|
<PinnedTargetsRow launchers={launchers} testIdPrefix="workspace-pinned-target" />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,6 +989,12 @@ export function WorkspaceDesktopTabsRow({
|
|||||||
/>
|
/>
|
||||||
<WorkspaceInlineAddTabButton
|
<WorkspaceInlineAddTabButton
|
||||||
shortcutKeys={newTabKeys}
|
shortcutKeys={newTabKeys}
|
||||||
|
onCreateAgentTab={handleCreateAgentTab}
|
||||||
|
onLayout={handleInlineAddButtonLayout}
|
||||||
|
/>
|
||||||
|
</ScrollView>
|
||||||
|
<View style={styles.tabsActions} onLayout={handleTabsActionsLayout}>
|
||||||
|
<WorkspaceTabRowExtras
|
||||||
onCreateAgentTab={handleCreateAgentTab}
|
onCreateAgentTab={handleCreateAgentTab}
|
||||||
onCreateTerminal={handleCreateTerminal}
|
onCreateTerminal={handleCreateTerminal}
|
||||||
onCreateBrowser={handleCreateBrowser}
|
onCreateBrowser={handleCreateBrowser}
|
||||||
@@ -983,10 +1003,7 @@ export function WorkspaceDesktopTabsRow({
|
|||||||
normalizedServerId={normalizedServerId}
|
normalizedServerId={normalizedServerId}
|
||||||
showCreateBrowserTab={showCreateBrowserTab}
|
showCreateBrowserTab={showCreateBrowserTab}
|
||||||
terminalDisabled={terminalDisabled}
|
terminalDisabled={terminalDisabled}
|
||||||
onLayout={handleInlineAddButtonLayout}
|
|
||||||
/>
|
/>
|
||||||
</ScrollView>
|
|
||||||
<View style={styles.tabsActions} onLayout={handleTabsActionsLayout}>
|
|
||||||
{showPaneSplitActions ? (
|
{showPaneSplitActions ? (
|
||||||
<>
|
<>
|
||||||
<SplitActionButton
|
<SplitActionButton
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
pinButton: {
|
pinButton: {
|
||||||
width: 28,
|
width: 22,
|
||||||
height: 28,
|
height: 22,
|
||||||
borderRadius: theme.borderRadius.md,
|
borderRadius: theme.borderRadius.md,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
|
|||||||
@@ -9,6 +9,18 @@ interface PinnedTargetsState {
|
|||||||
isPinned: (target: PinnedTabTarget) => boolean;
|
isPinned: (target: PinnedTabTarget) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_PINNED_TARGETS: PinnedTabTarget[] = [{ kind: "terminal" }, { kind: "browser" }];
|
||||||
|
|
||||||
|
function applyDefaultPinnedTargets(pinned: PinnedTabTarget[]): PinnedTabTarget[] {
|
||||||
|
const next = [...DEFAULT_PINNED_TARGETS];
|
||||||
|
for (const target of pinned) {
|
||||||
|
if (!isTargetPinned(next, target)) {
|
||||||
|
next.push(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
export const usePinnedTargetsStore = create<PinnedTargetsState>()(
|
export const usePinnedTargetsStore = create<PinnedTargetsState>()(
|
||||||
persist(
|
persist(
|
||||||
(set, get) => ({
|
(set, get) => ({
|
||||||
@@ -18,8 +30,16 @@ export const usePinnedTargetsStore = create<PinnedTargetsState>()(
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: "pinned-tab-targets",
|
name: "pinned-tab-targets",
|
||||||
|
version: 1,
|
||||||
storage: createJSONStorage(() => AsyncStorage),
|
storage: createJSONStorage(() => AsyncStorage),
|
||||||
partialize: (state) => ({ pinned: state.pinned }),
|
partialize: (state) => ({ pinned: state.pinned }),
|
||||||
|
migrate: (persistedState, version) => {
|
||||||
|
if (version === 0) {
|
||||||
|
const pinned = (persistedState as { pinned?: PinnedTabTarget[] } | null)?.pinned ?? [];
|
||||||
|
return { pinned: applyDefaultPinnedTargets(pinned) };
|
||||||
|
}
|
||||||
|
return persistedState as PinnedTargetsState;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user