UNPKG

@applicaster/quick-brick-core

Version:

Core package for Applicaster's Quick Brick App

189 lines (157 loc) 4.96 kB
import { Linking } from "react-native"; import * as R from "ramda"; import { getRiverFromRoute, getTargetRoute, } from "@applicaster/zapp-react-native-utils/navigationUtils"; import { findPluginByType } from "@applicaster/zapp-react-native-utils/pluginUtils"; import { coreAppLogger } from "../logger"; import { isString } from "@applicaster/zapp-react-native-utils/stringUtils"; import { SCREEN_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/itemTypes"; import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers"; const EXTERNAL_URL_TYPE = "external_url"; const EXTERNAL_URL_FLAG = "open_external_url"; const WEBVIEW_SCREEN_IDENTIFIER = "webview_screen_qb"; const logger = coreAppLogger.addSubsystem("Navigator"); export function targetShouldOpenExternally( target: ZappEntry, targetScreen: ZappRiver | null, rivers: Record<string, ZappRiver> ) { const href = target?.link?.href; const hasWebviewScreen = R.compose( R.not, isNilOrEmpty, R.find(R.propEq("type", WEBVIEW_SCREEN_IDENTIFIER)), R.values )(rivers); const isExternalLink = isString(href) && (target?.type?.value === EXTERNAL_URL_TYPE || href.includes(`${EXTERNAL_URL_TYPE}=true`) || target?.extensions?.[EXTERNAL_URL_FLAG] === true || target?.extensions?.[EXTERNAL_URL_FLAG] === "true" || href.startsWith("mailto:")); return ( isExternalLink || (targetScreen?.screenType === SCREEN_TYPES.LINK && !hasWebviewScreen) ); } export function openExternalUrl(url: string) { Linking.openURL(url); } export function legacyScreenData( screenState: NavigationScreenData, plugins?: QuickBrickPlugin[] ): QuickBrickNavigationData { let targetScreen = screenState?.screen; const entry = screenState?.entry; // @ts-ignore - this happens only on launch if (!targetScreen) return {}; /** * HACK: We mutate targetScreen by merging screenOrientation for the player. * screen_orientation value is used inside the Transitioner to determine if app should animate the transition. * (Transitions with the orientation change shouldn't be animated). * * I tried adding screen_orientation directly to the default-player manifest but unfortunately, * Zapp is not passing new configuration values to the layout.json manifest. * * TODO: add general.screen_orientation to player configuration and find a way to merge defaults into data before we * inject data to redux. */ if (!targetScreen?.general?.screen_orientation) { const isPlayer = targetScreen.plugin_type === "player" || targetScreen.screenType === "playable"; if (isPlayer) { const player = findPluginByType("player", plugins, { returnFullObject: true, }); const orientation = player?.configuration?.screen_orientation || "landscapeSensor"; targetScreen = R.mergeDeepRight(targetScreen, { general: { screen_orientation: orientation }, }); } } if (entry) { return { ...entry, targetScreen, }; } return targetScreen; } function itemIsEntry( item: ZappEntry | ZappRiver, layoutVersion: ZappLayoutVersions ): Nullable<ZappEntry> { if ( typeof (item as ZappEntry)?.type?.value !== "undefined" || layoutVersion === "v1" ) { return item as ZappEntry; } return null; } export function getNavigationTarget( item: ZappEntry | ZappRiver, pathname: string, contentTypes: ZappContentTypes, layoutVersion: ZappLayoutVersions, rivers: Record<string, ZappRiver> ): { entry?: ZappEntry; screen?: ZappRiver; targetRoute?: string; externalUrl?: string; } { if (!item) { return {}; } const targetRoute = getTargetRoute(item, pathname, { layoutVersion, contentTypes, rivers, }); const targetScreen = getRiverFromRoute({ route: targetRoute, rivers }); if (targetShouldOpenExternally(item as ZappEntry, targetScreen, rivers)) { return { externalUrl: (item as ZappEntry)?.link?.href }; } if ( "screen_type" in item && !item.screen_type && !contentTypes?.[(item as ZappEntry)?.type?.value] ) { logger.warning({ message: `Couldn't find a navigation target\nCheck your ${ layoutVersion === "v1" ? "connected screen or feed" : "types mapping or feed" }`, }); return {}; } const data: { entry?: ZappEntry; screen: ZappRiver; targetRoute: string } = { screen: targetScreen, targetRoute, }; const targetEntry = itemIsEntry(item, layoutVersion); if (targetEntry) { data.entry = targetEntry; } return data; } export function getTargetScreen({ entry, rivers, contentTypes, }: { entry: ZappEntry; rivers: Record<string, ZappRiver>; contentTypes: ZappContentTypes; }): ZappRiver | undefined { const type = entry?.type?.value; const contentType = contentTypes?.[type]; return rivers[contentType?.screen_id]; }