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 @@ -23,6 +23,7 @@ import {
LuLaptop,
LuList,
LuMonitor,
LuMonitorSmartphone,
LuSearch,
LuSquareKanban,
LuTerminal,
Expand All @@ -33,6 +34,7 @@ import type {
V2WorkspaceProjectOption,
} from "renderer/routes/_authenticated/_dashboard/v2-workspaces/hooks/useAccessibleV2Workspaces";
import {
DEVICE_FILTER_ALL_DEVICES,
DEVICE_FILTER_THIS_DEVICE,
PROJECT_FILTER_SESSIONS,
useV2WorkspacesFilterStore,
Expand Down Expand Up @@ -128,7 +130,9 @@ export function V2WorkspacesHeader({
(host) => host.hostId === deviceFilter,
);
const selectedHostFallback =
!selectedRemoteHostFromOptions && deviceFilter !== DEVICE_FILTER_THIS_DEVICE
!selectedRemoteHostFromOptions &&
deviceFilter !== DEVICE_FILTER_THIS_DEVICE &&
deviceFilter !== DEVICE_FILTER_ALL_DEVICES
? hostsById.get(deviceFilter)
: undefined;
const selectedHostLabel = selectedRemoteHostFromOptions
Expand Down Expand Up @@ -240,6 +244,12 @@ export function V2WorkspacesHeader({
</SelectTrigger>
<SelectContent align="end" className="min-w-[16rem]">
<SelectGroup>
<SelectItem value={DEVICE_FILTER_ALL_DEVICES}>
<DeviceOptionLabel
icon={<LuMonitorSmartphone className="size-3.5" />}
label="All devices"
/>
</SelectItem>
<SelectItem value={DEVICE_FILTER_THIS_DEVICE}>
<DeviceOptionLabel
icon={<LuLaptop className="size-3.5" />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { cn } from "@superset/ui/utils";
import { LuLaptop, LuMonitor } from "react-icons/lu";
import { DEVICE_FILTER_THIS_DEVICE } from "renderer/routes/_authenticated/_dashboard/v2-workspaces/stores/v2WorkspacesFilterStore";
import { LuLaptop, LuMonitor, LuMonitorSmartphone } from "react-icons/lu";
import {
DEVICE_FILTER_ALL_DEVICES,
DEVICE_FILTER_THIS_DEVICE,
} from "renderer/routes/_authenticated/_dashboard/v2-workspaces/stores/v2WorkspacesFilterStore";

interface DeviceFilterTriggerLabelProps {
deviceFilter: string;
Expand All @@ -11,6 +14,14 @@ export function DeviceFilterTriggerLabel({
deviceFilter,
selectedRemoteHost,
}: DeviceFilterTriggerLabelProps) {
if (deviceFilter === DEVICE_FILTER_ALL_DEVICES) {
return (
<span className="flex items-center gap-2">
<LuMonitorSmartphone className="size-3.5" />
<span>All devices</span>
</span>
);
}
if (deviceFilter === DEVICE_FILTER_THIS_DEVICE) {
return (
<span className="flex items-center gap-2">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { cloudTrpc } from "renderer/lib/cloud-trpc";
import { getHostServiceClientByUrl } from "renderer/lib/host-service-client";
import { derivePullRequestQueryTargets } from "renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/derivePullRequestQueryTargets";
import {
DEVICE_FILTER_ALL_DEVICES,
DEVICE_FILTER_THIS_DEVICE,
PROJECT_FILTER_SESSIONS,
type V2WorkspacesAgentStatusFilter,
Expand Down Expand Up @@ -209,19 +210,24 @@ export function useAccessibleV2Workspaces(
: (session?.session?.activeOrganizationId ?? null);
const currentUserId = session?.user?.id ?? null;

// With a device filter (the page), rows come from a single `workspace.list`
// against that host — no fan-out, so ten idle hosts can't slow down or
// silently thin out the list. Without one (palette, dev seeding), rows come
// from the provider's already-running fan-out. Both hooks always run per the
// rules of hooks; the unused one is passed null / left unread and does no
// work of its own.
const selectedHostId =
// With a specific device filter (the page), rows come from a single
// `workspace.list` against that host — no fan-out, so ten idle hosts can't
// slow down or silently thin out the list. "All devices" is the user opting
// into that fan-out: the scoped source runs unscoped (undefined), sharing
// query keys with the provider so nothing fetches twice, and archived
// tombstones still ride along. Without a filter (palette, dev seeding),
// rows come from the provider's already-running fan-out. Both hooks always
// run per the rules of hooks; the unused one is passed null / left unread
// and does no work of its own.
const scopedHostId =
deviceFilter === undefined
? null
: deviceFilter === DEVICE_FILTER_THIS_DEVICE
? machineId
: deviceFilter;
const scopedSource = useHostWorkspacesSource(selectedHostId, {
: deviceFilter === DEVICE_FILTER_ALL_DEVICES
? undefined
: deviceFilter === DEVICE_FILTER_THIS_DEVICE
? machineId
: deviceFilter;
const scopedSource = useHostWorkspacesSource(scopedHostId, {
includeArchived: options.includeArchived ?? false,
});
const fanoutSource = useHostWorkspaces();
Expand Down Expand Up @@ -439,10 +445,11 @@ export function useAccessibleV2Workspaces(
]);

// The authoritative link lives in host.db (`workspace.pullRequestId`), not
// any collection. With host-scoped rows this derives a single target; a
// client-side `repositoryId::branch` map mistracks on fork branch
// collisions. Unscoped callers (palette, dev seeding) don't render PR data,
// so skip the queries entirely rather than fanning them out per host.
// any collection. With host-scoped rows this derives a single target ("All
// devices" derives one per host with visible rows); a client-side
// `repositoryId::branch` map mistracks on fork branch collisions. Unscoped
// callers (palette, dev seeding) don't render PR data, so skip the queries
// entirely rather than fanning them out per host.
const pullRequestQueryTargets = useMemo(
() =>
deviceFilter === undefined
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export {
DEVICE_FILTER_ALL_DEVICES,
DEVICE_FILTER_THIS_DEVICE,
PROJECT_FILTER_SESSIONS,
useV2WorkspacesFilterStore,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { create } from "zustand";

export const DEVICE_FILTER_THIS_DEVICE = "this-device";
export const DEVICE_FILTER_ALL_DEVICES = "all-devices";
/** Sentinel for project-less "session" workspaces in the project filter. */
export const PROJECT_FILTER_SESSIONS = "__sessions__";

Expand Down
Loading