'use client'; import { useState } from 'react'; import type { LucideIcon } from 'lucide-react'; import { Image as ImageIcon, Video, Volume2, Mic, Globe2, SlidersHorizontal, ChevronRight, } from 'lucide-react'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Switch } from '@/components/ui/switch'; import { cn } from '@/lib/utils'; import { useI18n } from '@/lib/hooks/use-i18n'; import { useSettingsStore } from '@/lib/store/settings'; import type { SettingsSection } from '@/lib/types/settings'; import { isSettingsManagementEnabled } from '@/lib/config/deployment-role'; import { WEB_SEARCH_PROVIDERS, getWebSearchProviderDisplayName, isWebSearchProviderConfigured, } from '@/lib/web-search/constants'; interface MediaPopoverProps { onSettingsOpen?: (section: SettingsSection) => void; webSearch: boolean; onWebSearchChange: (enabled: boolean) => void; capabilityOverrides?: Partial>; } export type MediaCapabilityId = 'image' | 'video' | 'tts' | 'asr'; export interface MediaCapabilityOverride { enabled: boolean; onToggle?: (enabled: boolean) => void; disabled?: boolean; } type TabId = MediaCapabilityId | 'web-search'; const TABS: Array<{ id: TabId; icon: LucideIcon; labelKey: string }> = [ { id: 'image', icon: ImageIcon, labelKey: 'media.imageShort' }, { id: 'video', icon: Video, labelKey: 'media.videoShort' }, { id: 'tts', icon: Volume2, labelKey: 'media.ttsShort' }, { id: 'asr', icon: Mic, labelKey: 'media.asrShort' }, { id: 'web-search', icon: Globe2, labelKey: 'media.webSearchShort' }, ]; export function MediaPopover({ onSettingsOpen, webSearch, onWebSearchChange, capabilityOverrides, }: MediaPopoverProps) { const { t } = useI18n(); const [open, setOpen] = useState(false); const [activeTab, setActiveTab] = useState('image'); const settingsManagementEnabled = isSettingsManagementEnabled(); // ─── Store ─── const imageGenerationEnabled = useSettingsStore((s) => s.imageGenerationEnabled); const videoGenerationEnabled = useSettingsStore((s) => s.videoGenerationEnabled); const ttsEnabled = useSettingsStore((s) => s.ttsEnabled); const asrEnabled = useSettingsStore((s) => s.asrEnabled); const setImageGenerationEnabled = useSettingsStore((s) => s.setImageGenerationEnabled); const setVideoGenerationEnabled = useSettingsStore((s) => s.setVideoGenerationEnabled); const setTTSEnabled = useSettingsStore((s) => s.setTTSEnabled); const setASREnabled = useSettingsStore((s) => s.setASREnabled); const webSearchProviderId = useSettingsStore((s) => s.webSearchProviderId); const webSearchProvidersConfig = useSettingsStore((s) => s.webSearchProvidersConfig); const webSearchProvider = WEB_SEARCH_PROVIDERS[webSearchProviderId]; const selectedWebSearchAvailable = webSearchProvider ? isWebSearchProviderConfigured( webSearchProvider, webSearchProvidersConfig[webSearchProviderId], ) : false; const webSearchAvailable = Object.values(WEB_SEARCH_PROVIDERS).some((provider) => isWebSearchProviderConfigured(provider, webSearchProvidersConfig[provider.id]), ); const capabilities: Record = { image: capabilityOverrides?.image ?? { enabled: imageGenerationEnabled, onToggle: setImageGenerationEnabled, }, video: capabilityOverrides?.video ?? { enabled: videoGenerationEnabled, onToggle: setVideoGenerationEnabled, }, tts: capabilityOverrides?.tts ?? { enabled: ttsEnabled, onToggle: setTTSEnabled }, asr: capabilityOverrides?.asr ?? { enabled: asrEnabled, onToggle: setASREnabled }, }; const enabledMap: Record = { image: capabilities.image.enabled, video: capabilities.video.enabled, tts: capabilities.tts.enabled, asr: capabilities.asr.enabled, 'web-search': webSearch, }; const enabledCount = Object.values(enabledMap).filter(Boolean).length; // Auto-select first enabled tab on open const handleOpenChange = (isOpen: boolean) => { setOpen(isOpen); if (isOpen) { const first = (['image', 'video', 'tts', 'asr', 'web-search'] as TabId[]).find( (id) => enabledMap[id], ); setActiveTab(first || 'image'); } }; return ( {/* ── Tab bar (segmented control) ── */}
{TABS.map((tab) => { const isActive = activeTab === tab.id; const isEnabled = enabledMap[tab.id]; const Icon = tab.icon; return ( ); })}
{/* ── Tab content ── */}
{activeTab === 'image' && ( )} {activeTab === 'video' && ( )} {activeTab === 'tts' && ( )} {activeTab === 'asr' && ( )} {activeTab === 'web-search' && (

{selectedWebSearchAvailable ? t('toolbar.webSearchDesc') : t('toolbar.webSearchNoProvider')}

{selectedWebSearchAvailable && (

{t('toolbar.webSearchProvider')}:{' '} {getWebSearchProviderDisplayName(webSearchProviderId, t)}

)}
)}
{/* ── Footer ── */} {settingsManagementEnabled && onSettingsOpen && (
)}
); } // ─── Tab panel: header (label + switch) ─── function TabPanel({ icon: Icon, label, enabled, onToggle, disabled, }: { icon: LucideIcon; label: string; enabled: boolean; onToggle?: (v: boolean) => void; disabled?: boolean; }) { return (
{label}
); }