import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../providers/gitea_sync_provider.dart'; import '../core/markdown_mindmap_parser.dart'; class GiteaMindmapsListScreen extends ConsumerWidget { const GiteaMindmapsListScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(mindmapSyncProvider); final notifier = ref.read(mindmapSyncProvider.notifier); return Scaffold( appBar: AppBar( title: const Text('Mindmaps из Gitea'), actions: [ IconButton( icon: const Icon(Icons.settings), onPressed: () => context.pushNamed('gitea-sync'), ), if (state.isConfigured) IconButton( icon: state.isSyncing ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white), ) : const Icon(Icons.sync), onPressed: state.isSyncing ? null : () => notifier.syncFromGitea(), ), ], ), body: _buildBody(context, state, notifier), ); } Widget _buildBody(BuildContext context, MindmapSyncState state, MindmapSyncNotifier notifier) { if (!state.isConfigured) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.cloud_off, size: 64, color: Colors.grey), const SizedBox(height: 16), const Text('Gitea не настроен'), const SizedBox(height: 16), ElevatedButton( onPressed: () => context.pushNamed('gitea-sync'), child: const Text('Настроить'), ), ], ), ); } if (state.isSyncing && state.cachedMindmaps.isEmpty) { return const Center(child: CircularProgressIndicator()); } if (state.error != null && state.cachedMindmaps.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 64, color: Colors.red), const SizedBox(height: 16), Text('Ошибка: ${state.error}'), const SizedBox(height: 16), ElevatedButton( onPressed: () => notifier.syncFromGitea(), child: const Text('Повторить'), ), ], ), ); } final mindmaps = state.cachedMindmaps; if (mindmaps.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.folder_open, size: 64, color: Colors.grey), const SizedBox(height: 16), const Text('Нет mindmaps в кэше'), const SizedBox(height: 16), ElevatedButton( onPressed: () => notifier.syncFromGitea(), child: const Text('Синхронизировать с Gitea'), ), ], ), ); } return ListView.builder( itemCount: mindmaps.length, itemBuilder: (context, index) { final mm = mindmaps[index]; final nodes = MarkdownMindmapParser.parse(mm.content, mm.path); final rootTitle = nodes.isNotEmpty ? nodes.first.title : mm.path; return Card( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), child: ListTile( leading: CircleAvatar( backgroundColor: _getColorForPath(mm.path), child: const Icon(Icons.account_tree, color: Colors.white), ), title: Text(rootTitle), subtitle: Text( '${mm.path}\n' '${mm.lastSync.toLocal().toString().split('.').first}', maxLines: 2, overflow: TextOverflow.ellipsis, ), isThreeLine: true, trailing: Row( mainAxisSize: MainAxisSize.min, children: [ if (mm.path.endsWith('.canvas')) const Chip( label: Text('Canvas', style: TextStyle(fontSize: 10)), padding: EdgeInsets.zero, ), const Icon(Icons.chevron_right), ], ), onTap: () { // TODO: открыть просмотр mindmap ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Открытие ${mm.path}...')), ); }, ), ); }, ); } Color _getColorForPath(String path) { if (path.endsWith('.canvas')) return Colors.purple; if (path.endsWith('.md')) return Colors.blue; return Colors.grey; } }