UNPKG

@applicaster/quick-brick-core

Version:

Core package for Applicaster's Quick Brick App

241 lines (198 loc) • 7.38 kB
/// <reference types="@types/tizen-tv-webapis" /> import * as R from "ramda"; import { NetInfoState } from "@react-native-community/netinfo"; import { NETWORK_HOOKS_KEYS } from "./const"; import { isVizioPlatform, platformSelect, } from "@applicaster/zapp-react-native-utils/reactUtils"; import { Platform } from "react-native"; type ConnectionStatus = boolean; type NetInfoNotReady = null; // Cmn eslint... It's not a hook... // eslint-disable-next-line react-hooks/rules-of-hooks export const pluckPath = R.useWith(R.map, [R.path, R.identity]); export const callAllWith = (func: ((...any) => void)[], arg) => R.forEach((x) => R.call(x, arg), func); export const getNetworkHooks = (plugins): NetworkHooks => { const filterModulesWithNetworkHooks = R.filter( R.where({ module: R.prop("networkHooks") }) ); const networkHooks = R.compose( // @ts-ignore pluckPath(["module", "networkHooks"]), filterModulesWithNetworkHooks )(plugins); return R.compose( R.reject(R.isEmpty), R.reduce( (acc, key) => R.mergeLeft( acc, // @ts-ignore R.compose( // @ts-ignore R.objOf(key), R.without([undefined]), // @ts-ignore R.pluck(key) )(networkHooks) ), {} ) )(NETWORK_HOOKS_KEYS); }; export function isConnectionInfoReady( connectionInfo: NetInfoState & { deviceStatus?: NetStatus } ) { const { details, isConnected, isInternetReachable, deviceStatus } = connectionInfo; const hasNetInfo = !R.isNil(isConnected) && !R.isNil(isInternetReachable); const hasDeviceInfo = !R.isNil(deviceStatus?.online); // Details returns null on web when offline, it is incorrect to label it as non-ready return platformSelect({ native: !!details && !R.isNil(isConnected) && !R.isNil(isInternetReachable), web: hasDeviceInfo || hasNetInfo, }); } export const isOnline = ( connectionInfo: NetInfoState & { deviceStatus?: NetStatus } ): ConnectionStatus | NetInfoNotReady => { if (!isConnectionInfoReady(connectionInfo)) { return true; } const netInfoIsOnline = connectionInfo.isConnected === true && connectionInfo.isInternetReachable === true; const deviceIsOnline = connectionInfo?.deviceStatus?.online; return deviceIsOnline || netInfoIsOnline; }; // REGISTERED DEVICE LISTENERS let registeredListener = 0; /** * This method detects whether we have the necesarry APIs to check network status * We have created a few ways to detect whether the target device is a Samsung Tizen * isSamsungPlatform checks if there is a global tizen object, or checks the UserAgent * The only thing missing is whether we have the necesarry WebAPIs. This method does that. */ export const hasTizenAPIs = () => { const hasWebAPI = typeof webapis !== "undefined"; const isSamsungOS = Platform.OS === ("samsung_tv" as string); if (isSamsungOS && hasWebAPI) { return true; } else { return false; } }; /** * This method is designed to be a handler for Tizen's networkStateChangeListener * The first argument is a callback provided by whatever is requesting the network state info * The second argument is invoked by the networkStateChangeListener and it is supposed to return networkState * ChangeCb - https://developer.samsung.com/smarttv/develop/api-references/samsung-product-api-references/network-api.html#1.3-NetworkStateChangedCallback * NetworkState - https://developer.samsung.com/smarttv/develop/api-references/samsung-product-api-references/network-api.html#1.6-NetworkState */ const samsungNetworkChangeHandler = (callback: NetCb) => (networkState) => { let online: NetStatus["online"] = null; const details: NetStatus["details"] = { internetConnected: null, lanCableAttached: null, gatewayConnected: null, wifiModuleStateAttached: null, networkState, }; if (webapis.network.NetworkState) { const { LAN_CABLE_ATTACHED, LAN_CABLE_DETACHED, LAN_CABLE_STATE_UNKNOWN, GATEWAY_CONNECTED, GATEWAY_DISCONNECTED, WIFI_MODULE_STATE_ATTACHED, WIFI_MODULE_STATE_DETACHED, WIFI_MODULE_STATE_UNKNOWN, } = webapis.network.NetworkState; // @ts-ignore const { INTERNET_CONNECTED, INTERNET_DISCONNECTED } = webapis.network.NetworkState; // Our type declaration says internet enums don't exist // Link says otherwise ^ switch (networkState) { case GATEWAY_DISCONNECTED: details.gatewayConnected = false; online = false; break; case GATEWAY_CONNECTED: details.gatewayConnected = true; online = true; break; case INTERNET_CONNECTED: details.internetConnected = true; online = true; break; case INTERNET_DISCONNECTED: details.internetConnected = false; online = false; break; case LAN_CABLE_ATTACHED: details.lanCableAttached = true; break; case LAN_CABLE_DETACHED: details.lanCableAttached = false; break; case LAN_CABLE_STATE_UNKNOWN: details.lanCableAttached = null; break; case WIFI_MODULE_STATE_ATTACHED: details.wifiModuleStateAttached = true; break; case WIFI_MODULE_STATE_DETACHED: details.wifiModuleStateAttached = false; break; case WIFI_MODULE_STATE_UNKNOWN: details.wifiModuleStateAttached = null; break; default: break; } } return callback({ online, details }); }; /** * This method helps you subscribe to networkchanges for each device. It is designed to replace NetInfo. * The NetInfo library does not seem to work in all test scenarios on the web tvs so this method uses the native * APIs for each device. At the moment we only support Tizen which is using the native addNetworkStateChangeListener * https://developer.samsung.com/smarttv/develop/api-references/samsung-product-api-references/network-api.html#NetworkManager-addNetworkStateChangeListener * The native Samsung listener returns an ID which can be used to unregister the listener. * TODO: come up with way to store IDs for unregister, at the moment using local var in memory */ export const subscribeToDeviceNetworkChanges = (callback: NetCb) => { if (hasTizenAPIs()) { registeredListener = webapis.network.addNetworkStateChangeListener( samsungNetworkChangeHandler(callback) ); return; } if (isVizioPlatform()) { window.addEventListener("online", function () { callback({ online: true }); }); window.addEventListener("offline", function () { callback({ online: false }); }); } }; /** * Method used to unsubscribe to any device network changes or updates * The only thing you need to unsubscribe is the id given to you when you subscribed * https://developer.samsung.com/smarttv/develop/api-references/samsung-product-api-references/network-api.html#NetworkManager-removeNetworkStateChangeListener */ export const unsubscribeToDeviceNetworkChanges = (id = registeredListener) => { if (hasTizenAPIs()) { webapis.network.removeNetworkStateChangeListener(id); return; } if (isVizioPlatform()) { window.removeEventListener("online", function () {}); window.removeEventListener("offline", function () {}); } };