@applicaster/zapp-react-native-ui-components
Version:
Applicaster Zapp React Native ui components for the Quick Brick App
137 lines (102 loc) • 4.04 kB
text/typescript
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageSingleSelectProvider";
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
import React, { useEffect } from "react";
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
import { BehaviorSubject } from "rxjs";
import { masterCellLogger } from "../logger";
import get from "lodash/get";
const parseContextKey = (key: string): string | null => {
if (!key?.startsWith("@{ctx/")) return null;
return key.substring("@{ctx/".length, key.length - 1);
};
const getDataSourceProvider = (
behavior: Behavior
): BehaviorSubject<string[] | string> | null => {
if (!behavior) return null;
const selection = String(behavior.current_selection);
const contextKey = parseContextKey(selection);
if (contextKey) {
if (behavior.select_mode === "multi") {
return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
}
if (behavior.select_mode === "single") {
return StorageSingleValueProvider.getProvider(contextKey).getObservable();
}
}
if (behavior.selection_source === "@{push/topics}") {
return PushTopicManager.getInstance().getEntryObservable();
}
return null;
};
export const useBehaviorUpdate = (behavior: Behavior) => {
const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
const player = usePlayer();
const triggerUpdate = () => setLastUpdate(Date.now());
useEffect(() => {
if (!behavior) return;
const dataSource = getDataSourceProvider(behavior);
if (dataSource) {
const subscription = dataSource.subscribe(triggerUpdate);
return () => subscription.unsubscribe();
}
}, [behavior]);
useEffect(() => {
if (!behavior || !player || behavior.selection_source !== "now_playing") {
return;
}
const subscription = player.getEntryObservable().subscribe(triggerUpdate);
return () => subscription.unsubscribe();
}, [behavior, player]);
return lastUpdate;
};
// We cant use async in this function (its inside render),
// so we rely on useBehaviorUpdate to update current value and trigger re-render
export const isCellSelected = (
item: ZappEntry,
behavior?: Behavior
): boolean => {
if (!behavior) return false;
const id = behavior.selector ? get(item, behavior.selector) : item.id;
if (behavior.selection_source === "now_playing") {
const player = playerManager.getActivePlayer();
return player?.entry?.id === id;
}
if (behavior.selection_source === "@{push/topics}") {
if (behavior.select_mode === "single") {
masterCellLogger.warning(
"Unexpected single selection mode for push topics"
);
}
const tags = PushTopicManager.getInstance().getRegisteredTags();
return tags.includes(String(id));
}
const selection = String(behavior.current_selection);
const contextKey = parseContextKey(selection);
if (contextKey) {
if (behavior.select_mode === "single") {
const selectedItem =
StorageSingleValueProvider.getProvider(contextKey)?.getValue();
return selectedItem === String(id);
}
if (behavior.select_mode === "multi") {
const selectedItems =
StorageMultiSelectProvider.getProvider(contextKey)?.getSelectedItems();
return selectedItems?.includes(String(id));
}
}
if (behavior.select_mode === "single") {
return behavior.current_selection === id;
}
if (
behavior.select_mode === "multi" &&
Array.isArray(behavior.current_selection)
) {
const currentSelection: string[] = behavior.current_selection.map(
(item): string => String(item)
);
return currentSelection.includes(String(id));
}
return false;
};