import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../models/language.dart'; import '../models/history_item.dart'; import '../services/settings_service.dart'; import '../services/translate_service.dart'; import '../services/history_service.dart'; import 'settings_screen.dart'; import 'history_screen.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State { final _settingsService = SettingsService(); late final TranslateService _translateService = TranslateService(_settingsService); final _historyService = HistoryService(); final _sourceController = TextEditingController(); Timer? _debounce; List _languages = []; Language _sourceLang = Language.auto; Language _targetLang = const Language(code: 'en', name: 'İngilizce'); String _resultText = ''; String? _detectedLangLabel; bool _loadingLanguages = true; bool _translating = false; String? _connectionError; @override void initState() { super.initState(); _bootstrap(); _sourceController.addListener(_onTextChanged); } @override void dispose() { _debounce?.cancel(); _sourceController.dispose(); super.dispose(); } /// Uygulama açılışında sunucuya otomatik bağlanmayı dener. Future _bootstrap() async { final hasSettings = await _settingsService.hasSettings(); if (!hasSettings) { final saved = await Navigator.of(context).push( MaterialPageRoute(builder: (_) => const SettingsScreen(isFirstRun: true)), ); if (saved != true) { // Kullanıcı ayarları kaydetmeden geri döndüyse yine de tekrar dene. } } await _loadLanguages(); } Future _loadLanguages() async { setState(() { _loadingLanguages = true; _connectionError = null; }); try { final langs = await _translateService.fetchLanguages(); setState(() { _languages = langs; // Hedef dil listede yoksa ilk uygun dile düş. if (!_languages.any((l) => l.code == _targetLang.code) && _languages.isNotEmpty) { _targetLang = _languages.firstWhere((l) => l.code != 'auto', orElse: () => _languages.first); } }); } catch (e) { setState(() => _connectionError = e.toString()); } finally { setState(() => _loadingLanguages = false); } } void _onTextChanged() { _debounce?.cancel(); _debounce = Timer(const Duration(milliseconds: 600), _runTranslate); } Future _runTranslate() async { final text = _sourceController.text; if (text.trim().isEmpty) { setState(() { _resultText = ''; _detectedLangLabel = null; }); return; } setState(() => _translating = true); try { String effectiveSource = _sourceLang.code; if (_sourceLang.code == 'auto') { final detected = await _translateService.detect(text); if (detected != null) { effectiveSource = detected.language; final match = _languages.firstWhere( (l) => l.code == detected.language, orElse: () => Language(code: detected.language, name: detected.language), ); setState(() => _detectedLangLabel = 'Algılanan dil: ${match.name}'); } } else { _detectedLangLabel = null; } final translated = await _translateService.translate( text: text, sourceLang: effectiveSource, targetLang: _targetLang.code, ); if (!mounted) return; setState(() => _resultText = translated); await _historyService.add(HistoryItem( sourceLang: effectiveSource, targetLang: _targetLang.code, sourceText: text, translatedText: translated, timestamp: DateTime.now(), )); } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Çeviri hatası: $e')), ); } finally { if (mounted) setState(() => _translating = false); } } void _swapLanguages() { if (_sourceLang.code == 'auto') return; // otomatik iken takas anlamsız setState(() { final tmp = _sourceLang; _sourceLang = _targetLang; _targetLang = tmp; final tmpText = _sourceController.text; _sourceController.text = _resultText; _resultText = tmpText; }); } List get _sourceOptions => [Language.auto, ..._languages]; List get _targetOptions => _languages; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Çeviri'), actions: [ IconButton( tooltip: 'Geçmiş', icon: const Icon(Icons.history), onPressed: () => Navigator.of(context).push( MaterialPageRoute(builder: (_) => const HistoryScreen()), ), ), IconButton( tooltip: 'Ayarlar', icon: const Icon(Icons.settings_outlined), onPressed: () async { await Navigator.of(context).push( MaterialPageRoute(builder: (_) => const SettingsScreen()), ); _loadLanguages(); }, ), ], ), body: _loadingLanguages ? const Center(child: CircularProgressIndicator()) : _connectionError != null ? _buildConnectionError() : _buildTranslator(), ); } Widget _buildConnectionError() { return Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.cloud_off, size: 48, color: Colors.grey), const SizedBox(height: 16), Text('Sunucuya bağlanılamadı', style: Theme.of(context).textTheme.titleMedium), const SizedBox(height: 8), Text(_connectionError!, textAlign: TextAlign.center), const SizedBox(height: 20), Wrap( spacing: 12, children: [ OutlinedButton(onPressed: _loadLanguages, child: const Text('Tekrar Dene')), FilledButton( onPressed: () async { await Navigator.of(context).push( MaterialPageRoute(builder: (_) => const SettingsScreen()), ); _loadLanguages(); }, child: const Text('Ayarları Aç'), ), ], ), ], ), ), ); } Widget _buildTranslator() { return Padding( padding: const EdgeInsets.all(16), child: Column( children: [ _buildLanguageBar(), const SizedBox(height: 12), Expanded( child: Column( children: [ Expanded(child: _buildInputCard()), const SizedBox(height: 12), Expanded(child: _buildResultCard()), ], ), ), ], ), ); } Widget _buildLanguageBar() { return Row( children: [ Expanded(child: _buildLangDropdown(isSource: true)), IconButton( icon: const Icon(Icons.swap_horiz), tooltip: 'Dilleri değiştir', onPressed: _sourceLang.code == 'auto' ? null : _swapLanguages, ), Expanded(child: _buildLangDropdown(isSource: false)), ], ); } Widget _buildLangDropdown({required bool isSource}) { final options = isSource ? _sourceOptions : _targetOptions; final value = isSource ? _sourceLang : _targetLang; return DropdownButtonFormField( isExpanded: true, value: options.contains(value) ? value : null, decoration: const InputDecoration(isDense: true), items: options .map((l) => DropdownMenuItem(value: l, child: Text(l.name, overflow: TextOverflow.ellipsis))) .toList(), onChanged: (l) { if (l == null) return; setState(() { if (isSource) { _sourceLang = l; } else { _targetLang = l; } }); _runTranslate(); }, ); } Widget _buildInputCard() { return Card( margin: EdgeInsets.zero, child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( child: TextField( controller: _sourceController, maxLines: null, expands: true, textAlignVertical: TextAlignVertical.top, decoration: const InputDecoration( border: InputBorder.none, hintText: 'Çevrilecek metni yazın...', ), ), ), if (_detectedLangLabel != null) Padding( padding: const EdgeInsets.only(top: 4), child: Text(_detectedLangLabel!, style: Theme.of(context).textTheme.bodySmall), ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ IconButton( icon: const Icon(Icons.clear, size: 20), tooltip: 'Temizle', onPressed: () => _sourceController.clear(), ), ], ), ], ), ), ); } Widget _buildResultCard() { return Card( margin: EdgeInsets.zero, color: Theme.of(context).colorScheme.surfaceContainerHighest, child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( child: _translating ? const Center(child: CircularProgressIndicator()) : SingleChildScrollView( child: SelectableText( _resultText, style: Theme.of(context).textTheme.bodyLarge, ), ), ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ IconButton( icon: const Icon(Icons.copy, size: 20), tooltip: 'Kopyala', onPressed: _resultText.isEmpty ? null : () { Clipboard.setData(ClipboardData(text: _resultText)); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Kopyalandı'), duration: Duration(seconds: 1)), ); }, ), ], ), ], ), ), ); } }