import React, { useCallback, useState } from "react"; import { Switch } from "react-native"; import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions"; import { useCellClick } from "@applicaster/zapp-react-native-utils/reactHooks/cell-click"; type Props = { item: ZappEntry | ZappFeed; action: { identifier: string; type?: string; }; style: Styles; cellState: CellState; }; export const Toggle = (props: Props) => { const { style, item, action, cellState } = props; const { trackColor, trackColorActive, thumbColor, thumbColorActive } = style; // `focused_selected` is the selected state with a finger on the row, so the // switch has to read as on for both. Leaving it out reads a pressed selected // row as off, which flips the thumb for the duration of the press. const isSelected = React.useMemo( () => cellState === "selected" || cellState === "focused_selected", [item?.id, cellState] ); const actionContext = useActions(action?.identifier); const onCellClick = useCellClick({ item: item as ZappEntry }); // A form toggle has no action plugin behind the switch: it reflects the cell // selection state and writes through the entry's tap actions, the same path a // tap on the row takes. // // An empty identifier is the way to ask for that, which is why the cell // manifest declares no initial_value for `toggle_action_identifier`: // `castOrDefault` substitutes the default whenever the configured value is // empty - and an empty string counts as empty - so any default there would be // uncleanable and would force every toggle onto that plugin. // // The route is still decided on whether the identifier resolves to an // installed action plugin rather than on the string being non-empty. App // configurations saved while the old default was in the manifest still carry // it, and a mistyped plugin id has to fall back the same way. const hasActionPlugin = Boolean( action?.identifier && actionContext?.invokeAction ); const [actionState, setActionState] = useState(() => hasActionPlugin ? actionContext?.initialEntryState?.(item) : undefined ); const onPress = useCallback(() => { if (!hasActionPlugin) { onCellClick(); return; } actionContext?.invokeAction?.(item, { updateState: setActionState, }); }, [hasActionPlugin, onCellClick, actionState, actionContext?.state]); return ( ); };