Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop using deprecated selection APIs #346

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

grigasp
Copy link
Member

@grigasp grigasp commented Feb 21, 2025

Closes #344. Also reduces usage of deprecated AppUI APIs.

For selection scopes we now have 3 options for consumers:

  • Option 1: Don't supply selectionScopes prop.

    We default to using Presentation.selection.scopes for getting available and active scopes.

    If AppUI's selection scopes' picker is used, it will be used to set the active scope both in the app's state, and on Presentation.selection.scopes for backwards compatibility.

    This option is basically just for backwards compatibility.

  • Option 2: Supply selectionScopes prop with only available and active properties.

    The active prop is used to determine the initially active scope by looking up the available map.

    If AppUI's selection scopes' picker is used, it's populated with scopes from available map and the initially selected value is based on the active prop. When another value is selected, the default scope change handler changes the active scope in the app's state and on Presentation.selection.scopes for backwards compatibility.

    This option is for consumers who don't care about the active scope, as long as it's applied when selecting elements in graphics view and can be changed through selection scopes picker in the toolbar.

  • Option 3: Supply selectionScopes prop with all properties, including onChange.

    In this case, it's consumer's responsibility to update the active scope by setting a new value.

    This option is for consumers who want to have full control over the active scope. The source of truth for it in on consumer's side, so consumer can use it in multiple components and change it whenever they want, using whatever component they want.

@grigasp grigasp requested a review from saskliutas February 24, 2025 07:07
@aruniverse
Copy link
Member

Do we expect all apps to make similar to changes to this? Wonder if we can extract some of this out to the unified-selction-react pkg, but I guess you are trying to avoid presentation-frontend dep.

cc @jjbeckman13 for web and @kckst8 @johnnyd710 for desktop apps

Does option 3 here provide a path forward for the issue described in iTwin/presentation#767 ?

@grigasp
Copy link
Member Author

grigasp commented Feb 26, 2025

Do we expect all apps to make similar to changes to this? Wonder if we can extract some of this out to the unified-selction-react pkg, but I guess you are trying to avoid presentation-frontend dep.

Most of the complexity is due to me trying to keep backwards compatibility - in multiple places you can see that I handle selection storage if it's provided and then fall back to Presentation.selection if not. That also involves mapping of new vs legacy types.

For apps it's much simpler:

  1. Define a list of supported scopes like here:
    const availableSelectionScopes = {
    element: {
    label: "Element",
    def: { id: "element" as const },
    },
    assembly: {
    label: "Assembly",
    def: { id: "element" as const, ancestorLevel: 1 },
    },
    "top-assembly": {
    label: "Top assembly",
    def: { id: "element" as const, ancestorLevel: -1 },
    }
    };
  2. Supply the necessary props to selection scopes status bar item:
    function SelectionScopeField() {
    const ctx = React.useContext(selectionScopesContext);
    const selectionScopes = React.useMemo(
    () =>
    Object.entries(ctx.availableScopes).map(([id, { label }]) => ({
    id,
    label,
    })),
    [ctx.availableScopes]
    );
    return (
    <AppUiSelectionScopeField
    selectionScopes={selectionScopes}
    activeScope={ctx.activeScope.id}
    onChange={ctx.onScopeChange}
    />
    );
    }
    const selectionScopesContext = React.createContext<
    ReturnType<typeof useUnifiedSelectionScopes>
    >({
    activeScope: { id: "element", def: "element" },
    availableScopes: {
    element: {
    label: "Element",
    def: "element",
    },
    },
    onScopeChange: () => {},
    });
    /** @internal */
    export function SelectionScopesContextProvider({
    selectionScopes,
    children,
    }: React.PropsWithChildren<{
    selectionScopes: ReturnType<typeof useUnifiedSelectionScopes>;
    }>) {
    return (
    <selectionScopesContext.Provider value={selectionScopes}>
    {children}
    </selectionScopesContext.Provider>
    );
    }
  3. Supply the activeScopeProvider prop to enableUnifiedSelectionSyncWithIModel:
    activeScopeProvider: () => activeScope.current,

Does option 3 here provide a path forward for the issue described in iTwin/presentation#767 ?

Not really. As stated in this comment: "User workflows need to be investigated, considering both - read-only and the new read-write - scenarios".

@grigasp
Copy link
Member Author

grigasp commented Mar 12, 2025

@aruniverse, FYI I made some improvements to the migration guide in unified selection package, targeting specifically selection scopes: https://github.com/iTwin/presentation/blob/840e23a34cf9964e93929d869736ab3d53bcf5f7/packages/unified-selection/learning/MigrationGuide.md#appui-integration. This PR is used as a base for example code there, but without all the backwards-compatibility and configuration stuff that we have here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Stop using selection-related APIs from @itwin/presentation-frontend
4 participants