UNPKG

@applicaster/zapp-react-native-ui-components

Version:

Applicaster Zapp React Native ui components for the Quick Brick App

205 lines (161 loc) 6 kB
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils"; import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/StorageSingleSelectProvider"; import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager"; import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/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"; import { ScreenMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenStateMultiSelectProvider"; import { ScreenSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenSingleValueProvider"; import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks"; import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore"; const parseContextKey = ( key: string, context: string = "ctx" ): string | null => { if (!key?.startsWith(`@{${context}/`)) return null; return key.substring(`@{${context}/`.length, key.length - 1); }; const getDataSourceProvider = ( behavior: Behavior, screenRoute: string, screenStateStore: ReturnType<typeof useScreenStateStore> ): BehaviorSubject<string[] | string> | null => { if (!behavior) return null; const selection = String(behavior.current_selection); const screenKey = parseContextKey(selection, "screen"); if (screenKey) { if (behavior.select_mode === "multi") { return ScreenMultiSelectProvider.getProvider( screenKey, screenRoute, screenStateStore ).getObservable(); } if (behavior.select_mode === "single") { return ScreenSingleValueProvider.getProvider( screenKey, screenRoute, screenStateStore ).getObservable(); } } const contextKey = parseContextKey(selection); if (contextKey) { // TODO: Add storage scope to behavior 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 screenRoute = useRoute()?.pathname || ""; const screenStateStore = useScreenStateStore(); const player = usePlayer(); const triggerUpdate = () => setLastUpdate(Date.now()); useEffect(() => { if (!behavior) return; const dataSource = getDataSourceProvider( behavior, screenRoute, screenStateStore ); 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, screenRoute, screenStateStore, behavior, }: { item: ZappEntry; screenRoute: string; screenStateStore: ReturnType<typeof useScreenStateStore>; 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 screenKey = parseContextKey(selection, "screen"); if (screenKey) { if (behavior.select_mode === "single") { const selectedItem = ScreenSingleValueProvider.getProvider( screenKey, screenRoute, screenStateStore ).getValue(); return selectedItem === String(id); } if (behavior.select_mode === "multi") { const selectedItems = ScreenMultiSelectProvider.getProvider( screenKey, screenRoute, screenStateStore ).getSelectedItems(); return selectedItems?.includes(String(id)); } } const contextKey = parseContextKey(selection, "ctx"); 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; };