@applicaster/zapp-react-native-utils
Version:
Applicaster Zapp React Native utilities package
80 lines (67 loc) • 2.25 kB
text/typescript
import { ReplaySubject, Subject } from "rxjs";
import { filter, first, switchMap } from "rxjs/operators";
import { BUTTON_PREFIX } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const";
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios";
type FocusableID = string;
type RegistrationEvent = {
id: FocusableID;
registered: boolean;
};
const isFocusableButton = (id: Option<FocusableID>): boolean =>
id && id.includes?.(BUTTON_PREFIX);
const registeredSubject$ = new ReplaySubject<RegistrationEvent>(1);
export const focusableButtonsRegistration$ = (focusableGroupId: string) =>
registeredSubject$.pipe(
filter(
(value) =>
value.registered && focusManager.isChildOf(value.id, focusableGroupId)
)
);
const focusableViewRegistrationSubject$ = new Subject<{
id: FocusableID;
parentId: FocusableID;
}>();
let focusableGroupRegistrationSubject$ = new ReplaySubject<{
id: FocusableID;
}>();
export const resetFocusableGroupRegistration = () => {
// complete the old subject so subscribers are notified and resources are freed
focusableGroupRegistrationSubject$.complete();
focusableGroupRegistrationSubject$ = new ReplaySubject<{
id: FocusableID;
}>();
};
export const firstFocusableViewRegistration$ =
focusableViewRegistrationSubject$.pipe(
first(), // we care about only first FocusableView registration
switchMap(({ parentId }) =>
// start waiting registration of its parent
focusableGroupRegistrationSubject$.pipe(
filter(({ id }) => id === parentId)
)
),
first()
);
export const emitRegistered = ({
id,
parentId,
isGroup,
}: {
id: Option<FocusableID>;
parentId: Option<FocusableID>;
isGroup: boolean;
}): void => {
if (isFocusableButton(id)) {
registeredSubject$.next({ id, registered: true });
}
if (!isGroup) {
focusableViewRegistrationSubject$.next({ id, parentId });
} else {
focusableGroupRegistrationSubject$.next({ id });
}
};
export const emitUnregistered = (id: Option<FocusableID>): void => {
if (isFocusableButton(id)) {
registeredSubject$.next({ id, registered: false });
}
};