import 'package:flutter/material.dart'; import '../app/tasarim.dart'; import '../app/tema.dart'; export 'negatif_sihirbazi.dart'; /// FikoYT Stüdyo merkezi UI bileşenleri — Atomic Design organizma/molekül katmanı. /// Denetim bulgusu: _UstBar 6, _UretButonu 4, kart kalıbı N dosyada kopyalanmış. /// Bunlar tek doğruluk kaynağı; premium görünüm + kod tekrarsızlığı. /// PREMIUM KART — rim-light gradyan kenarlık + iç gradyan + pointer-takipli 3D /// tilt + hover glow. Oyun-UI estetiği. İçeriği [child] olarak alır. class FikoKart extends StatefulWidget { const FikoKart({ super.key, required this.child, this.accent, this.onTap, this.secili = false, this.padding = const EdgeInsets.all(FikoBosluk.md), this.tilt = true, }); final Widget child; /// Kimlik/vurgu rengi — köşe vurgusu + seçili glow (yoksa marka moru). final Color? accent; final VoidCallback? onTap; final bool secili; final EdgeInsets padding; /// Pointer-takipli 3D eğim efekti (yoğun listelerde kapatılabilir). final bool tilt; @override State createState() => _FikoKartState(); } class _FikoKartState extends State { bool _hover = false; Offset _merkezSapma = Offset.zero; // -1..1 normalize void _hoverGuncelle(PointerEvent e, Size boyut) { if (!widget.tilt) return; final dx = (e.localPosition.dx / boyut.width - 0.5) * 2; final dy = (e.localPosition.dy / boyut.height - 0.5) * 2; setState(() => _merkezSapma = Offset(dx.clamp(-1, 1), dy.clamp(-1, 1))); } @override Widget build(BuildContext context) { final koyu = Theme.of(context).brightness == Brightness.dark; final accent = widget.accent ?? FikoRenkler.neonMor; final yuzey = Theme.of(context).cardColor; final cizgi = Theme.of(context).dividerColor; final aktif = _hover || widget.secili; // Hover 3D eğim (±~2.3°). final tiltX = widget.tilt ? -_merkezSapma.dy * 0.04 : 0.0; final tiltY = widget.tilt ? _merkezSapma.dx * 0.04 : 0.0; final donus = Matrix4.identity() ..setEntry(3, 2, 0.0011) ..rotateX(_hover ? tiltX : 0) ..rotateY(_hover ? tiltY : 0); return LayoutBuilder(builder: (context, kis) { final boyut = Size(kis.maxWidth, kis.maxHeight); return MouseRegion( onEnter: (_) => setState(() => _hover = true), onExit: (_) => setState(() { _hover = false; _merkezSapma = Offset.zero; }), onHover: (e) => _hoverGuncelle(e, boyut), cursor: widget.onTap != null ? SystemMouseCursors.click : MouseCursor.defer, child: GestureDetector( onTap: widget.onTap, child: AnimatedContainer( duration: FikoHareket.kisa, curve: FikoHareket.standart, transform: donus, transformAlignment: Alignment.center, decoration: BoxDecoration( borderRadius: FikoYaricap.rMd, boxShadow: [ ...(aktif ? FikoGolge.hover(koyu) : FikoGolge.kart(koyu)), if (aktif) ...FikoGolge.glow(accent, guc: 0.22, yaricap: 22), ], ), // Rim-light gradyan kenarlık (1px) — düz kenarlık yerine. child: Container( padding: const EdgeInsets.all(1), decoration: BoxDecoration( borderRadius: FikoYaricap.rMd, gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: aktif ? [accent.withValues(alpha: 0.85), accent.withValues(alpha: 0.2)] : [ Colors.white.withValues(alpha: koyu ? 0.10 : 0.55), cizgi.withValues(alpha: 0.6), ], ), ), child: Container( padding: widget.padding, decoration: BoxDecoration( borderRadius: BorderRadius.circular(FikoYaricap.md - 1), // İç dikey gradyan — hafif derinlik. gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ yuzey, Color.alphaBlend(Colors.black.withValues(alpha: 0.05), yuzey), ], ), ), child: widget.child, ), ), ), ), ); }); } } /// PREMIUM ÜRET BUTONU — gradyan + glow + basınç (press scale) + inline yükleme. /// Mikro-etkileşim anatomisi (tetik→anticipation→geri bildirim). class FikoUretButonu extends StatefulWidget { const FikoUretButonu({ super.key, required this.etiket, required this.onBas, this.ikon = Icons.play_arrow_rounded, this.renkler = const [FikoRenkler.neonMor, FikoRenkler.neonPembe], this.yogun = false, }); final String etiket; /// Asenkron üretim çağrısı — sürerken buton içinde spinner gösterilir. final Future Function() onBas; final IconData ikon; final List renkler; final bool yogun; @override State createState() => _FikoUretButonuState(); } class _FikoUretButonuState extends State { bool _basili = false; bool _calisiyor = false; Future _calistir() async { if (_calisiyor) return; setState(() => _calisiyor = true); try { await widget.onBas(); } finally { if (mounted) setState(() => _calisiyor = false); } } @override Widget build(BuildContext context) { return GestureDetector( onTapDown: (_) => setState(() => _basili = true), onTapUp: (_) => setState(() => _basili = false), onTapCancel: () => setState(() => _basili = false), onTap: _calistir, child: AnimatedScale( scale: _basili ? 0.95 : 1.0, duration: FikoHareket.aninda, curve: FikoHareket.standart, child: AnimatedContainer( duration: FikoHareket.kisa, padding: EdgeInsets.symmetric( horizontal: widget.yogun ? 12 : 16, vertical: 10), decoration: BoxDecoration( borderRadius: FikoYaricap.rMd, gradient: LinearGradient(colors: widget.renkler), boxShadow: FikoGolge.glow(widget.renkler.first, guc: _basili ? 0.5 : 0.35, yaricap: _basili ? 18 : 14), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ if (_calisiyor) const SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white), ) else Icon(widget.ikon, size: 18, color: Colors.white), const SizedBox(width: 7), Text(widget.etiket, style: const TextStyle( fontWeight: FontWeight.w800, fontSize: 13, color: Colors.white)), ], ), ), ), ); } } /// JENERİK ÜST BAR — ikon + başlık (+ kimlik şeridi) + eylemler. /// 6 ekrandaki kopyalanmış _UstBar yerine. class FikoUstBar extends StatelessWidget { const FikoUstBar({ super.key, required this.ikon, required this.baslik, required this.renk, this.solEylemler = const [], this.eylemler = const [], }); final IconData ikon; final String baslik; final Color renk; /// Başlığın hemen sağındaki öğeler (görünüm seçici vb.). final List solEylemler; /// Spacer sonrası sağ öğeler (geçmiş, sihirbaz, üret butonu vb.). final List eylemler; @override Widget build(BuildContext context) { return Row( children: [ Icon(ikon, color: renk, size: 20), const SizedBox(width: FikoBosluk.sm), Text(baslik, style: FikoTipo.baslikM), if (solEylemler.isNotEmpty) const SizedBox(width: FikoBosluk.md), ...solEylemler, const Spacer(), ...eylemler, ], ); } } /// SİHİRBAZ DIALOG — prompt/negatif sihirbazlarını dialog içinde barındırır /// (inline yer kaplamasın). İçerik form state'i canlı günceller; "Bitti" kapatır. Future sihirbazDialogAc( BuildContext context, { required String baslik, required Widget icerik, IconData ikon = Icons.auto_fix_high_rounded, Color renk = FikoRenkler.neonMor, double genislik = 780, }) { return showDialog( context: context, barrierColor: Colors.black.withValues(alpha: 0.55), builder: (ctx) { final tema = Theme.of(ctx); return Dialog( backgroundColor: tema.canvasColor, insetPadding: const EdgeInsets.all(FikoBosluk.xl), shape: RoundedRectangleBorder( borderRadius: FikoYaricap.rLg, side: BorderSide(color: tema.dividerColor), ), child: ConstrainedBox( constraints: BoxConstraints( maxWidth: genislik, maxHeight: MediaQuery.of(ctx).size.height * 0.86, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.fromLTRB( FikoBosluk.lg, FikoBosluk.md, FikoBosluk.sm, FikoBosluk.sm), child: Row(children: [ Icon(ikon, color: renk, size: 20), const SizedBox(width: FikoBosluk.sm), Expanded(child: Text(baslik, style: FikoTipo.baslikM)), IconButton( tooltip: 'Kapat', icon: const Icon(Icons.close_rounded, size: 20), onPressed: () => Navigator.of(ctx).pop(), ), ]), ), Divider(height: 1, color: tema.dividerColor), Flexible( child: SingleChildScrollView( padding: const EdgeInsets.all(FikoBosluk.lg), child: icerik, ), ), Divider(height: 1, color: tema.dividerColor), Padding( padding: const EdgeInsets.all(FikoBosluk.sm), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ FilledButton.icon( style: FilledButton.styleFrom(backgroundColor: renk), icon: const Icon(Icons.check_rounded, size: 18), label: const Text('Bitti'), onPressed: () => Navigator.of(ctx).pop(), ), ], ), ), ], ), ), ); }, ); } /// DURUM KATMANI SARMALAYICISI — hover + press scale + overlay. /// Mükerrer hover/press kodunu tek yere indirir (kart/çip/buton). class FikoEtkilesimli extends StatefulWidget { const FikoEtkilesimli({ super.key, required this.child, this.onTap, this.basincOlcek = 0.97, this.yaricap, }); final Widget child; final VoidCallback? onTap; final double basincOlcek; final BorderRadius? yaricap; @override State createState() => _FikoEtkilesimliState(); } class _FikoEtkilesimliState extends State { bool _basili = false; @override Widget build(BuildContext context) { return MouseRegion( cursor: widget.onTap != null ? SystemMouseCursors.click : MouseCursor.defer, child: GestureDetector( onTapDown: (_) => setState(() => _basili = true), onTapUp: (_) => setState(() => _basili = false), onTapCancel: () => setState(() => _basili = false), onTap: widget.onTap, child: AnimatedScale( scale: _basili ? widget.basincOlcek : 1.0, duration: FikoHareket.aninda, curve: FikoHareket.standart, child: widget.child, ), ), ); } }