import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/settings_provider.dart'; import '../providers/auth_provider.dart'; import '../services/api_service.dart'; class SettingsPage extends StatefulWidget { @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); 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) { 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(); 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: [ // User Profile Section _buildProfileSection(auth), SizedBox(height: 32), // Network Configuration _buildSectionTitle("Network Configuration"), 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)), ), ), 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)), ), ), ), SizedBox(height: 32), // Theme Color Section _buildSectionTitle("Theme Customization"), SizedBox(height: 16), Wrap( spacing: 12, runSpacing: 12, children: _availableColors.map((color) { bool isSelected = settings.themeColor.value == color.value; 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(), ), SizedBox(height: 32), // Security Section _buildSectionTitle("Security"), SizedBox(height: 16), TextField( controller: _oldPasswordController, obscureText: true, decoration: InputDecoration( labelText: "Old Password", prefixIcon: Icon(Icons.lock_outline), border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), ), ), SizedBox(height: 12), TextField( controller: _newPasswordController, obscureText: true, decoration: InputDecoration( labelText: "New Password", prefixIcon: Icon(Icons.lock_reset), border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), ), ), SizedBox(height: 12), SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: _handleChangePassword, icon: Icon(Icons.update), label: Text("Change Password"), style: OutlinedButton.styleFrom( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ), ), SizedBox(height: 40), // About Section Divider(), 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-beta3.5", style: TextStyle(color: Colors.grey)), Text("Author: Highground-Soft & Minimax", style: TextStyle(color: Colors.grey)), SizedBox(height: 20), Text("© 2026 Hightube Project", style: TextStyle(fontSize: 12, color: Colors.grey)), ], ), ), 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: EdgeInsets.all(20), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surfaceVariant, 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), ), ), 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), ), ], ), ), IconButton( onPressed: () => auth.logout(), icon: Icon(Icons.logout, color: Colors.redAccent), tooltip: "Logout", ), ], ), ); } }