import { useCallback, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Platform, Text, View } from "react-native"; import { StyleSheet, withUnistyles } from "react-native-unistyles"; import { router } from "expo-router"; import type { PluginHostProps } from "@getpaseo/plugin/client"; import { Button } from "@/components/ui/button"; import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; import { useIsCompactFormFactor } from "@/constants/layout"; import { useHostFeature } from "@/runtime/host-features"; import { useHostRuntimeClient, useHostRuntimeIsConnected, useHosts } from "@/runtime/host-runtime"; import type { Theme } from "@/styles/theme"; import { useInstalledPlugin } from "../registry"; import { PluginRuntimeBoundary } from "../runtime-boundary"; import { SurfaceErrorBoundary } from "../surface-error-boundary"; import { toPluginTheme } from "../theme"; import { buildPluginSettingsRoute } from "./routes"; interface SettingsIdentity { serverId: string; pluginId: string; screenId: string; } function PluginSettingsMenuItem({ serverId, pluginId, screenId, title, disabled, }: SettingsIdentity & { title: string; disabled?: boolean }) { const open = useCallback( () => router.push(buildPluginSettingsRoute(serverId, pluginId, screenId)), [serverId, pluginId, screenId], ); return ( {title} ); } export function PluginSettingsMenuItems({ serverId, pluginId, disabled, }: Omit & { disabled?: boolean }) { const plugin = useInstalledPlugin(serverId, pluginId); const supported = useHostFeature(serverId, "pluginSettings"); if (!supported || !plugin) return null; return ( <> {plugin.settingsScreens.map((screen) => ( ))} ); } function SettingsContent({ serverId, pluginId, screenId, theme, }: SettingsIdentity & { theme: PluginHostProps["theme"] }) { const { t } = useTranslation(); const plugin = useInstalledPlugin(serverId, pluginId); const client = useHostRuntimeClient(serverId); const connected = useHostRuntimeIsConnected(serverId); const supported = useHostFeature(serverId, "pluginSettings"); const compact = useIsCompactFormFactor(); const hosts = useHosts(); const [attempt, setAttempt] = useState(0); const screen = plugin?.settingsScreens.find((item) => item.id === screenId); const retry = useCallback(() => setAttempt((value) => value + 1), []); const renderError = useCallback( (error: string) => ( {error} ), [retry, t], ); const host = useMemo( () => ({ id: serverId, label: hosts.find((candidate) => candidate.serverId === serverId)?.label ?? serverId, }), [hosts, serverId], ); const platform = Platform.OS === "ios" || Platform.OS === "android" ? Platform.OS : "web"; const layout = useMemo( () => ({ compact, platform }), [compact, platform], ); if (!connected) return {t("settings.plugins.screens.offline")}; // COMPAT(pluginSettings): added in v0.8, remove after 2027-03-05. if (!supported) return {t("settings.plugins.screens.update")}; if (!plugin || !screen || !client) return {t("settings.plugins.screens.unavailable")}; const Component = screen.Component; return ( ); } const ThemedSettingsContent = withUnistyles(SettingsContent); const themeMapping = (theme: Theme) => ({ theme: toPluginTheme(theme) }); export function PluginSettingsContent(props: SettingsIdentity) { return ; } const styles = StyleSheet.create((theme) => ({ message: { color: theme.colors.foregroundMuted } }));