import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/auth_provider.dart'; import '../providers/settings_provider.dart'; import '../services/api_service.dart'; class SettingsPage extends StatefulWidget { const SettingsPage({super.key}); @override _SettingsPageState createState() => _SettingsPageState(); } class _SettingsPageState extends State { late TextEditingController _urlController; final TextEditingController _oldPasswordController = TextEditingController(); final TextEditingController _newPasswordController = TextEditingController(); final List _availableColors = [ Colors.blue, Colors.deepPurple, Colors.red, Colors.green, Colors.orange, Colors.teal, Colors.pink, ]; @override void initState() { super.initState(); _urlController = TextEditingController( text: context.read().baseUrl, ); } @override void dispose() { _urlController.dispose(); _oldPasswordController.dispose(); _newPasswordController.dispose(); super.dispose(); } void _handleChangePassword() async { final settings = context.read(); final auth = context.read(); final api = ApiService(settings, auth.token); if (_oldPasswordController.text.isEmpty || _newPasswordController.text.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Please fill in both password fields")), ); return; } try { final resp = await api.changePassword( _oldPasswordController.text, _newPasswordController.text, ); if (!mounted) { return; } final data = jsonDecode(resp.body); if (resp.statusCode == 200) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Password updated successfully")), ); _oldPasswordController.clear(); _newPasswordController.clear(); } else { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text("Error: ${data['error']}"))); } } catch (e) { if (!mounted) { return; } ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text("Failed to connect to server"))); } } @override Widget build(BuildContext context) { final auth = context.watch(); final settings = context.watch(); final isAuthenticated = auth.isAuthenticated; return Scaffold( appBar: AppBar( title: Text("Settings", style: TextStyle(fontWeight: FontWeight.bold)), centerTitle: true, ), body: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (isAuthenticated) ...[ _buildProfileSection(auth), const SizedBox(height: 32), ], _buildSectionTitle("Network Configuration"), const SizedBox(height: 16), TextField( controller: _urlController, decoration: InputDecoration( labelText: "Backend Server URL", hintText: "http://127.0.0.1:8080", prefixIcon: Icon(Icons.lan), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), ), ), const SizedBox(height: 12), SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: () { context.read().setBaseUrl( _urlController.text, ); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text("Server URL Updated"), behavior: SnackBarBehavior.floating, ), ); }, icon: Icon(Icons.save), label: Text("Save Network Settings"), style: ElevatedButton.styleFrom( backgroundColor: Theme.of( context, ).colorScheme.primaryContainer, foregroundColor: Theme.of( context, ).colorScheme.onPrimaryContainer, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), const SizedBox(height: 32), _buildSectionTitle("Theme Customization"), const SizedBox(height: 16), Text( "Appearance Mode", style: Theme.of(context).textTheme.labelLarge, ), const SizedBox(height: 12), SegmentedButton( segments: const [ ButtonSegment( value: ThemeMode.system, label: Text("System"), icon: Icon(Icons.brightness_auto), ), ButtonSegment( value: ThemeMode.light, label: Text("Light"), icon: Icon(Icons.light_mode), ), ButtonSegment( value: ThemeMode.dark, label: Text("Dark"), icon: Icon(Icons.dark_mode), ), ], selected: {settings.themeMode}, onSelectionChanged: (selection) { settings.setThemeMode(selection.first); }, ), const SizedBox(height: 20), Text("Accent Color", style: Theme.of(context).textTheme.labelLarge), const SizedBox(height: 12), Wrap( spacing: 12, runSpacing: 12, children: _availableColors.map((color) { final isSelected = settings.themeColor.toARGB32() == color.toARGB32(); return GestureDetector( onTap: () => settings.setThemeColor(color), child: Container( width: 44, height: 44, decoration: BoxDecoration( color: color, shape: BoxShape.circle, border: isSelected ? Border.all( color: Theme.of(context).colorScheme.onSurface, width: 3, ) : null, boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 4, offset: Offset(0, 2), ), ], ), child: isSelected ? Icon(Icons.check, color: Colors.white) : null, ), ); }).toList(), ), if (isAuthenticated) ...[ const SizedBox(height: 32), _buildSectionTitle("Security"), const SizedBox(height: 16), TextField( controller: _oldPasswordController, obscureText: true, decoration: InputDecoration( labelText: "Old Password", prefixIcon: const Icon(Icons.lock_outline), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), ), ), const SizedBox(height: 12), TextField( controller: _newPasswordController, obscureText: true, decoration: InputDecoration( labelText: "New Password", prefixIcon: const Icon(Icons.lock_reset), border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), ), ), const SizedBox(height: 12), SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: _handleChangePassword, icon: const Icon(Icons.update), label: const Text("Change Password"), style: OutlinedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: FilledButton.tonalIcon( onPressed: auth.logout, icon: const Icon(Icons.logout), label: const Text("Logout"), style: FilledButton.styleFrom( foregroundColor: Colors.redAccent, padding: const EdgeInsets.symmetric(vertical: 14), ), ), ), ], const SizedBox(height: 40), const Divider(), const SizedBox(height: 20), Center( child: Column( children: [ Container( width: 60, height: 60, decoration: BoxDecoration( color: settings.themeColor, borderRadius: BorderRadius.circular(12), ), child: Center( child: Text( "H", style: TextStyle( color: Colors.white, fontSize: 32, fontWeight: FontWeight.bold, ), ), ), ), SizedBox(height: 12), Text( "Hightube", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), Text( "Version: 1.0.0-beta4.1", style: TextStyle(color: Colors.grey), ), Text( "Author: Highground-Soft", style: TextStyle(color: Colors.grey), ), SizedBox(height: 20), Text( "© 2026 Hightube Project", style: TextStyle(fontSize: 12, color: Colors.grey), ), ], ), ), const SizedBox(height: 40), ], ), ), ); } Widget _buildSectionTitle(String title) { return Text( title, style: Theme.of(context).textTheme.titleMedium?.copyWith( color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold, ), ); } Widget _buildProfileSection(AuthProvider auth) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(20), ), child: Row( children: [ CircleAvatar( radius: 35, backgroundColor: Theme.of(context).colorScheme.primary, child: Text( (auth.username ?? "U")[0].toUpperCase(), style: TextStyle( fontSize: 32, color: Colors.white, fontWeight: FontWeight.bold, ), ), ), const SizedBox(width: 20), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( auth.username ?? "Unknown User", style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), Text( "Self-hosted Streamer", style: TextStyle( color: Theme.of(context).colorScheme.outline, ), ), ], ), ), ], ), ); } }