import type { ModelCapabilities, ProviderOptionDescriptor, ProviderOptionSelection, } from "@t3tools/contracts"; import type { MenuAction } from "@react-native-menu/menu"; import { buildProviderOptionSelectionsFromDescriptors, getProviderOptionCurrentLabel, getProviderOptionCurrentValue, getProviderOptionDescriptors, } from "@t3tools/shared/model"; const PROVIDER_OPTION_EVENT_PREFIX = "provider-option:"; function providerOptionEvent(id: string, value: string | boolean): string { return `${PROVIDER_OPTION_EVENT_PREFIX}${encodeURIComponent(JSON.stringify({ id, value }))}`; } function parseProviderOptionEvent( event: string, ): { readonly id: string; readonly value: string | boolean } | null { if (!event.startsWith(PROVIDER_OPTION_EVENT_PREFIX)) { return null; } try { const parsed: unknown = JSON.parse( decodeURIComponent(event.slice(PROVIDER_OPTION_EVENT_PREFIX.length)), ); if ( typeof parsed === "object" && parsed !== null && "id" in parsed && typeof parsed.id === "string" && "value" in parsed && (typeof parsed.value === "string" || typeof parsed.value === "boolean") ) { return { id: parsed.id, value: parsed.value }; } } catch { return null; } return null; } export function resolveProviderOptionDescriptors(input: { readonly capabilities: ModelCapabilities | null | undefined; readonly selections: ReadonlyArray | null | undefined; }): ReadonlyArray { if (!input.capabilities) { return []; } return getProviderOptionDescriptors({ caps: input.capabilities, selections: input.selections, }); } export function buildProviderOptionMenuActions( descriptors: ReadonlyArray, ): ReadonlyArray { return descriptors.map((descriptor) => { const currentValue = descriptor.type === "boolean" ? (descriptor.currentValue ?? false) : getProviderOptionCurrentValue(descriptor); const choices = descriptor.type === "select" ? descriptor.options.map((option) => ({ id: providerOptionEvent(descriptor.id, option.id), title: `${option.label}${option.isDefault ? " (default)" : ""}`, state: currentValue === option.id ? ("on" as const) : undefined, })) : ([false, true] as const).map((value) => ({ id: providerOptionEvent(descriptor.id, value), title: value ? "On" : "Off", state: currentValue === value ? ("on" as const) : undefined, })); return { id: `provider-option-menu:${descriptor.id}`, title: descriptor.label, subtitle: descriptor.type === "boolean" ? currentValue ? "On" : "Off" : getProviderOptionCurrentLabel(descriptor), subactions: choices, }; }); } export function providerOptionsConfigurationLabel( descriptors: ReadonlyArray, ): string { const labels = descriptors.flatMap((descriptor) => { if (descriptor.type === "boolean") { return descriptor.currentValue ? [descriptor.label] : []; } const label = getProviderOptionCurrentLabel(descriptor); return label ? [label] : []; }); return labels.length > 0 ? labels.join(" ยท ") : "Configuration"; } export function applyProviderOptionMenuEvent( descriptors: ReadonlyArray, event: string, ): ReadonlyArray | null { const selection = parseProviderOptionEvent(event); if (!selection) { return null; } const descriptor = descriptors.find((candidate) => candidate.id === selection.id); if (!descriptor) { return null; } if ( (descriptor.type === "boolean" && typeof selection.value !== "boolean") || (descriptor.type === "select" && (typeof selection.value !== "string" || !descriptor.options.some((option) => option.id === selection.value))) ) { return null; } const nextDescriptors = descriptors.map((candidate) => candidate.id === descriptor.id ? { ...candidate, currentValue: selection.value, } : candidate, ) as ReadonlyArray; return buildProviderOptionSelectionsFromDescriptors(nextDescriptors) ?? []; }