Skip to content

Commit

Permalink
use only local state atom for modal spaces
Browse files Browse the repository at this point in the history
  • Loading branch information
imanjra committed Sep 11, 2024
1 parent df69d15 commit aa52d50
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 26 deletions.
5 changes: 1 addition & 4 deletions app/packages/operators/src/built-in-operators.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
Layout,
SpaceNode,
usePanelState,
usePanelTitle,
usePanels,
useSetPanelStateById,
Expand All @@ -12,6 +11,7 @@ import * as fos from "@fiftyone/state";
import * as types from "./types";

import { useTrackEvent } from "@fiftyone/analytics";
import { setPathUserUnchanged } from "@fiftyone/core/src/plugins/SchemaIO/hooks";
import { LOAD_WORKSPACE_OPERATOR } from "@fiftyone/spaces/src/components/Workspaces/constants";
import { toSlug } from "@fiftyone/utilities";
import copyToClipboard from "copy-to-clipboard";
Expand All @@ -31,7 +31,6 @@ import {
} from "./operators";
import { useShowOperatorIO } from "./state";
import usePanelEvent from "./usePanelEvent";
import { setPathUserUnchanged } from "@fiftyone/core/src/plugins/SchemaIO/hooks";

//
// BUILT-IN OPERATORS
Expand Down Expand Up @@ -1029,8 +1028,6 @@ class PromptUserForOperation extends Operator {
return new types.Property(inputs);
}
useHooks(ctx: ExecutionContext): {} {
const panelId = ctx.getCurrentPanelId();
const [panelState] = usePanelState(panelId);
const triggerEvent = usePanelEvent();
return { triggerEvent };
}
Expand Down
12 changes: 10 additions & 2 deletions app/packages/spaces/src/components/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import { CenteredStack, scrollable } from "@fiftyone/components";
import * as fos from "@fiftyone/state";
import React from "react";
import React, { useEffect } from "react";
import { PANEL_LOADING_TIMEOUT } from "../constants";
import { PanelContext } from "../contexts";
import { useReactivePanel } from "../hooks";
import { PanelProps } from "../types";
import PanelNotFound from "./PanelNotFound";
import PanelSkeleton from "./PanelSkeleton";
import { StyledPanel } from "./StyledElements";
import { useSetRecoilState } from "recoil";
import { panelIdToScopeAtom } from "../state";

function Panel(props: PanelProps) {
const { node, isModalPanel } = props;
const panelName = node.type as string;
const panel = useReactivePanel(panelName);
const dimensions = fos.useDimensions();
const pending = fos.useTimeout(PANEL_LOADING_TIMEOUT);
const setPanelIdToScope = useSetRecoilState(panelIdToScopeAtom);
const scope = isModalPanel ? "modal" : "grid";

useEffect(() => {
setPanelIdToScope((ids) => ({ ...ids, [node.id]: scope }));
}, [scope, setPanelIdToScope, node.id]);

const panelContentTestId = `panel-content-${panelName}`;
if (!panel) {
Expand All @@ -41,7 +49,7 @@ function Panel(props: PanelProps) {
className={scrollable}
ref={dimensions.ref}
>
<PanelContext.Provider value={{ node }}>
<PanelContext.Provider value={{ node, scope }}>
<Component panelNode={node} dimensions={dimensions} />
</PanelContext.Provider>
</StyledPanel>
Expand Down
4 changes: 3 additions & 1 deletion app/packages/spaces/src/contexts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { createContext } from "react";
import SpaceNode from "./SpaceNode";

export const PanelContext = createContext<{ node?: SpaceNode }>({});
export const PanelContext = createContext<PanelContextType>({});

type PanelContextType = { node?: SpaceNode; scope?: string };
50 changes: 37 additions & 13 deletions app/packages/spaces/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import SpaceTree from "./SpaceTree";
import { PanelContext } from "./contexts";
import {
panelIdToScopeAtom,
panelStatePartialSelector,
panelStateSelector,
panelTitlesState,
Expand Down Expand Up @@ -245,27 +246,35 @@ export function usePanelContext() {
export function usePanelState<T>(
defaultState?: T,
id?: string,
local?: boolean
local?: boolean,
scope?: string
) {
const panelScope = useScope(scope);
const panelContext = usePanelContext();
const panelId = id || (panelContext?.node?.id as string);
const [state, setState] = useRecoilState<T>(
panelStateSelector({ panelId, local })
panelStateSelector({ panelId, local, scope: panelScope })
);
const computedState = state || defaultState;

return [computedState, setState];
}

export function useSetPanelStateById<T>(local?: boolean) {
export function useSetPanelStateById<T>(local?: boolean, scope?: string) {
const panelScope = useScope(scope);
return useRecoilCallback(
({ set, snapshot }) =>
async (panelId: string, fn: (state: any) => any) => {
const panelIdToScope = await snapshot.getPromise(panelIdToScopeAtom);
const computedScope = panelScope || panelIdToScope?.[panelId];
const panelState = await snapshot.getPromise(
panelStateSelector({ panelId, local })
panelStateSelector({ panelId, local, scope: computedScope })
);
const updatedValue = fn(panelState);
set(panelStateSelector({ panelId, local }), updatedValue);
set(
panelStateSelector({ panelId, local, scope: computedScope }),
updatedValue
);
},
[]
);
Expand Down Expand Up @@ -293,15 +302,17 @@ export function useSetCustomPanelState<T>(local?: boolean) {
*/
export function usePanelStateCallback<T>(
callback: (panelState: T) => void,
local?: boolean
local?: boolean,
scope?: string
) {
const panelScope = useScope(scope);
const panelContext = usePanelContext();
const panelId = panelContext?.node?.id as string;
return useRecoilCallback(
({ snapshot }) =>
async () => {
const panelState = await snapshot.getPromise(
panelStateSelector({ panelId, local })
panelStateSelector({ panelId, local, scope: panelScope })
);
callback(panelState);
},
Expand All @@ -311,13 +322,15 @@ export function usePanelStateCallback<T>(

export function usePanelStateByIdCallback<T>(
callback: (panelId: string, panelState: T, args: any[]) => void,
local?: boolean
local?: boolean,
scope?: string
) {
const panelScope = useScope(scope);
return useRecoilCallback(
({ snapshot }) =>
async (panelId: string, ...args) => {
const panelState = await snapshot.getPromise(
panelStateSelector({ panelId, local })
panelStateSelector({ panelId, local, scope: panelScope })
);
callback(panelId, panelState, args as any[]);
},
Expand All @@ -330,14 +343,17 @@ export function usePanelStateByIdCallback<T>(
* @returns a state resolver function which return promise that resolves to the
* current state of a panel
*/
export function usePanelStateLazy(local?: boolean) {
export function usePanelStateLazy(local?: boolean, scope?: string) {
const panelScope = useScope(scope);
const panelContext = usePanelContext();
const panelId = panelContext?.node?.id as string;

const resolvePanelState = useRecoilCallback(
({ snapshot }) =>
async () =>
snapshot.getPromise(panelStateSelector({ panelId, local }))
snapshot.getPromise(
panelStateSelector({ panelId, local, scope: panelScope })
)
);

return () => resolvePanelState();
Expand All @@ -352,12 +368,14 @@ export function usePanelStateLazy(local?: boolean) {
export function usePanelStatePartial<T>(
key: string,
defaultState: T,
local?: boolean
local?: boolean,
scope?: string
) {
const panelScope = useScope(scope);
const panelContext = usePanelContext();
const panelId = panelContext?.node?.id as string;
const [state, setState] = useRecoilState<T>(
panelStatePartialSelector({ panelId, key, local })
panelStatePartialSelector({ panelId, key, local, scope: panelScope })
);
const computedState = useComputedState(state, defaultState);
return [computedState, setState];
Expand Down Expand Up @@ -436,3 +454,9 @@ export function usePanelCloseEffect(panelId?: string) {
}
};
}

function useScope(scope?: string) {
const panelContext = usePanelContext();
if (typeof scope === "string") return scope;
return panelContext?.scope;
}
18 changes: 12 additions & 6 deletions app/packages/spaces/src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ export const panelStateSelector = selectorFamily({
get:
(params: PanelStateParameter) =>
({ get }) => {
const { panelId, local } = params;
const stateAtom = getStateAtom(local);
const { panelId, local, scope } = params;
const stateAtom = getStateAtom(local, scope);
return get(stateAtom).get(panelId);
},
set:
(params: PanelStateParameter) =>
({ get, set }, newValue) => {
const { panelId, local } = params;
const stateAtom = getStateAtom(local);
const { panelId, local, scope } = params;
const stateAtom = getStateAtom(local, scope);
const newState = new Map(get(stateAtom));
newState.set(panelId, newValue);
set(stateAtom, newState);
Expand Down Expand Up @@ -125,6 +125,12 @@ export const savedWorkspacesAtom = atom({
},
});

function getStateAtom(local?: boolean) {
return local ? panelsLocalStateAtom : panelsStateAtom;
export const panelIdToScopeAtom = atom({
key: "panelIdToScopeAtom",
default: {},
});

function getStateAtom(local?: boolean, scope?: string) {
const nonGridScope = scope !== "grid";
return local || nonGridScope ? panelsLocalStateAtom : panelsStateAtom;
}
1 change: 1 addition & 0 deletions app/packages/spaces/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export type SpaceProps = {
export type PanelStateParameter = {
panelId: string;
local?: boolean;
scope?: string;
};

export type PanelStatePartialParameter = PanelStateParameter & {
Expand Down

0 comments on commit aa52d50

Please sign in to comment.