import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../cekirdek/kimlik.dart'; import '../../modeller/segment.dart'; import '../../modeller/wangp_ayarlari.dart'; import '../../modeller/wangp_profili.dart'; import '../../servisler/wangp/wangp_profilleri.dart'; import '../ortak/lora_yoneticisi_modal.dart'; import 'wangp_video_sihirbazi.dart'; /// WanGP profil seçici — Inspector'da gelişmiş panelin üstünde. /// /// - Hazır profiller (4090 Ultra, 16GB Dengeli, vb.) tek tıkla uygulanır /// - "Mevcut ayarı kaydet" → kullanıcı profilini Hive'a yazar /// - Profilleri yönet → silme/yeniden adlandırma class WanGpProfilSecici extends ConsumerStatefulWidget { final Segment segment; final void Function(Segment Function(Segment)) guncelle; const WanGpProfilSecici({ super.key, required this.segment, required this.guncelle, }); @override ConsumerState createState() => _WanGpProfilSeciciState(); } class _WanGpProfilSeciciState extends ConsumerState { List _profiller = const []; bool _yukleniyor = true; String? _aktifProfilId; @override void initState() { super.initState(); _profilleriYukle(); } @override void didUpdateWidget(WanGpProfilSecici eski) { super.didUpdateWidget(eski); // Segment değişti → aktif profil vurgusu sıfırlansın (eski segmentin // profilini yeni segment için göstermek yanıltıcı) if (eski.segment.id != widget.segment.id) { _aktifProfilId = null; } } Future _profilleriYukle() async { setState(() => _yukleniyor = true); final liste = await WanGpProfilServisi.liste(); if (!mounted) return; setState(() { _profiller = liste; _yukleniyor = false; }); } void _profilUygula(WanGpProfili p) { // Profil-seviyesi alanları (vramSafetyCoefficient) ozelAlanlar'a taşı ki // orchestrator settings birleştirmesinde okuyabilsin (asıl WanGpAyarlari // bu alanı içermiyor). final ekAlanlar = { ...p.ayarlar.ozelAlanlar, if (p.vramSafetyCoefficient != null) 'vram_safety_coefficient': p.vramSafetyCoefficient, }; final tamAyar = p.ayarlar.copyWith(ozelAlanlar: ekAlanlar); widget.guncelle((s) => s.copyWith(wangpAyarlari: tamAyar)); setState(() => _aktifProfilId = p.id); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('"${p.ad}" profili uygulandı'), duration: const Duration(seconds: 2), ), ); } } Future _mevcutuKaydet() async { final mevcut = widget.segment.wangpAyarlari; if (mevcut == null) { _bildirim('Önce ayar yap, sonra kaydet'); return; } final ad = await _adSor(context, baslangic: 'Yeni Profil'); if (ad == null || ad.trim().isEmpty) return; final profil = WanGpProfili( id: 'usr_${FikoYTId.yeni()}', ad: ad.trim(), aciklama: 'Kullanıcı tanımlı', hedefDonanim: '', ayarlar: mevcut, olusturma: DateTime.now(), ); await WanGpProfilServisi.kaydet(profil); await _profilleriYukle(); setState(() => _aktifProfilId = profil.id); _bildirim('"${profil.ad}" kaydedildi'); } Future _profilleriYonet() async { // Sadece kullanıcı profilleri — sistem profilleri silinemediği için // yönet dialog'unda göstermek kafa karıştırıcı. final kullaniciProfilleri = _profiller.where((p) => !p.sistemiMi).toList(); await showDialog( context: context, builder: (ctx) => _ProfillerYonetDialog( profiller: kullaniciProfilleri, onSilindi: (id) async { await WanGpProfilServisi.sil(id); await _profilleriYukle(); }, ), ); } void _bildirim(String mesaj) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(mesaj), duration: const Duration(seconds: 2)), ); } Future _adSor(BuildContext ctx, {required String baslangic}) async { final ctrl = TextEditingController(text: baslangic); return showDialog( context: ctx, builder: (c) => AlertDialog( title: const Text('Profil adı'), content: TextField( controller: ctrl, autofocus: true, decoration: const InputDecoration(hintText: 'Örn: Benim 4090 Ayarım'), ), actions: [ TextButton( onPressed: () => Navigator.pop(c), child: const Text('İptal')), FilledButton( onPressed: () => Navigator.pop(c, ctrl.text), child: const Text('Kaydet')), ], ), ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final cs = theme.colorScheme; if (_yukleniyor) { return const Padding( padding: EdgeInsets.symmetric(vertical: 8), child: LinearProgressIndicator(minHeight: 2), ); } final sistem = _profiller.where((p) => p.sistemiMi).toList(); final kullanici = _profiller.where((p) => !p.sistemiMi).toList(); return Card( margin: const EdgeInsets.symmetric(vertical: 8), color: cs.secondaryContainer.withValues(alpha: 0.25), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide(color: cs.secondary.withValues(alpha: 0.3)), ), child: Padding( padding: const EdgeInsets.all(10), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ Icon(Icons.tune, size: 16, color: cs.secondary), const SizedBox(width: 6), Expanded( child: Text( 'WanGP Profil / Şablon', style: theme.textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w700, ), ), ), IconButton( icon: const Icon(Icons.auto_fix_high, size: 18), tooltip: 'Video Üretim Sihirbazı (detaylı seçim ile)', onPressed: () => WanGpVideoSihirbazi.goster( context, segment: widget.segment, guncelle: widget.guncelle, ), ), IconButton( icon: const Icon(Icons.bookmark_add_outlined, size: 18), tooltip: 'Video LoRA Yöneticisi (indir/yönet)', onPressed: () => LoraYoneticisiModal.goster(context, LoraModulu.video), ), IconButton( icon: const Icon(Icons.save_outlined, size: 18), tooltip: 'Mevcut ayarı yeni profil olarak kaydet', onPressed: _mevcutuKaydet, ), IconButton( icon: const Icon(Icons.settings_outlined, size: 18), tooltip: 'Profilleri yönet', onPressed: _profilleriYonet, ), ], ), const SizedBox(height: 6), Text( 'Hazır profillerden birini seç veya kendi ayarını kaydet. ' 'Tıklayınca tüm gelişmiş alanlar tek seferde dolar.', style: theme.textTheme.labelSmall ?.copyWith(color: cs.onSurfaceVariant), ), const SizedBox(height: 8), // Sistem profilleri if (sistem.isNotEmpty) ...[ Text('HAZIR PROFİLLER', style: theme.textTheme.labelSmall?.copyWith( fontWeight: FontWeight.w700, color: cs.outline, letterSpacing: 0.5, )), const SizedBox(height: 4), Wrap( spacing: 6, runSpacing: 6, children: sistem .map((p) => _profilCipi(p, theme, sistemMi: true)) .toList(), ), ], // Kullanıcı profilleri if (kullanici.isNotEmpty) ...[ const SizedBox(height: 10), Text('KAYITLI ŞABLONLARIM', style: theme.textTheme.labelSmall?.copyWith( fontWeight: FontWeight.w700, color: cs.outline, letterSpacing: 0.5, )), const SizedBox(height: 4), Wrap( spacing: 6, runSpacing: 6, children: kullanici .map((p) => _profilCipi(p, theme, sistemMi: false)) .toList(), ), ], ], ), ), ); } Widget _profilCipi(WanGpProfili p, ThemeData theme, {required bool sistemMi}) { final aktif = _aktifProfilId == p.id; final cs = theme.colorScheme; return Tooltip( message: '${p.ad}\n${p.aciklama}' '${p.hedefDonanim.isNotEmpty ? '\n→ ${p.hedefDonanim}' : ''}', child: ActionChip( avatar: Icon( sistemMi ? Icons.auto_awesome : Icons.bookmark, size: 14, color: aktif ? cs.onPrimary : cs.primary, ), label: Text( p.ad, style: TextStyle( fontSize: 11, fontWeight: aktif ? FontWeight.w700 : FontWeight.normal, color: aktif ? cs.onPrimary : null, ), ), backgroundColor: aktif ? cs.primary : null, onPressed: () => _profilUygula(p), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, ), ); } } class _ProfillerYonetDialog extends StatefulWidget { final List profiller; final Future Function(String id) onSilindi; const _ProfillerYonetDialog({ required this.profiller, required this.onSilindi, }); @override State<_ProfillerYonetDialog> createState() => _ProfillerYonetDialogState(); } class _ProfillerYonetDialogState extends State<_ProfillerYonetDialog> { late List _liste; @override void initState() { super.initState(); _liste = List.of(widget.profiller); } @override Widget build(BuildContext context) { return AlertDialog( title: const Text('Profilleri Yönet'), content: SizedBox( width: 480, height: 400, child: ListView.builder( itemCount: _liste.length, itemBuilder: (c, i) { final p = _liste[i]; return ListTile( dense: true, leading: Icon( p.sistemiMi ? Icons.auto_awesome : Icons.bookmark, size: 18, color: p.sistemiMi ? Colors.amber : Colors.blue, ), title: Text(p.ad, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600)), subtitle: Text( '${p.aciklama}' '${p.hedefDonanim.isNotEmpty ? ' • ${p.hedefDonanim}' : ''}', style: const TextStyle(fontSize: 11), ), trailing: p.sistemiMi ? const Tooltip( message: 'Sistem profili — silinemez', child: Icon(Icons.lock_outline, size: 16)) : IconButton( icon: const Icon(Icons.delete_outline, size: 18), onPressed: () async { await widget.onSilindi(p.id); setState(() => _liste.removeWhere((x) => x.id == p.id)); }, ), ); }, ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Kapat')), ], ); } }