import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../utils/translations.dart'; class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { List _cameraIPs = List.generate(6, (index) => 'Not Set'); final List _defaultIPs = [ '192.168.0.134:9081', '192.168.0.134:9082', '192.168.0.134:9083', '192.168.0.134:9084', '192.168.0.134:9085', '192.168.0.134:9086', ]; String _selectedBulletColor = 'Blue'; final List _bulletColors = [ 'Blue', 'Green', 'Yellow', 'Purple', 'Cyan', 'Teal', 'Indigo', 'Pink', 'Lime', 'Mint', 'Orange', 'Violet', 'Amber', 'Brown', 'Grey', ]; String _selectedLanguage = 'English'; final List> _languages = [ {'code': 'en', 'name': 'English', 'flag': '🇬🇧'}, {'code': 'sl', 'name': 'Slovenian', 'flag': '🇸🇮'}, ]; @override void initState() { super.initState(); _loadCameraIPs(); _loadBulletColor(); _loadLanguage(); } String _t(String key) { return AppTranslations.translate(key, _selectedLanguage); } Color _getColorFromName(String colorName) { switch (colorName.toLowerCase()) { case 'blue': return Colors.blue; case 'green': return Colors.green; case 'yellow': return Colors.yellow; case 'purple': return Colors.purple; case 'cyan': return Colors.cyan; case 'teal': return Colors.teal; case 'indigo': return Colors.indigo; case 'pink': return Colors.pink; case 'lime': return Colors.lime; case 'mint': return Colors.greenAccent; case 'orange': return Colors.orange; case 'violet': return Colors.deepPurpleAccent; case 'amber': return Colors.amber; case 'brown': return Colors.brown; case 'grey': return Colors.grey; default: return Colors.blue; // fallback } } Future _loadBulletColor() async { final prefs = await SharedPreferences.getInstance(); String savedColor = prefs.getString('bulletColor') ?? 'Blue'; // Fallback in case old color is no longer valid if (!_bulletColors.contains(savedColor)) { savedColor = 'Blue'; await prefs.setString('bulletColor', savedColor); } setState(() { _selectedBulletColor = savedColor; }); } Future _saveBulletColor(String color) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('bulletColor', color); setState(() => _selectedBulletColor = color); } Future _loadLanguage() async { final prefs = await SharedPreferences.getInstance(); String savedLanguage = prefs.getString('language') ?? 'English'; setState(() { _selectedLanguage = savedLanguage; }); } Future _saveLanguage(String language) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('language', language); setState(() => _selectedLanguage = language); } Future _loadCameraIPs() async { final prefs = await SharedPreferences.getInstance(); List tempIPs = []; for (int i = 0; i < 6; i++) { String key = 'cameraIP_${i + 1}'; String? savedIP = prefs.getString(key); // If not saved, use default and write it to prefs if (savedIP == null) { await prefs.setString(key, _defaultIPs[i]); tempIPs.add(_defaultIPs[i]); } else { tempIPs.add(savedIP); } } setState(() { _cameraIPs = tempIPs; }); } Future _saveCameraIP(int index, String ip) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('cameraIP_${index + 1}', ip); _loadCameraIPs(); } Future _clearCameraIP(int index) async { final prefs = await SharedPreferences.getInstance(); await prefs.remove('cameraIP_${index + 1}'); _loadCameraIPs(); } void _editCameraIP(int index) { TextEditingController controller = TextEditingController( text: _cameraIPs[index], ); showDialog( context: context, builder: (context) { return Dialog( backgroundColor: Colors.grey[900], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(24.0), child: StatefulBuilder( builder: (context, setState) { return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "${_t('Camera')} ${index + 1}", style: const TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), const SizedBox(height: 16), SizedBox( width: double.infinity, child: TextField( controller: controller, style: const TextStyle(color: Colors.white), textAlign: TextAlign.center, decoration: InputDecoration( filled: true, fillColor: Colors.grey[800], hintText: _t("Enter Camera IP"), hintStyle: const TextStyle(color: Colors.white54), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: _getColorFromName(_selectedBulletColor)), ), ), ), ), const SizedBox(height: 24), // Save Button SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () async { String newIP = controller.text.trim(); if (newIP.isNotEmpty) { await _saveCameraIP(index, newIP); if (context.mounted) { Navigator.pop(context); } } }, style: ElevatedButton.styleFrom( backgroundColor: _getColorFromName(_selectedBulletColor), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text(_t("Save")), ), ), const SizedBox(height: 12), // Reset Button SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () async { await _clearCameraIP(index); if (context.mounted) { Navigator.pop(context); } }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[700], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text(_t("Reset to Default")), ), ), const SizedBox(height: 12), // Cancel Button SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[800], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text(_t("Cancel")), ), ), ], ); }, ), ), ); }, ); } @override Widget build(BuildContext context) { return Scaffold( body: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Column( children: [ const SizedBox(height: 8), _buildLanguageSelector(), const SizedBox(height: 16), _buildBulletColorSelector(), const SizedBox(height: 16), _buildCameraList(), ], ), ), ); } Widget _buildLanguageSelector() { final selectedLang = _languages.firstWhere( (lang) => lang['name'] == _selectedLanguage, orElse: () => _languages[0], ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _t("Language"), style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87, ), ), const SizedBox(height: 8), GestureDetector( onTap: _showLanguagePopup, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Text( selectedLang['flag'] ?? '🌐', style: const TextStyle(fontSize: 20), ), const SizedBox(width: 12), Expanded( child: Text( _t(selectedLang['name'] ?? 'English'), style: const TextStyle(color: Colors.black87, fontSize: 14), ), ), const Icon(Icons.chevron_right, color: Colors.black54), ], ), ), ), ], ); } Widget _buildBulletColorSelector() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _t("Select Bullet Color"), style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87, ), ), const SizedBox(height: 8), GestureDetector( onTap: _showBulletColorPopup, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Container( width: 16, height: 16, margin: const EdgeInsets.only(right: 12), decoration: BoxDecoration( color: _getColorFromName(_selectedBulletColor), shape: BoxShape.circle, border: Border.all(color: Colors.black26), ), ), Expanded( child: Text( _t(_selectedBulletColor), style: const TextStyle(color: Colors.black87, fontSize: 14), ), ), const Icon(Icons.chevron_right, color: Colors.black54), ], ), ), ), ], ); } void _showLanguagePopup() { showDialog( context: context, builder: (context) { return Dialog( backgroundColor: Colors.grey[900], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( _t("Select Language"), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 20), ..._languages.map((lang) { final isSelected = lang['name'] == _selectedLanguage; return Padding( padding: const EdgeInsets.only(bottom: 12.0), child: SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () async { await _saveLanguage(lang['name']!); if (context.mounted) { Navigator.of(context).pop(); } }, style: ElevatedButton.styleFrom( backgroundColor: isSelected ? _getColorFromName(_selectedBulletColor) : Colors.grey[800], foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( lang['flag']!, style: const TextStyle(fontSize: 20), ), const SizedBox(width: 12), Text( _t(lang['name']!), style: const TextStyle(fontSize: 16), ), ], ), ), ), ); }), const SizedBox(height: 8), TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(_t("Cancel"), style: const TextStyle(color: Colors.white70)), ), ], ), ), ); }, ); } void _showBulletColorPopup() { showDialog( context: context, builder: (context) { return Dialog( backgroundColor: Colors.grey[900], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( _t("Select Bullet Color"), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 20), Wrap( spacing: 12, runSpacing: 12, children: _bulletColors.map((colorName) { final color = _getColorFromName(colorName); final isSelected = colorName == _selectedBulletColor; return GestureDetector( onTap: () async { await _saveBulletColor(colorName); if (context.mounted) { Navigator.of(context).pop(); } }, child: Container( width: 48, height: 48, decoration: BoxDecoration( color: color, shape: BoxShape.circle, border: Border.all( color: isSelected ? Colors.white : Colors.white24, width: isSelected ? 3 : 1, ), ), ), ); }).toList(), ), const SizedBox(height: 20), TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(_t("Cancel"), style: const TextStyle(color: Colors.white70)), ), ], ), ), ); }, ); } Widget _buildCameraList() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _t("Camera Settings"), style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87, ), ), const SizedBox(height: 8), ...List.generate(6, (index) { return GestureDetector( onTap: () => _editCameraIP(index), child: Container( margin: const EdgeInsets.symmetric(vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(12), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${_t('Camera')} ${index + 1}", style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.black87, ), ), Text( _cameraIPs[index], style: const TextStyle(color: Colors.black54), ), ], ), const Icon(Icons.chevron_right, color: Colors.black45), ], ), ), ); }), ], ); } }