Skip to content
Draft
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
51 changes: 29 additions & 22 deletions src/mobile-ui-react/MobileUi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,36 @@
import * as React from "react";
import { BackendError, Localization } from "@itwin/core-common";
import { getCssVariable, getCssVariableAsNumber } from "@itwin/core-react";
import { ColorTheme, SessionStateActionId, SyncUiEventDispatcher, SyncUiEventId, SYSTEM_PREFERRED_COLOR_THEME, UiFramework, UiSyncEventArgs } from "@itwin/appui-react";
import { ColorTheme, SessionStateActionId, SyncUiEventDispatcher, SyncUiEventId, SYSTEM_PREFERRED_COLOR_THEME, UiFramework } from "@itwin/appui-react";
import { EmphasizeElements, IModelApp, IModelConnection, ScreenViewport, SelectionSet, Tool, Viewport } from "@itwin/core-frontend";
import { BeEvent, BeUiEvent, BriefcaseStatus, Id64Set, Listener } from "@itwin/core-bentley";
import { getAllViewports, getEmphasizeElements, Messenger, MobileCore, UIError } from "@itwin/mobile-sdk-core";

import "./MobileUi.scss";

// @todo: Import this from @itwin/core-bentley in iTwin 4.8.
/**
* Convenience type to extract the listener type from a specific BeEvent. This will go away when the
* same type is exported from @itwin/core-bentley in iTwin 4.8.
* @internal
*/
export type ListenerType<TEvent extends BeEvent<Listener>> = TEvent extends BeEvent<infer TListener> ? TListener : never;

/**
* Convenience type to extract the parameters for a specific BeEvent.
*
* Example usage:
*
* const onSyncUi = (...[args]: ListenerArgs<typeof SyncUiEventDispatcher.onSyncUiEvent>) => {
* if (args.eventIds.has(someEvent)) {
* // process event
* }
* }
*
* @internal
*/
export type ListenerArgs<TEvent extends BeEvent<Listener>> = Parameters<ListenerType<TEvent>>;

/** Type used for MobileUi.onClose BeEvent. */
export declare type CloseListener = () => void;

Expand Down Expand Up @@ -328,32 +351,16 @@ export const useScrolling = (scrollable: HTMLElement | undefined | null) => {
return scrolling;
};

function stringSetHas(set: Set<string>, values: ReadonlyArray<string>) {
for (const value of values) {
if (set.has(value)) {
return true;
}
}
return false;
}

/**
* A custom React hook function for UiSyncEvents.
* @param handler - The callback function.
* @param eventIds - The optional event ids to handle.
*
* __NOTE__: This function should probably be deprecated, but right now there is no obvious way to
* replace it. Consequently, the following is for information only:
* NOT@deprecated in 0.22.5. UiSyncEventArgs were deprecated in appui-react 4.13.x.
* @param eventIds - The optional event ids to handle. Note: if these are missing, ALL SyncUi events
* will be handled.
*/
// @todo FIX Remove deprecated usage once appui-react provides a reasonable solution.
// eslint-disable-next-line deprecation/deprecation
export function useSyncUiEvent(handler: (args: UiSyncEventArgs) => void, ...eventIds: ReadonlyArray<string>) {
export function useSyncUiEvent(handler: ListenerType<typeof SyncUiEventDispatcher.onSyncUiEvent>, ...eventIds: string[]) {
React.useEffect(() => {
// @todo FIX Remove deprecated usage once appui-react provides a reasonable solution.
// eslint-disable-next-line deprecation/deprecation
return SyncUiEventDispatcher.onSyncUiEvent.addListener((args: UiSyncEventArgs) => {
if (eventIds.length === 0 || stringSetHas(args.eventIds, eventIds)) {
return SyncUiEventDispatcher.onSyncUiEvent.addListener((args) => {
if (eventIds.length === 0 || SyncUiEventDispatcher.hasEventOfInterest(args.eventIds, eventIds)) {
handler(args);
}
});
Expand Down
13 changes: 7 additions & 6 deletions src/mobile-ui-react/PanViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import { Point3d, SmoothTransformBetweenFrusta, Transform } from "@itwin/core-geometry";
import { Easing, Frustum, Tweens } from "@itwin/core-common";
import { SessionStateActionId, SyncUiEventDispatcher, UiFramework, UiSyncEventArgs } from "@itwin/appui-react";
import { SessionStateActionId, SyncUiEventDispatcher, UiFramework } from "@itwin/appui-react";
import { Animator, IModelApp, ScreenViewport, ViewAnimationOptions } from "@itwin/core-frontend";
import { ListenerArgs } from "./MobileUi";

/**
* Custom animator to animate the 8 corners of a view frustum change.
Expand Down Expand Up @@ -54,6 +55,7 @@ class InterpolateFrustumAnimator implements Animator {
export class PanTracker {
private static _panTrackers: { [key: string]: PanTracker } = {};
private _vpParentDivId: string;
private _removeSyncUiListener: () => void | undefined;
public x = 0;
public y = 0;
public nextX = 0;
Expand All @@ -63,16 +65,14 @@ export class PanTracker {
this._vpParentDivId = vpParentDivId;
IModelApp.viewManager.onViewOpen.addListener(this._onViewOpen);
IModelApp.viewManager.onViewClose.addListener(this._onViewClose);
SyncUiEventDispatcher.onSyncUiEvent.addListener(this._onSyncUi);
this._removeSyncUiListener = SyncUiEventDispatcher.onSyncUiEvent.addListener(this._onSyncUi);
}

public get vpParentDivId() {
return this._vpParentDivId;
}

// @todo FIX Remove deprecated usage once appui-react provides a reasonable solution.
// eslint-disable-next-line deprecation/deprecation
private _onSyncUi = (args: UiSyncEventArgs) => {
private _onSyncUi = (...[args]: ListenerArgs<typeof SyncUiEventDispatcher.onSyncUiEvent>) => {
if (args.eventIds.has(SessionStateActionId.SetIModelConnection) && this._vpParentDivId) {
let panTracker = PanTracker.getWithKey(this._vpParentDivId);
const nextX = panTracker.nextX;
Expand Down Expand Up @@ -119,7 +119,8 @@ export class PanTracker {
private detach() {
IModelApp.viewManager.onViewOpen.removeListener(this._onViewOpen);
IModelApp.viewManager.onViewClose.removeListener(this._onViewClose);
SyncUiEventDispatcher.onSyncUiEvent.removeListener(this._onSyncUi);
this._removeSyncUiListener?.();
this._removeSyncUiListener = undefined;
delete PanTracker._panTrackers[this._vpParentDivId];
}

Expand Down