import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:pasteboard/pasteboard.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; /// Karakter yüz seti yönetimi — hem karakter düzenle dialogu hem LoRA /// sayfasından çağrılabilir. Sonuç: kullanıcı dosya ekledi mi (true/false). Future yuzSetiDialogGoster( BuildContext ctx, { required String karakterId, required String karakterIsmi, }) async { final docs = await getApplicationDocumentsDirectory(); final klasor = Directory(p.join( docs.path, 'FikoYT-VideoStudyo', 'karakterler', '${karakterId}_set')); if (!await klasor.exists()) await klasor.create(recursive: true); bool degisti = false; if (!ctx.mounted) return false; await showDialog( context: ctx, builder: (dctx) => StatefulBuilder( builder: (dctx, setS) { final mevcut = klasor .listSync() .whereType() .where((f) { final ext = p.extension(f.path).toLowerCase(); return ['.png', '.jpg', '.jpeg', '.webp'].contains(ext); }) .toList(); return AlertDialog( title: Text('$karakterIsmi — Yüz Seti (${mevcut.length})'), content: SizedBox( width: 600, height: 460, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '10-20 farklı açıdan yüz fotoğrafı: önden, yandan, farklı ' 'ışık ve ifadelerde. LoRA eğitiminde bu fotoğraflar ' 'kullanılacak.', style: Theme.of(dctx).textTheme.labelSmall?.copyWith( color: Theme.of(dctx).colorScheme.outline, ), ), const SizedBox(height: 8), Row( children: [ OutlinedButton.icon( icon: const Icon(Icons.folder_open, size: 14), label: const Text('Dosya ekle'), onPressed: () async { final r = await FilePicker.platform.pickFiles( type: FileType.custom, allowMultiple: true, allowedExtensions: const [ 'png', 'jpg', 'jpeg', 'webp' ], ); if (r != null) { for (final f in r.files) { if (f.path == null) continue; final hedef = p.join(klasor.path, '${DateTime.now().millisecondsSinceEpoch}_${f.name}'); await File(f.path!).copy(hedef); } degisti = true; setS(() {}); } }, ), const SizedBox(width: 8), OutlinedButton.icon( icon: const Icon(Icons.content_paste, size: 14), label: const Text('Panodan ekle'), onPressed: () async { final bytes = await Pasteboard.image; if (bytes == null) return; final hedef = p.join(klasor.path, '${DateTime.now().millisecondsSinceEpoch}_pano.png'); await File(hedef).writeAsBytes(bytes); degisti = true; setS(() {}); }, ), const Spacer(), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.green.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(6), ), child: Text( '${klasor.path}', style: Theme.of(dctx).textTheme.labelSmall?.copyWith( fontFamily: 'monospace', fontSize: 9, color: Colors.green.shade800, ), ), ), ], ), const SizedBox(height: 8), Expanded( child: mevcut.isEmpty ? Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.add_photo_alternate_outlined, size: 48, color: Theme.of(dctx).colorScheme.outline), const SizedBox(height: 8), Text('Henüz fotoğraf yok', style: Theme.of(dctx) .textTheme .titleSmall ?.copyWith( color: Theme.of(dctx) .colorScheme .outline)), ], ), ) : GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 5, mainAxisSpacing: 6, crossAxisSpacing: 6, ), itemCount: mevcut.length, itemBuilder: (gctx, i) { final f = mevcut[i]; return Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(4), child: Image.file(f, fit: BoxFit.cover, width: double.infinity, height: double.infinity), ), Positioned( top: 2, right: 2, child: GestureDetector( onTap: () async { await f.delete(); degisti = true; setS(() {}); }, child: Container( decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), padding: const EdgeInsets.all(2), child: const Icon(Icons.close, size: 12, color: Colors.white), ), ), ), ], ); }, ), ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(dctx), child: const Text('Kapat'), ), ], ); }, ), ); return degisti; } /// Veri klasörünü hesapla (LoRA sayfası için) Future yuzSetiKlasoru(String karakterId) async { final docs = await getApplicationDocumentsDirectory(); return p.join( docs.path, 'FikoYT-VideoStudyo', 'karakterler', '${karakterId}_set'); }