*/ public array $data = []; public ?string $currentDjId = null; private const string CACHE_KEY = 'website_settings'; public function mount(): void { $this->fillForm(); } protected function fillForm(): void { $this->data = [ 'radio_enabled' => $this->getSettingBool('radio_enabled'), 'radio_stream_url' => $this->getSetting('radio_stream_url', ''), 'radio_stream_backup_url' => $this->getSetting('radio_stream_backup_url', ''), 'radio_style' => $this->getSetting('radio_style', 'dark'), 'radio_player_type' => $this->getSetting('radio_player_type', 'default'), 'radio_auto_play' => $this->getSettingBool('radio_auto_play'), 'radio_auto_play_delay' => (int) $this->getSetting('radio_auto_play_delay', '0'), 'radio_mute_on_start' => $this->getSettingBool('radio_mute_on_start'), 'radio_volume' => (int) $this->getSetting('radio_volume', '80'), 'radio_applications_enabled' => $this->getSettingBool('radio_applications_enabled'), 'radio_applications_max_per_day' => (int) $this->getSetting('radio_applications_max_per_day', '1'), 'radio_applications_require_approval' => $this->getSettingBool('radio_applications_require_approval'), 'radio_widget_enabled' => $this->getSettingBool('radio_widget_enabled'), 'radio_widget_show_globally' => $this->getSettingBool('radio_widget_show_globally'), 'radio_widget_position' => $this->getSetting('radio_widget_position', 'bottom-right'), 'radio_embed_enabled' => $this->getSettingBool('radio_embed_enabled'), 'radio_embed_allowed_domains' => $this->getSetting('radio_embed_allowed_domains', ''), 'radio_embed_theme' => $this->getSetting('radio_embed_theme', 'dark'), 'radio_embed_height' => (int) $this->getSetting('radio_embed_height', '400'), 'radio_embed_width' => $this->getSetting('radio_embed_width', '100%'), 'radio_embed_auto_play' => $this->getSettingBool('radio_embed_auto_play'), 'radio_shouts_enabled' => $this->getSettingBool('radio_shouts_enabled'), 'radio_shouts_max_length' => (int) $this->getSetting('radio_shouts_max_length', '280'), 'radio_shouts_cooldown' => (int) $this->getSetting('radio_shouts_cooldown', '30'), 'radio_shouts_require_moderation' => $this->getSettingBool('radio_shouts_require_moderation'), 'radio_chat_enabled' => $this->getSettingBool('radio_chat_enabled'), 'radio_chat_position' => $this->getSetting('radio_chat_position', 'right'), 'radio_chat_width' => (int) $this->getSetting('radio_chat_width', '350'), 'radio_chat_height' => (int) $this->getSetting('radio_chat_height', '500'), 'radio_chat_messages_count' => (int) $this->getSetting('radio_chat_messages_count', '50'), 'radio_chat_show_timestamps' => $this->getSettingBool('radio_chat_show_timestamps'), 'radio_chat_allow_links' => $this->getSettingBool('radio_chat_allow_links'), 'radio_chat_allow_emojis' => $this->getSettingBool('radio_chat_allow_emojis'), 'radio_now_playing_enabled' => $this->getSettingBool('radio_now_playing_enabled'), 'radio_now_playing_api_url' => $this->getSetting('radio_now_playing_api_url', ''), 'radio_now_playing_cache_duration' => (int) $this->getSetting('radio_now_playing_cache_duration', '30'), 'radio_show_song_history' => $this->getSettingBool('radio_show_song_history'), 'radio_song_history_count' => (int) $this->getSetting('radio_song_history_count', '10'), 'radio_listeners_enabled' => $this->getSettingBool('radio_listeners_enabled'), 'radio_listeners_api_url' => $this->getSetting('radio_listeners_api_url', ''), 'radio_show_listener_peak' => $this->getSettingBool('radio_show_listener_peak'), 'radio_peak_reset_time' => $this->getSetting('radio_peak_reset_time', '00:00'), 'radio_listeners_update_interval' => (int) $this->getSetting('radio_listeners_update_interval', '30'), 'radio_store_listener_stats' => $this->getSettingBool('radio_store_listener_stats'), 'radio_stats_retention_days' => (int) $this->getSetting('radio_stats_retention_days', '30'), 'radio_min_listeners_threshold' => (int) $this->getSetting('radio_min_listeners_threshold', '0'), 'radio_listener_alerts_enabled' => $this->getSettingBool('radio_listener_alerts_enabled'), 'radio_listener_alert_threshold_high' => (int) $this->getSetting('radio_listener_alert_threshold_high', '100'), 'radio_listener_alert_threshold_low' => (int) $this->getSetting('radio_listener_alert_threshold_low', '5'), 'radio_show_listener_graph' => $this->getSettingBool('radio_show_listener_graph'), 'radio_listener_graph_period' => $this->getSetting('radio_listener_graph_period', '24h'), 'radio_show_average_listeners' => $this->getSettingBool('radio_show_average_listeners'), 'radio_show_unique_listeners' => $this->getSettingBool('radio_show_unique_listeners'), 'radio_show_current_dj' => $this->getSettingBool('radio_show_current_dj'), 'current_dj_id' => $this->getSetting('radio_current_dj_id', ''), 'radio_dj_avatar_size' => (int) $this->getSetting('radio_dj_avatar_size', '64'), 'radio_default_avatar_figure' => $this->getSetting('radio_default_avatar_figure', 'hr-893-45.hd-180-2.ch-210-62.lg-285-62.sh-295-62.ha-1012-62.wa-2007-0'), 'radio_default_dj_name' => $this->getSetting('radio_default_dj_name', 'Frank'), 'radio_show_dj_avatar_popup' => $this->getSettingBool('radio_show_dj_avatar_popup'), 'radio_dj_avatar_popup_duration' => (int) $this->getSetting('radio_dj_avatar_popup_duration', '5'), 'radio_show_dj_schedule' => $this->getSettingBool('radio_show_dj_schedule'), 'radio_auto_dj_detection' => $this->getSettingBool('radio_auto_dj_detection'), 'radio_dj_detection_interval' => (int) $this->getSetting('radio_dj_detection_interval', '60'), 'auto_dj_detected_action' => $this->getSetting('auto_dj_detected_action', 'set_dj'), 'radio_sambroadcaster_api_url' => $this->getSetting('radio_sambroadcaster_api_url', ''), 'radio_sambroadcaster_password' => $this->getSetting('radio_sambroadcaster_password', ''), 'radio_virtual_dj_url' => $this->getSetting('radio_virtual_dj_url', ''), 'radio_virtual_dj_password' => $this->getSetting('radio_virtual_dj_password', ''), 'radio_djs_api_url' => $this->getSetting('radio_djs_api_url', ''), 'radio_request_form_enabled' => $this->getSettingBool('radio_request_form_enabled'), 'radio_request_max_per_user' => (int) $this->getSetting('radio_request_max_per_user', '3'), 'radio_request_cooldown' => (int) $this->getSetting('radio_request_cooldown', '300'), 'radio_voting_enabled' => $this->getSettingBool('radio_voting_enabled'), 'radio_voting_show_song_requests' => $this->getSettingBool('radio_voting_show_song_requests'), 'radio_stats_show_daily' => $this->getSettingBool('radio_stats_show_daily'), 'radio_stats_show_weekly' => $this->getSettingBool('radio_stats_show_weekly'), 'radio_stats_show_monthly' => $this->getSettingBool('radio_stats_show_monthly'), 'radio_stats_show_top_djs' => $this->getSettingBool('radio_stats_show_top_djs'), 'radio_stats_show_top_songs' => $this->getSettingBool('radio_stats_show_top_songs'), 'radio_show_offline_message' => $this->getSettingBool('radio_show_offline_message'), 'radio_offline_message' => $this->getSetting('radio_offline_message', 'We zijn momenteel offline. Check onze socials voor updates!'), 'radio_offline_image' => $this->getSetting('radio_offline_image', ''), 'radio_background_image' => $this->getSetting('radio_background_image', ''), 'radio_logo_url' => $this->getSetting('radio_logo_url', ''), 'radio_player_color_primary' => $this->getSetting('radio_player_color_primary', '#eeb425'), 'radio_player_color_secondary' => $this->getSetting('radio_player_color_secondary', '#1a1a2e'), 'radio_player_color_text' => $this->getSetting('radio_player_color_text', '#ffffff'), 'radio_player_color_accent' => $this->getSetting('radio_player_color_accent', '#eeb425'), 'radio_custom_css' => $this->getSetting('radio_custom_css', ''), 'radio_custom_js' => $this->getSetting('radio_custom_js', ''), 'radio_social_facebook' => $this->getSetting('radio_social_facebook', ''), 'radio_social_twitter' => $this->getSetting('radio_social_twitter', ''), 'radio_social_instagram' => $this->getSetting('radio_social_instagram', ''), 'radio_social_discord' => $this->getSetting('radio_social_discord', ''), 'radio_social_youtube' => $this->getSetting('radio_social_youtube', ''), 'radio_social_twitch' => $this->getSetting('radio_social_twitch', ''), 'radio_contact_email' => $this->getSetting('radio_contact_email', ''), 'radio_contact_phone' => $this->getSetting('radio_contact_phone', ''), 'radio_about_text' => $this->getSetting('radio_about_text', ''), 'radio_azurecast_base_url' => $this->getSetting('radio_azurecast_base_url', ''), 'radio_azurecast_station_id' => (int) $this->getSetting('radio_azurecast_station_id', '1'), 'radio_azurecast_api_key' => $this->getSetting('radio_azurecast_api_key', ''), 'radio_azurecast_port' => (int) $this->getSetting('radio_azurecast_port', '8443'), 'radio_azurecast_protocol' => $this->getSetting('radio_azurecast_protocol', 'https'), 'radio_azurecast_use_proxy' => $this->getSettingBool('radio_azurecast_use_proxy'), 'radio_language' => $this->getSetting('radio_language', 'nl'), 'radio_multi_language_enabled' => $this->getSettingBool('radio_multi_language_enabled'), 'radio_discord_webhook_url' => $this->getSetting('radio_discord_webhook_url', ''), 'radio_discord_enabled' => $this->getSettingBool('radio_discord_enabled'), 'radio_discord_dj_live' => $this->getSettingBool('radio_discord_dj_live'), 'radio_discord_song_changes' => $this->getSettingBool('radio_discord_song_changes'), 'radio_discord_custom_message' => $this->getSetting('radio_discord_custom_message', 'DJ {dj_name} is nu live!'), ]; $this->currentDjId = $this->data['current_dj_id'] ?? null; } public function form(Schema $schema): Schema { return $schema ->components([ Section::make('Radio Auto-Setup') ->description('In 1 klik je radio installeren en configureren') ->columns(2) ->afterHeader([ Action::make('install_azurecast') ->label('Installeer AzureCast') ->action('installAndSetupAzurecast') ->color('success'), Action::make('auto_setup') ->label('Auto-Setup') ->action('fullAutoSetup') ->color('primary'), ]) ->schema([ TextInput::make('radio_stream_url') ->label('Stream URL') ->placeholder('https://jouw-radio.nl/radio.mp3') ->url() ->columnSpan(2) ->hint('Voer je AzureCast stream URL in'), Toggle::make('radio_enabled') ->label('Radio Inschakelen') ->columnSpanFull(), ]), Section::make('AzureCast Configuratie') ->description('Handmatige AzureCast instellingen') ->collapsed() ->columns(2) ->afterHeader([ Action::make('save_azurecast') ->label('Opslaan') ->action('saveAzurecast') ->color('primary'), ]) ->schema([ TextInput::make('radio_azurecast_base_url') ->label('AzureCast Basis URL') ->placeholder('https://radio.jouwdomein.nl') ->url() ->columnSpan(2), TextInput::make('radio_azurecast_station_id') ->label('Station ID') ->numeric() ->default(1), TextInput::make('radio_azurecast_api_key') ->label('API Key') ->password(), TextInput::make('radio_azurecast_port') ->label('Poort') ->numeric() ->default(8443), Select::make('radio_azurecast_protocol') ->label('Protocol') ->options([ 'http' => 'HTTP', 'https' => 'HTTPS', ]) ->default('https'), Toggle::make('radio_azurecast_use_proxy') ->label('Proxy Gebruiken'), ]), Section::make('Sambroadcaster & Virtual DJ') ->description('Verbinding met Sambroadcaster en Virtual DJ software') ->columns(2) ->afterHeader([ Action::make('check_dj') ->label('Check DJ Verbinding') ->action('checkDjConnection') ->color('info'), Action::make('save_sambroadcaster') ->label('Opslaan') ->action('saveSambroadcaster') ->color('primary'), ]) ->schema([ TextInput::make('radio_sambroadcaster_api_url') ->label('Sambroadcaster API URL') ->url(), TextInput::make('radio_sambroadcaster_password') ->label('Sambroadcaster Wachtwoord') ->password(), TextInput::make('radio_virtual_dj_url') ->label('Virtual DJ URL') ->url(), TextInput::make('radio_virtual_dj_password') ->label('Virtual DJ Wachtwoord') ->password(), TextInput::make('radio_djs_api_url') ->label('DJs API URL') ->url(), ]), Section::make('Player Configuratie') ->description('Basis player instellingen') ->columns(2) ->afterHeader([ Action::make('save_player') ->label('Opslaan') ->action('savePlayer') ->color('primary'), ]) ->schema([ Select::make('radio_style') ->label('Player Stijl') ->options([ 'dark' => 'Donker', 'light' => 'Licht', 'blue' => 'Blauw', 'purple' => 'Paars', 'pink' => 'Roze', 'gold' => 'Goud', ]) ->default('dark'), Select::make('radio_player_type') ->label('Player Type') ->options([ 'default' => 'Standaard', 'minimal' => 'Minimaal', 'embedded' => 'Ingebed', ]) ->default('default'), Toggle::make('radio_auto_play') ->label('Auto-Play'), TextInput::make('radio_auto_play_delay') ->label('Auto-Play Vertraging (seconden)') ->numeric() ->default(0), Toggle::make('radio_mute_on_start') ->label('Gedempt Starten'), TextInput::make('radio_volume') ->label('Standaard Volume') ->numeric() ->minValue(0) ->maxValue(100) ->default(80), Select::make('radio_language') ->label('Systeem Taal') ->options([ 'nl' => 'Nederlands', 'en' => 'English', 'de' => 'Deutsch', 'fr' => 'Français', 'es' => 'Español', 'pt' => 'Português', 'it' => 'Italiano', 'br' => 'Português Brasil', ]) ->default('nl'), Toggle::make('radio_multi_language_enabled') ->label('Multi-taal Ondersteuning'), ]), Section::make('Player Kleuren') ->description('Player kleuren aanpassen') ->columns(3) ->afterHeader([ Action::make('save_colors') ->label('Opslaan') ->action('saveColors') ->color('primary'), ]) ->schema([ ColorPicker::make('radio_player_color_primary') ->label('Primaire Kleur') ->default('#eeb425'), ColorPicker::make('radio_player_color_secondary') ->label('Secundaire Kleur') ->default('#1a1a2e'), ColorPicker::make('radio_player_color_text') ->label('Tekst Kleur') ->default('#ffffff'), ColorPicker::make('radio_player_color_accent') ->label('Accent Kleur') ->default('#eeb425'), ]), Section::make('Nu Afspelen') ->description('Nu afspelen informatie') ->columns(2) ->afterHeader([ Action::make('save_now_playing') ->label('Opslaan') ->action('saveNowPlaying') ->color('primary'), ]) ->schema([ Toggle::make('radio_now_playing_enabled') ->label('Nu Afspelen Inschakelen'), TextInput::make('radio_now_playing_api_url') ->label('API URL') ->url(), TextInput::make('radio_now_playing_cache_duration') ->label('Cache Duur (seconden)') ->numeric() ->default(30), Toggle::make('radio_show_song_history') ->label('Song Geschiedenis Tonen'), TextInput::make('radio_song_history_count') ->label('Aantal Songs in Geschiedenis') ->numeric() ->default(10), ]), Section::make('Luisteraars Statistieken') ->description('Luisteraars informatie en statistieken') ->columns(2) ->afterHeader([ Action::make('save_listeners') ->label('Opslaan') ->action('saveListeners') ->color('primary'), ]) ->schema([ Toggle::make('radio_listeners_enabled') ->label('Luisteraars Aantal Inschakelen'), TextInput::make('radio_listeners_api_url') ->label('API URL') ->url(), TextInput::make('radio_listeners_update_interval') ->label('Update Interval (seconden)') ->numeric() ->default(30), Toggle::make('radio_show_listener_peak') ->label('Piek Luisteraars Tonen'), TimePicker::make('radio_peak_reset_time') ->label('Piektijd Reset') ->seconds(false) ->format('H:i') ->default('00:00'), Toggle::make('radio_store_listener_stats') ->label('Statistieken Opslaan'), TextInput::make('radio_stats_retention_days') ->label('Retentie Dagen') ->numeric() ->default(30), Toggle::make('radio_show_listener_graph') ->label('Luisteraars Grafiek Tonen'), Select::make('radio_listener_graph_period') ->label('Grafiek Periode') ->options([ '1h' => '1 Uur', '6h' => '6 Uur', '12h' => '12 Uur', '24h' => '24 Uur', '7d' => '7 Dagen', ]) ->default('24h'), Toggle::make('radio_show_average_listeners') ->label('Gemiddelde Luisteraars Tonen'), Toggle::make('radio_show_unique_listeners') ->label('Unieke Luisteraars Tonen'), ]), Section::make('Luisteraars Meldingen') ->description('Meldingen bij luisteraars changes') ->columns(2) ->schema([ Toggle::make('radio_listener_alerts_enabled') ->label('Luisteraars Meldingen Inschakelen'), TextInput::make('radio_min_listeners_threshold') ->label('Minimale Luisteraars Drempel') ->numeric() ->default(0), TextInput::make('radio_listener_alert_threshold_high') ->label('Hoge Luisteraars Melding') ->numeric() ->default(100), TextInput::make('radio_listener_alert_threshold_low') ->label('Lage Luisteraars Melding') ->numeric() ->default(5), ]), Section::make('DJ Instellingen') ->description('Huidige DJ en schedule') ->columns(2) ->afterHeader([ Action::make('save_dj') ->label('Opslaan') ->action('saveDj') ->color('primary'), ]) ->schema([ Toggle::make('radio_show_current_dj') ->label('Huidige DJ Tonen'), TextInput::make('current_dj_id') ->label('Handmatige DJ (User ID)') ->numeric(), TextInput::make('radio_dj_avatar_size') ->label('Avatar Grootte (px)') ->numeric() ->default(64), TextInput::make('radio_default_avatar_figure') ->label('Default Avatar Figure (geen DJ)') ->helperText('Habbo figure code voor wanneer er geen DJ live is (bijv. hr-893-45.hd-180-2...)') ->placeholder('hr-893-45.hd-180-2.ch-210-62.lg-285-62.sh-295-62.ha-1012-62.wa-2007-0'), TextInput::make('radio_default_dj_name') ->label('Default DJ Naam (geen DJ)') ->default('Frank'), Toggle::make('radio_show_dj_avatar_popup') ->label('DJ Avatar Popup Tonen') ->helperText('Toon een popup met DJ avatar wanneer een DJ live gaat'), TextInput::make('radio_dj_avatar_popup_duration') ->label('Popup Duur (seconden)') ->numeric() ->default(5) ->helperText('Hoe lang de popup zichtbaar blijft'), Toggle::make('radio_show_dj_schedule') ->label('DJ Schedule Tonen'), ]), Section::make('Auto DJ Detectie') ->description('Automatisch DJ detecteren') ->columns(2) ->afterHeader([ Action::make('check_connection') ->label('Check Verbinding') ->action('checkDjConnection') ->color('info'), Action::make('save_auto_dj') ->label('Opslaan') ->action('saveAutoDj') ->color('primary'), ]) ->schema([ Toggle::make('radio_auto_dj_detection') ->label('Auto DJ Detectie Inschakelen'), TextInput::make('radio_dj_detection_interval') ->label('Detectie Interval (seconden)') ->numeric() ->default(60), Select::make('auto_dj_detected_action') ->label('Bij Detectie') ->options([ 'set_dj' => 'DJ Automatisch Instellen', 'notify' => 'Alleen Melding Sturen', 'both' => 'Instellen en Melden', ]) ->default('set_dj'), ]), Section::make('Shouts') ->description('Shoutbox instellingen') ->columns(2) ->afterHeader([ Action::make('save_shouts') ->label('Opslaan') ->action('saveShouts') ->color('primary'), ]) ->schema([ Toggle::make('radio_shouts_enabled') ->label('Shouts Inschakelen'), TextInput::make('radio_shouts_max_length') ->label('Max. Karakters') ->numeric() ->default(280), TextInput::make('radio_shouts_cooldown') ->label('Cooldown (seconden)') ->numeric() ->default(30), Toggle::make('radio_shouts_require_moderation') ->label('Moderatie Vereist'), ]), Section::make('Live Chat') ->description('Live chat naast de player') ->columns(2) ->afterHeader([ Action::make('save_chat') ->label('Opslaan') ->action('saveChat') ->color('primary'), ]) ->schema([ Toggle::make('radio_chat_enabled') ->label('Chat Inschakelen'), Select::make('radio_chat_position') ->label('Chat Positie') ->options([ 'left' => 'Links', 'right' => 'Rechts', 'bottom' => 'Onder', ]) ->default('right'), TextInput::make('radio_chat_width') ->label('Chat Breedte (px)') ->numeric() ->default(350), TextInput::make('radio_chat_height') ->label('Chat Hoogte (px)') ->numeric() ->default(500), TextInput::make('radio_chat_messages_count') ->label('Aantal Berichten') ->numeric() ->default(50), Toggle::make('radio_chat_show_timestamps') ->label('Tijden Tonen'), Toggle::make('radio_chat_allow_links') ->label('Links Toestaan'), Toggle::make('radio_chat_allow_emojis') ->label('Emojis Toestaan'), ]), Section::make('Song Verzoeken') ->description('Song request formulier instellingen') ->columns(2) ->afterHeader([ Action::make('save_requests') ->label('Opslaan') ->action('saveRequests') ->color('primary'), ]) ->schema([ Toggle::make('radio_request_form_enabled') ->label('Verzoekformulier Inschakelen'), TextInput::make('radio_request_max_per_user') ->label('Max. Verzoeken per Gebruiker') ->numeric() ->default(3), TextInput::make('radio_request_cooldown') ->label('Cooldown (seconden)') ->numeric() ->default(300), Toggle::make('radio_voting_enabled') ->label('Stemmen Inschakelen'), Toggle::make('radio_voting_show_song_requests') ->label('Verzoeken met Stemmen Tonen'), ]), Section::make('Radio Widget') ->description('Kleine radio widget voor op de site') ->columns(2) ->afterHeader([ Action::make('save_widget') ->label('Opslaan') ->action('saveWidget') ->color('primary'), ]) ->schema([ Toggle::make('radio_widget_enabled') ->label('Widget Inschakelen'), Toggle::make('radio_widget_show_globally') ->label('Widget Overal Tonen'), Select::make('radio_widget_position') ->label('Widget Positie') ->options([ 'bottom-right' => 'Rechts Onder', 'bottom-left' => 'Links Onder', 'top-right' => 'Rechts Boven', 'top-left' => 'Links Boven', ]) ->default('bottom-right'), Toggle::make('radio_embed_enabled') ->label('Externe Embed Inschakelen') ->columnSpanFull() ->helperText('Sta toe dat de radio als iframe op externe sites wordt geplaatst.'), TextInput::make('radio_embed_allowed_domains') ->label('Toegestane Domeinen') ->placeholder('voorbeeld.nl, anderedomein.com') ->helperText('Komma-gescheiden lijst. Leeg = alle domeinen toegestaan.'), Select::make('radio_embed_theme') ->label('Embed Thema') ->options([ 'dark' => 'Donker', 'light' => 'Licht', 'transparent' => 'Transparant', ]) ->default('dark'), TextInput::make('radio_embed_height') ->label('Embed Hoogte (px)') ->numeric() ->default(400), TextInput::make('radio_embed_width') ->label('Embed Breedte') ->placeholder('100% of 400px') ->default('100%'), Toggle::make('radio_embed_auto_play') ->label('Auto-Play in Embed'), ]), Section::make('Offline Pagina') ->description('Instellingen voor wanneer de radio offline is') ->columns(2) ->afterHeader([ Action::make('save_offline') ->label('Opslaan') ->action('saveOffline') ->color('primary'), ]) ->schema([ Toggle::make('radio_show_offline_message') ->label('Offline Bericht Tonen'), Textarea::make('radio_offline_message') ->label('Offline Bericht') ->rows(3), TextInput::make('radio_offline_image') ->label('Offline Afbeelding URL') ->url(), TextInput::make('radio_background_image') ->label('Achtergrond Afbeelding URL') ->url(), TextInput::make('radio_logo_url') ->label('Logo URL') ->url(), ]), Section::make('DJ Aanmeldingen') ->description('Instellingen voor DJ sollicitaties') ->columns(2) ->afterHeader([ Action::make('save_applications') ->label('Opslaan') ->action('saveApplications') ->color('primary'), ]) ->schema([ Toggle::make('radio_applications_enabled') ->label('Aanmeldingen Inschakelen'), TextInput::make('radio_applications_max_per_day') ->label('Max. Aanmeldingen per Dag') ->numeric() ->default(1), Toggle::make('radio_applications_require_approval') ->label('Goedkeuring Vereist'), ]), Section::make('Statistieken Weergave') ->description('Welke statistieken tonen op de site') ->columns(2) ->afterHeader([ Action::make('save_stats') ->label('Opslaan') ->action('saveStats') ->color('primary'), ]) ->schema([ Toggle::make('radio_stats_show_daily') ->label('Dagelijkse Statistieken'), Toggle::make('radio_stats_show_weekly') ->label('Wekelijkse Statistieken'), Toggle::make('radio_stats_show_monthly') ->label('Maandelijkse Statistieken'), Toggle::make('radio_stats_show_top_djs') ->label('Top DJs'), Toggle::make('radio_stats_show_top_songs') ->label('Top Songs'), ]), Section::make('Social Media Links') ->description('Links naar je social media') ->columns(2) ->afterHeader([ Action::make('save_social') ->label('Opslaan') ->action('saveSocial') ->color('primary'), ]) ->schema([ TextInput::make('radio_social_facebook') ->label('Facebook URL') ->url(), TextInput::make('radio_social_twitter') ->label('Twitter URL') ->url(), TextInput::make('radio_social_instagram') ->label('Instagram URL') ->url(), TextInput::make('radio_social_discord') ->label('Discord URL') ->url(), TextInput::make('radio_social_youtube') ->label('YouTube URL') ->url(), TextInput::make('radio_social_twitch') ->label('Twitch URL') ->url(), ]), Section::make('Contact Informatie') ->description('Contact informatie') ->columns(2) ->schema([ TextInput::make('radio_contact_email') ->label('E-mail') ->email(), TextInput::make('radio_contact_phone') ->label('Telefoon'), Textarea::make('radio_about_text') ->label('Over Ons Tekst') ->rows(4), ]), Section::make('Discord Webhook') ->description('Discord notificaties voor DJ live, nummers, etc.') ->columns(2) ->afterHeader([ Action::make('test_discord') ->label('Test Webhook') ->action('testDiscordWebhook') ->color('warning'), Action::make('save_discord') ->label('Opslaan') ->action('saveDiscord') ->color('primary'), ]) ->schema([ Toggle::make('radio_discord_enabled') ->label('Discord Inschakelen') ->columnSpanFull(), TextInput::make('radio_discord_webhook_url') ->label('Webhook URL') ->url() ->columnSpanFull(), Toggle::make('radio_discord_dj_live') ->label('DJ Live Melding'), Toggle::make('radio_discord_song_changes') ->label('Nummer Wijziging Melding'), Textarea::make('radio_discord_custom_message') ->label('Custom Bericht') ->rows(3) ->columnSpanFull() ->helperText('Gebruik {dj_name}, {song}, {listeners}'), ]), Section::make('Custom Code') ->description('Aangepaste CSS en JavaScript') ->columns(1) ->afterHeader([ Action::make('save_custom') ->label('Opslaan') ->action('saveCustom') ->color('primary'), ]) ->schema([ Textarea::make('radio_custom_css') ->label('Custom CSS') ->rows(10), Textarea::make('radio_custom_js') ->label('Custom JavaScript') ->rows(10), ]), ]) ->statePath('data'); } public function savePlayer(): void { $this->saveSettings([ 'radio_style', 'radio_player_type', 'radio_auto_play', 'radio_auto_play_delay', 'radio_mute_on_start', 'radio_volume', 'radio_language', 'radio_multi_language_enabled', ]); } public function saveAzurecast(): void { $this->saveSettings([ 'radio_enabled', 'radio_azurecast_base_url', 'radio_azurecast_station_id', 'radio_azurecast_api_key', 'radio_azurecast_port', 'radio_azurecast_protocol', 'radio_azurecast_use_proxy', 'radio_stream_url', 'radio_stream_backup_url', ]); } public function saveSambroadcaster(): void { $this->saveSettings([ 'radio_sambroadcaster_api_url', 'radio_sambroadcaster_password', 'radio_virtual_dj_url', 'radio_virtual_dj_password', 'radio_djs_api_url', ]); } public function saveAutoDj(): void { $this->saveSettings([ 'radio_auto_dj_detection', 'radio_dj_detection_interval', 'auto_dj_detected_action', ]); } public function saveChat(): void { $this->saveSettings([ 'radio_chat_enabled', 'radio_chat_position', 'radio_chat_width', 'radio_chat_height', 'radio_chat_messages_count', 'radio_chat_show_timestamps', 'radio_chat_allow_links', 'radio_chat_allow_emojis', ]); } public function saveColors(): void { $this->saveSettings([ 'radio_player_color_primary', 'radio_player_color_secondary', 'radio_player_color_text', 'radio_player_color_accent', ]); } public function saveNowPlaying(): void { $this->saveSettings([ 'radio_now_playing_enabled', 'radio_now_playing_api_url', 'radio_now_playing_cache_duration', 'radio_show_song_history', 'radio_song_history_count', ]); } public function saveListeners(): void { $this->saveSettings([ 'radio_listeners_enabled', 'radio_listeners_api_url', 'radio_listeners_update_interval', 'radio_show_listener_peak', 'radio_peak_reset_time', 'radio_store_listener_stats', 'radio_stats_retention_days', 'radio_show_listener_graph', 'radio_listener_graph_period', 'radio_show_average_listeners', 'radio_show_unique_listeners', ]); } public function saveDj(): void { $this->saveSettings([ 'radio_show_current_dj', 'current_dj_id', 'radio_dj_avatar_size', 'radio_default_avatar_figure', 'radio_default_dj_name', 'radio_show_dj_avatar_popup', 'radio_dj_avatar_popup_duration', 'radio_show_dj_schedule', ]); } public function saveShouts(): void { $this->saveSettings([ 'radio_shouts_enabled', 'radio_shouts_max_length', 'radio_shouts_cooldown', 'radio_shouts_require_moderation', ]); } public function saveRequests(): void { $this->saveSettings([ 'radio_request_form_enabled', 'radio_request_max_per_user', 'radio_request_cooldown', 'radio_voting_enabled', 'radio_voting_show_song_requests', ]); } public function saveWidget(): void { $this->saveSettings([ 'radio_widget_enabled', 'radio_widget_show_globally', 'radio_widget_position', 'radio_embed_enabled', 'radio_embed_allowed_domains', 'radio_embed_theme', 'radio_embed_height', 'radio_embed_width', 'radio_embed_auto_play', ]); } public function saveOffline(): void { $this->saveSettings([ 'radio_show_offline_message', 'radio_offline_message', 'radio_offline_image', 'radio_background_image', 'radio_logo_url', ]); } public function saveApplications(): void { $this->saveSettings([ 'radio_applications_enabled', 'radio_applications_max_per_day', 'radio_applications_require_approval', ]); } public function saveStats(): void { $this->saveSettings([ 'radio_stats_show_daily', 'radio_stats_show_weekly', 'radio_stats_show_monthly', 'radio_stats_show_top_djs', 'radio_stats_show_top_songs', ]); } public function saveSocial(): void { $this->saveSettings([ 'radio_social_facebook', 'radio_social_twitter', 'radio_social_instagram', 'radio_social_discord', 'radio_social_youtube', 'radio_social_twitch', 'radio_contact_email', 'radio_contact_phone', 'radio_about_text', ]); } public function saveCustom(): void { $this->saveSettings([ 'radio_custom_css', 'radio_custom_js', ]); } public function saveDiscord(): void { $this->saveSettings([ 'radio_discord_enabled', 'radio_discord_webhook_url', 'radio_discord_dj_live', 'radio_discord_song_changes', 'radio_discord_custom_message', ]); } public function autoSetupAzurecast(): void { $streamUrl = $this->data['radio_stream_url'] ?? ''; $baseUrl = $this->data['radio_azurecast_base_url'] ?? ''; if (empty($streamUrl) && empty($baseUrl)) { Notification::make() ->warning() ->title('URL Vereist') ->body('Vul de Stream URL of AzureCast Basis URL in.') ->send(); return; } try { if (! empty($streamUrl)) { $parsed = parse_url((string) $streamUrl); if ($parsed) { $scheme = $parsed['scheme'] ?? 'https'; $host = $parsed['host'] ?? ''; $detectedBaseUrl = $scheme . '://' . $host; $testUrl = $detectedBaseUrl . '/api/nowplaying'; $response = Http::timeout(5)->get($testUrl); if ($response->ok()) { $data = $response->json(); if (is_array($data)) { $stationId = $data[0]['station']['id'] ?? $data['station']['id'] ?? 1; $this->saveSettings([ 'radio_enabled' => true, 'radio_azurecast_base_url' => $detectedBaseUrl, 'radio_azurecast_station_id' => $stationId, 'radio_now_playing_enabled' => true, 'radio_listeners_enabled' => true, 'radio_show_current_dj' => true, 'radio_widget_enabled' => true, 'radio_widget_show_globally' => true, ]); Notification::make() ->success() ->title('Success!') ->body("AzureCast gedetecteerd! Station ID: {$stationId}") ->send(); return; } } } } if (! empty($baseUrl)) { $baseUrl = rtrim((string) $baseUrl, '/'); $response = Http::timeout(10)->get($baseUrl . '/api/stations'); if ($response->ok()) { $stations = $response->json(); if (! empty($stations) && is_array($stations)) { $station = $stations[0]; $stationId = $station['id'] ?? 1; $stationName = $station['name'] ?? 'Radio'; $streamFromStation = $station['url'] ?? $station['mounts'][0]['url'] ?? $streamUrl ?? ''; $this->saveSettings([ 'radio_enabled' => true, 'radio_azurecast_base_url' => $baseUrl, 'radio_azurecast_station_id' => $stationId, 'radio_stream_url' => $streamFromStation, 'radio_now_playing_enabled' => true, 'radio_listeners_enabled' => true, 'radio_show_current_dj' => true, 'radio_widget_enabled' => true, 'radio_widget_show_globally' => true, ]); Notification::make() ->success() ->title('Success!') ->body("Station '{$stationName}' (ID: {$stationId}) is geconfigureerd!") ->send(); return; } } } Notification::make() ->danger() ->title('Niet Gevonden') ->body('Kon AzureCast niet detecteren. Controleer de URL.') ->send(); } catch (\Exception $e) { Notification::make() ->danger() ->title('Verbindingsfout') ->body('Kon geen verbinding maken: ' . $e->getMessage()) ->send(); } } public function fullAutoSetup(): void { $streamUrl = $this->data['radio_stream_url'] ?? ''; if (empty($streamUrl)) { Notification::make() ->warning() ->title('Stream URL Vereist') ->body('Voer je AzureCast stream URL in (bijv. https://jouw-radio.nl/radio.mp3)') ->send(); return; } Notification::make() ->info() ->title('Auto-Setup') ->body('Configuratie wordt gestart...') ->send(); $detectedBaseUrl = null; $stationId = 1; $apiKey = ''; $parsed = parse_url($streamUrl); if ($parsed) { $scheme = $parsed['scheme'] ?? 'https'; $host = $parsed['host'] ?? ''; $detectedBaseUrl = $scheme . '://' . $host; $apiTestUrl = $detectedBaseUrl . '/api/nowplaying/1'; try { $response = Http::timeout(10)->get($apiTestUrl); if ($response->ok()) { $npData = $response->json(); if (isset($npData['station']['id'])) { $stationId = $npData['station']['id']; } } } catch (\Exception) { try { $response = Http::timeout(10)->get($detectedBaseUrl . '/api/stations'); if ($response->ok()) { $stations = $response->json(); if (! empty($stations)) { $stationId = $stations[0]['id'] ?? 1; if (! empty($stations[0]['url'])) { $streamUrl = $stations[0]['url']; } } } } catch (\Exception) { // Continue with defaults } } } if (empty($detectedBaseUrl)) { Notification::make() ->danger() ->title('AzureCast Niet Gevonden') ->body('Kon AzureCast server niet bereiken. Controleer de stream URL.') ->send(); return; } $settings = [ 'radio_enabled' => '1', 'radio_azurecast_base_url' => $detectedBaseUrl, 'radio_azurecast_station_id' => (string) $stationId, 'radio_stream_url' => $streamUrl, 'radio_now_playing_enabled' => '1', 'radio_listeners_enabled' => '1', 'radio_show_current_dj' => '1', 'radio_widget_enabled' => '1', 'radio_widget_show_globally' => '1', 'radio_azurecast_use_proxy' => '1', 'radio_shouts_enabled' => '1', 'radio_applications_enabled' => '1', ]; foreach ($settings as $key => $value) { WebsiteSetting::updateOrCreate( ['key' => $key], ['value' => $value], ); } Cache::flush(); Artisan::call('config:clear'); Artisan::call('cache:clear'); Notification::make() ->success() ->title('🎉 Radio Klaar!') ->body("Alles is geconfigureerd! Stream: {$streamUrl}") ->send(); } public function installAndSetupAzurecast(): void { Notification::make() ->info() ->title('Zoeken naar AzureCast...') ->body('Ik zoek naar een bestaande AzureCast server.') ->send(); $foundPort = null; $commonPorts = [2000, 2250, 8000, 8080, 8443, 9000]; foreach ($commonPorts as $testPort) { try { $response = Http::timeout(2)->get("http://localhost:{$testPort}/api/nowplaying/1"); if ($response->ok()) { $foundPort = $testPort; break; } } catch (\Exception) { // Try next port } } if ($foundPort) { Notification::make() ->success() ->title('AzureCast Gevonden!') ->body("AzureCast draait al op poort {$foundPort}") ->send(); $this->configureExistingAzureCast($foundPort); return; } Notification::make() ->info() ->title('Geen AzureCast Gevonden') ->body('Voer je stream URL in en klik op Auto-Setup') ->send(); $this->fullAutoSetup(); } private function configureExistingAzureCast(int $port): void { $baseUrl = "http://localhost:{$port}"; try { $response = Http::timeout(5)->get($baseUrl . '/api/stations'); $stations = $response->ok() ? $response->json() : []; $stationId = $stations[0]['id'] ?? 1; $streamUrl = $stations[0]['url'] ?? $baseUrl . '/radio.mp3'; } catch (\Exception $e) { $stationId = 1; $streamUrl = $baseUrl . '/radio.mp3'; } $settings = [ 'radio_enabled' => '1', 'radio_azurecast_base_url' => $baseUrl, 'radio_azurecast_station_id' => (string) $stationId, 'radio_stream_url' => $streamUrl, 'radio_now_playing_enabled' => '1', 'radio_listeners_enabled' => '1', 'radio_show_current_dj' => '1', 'radio_widget_enabled' => '1', 'radio_widget_show_globally' => '1', 'radio_shouts_enabled' => '1', ]; foreach ($settings as $key => $value) { WebsiteSetting::updateOrCreate( ['key' => $key], ['value' => $value], ); } Cache::flush(); Artisan::call('config:clear'); Artisan::call('cache:clear'); Notification::make() ->success() ->title('🎉 Alles Klaar!') ->body("Radio werkt op http://localhost:{$port}") ->send(); } private function autoConfigureFromUrl(string $streamUrl): void { $parsed = parse_url($streamUrl); if (! $parsed) { Notification::make() ->danger() ->title('Ongeldige URL') ->body(' Voer een geldige stream URL in.') ->send(); return; } $scheme = $parsed['scheme'] ?? 'https'; $host = $parsed['host'] ?? ''; $baseUrl = $scheme . '://' . $host; try { $response = Http::timeout(10)->get($baseUrl . '/api/nowplaying/1'); if (! $response->ok()) { $response = Http::timeout(10)->get($baseUrl . '/api/stations'); } } catch (\Exception $e) { Notification::make() ->danger() ->title('Verbindingsfout') ->body('Kon AzureCast niet bereiken.') ->send(); return; } $stationId = 1; $actualStreamUrl = $streamUrl; try { $npResponse = Http::timeout(5)->get($baseUrl . '/api/nowplaying/1'); if ($npResponse->ok()) { $npData = $npResponse->json(); $stationId = $npData['station']['id'] ?? 1; } $stationsResponse = Http::timeout(5)->get($baseUrl . '/api/stations'); if ($stationsResponse->ok()) { $stations = $stationsResponse->json(); if (! empty($stations)) { $stationId = $stations[0]['id'] ?? 1; $actualStreamUrl = $stations[0]['url'] ?? $streamUrl; } } } catch (\Exception) { // Use defaults } $settings = [ 'radio_enabled' => '1', 'radio_azurecast_base_url' => $baseUrl, 'radio_azurecast_station_id' => (string) $stationId, 'radio_stream_url' => $actualStreamUrl, 'radio_now_playing_enabled' => '1', 'radio_listeners_enabled' => '1', 'radio_show_current_dj' => '1', 'radio_widget_enabled' => '1', 'radio_widget_show_globally' => '1', 'radio_shouts_enabled' => '1', ]; foreach ($settings as $key => $value) { WebsiteSetting::updateOrCreate( ['key' => $key], ['value' => $value], ); } Cache::flush(); Artisan::call('config:clear'); Artisan::call('cache:clear'); Notification::make() ->success() ->title('🎉 Radio Klaar!') ->body("Alles geconfigureerd op {$baseUrl}") ->send(); } private function findFreePort(int $start = 2000, int $end = 9000): ?int { for ($port = $start; $port <= $end; $port++) { $connection = @fsockopen('127.0.0.1', $port); if ($connection === false) { return $port; } fclose($connection); } return null; } public function testDiscordWebhook(): void { $webhookUrl = $this->data['radio_discord_webhook_url'] ?? ''; if (empty($webhookUrl)) { Notification::make() ->warning() ->title('Webhook URL Vereist') ->body('Vul eerst de Discord Webhook URL in.') ->send(); return; } try { $payload = ['content' => '🎵 Radio Discord integration test - Success!']; $response = Http::post($webhookUrl, $payload); if ($response->ok()) { Notification::make() ->success() ->title('Test Verzonden!') ->body('Testbericht is succesvol naar Discord gestuurd.') ->send(); } else { Notification::make() ->danger() ->title(__('Error')) ->body('Kon bericht niet versturen. Status: ' . $response->status()) ->send(); } } catch (\Exception $e) { Notification::make() ->danger() ->title(__('Error')) ->body('Verbindingsfout: ' . $e->getMessage()) ->send(); } } public function checkDjConnection(): void { $detectedDj = null; $source = null; $sambroadcasterUrl = $this->data['radio_sambroadcaster_api_url'] ?? ''; $virtualDjUrl = $this->data['radio_virtual_dj_url'] ?? ''; if (! empty($sambroadcasterUrl)) { try { $response = Http::timeout(5)->get($sambroadcasterUrl . '/dj'); if ($response->ok()) { $data = $response->json(); $detectedDj = $data['dj_name'] ?? $data['dj'] ?? $data['current_dj'] ?? null; $source = 'Sambroadcaster'; } } catch (\Exception $e) { Notification::make() ->warning() ->title('Sambroadcaster Fout') ->body('Kon geen verbinding maken met Sambroadcaster: ' . $e->getMessage()) ->send(); } } if ($detectedDj === null && ! empty($virtualDjUrl)) { try { $response = Http::timeout(5)->withBasicAuth('admin', $this->data['radio_virtual_dj_password'] ?? '') ->get($virtualDjUrl . '/api/v1/status'); if ($response->ok()) { $data = $response->json(); $detectedDj = $data['current_dj'] ?? $data['dj'] ?? null; $source = 'Virtual DJ'; } } catch (\Exception $e) { Notification::make() ->warning() ->title('Virtual DJ Fout') ->body('Kon geen verbinding maken met Virtual DJ: ' . $e->getMessage()) ->send(); } } if ($detectedDj !== null) { $action = $this->data['auto_dj_detected_action'] ?? 'set_dj'; if (in_array($action, ['set_dj', 'both'])) { Notification::make() ->success() ->title('DJ Gedetecteerd!') ->body("{$detectedDj} is verbonden via {$source}.") ->send(); } else { Notification::make() ->info() ->title('DJ Gedetecteerd') ->body("{$detectedDj} is actief via {$source}.") ->send(); } } else { Notification::make() ->warning() ->title('Geen DJ Gevonden') ->body('Er kon geen actieve DJ worden gedetecteerd.') ->send(); } } private function saveSettings(array $keys): void { foreach ($keys as $key => $value) { if (is_numeric($key)) { $settingKey = $value; $settingValue = $this->data[$value] ?? ''; } else { $settingKey = $key; $settingValue = $value; } $boolSettings = [ 'radio_enabled', 'radio_auto_play', 'radio_mute_on_start', 'radio_multi_language_enabled', 'radio_show_current_dj', 'radio_now_playing_enabled', 'radio_show_song_history', 'radio_listeners_enabled', 'radio_show_listener_peak', 'radio_store_listener_stats', 'radio_show_listener_graph', 'radio_show_average_listeners', 'radio_show_unique_listeners', 'radio_show_dj_schedule', 'radio_auto_dj_detection', 'radio_shouts_enabled', 'radio_shouts_require_moderation', 'radio_chat_enabled', 'radio_chat_show_timestamps', 'radio_chat_allow_links', 'radio_chat_allow_emojis', 'radio_request_form_enabled', 'radio_voting_enabled', 'radio_voting_show_song_requests', 'radio_stats_show_daily', 'radio_stats_show_weekly', 'radio_stats_show_monthly', 'radio_stats_show_top_djs', 'radio_stats_show_top_songs', 'radio_show_offline_message', 'radio_widget_enabled', 'radio_widget_show_globally', 'radio_embed_enabled', 'radio_embed_auto_play', 'radio_applications_enabled', 'radio_applications_require_approval', 'radio_discord_enabled', 'radio_discord_dj_live', 'radio_discord_song_changes', 'radio_listener_alerts_enabled', 'radio_azurecast_use_proxy', ]; $intSettings = [ 'radio_auto_play_delay', 'radio_volume', 'radio_now_playing_cache_duration', 'radio_song_history_count', 'radio_listeners_update_interval', 'radio_stats_retention_days', 'radio_dj_avatar_size', 'radio_dj_detection_interval', 'radio_shouts_max_length', 'radio_shouts_cooldown', 'radio_chat_width', 'radio_chat_height', 'radio_chat_messages_count', 'radio_embed_height', 'radio_request_max_per_user', 'radio_request_cooldown', 'radio_min_listeners_threshold', 'radio_listener_alert_threshold_high', 'radio_listener_alert_threshold_low', 'radio_applications_max_per_day', 'radio_azurecast_station_id', ]; if (in_array($settingKey, $boolSettings)) { $dbValue = $settingValue ? '1' : '0'; } elseif (in_array($settingKey, $intSettings)) { $dbValue = (string) ($settingValue ?? 0); } else { $dbValue = (string) ($settingValue ?? ''); } WebsiteSetting::updateOrCreate( ['key' => $settingKey], ['value' => $dbValue], ); } $this->clearCache(); Notification::make() ->success() ->title(__('Saved')) ->body('Alle instellingen zijn succesvol opgeslagen!') ->send(); } private function clearCache(): void { Cache::forget(self::CACHE_KEY); } private function getSettingBool(string $key): bool { return (bool) WebsiteSetting::where('key', $key)->first()?->value; } private function getSetting(string $key, string $default = ''): string { return WebsiteSetting::where('key', $key)->first()?->value ?? $default; } #[\Override] protected function getHeaderActions(): array { return [ Action::make('setup') ->label('🚀 ' . __('radio.setup.button_label')) ->icon('heroicon-o-rocket-launch') ->color('warning') ->size('lg') ->requiresConfirmation() ->modalHeading(__('radio.setup.modal_heading')) ->modalDescription(__('radio.setup.modal_description')) ->modalSubmitActionLabel(__('radio.setup.modal_submit')) ->action(function () { $this->runAllInOneSetup(); }) ->tooltip(__('radio.setup.tooltip')), ]; } public function runAllInOneSetup(): void { try { // Standard radio settings $settings = [ 'radio_enabled' => '1', 'radio_stream_url' => 'https://stream.radioking.com/radio/83232/radio.mp3', 'radio_style' => 'dark', 'radio_auto_play' => '0', 'points_enabled' => '1', 'points_per_minute' => '2', 'max_points_per_day' => '100', 'points_for_request' => '5', 'points_for_vote' => '2', 'points_for_giveaway_win' => '50', 'points_for_contest_win' => '100', 'radio_shouts_enabled' => '1', 'radio_now_playing_enabled' => '1', 'radio_listeners_enabled' => '1', 'radio_show_current_dj' => '1', 'radio_widget_enabled' => '1', 'radio_widget_show_globally' => '1', 'radio_widget_position' => 'bottom-right', 'radio_applications_enabled' => '1', 'radio_auto_dj_detection' => '1', 'radio_monitoring_enabled' => '1', 'radio_monitoring_timeout' => '5', 'radio_stream_fallback_url' => '', 'radio_stream_backup_enabled' => '0', 'radio_show_song_history' => '1', 'radio_show_schedule_preview' => '1', 'radio_max_history_items' => '10', 'radio_social_links_enabled' => '1', 'radio_facebook_url' => '', 'radio_twitter_url' => '', 'radio_discord_url' => '', 'radio_instagram_url' => '', 'radio_youtube_url' => '', 'radio_twitch_url' => '', 'radio_word_filter_enabled' => '1', 'radio_max_shout_length' => '280', 'radio_shout_cooldown' => '30', 'radio_contests_enabled' => '1', 'radio_giveaways_enabled' => '1', 'radio_auto_contest_creation' => '0', ]; // Update all settings foreach ($settings as $key => $value) { WebsiteSetting::updateOrCreate( ['key' => $key], ['value' => $value, 'comment' => 'Auto-configured by All-in-One Setup'], ); } // Clear cache $this->clearCache(); // Reload form data $this->fillForm(); Notification::make() ->success() ->title(__('radio.setup.success_title')) ->body(__('radio.setup.success_body')) ->send(); } catch (\Exception $e) { Notification::make() ->danger() ->title(__('radio.setup.error_title')) ->body(__('radio.setup.error_body', ['message' => $e->getMessage()])) ->send(); } } }