import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../bilesenler/bilesenler.dart'; import 'kabuk.dart'; import 'komut.dart'; import 'tasarim.dart'; import 'tema.dart'; import '../veri/isar_servisi.dart'; /// GLOBAL KISAYOL KABUĞU — tüm uygulamayı sarar. Komut sistemiyle (komut.dart) /// birebir bağlı: Ctrl+K palet, Ctrl+1..0 ekran, Ctrl+L tema, F1/? yardım. class KisayolKabugu extends ConsumerWidget { const KisayolKabugu({super.key, required this.child}); final Widget child; @override Widget build(BuildContext context, WidgetRef ref) { void git(int i) { // Metin alanındayken Ctrl+1..0 ekran değiştirmesin. if (FocusManager.instance.primaryFocus?.context?.widget is EditableText) { return; } if (i >= 0 && i < kabukEkranlari.length) { ref.read(seciliEkranProvider.notifier).state = i; } } return Focus( autofocus: true, child: CallbackShortcuts( bindings: { const SingleActivator(LogicalKeyboardKey.keyK, control: true): () => komutPaletiniAc(context, ref), const SingleActivator(LogicalKeyboardKey.keyL, control: true): () => ref .read(ayarlarProvider.notifier) .guncelle((a) => a.koyuTema = !a.koyuTema), const SingleActivator(LogicalKeyboardKey.f1): () => kisayolYardimiAc(context, ref), const SingleActivator(LogicalKeyboardKey.slash, shift: true): () => kisayolYardimiAc(context, ref), const SingleActivator(LogicalKeyboardKey.digit1, control: true): () => git(0), const SingleActivator(LogicalKeyboardKey.digit2, control: true): () => git(1), const SingleActivator(LogicalKeyboardKey.digit3, control: true): () => git(2), const SingleActivator(LogicalKeyboardKey.digit4, control: true): () => git(3), const SingleActivator(LogicalKeyboardKey.digit5, control: true): () => git(4), const SingleActivator(LogicalKeyboardKey.digit6, control: true): () => git(5), const SingleActivator(LogicalKeyboardKey.digit7, control: true): () => git(6), const SingleActivator(LogicalKeyboardKey.digit8, control: true): () => git(7), const SingleActivator(LogicalKeyboardKey.digit9, control: true): () => git(8), const SingleActivator(LogicalKeyboardKey.digit0, control: true): () => git(9), }, child: child, ), ); } } /// Ctrl+K KOMUT PALETİ — fuzzy arama, klavye gezinme (↑/↓/Enter/Esc). Future komutPaletiniAc(BuildContext context, WidgetRef ref) { final komutlar = tumKomutlar(ref); return showGeneralDialog( context: context, barrierLabel: 'Komut Paleti', barrierDismissible: true, barrierColor: Colors.black.withValues(alpha: 0.45), transitionDuration: FikoHareket.kisa, // İçerik pageBuilder'da olmalı; transitionBuilder yalnız animasyon (yoksa // animasyon bitince palet kaybolur). pageBuilder: (_, _, _) => Align( alignment: const Alignment(0, -0.55), child: _KomutPaleti(komutlar: komutlar), ), transitionBuilder: (ctx, anim, _, child) { final egri = CurvedAnimation(parent: anim, curve: FikoHareket.cikis); return Opacity( opacity: egri.value, child: Transform.translate( offset: Offset(0, (1 - egri.value) * -12), child: child, ), ); }, ); } class _KomutPaleti extends StatefulWidget { const _KomutPaleti({required this.komutlar}); final List komutlar; @override State<_KomutPaleti> createState() => _KomutPaletiState(); } class _KomutPaletiState extends State<_KomutPaleti> { final _kontrol = TextEditingController(); final _kaydirma = ScrollController(); String _sorgu = ''; int _secili = 0; List get _filtre { final skorlu = widget.komutlar .map((k) => (k, k.eslesmeSkoru(_sorgu))) .where((e) => e.$2 > 0) .toList() ..sort((a, b) => b.$2.compareTo(a.$2)); return [for (final e in skorlu) e.$1]; } void _tasi(int yon) { final n = _filtre.length; if (n == 0) return; // Sarmalı gezinme (Dart % zaten non-negatif, yine de güvenli). setState(() => _secili = ((_secili + yon) % n + n) % n); } void _calistir(List liste) { if (liste.isEmpty) return; final komut = liste[_secili.clamp(0, liste.length - 1)]; Navigator.of(context).pop(); komut.calistir(); } @override void dispose() { _kontrol.dispose(); _kaydirma.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final liste = _filtre; final tema = Theme.of(context); return CallbackShortcuts( bindings: { const SingleActivator(LogicalKeyboardKey.arrowDown): () => _tasi(1), const SingleActivator(LogicalKeyboardKey.arrowUp): () => _tasi(-1), const SingleActivator(LogicalKeyboardKey.enter): () => _calistir(liste), const SingleActivator(LogicalKeyboardKey.escape): () => Navigator.of(context).maybePop(), }, child: Material( color: Colors.transparent, child: Container( width: 620, constraints: const BoxConstraints(maxHeight: 460), decoration: BoxDecoration( color: tema.canvasColor, borderRadius: FikoYaricap.rLg, border: Border.all(color: tema.dividerColor), boxShadow: [ ...FikoGolge.hover(tema.brightness == Brightness.dark), ...FikoGolge.glow(FikoRenkler.neonMor, guc: 0.18, yaricap: 32), ], ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Arama satırı. Padding( padding: const EdgeInsets.fromLTRB( FikoBosluk.lg, FikoBosluk.md, FikoBosluk.md, FikoBosluk.sm), child: Row( children: [ const Icon(Icons.bolt_rounded, color: FikoRenkler.neonMor, size: 22), const SizedBox(width: FikoBosluk.sm), Expanded( child: TextField( controller: _kontrol, autofocus: true, style: const TextStyle(fontSize: 15), decoration: const InputDecoration( border: InputBorder.none, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, filled: false, isDense: true, hintText: 'Komut ara… (ekran, tema, ComfyUI, üret)', ), onChanged: (v) => setState(() { _sorgu = v; _secili = 0; }), ), ), _Tus('Esc'), ], ), ), Divider(height: 1, color: tema.dividerColor), Flexible( child: liste.isEmpty ? Padding( padding: const EdgeInsets.all(FikoBosluk.xl), child: Text('Eşleşen komut yok', style: TextStyle( color: tema.colorScheme.onSurface .withValues(alpha: 0.5))), ) : ListView.builder( controller: _kaydirma, shrinkWrap: true, padding: const EdgeInsets.all(FikoBosluk.xs), itemCount: liste.length, itemBuilder: (_, i) => _KomutSatiri( komut: liste[i], secili: i == _secili, onTap: () { setState(() => _secili = i); _calistir(liste); }, onHover: () => setState(() => _secili = i), ), ), ), Divider(height: 1, color: tema.dividerColor), Padding( padding: const EdgeInsets.symmetric( horizontal: FikoBosluk.md, vertical: FikoBosluk.sm), child: Row( children: [ _Tus('↑'), _Tus('↓'), const SizedBox(width: 4), Text('gez', style: FikoTipo.mikro), const SizedBox(width: 12), _Tus('↵'), const SizedBox(width: 4), Text('çalıştır', style: FikoTipo.mikro), const Spacer(), Text('${liste.length} komut', style: FikoTipo.mikro), ], ), ), ], ), ), ), ); } } class _KomutSatiri extends StatelessWidget { const _KomutSatiri( {required this.komut, required this.secili, required this.onTap, required this.onHover}); final FikoKomut komut; final bool secili; final VoidCallback onTap; final VoidCallback onHover; @override Widget build(BuildContext context) { final renk = komut.renk ?? FikoRenkler.neonMor; return MouseRegion( onEnter: (_) => onHover(), cursor: SystemMouseCursors.click, child: GestureDetector( onTap: onTap, child: Container( margin: const EdgeInsets.symmetric(vertical: 1, horizontal: 2), padding: const EdgeInsets.symmetric( horizontal: FikoBosluk.md, vertical: 9), decoration: BoxDecoration( color: secili ? renk.withValues(alpha: FikoDurum.secili) : Colors.transparent, borderRadius: FikoYaricap.rSm, ), child: Row( children: [ Icon(komut.ikon, size: 18, color: secili ? renk : null), const SizedBox(width: FikoBosluk.md), Expanded(child: Text(komut.baslik, style: FikoTipo.govde)), Text(komut.kategori, style: FikoTipo.mikro.copyWith( color: Theme.of(context) .colorScheme .onSurface .withValues(alpha: 0.4))), if (komut.kisayol.isNotEmpty) ...[ const SizedBox(width: FikoBosluk.sm), for (final t in komut.kisayol) _Tus(t), ], ], ), ), ), ); } } /// Kısayol tuş rozeti. class _Tus extends StatelessWidget { const _Tus(this.metin); final String metin; @override Widget build(BuildContext context) { final tema = Theme.of(context); return Container( margin: const EdgeInsets.only(left: 3), padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: tema.colorScheme.onSurface.withValues(alpha: 0.06), borderRadius: FikoYaricap.rXs, border: Border.all(color: tema.dividerColor), ), child: Text(metin, style: const TextStyle(fontSize: 10, fontWeight: FontWeight.w700)), ); } } /// F1 / ? KISAYOL YARDIMI — komut kaydından kategorize liste. Future kisayolYardimiAc(BuildContext context, WidgetRef ref) { final komutlar = tumKomutlar(ref); final kategoriler = >{}; for (final k in komutlar) { (kategoriler[k.kategori] ??= []).add(k); } return showDialog( context: context, builder: (_) => AlertDialog( title: Row(children: const [ Icon(Icons.keyboard_rounded, color: FikoRenkler.neonMor), SizedBox(width: 8), Text('Kısayollar & Komutlar'), ]), content: SizedBox( width: 560, height: 480, child: ListView( children: [ _YardimSatir(const ['Ctrl', 'K'], 'Komut paletini aç'), _YardimSatir(const ['Ctrl', '1-9'], 'Ekranlar arası geçiş'), _YardimSatir(const ['Ctrl', 'L'], 'Tema değiştir'), _YardimSatir(const ['F1'], 'Bu yardımı aç'), const Divider(height: 20), for (final giris in kategoriler.entries) ...[ Padding( padding: const EdgeInsets.fromLTRB(0, 10, 0, 6), child: Text(giris.key.toUpperCase(), style: FikoTipo.etiket.copyWith( color: FikoRenkler.neonMor, letterSpacing: 0.8)), ), for (final k in giris.value) Padding( padding: const EdgeInsets.symmetric(vertical: 3), child: Row(children: [ Icon(k.ikon, size: 16, color: k.renk), const SizedBox(width: 10), Expanded(child: Text(k.baslik, style: FikoTipo.govdeK)), for (final t in k.kisayol) _Tus(t), ]), ), ], ], ), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Kapat')), ], ), ); } class _YardimSatir extends StatelessWidget { const _YardimSatir(this.tuslar, this.aciklama); final List tuslar; final String aciklama; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row(children: [ for (final t in tuslar) _Tus(t), const SizedBox(width: 12), Text(aciklama, style: FikoTipo.govde), ]), ); } } /// Sidebar üstündeki "Komut Paleti" hızlı erişim butonu (Linear/Slack tarzı). class PaletButonu extends ConsumerWidget { const PaletButonu({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final tema = Theme.of(context); return FikoEtkilesimli( onTap: () => komutPaletiniAc(context, ref), child: Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), decoration: BoxDecoration( color: tema.colorScheme.onSurface.withValues(alpha: 0.04), borderRadius: FikoYaricap.rMd, border: Border.all(color: tema.dividerColor), ), child: Row(children: [ Icon(Icons.search_rounded, size: 16, color: tema.colorScheme.onSurface.withValues(alpha: 0.5)), const SizedBox(width: 8), Expanded( child: Text('Komut ara…', style: FikoTipo.govdeK.copyWith( color: tema.colorScheme.onSurface.withValues(alpha: 0.5))), ), _Tus('Ctrl'), _Tus('K'), ]), ), ); } }