import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;

void main() {
  runApp(MyApp());
}

/// Модель данных для изображения
class ImageItem {
  final String title;
  final String assetPath;

  ImageItem({required this.title, required this.assetPath});
}

/// Основной виджет приложения
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'КотоГалерея',
      theme: ThemeData(
        primarySwatch: Colors.teal,
        visualDensity: VisualDensity.adaptivePlatformDensity,
        fontFamily: 'Roboto',
      ),
      home: ImageFeedPage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

/// Страница отображения ленты изображений с пагинацией
class ImageFeedPage extends StatefulWidget {
  @override
  _ImageFeedPageState createState() => _ImageFeedPageState();
}

class _ImageFeedPageState extends State<ImageFeedPage> {
  List<ImageItem> _allImages = [];
  bool _isLoading = true;

  // Параметры пагинации
  static const int imagesPerPage = 20;
  int _currentPage = 1;
  int _totalPages = 1;

  @override
  void initState() {
    super.initState();
    _loadImages();
  }

  /// Загружает список изображений из AssetManifest.json
  Future<void> _loadImages() async {
    try {
      final manifestContent = await rootBundle.loadString('AssetManifest.json');
      final Map<String, dynamic> manifestMap = json.decode(manifestContent);

      // Фильтруем только изображения из папки lib/images/
      final imagePaths = manifestMap.keys
          .where((String key) =>
              key.startsWith('lib/images/') &&
              (key.endsWith('.png') ||
                  key.endsWith('.jpg') ||
                  key.endsWith('.jpeg') ||
                  key.endsWith('.gif')))
          .toList();

      List<ImageItem> images = imagePaths.map((path) {
        // Извлекаем название из пути к файлу
        String fileName = path.split('/').last;
        String title = fileName.split('.').first; // Убираем расширение
        return ImageItem(title: title, assetPath: path);
      }).toList();

      setState(() {
        _allImages = images;
        _totalPages = (_allImages.length / imagesPerPage).ceil();
        _isLoading = false;
      });
    } catch (e) {
      print('Ошибка загрузки изображений: $e');
      setState(() {
        _isLoading = false;
      });
    }
  }

  /// Получает список изображений для текущей страницы
  List<ImageItem> get _currentImages {
    int start = (_currentPage - 1) * imagesPerPage;
    int end = start + imagesPerPage;
    if (end > _allImages.length) end = _allImages.length;
    return _allImages.sublist(start, end);
  }

  /// Переходит на предыдущую страницу
  void _previousPage() {
    if (_currentPage > 1) {
      setState(() {
        _currentPage--;
      });
    }
  }

  /// Переходит на следующую страницу
  void _nextPage() {
    if (_currentPage < _totalPages) {
      setState(() {
        _currentPage++;
      });
    }
  }

  /// Переходит на указанную страницу
  void _goToPage(int pageNumber) {
    if (pageNumber >= 1 && pageNumber <= _totalPages) {
      setState(() {
        _currentPage = pageNumber;
      });
    }
  }

  /// Определяет количество столбцов в сетке на основе ширины экрана
  int _calculateCrossAxisCount(double width) {
    if (width >= 1400) return 6;
    if (width >= 1200) return 5;
    if (width >= 1000) return 4;
    if (width >= 800) return 3;
    if (width >= 600) return 2;
    return 1;
  }

  /// Создаёт виджет пагинации
  Widget _buildPaginationControls() {
    List<Widget> pageButtons = [];

    // Ограничение количества отображаемых кнопок страниц для улучшения UX
    int displayedPages = 5;
    int startPage =
        (_currentPage - displayedPages ~/ 2).clamp(1, _totalPages - displayedPages + 1);
    startPage = startPage < 1 ? 1 : startPage;
    int endPage = (startPage + displayedPages - 1).clamp(1, _totalPages);

    for (int i = startPage; i <= endPage; i++) {
      pageButtons.add(
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 4.0),
          child: ElevatedButton(
            style: ElevatedButton.styleFrom(
              backgroundColor: _currentPage == i ? Colors.teal : Colors.grey[300],
              foregroundColor: _currentPage == i ? Colors.white : Colors.black,
              minimumSize: Size(40, 40),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8),
              ),
            ),
            child: Text('$i'),
            onPressed: () => _goToPage(i),
          ),
        ),
      );
    }

    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        // Кнопка "Предыдущая страница"
        IconButton(
          icon: Icon(Icons.arrow_back),
          onPressed: _currentPage > 1 ? _previousPage : null,
        ),
        // Кнопки страниц
        Expanded(
          child: SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(children: pageButtons),
          ),
        ),
        // Кнопка "Следующая страница"
        IconButton(
          icon: Icon(Icons.arrow_forward),
          onPressed: _currentPage < _totalPages ? _nextPage : null,
        ),
      ],
    );
  }

  /// Открывает форму добавления нового изображения
  void _openAddImageForm() {
    showDialog(
      context: context,
      builder: (context) {
        return AddImageDialog(
          onAdd: (title, path) {
            setState(() {
              _allImages.add(ImageItem(title: title, assetPath: path));
              _totalPages = (_allImages.length / imagesPerPage).ceil();
            });
          },
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    // Получаем ширину экрана
    final double screenWidth = MediaQuery.of(context).size.width;
    final int crossAxisCount = _calculateCrossAxisCount(screenWidth);

    return Scaffold(
      appBar: AppBar(
        title: Text('КотоГалерея'),
        centerTitle: true,
        actions: [
          IconButton(
            icon: Icon(Icons.add),
            tooltip: 'Добавить изображение',
            onPressed: _openAddImageForm, // Открыть диалог добавления изображения
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(12.0),
        child: _isLoading
            ? Center(child: CircularProgressIndicator())
            : _allImages.isEmpty
                ? Center(
                    child: Text(
                      'Нет изображений для отображения',
                      style: TextStyle(fontSize: 18, color: Colors.grey),
                    ),
                  )
                : Column(
                    children: [
                      Expanded(
                        child: GridView.builder(
                          itemCount: _currentImages.length,
                          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                            crossAxisCount: crossAxisCount,
                            crossAxisSpacing: 12,
                            mainAxisSpacing: 12,
                            childAspectRatio: 1,
                          ),
                          itemBuilder: (context, index) {
                            final imageItem = _currentImages[index];
                            return GestureDetector(
                              onTap: () {
                                Navigator.push(
                                  context,
                                  MaterialPageRoute(
                                    builder: (_) => ImageDetailPage(imageItem: imageItem),
                                  ),
                                );
                              },
                              child: Container(
                                decoration: BoxDecoration(
                                  color: Colors.white,
                                  borderRadius: BorderRadius.circular(12),
                                  boxShadow: [
                                    BoxShadow(
                                      color: Colors.black12,
                                      blurRadius: 4,
                                      offset: Offset(2, 2),
                                    ),
                                  ],
                                ),
                                child: ClipRRect(
                                  borderRadius: BorderRadius.circular(12),
                                  child: Stack(
                                    children: [
                                      Positioned.fill(
                                        child: Image.asset(
                                          imageItem.assetPath,
                                          fit: BoxFit.cover,
                                          errorBuilder: (context, error, stackTrace) {
                                            return Center(
                                              child: Icon(
                                                Icons.error,
                                                color: Colors.red,
                                                size: 40,
                                              ),
                                            );
                                          },
                                        ),
                                      ),
                                      Positioned(
                                        bottom: 0,
                                        left: 0,
                                        right: 0,
                                        child: Container(
                                          padding: EdgeInsets.symmetric(
                                              vertical: 6, horizontal: 8),
                                          decoration: BoxDecoration(
                                            gradient: LinearGradient(
                                              colors: [
                                                Colors.black54,
                                                Colors.transparent,
                                              ],
                                              begin: Alignment.bottomCenter,
                                              end: Alignment.topCenter,
                                            ),
                                            borderRadius: BorderRadius.only(
                                              bottomLeft: Radius.circular(12),
                                              bottomRight: Radius.circular(12),
                                            ),
                                          ),
                                          child: Text(
                                            imageItem.title,
                                            style: TextStyle(
                                              color: Colors.white,
                                              fontWeight: FontWeight.bold,
                                              shadows: [
                                                Shadow(
                                                  blurRadius: 2,
                                                  color: Colors.black,
                                                  offset: Offset(1, 1),
                                                ),
                                              ],
                                            ),
                                            maxLines: 1,
                                            overflow: TextOverflow.ellipsis,
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                            );
                          },
                        ),
                      ),
                      SizedBox(height: 16),
                      _buildPaginationControls(),
                    ],
                  ),
      ),
    );
  }
}

/// Диалоговое окно для добавления нового изображения (панель администратора)
class AddImageDialog extends StatefulWidget {
  final Function(String, String) onAdd;

  AddImageDialog({required this.onAdd});

  @override
  _AddImageDialogState createState() => _AddImageDialogState();
}

class _AddImageDialogState extends State<AddImageDialog> {
  final _formKey = GlobalKey<FormState>();
  String _title = '';
  String _assetPath = '';

  /// Обработка отправки формы
  void _submit() {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();
      widget.onAdd(_title, _assetPath);
      Navigator.of(context).pop(); // Закрыть диалог после добавления
    }
  }

  /// Выбор изображения из ассетов
  Future<void> _selectImage() async {
    // В реальном приложении вы можете реализовать выбор файла,
    // но Flutter Web не поддерживает выбор файлов из ассетов во время выполнения.
    // Поэтому администратору необходимо вручную добавлять изображения в папку lib/images/
    // и обновлять pubspec.yaml.
    // Здесь мы просто предлагаем ввести путь к изображению.
    
    TextEditingController _pathController = TextEditingController();

    await showDialog(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text("Выберите изображение"),
          content: TextField(
            controller: _pathController,
            decoration: InputDecoration(
              labelText: "Путь к изображению (например, lib/images/cat7.jpg)",
              border: OutlineInputBorder(),
            ),
          ),
          actions: [
            TextButton(
              child: Text("Отмена"),
              onPressed: () => Navigator.of(context).pop(),
            ),
            ElevatedButton(
              child: Text("Выбрать"),
              onPressed: () {
                if (_pathController.text.trim().isNotEmpty) {
                  setState(() {
                    _assetPath = _pathController.text.trim();
                  });
                  Navigator.of(context).pop();
                }
              },
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text('Добавить изображение'),
      content: SingleChildScrollView(
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              // Поле для ввода названия изображения
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Название',
                  border: OutlineInputBorder(),
                ),
                validator: (value) {
                  if (value == null || value.trim().isEmpty) {
                    return 'Пожалуйста, введите название';
                  }
                  return null;
                },
                onSaved: (value) {
                  _title = value!.trim();
                },
              ),
              SizedBox(height: 12),
              // Поле для ввода пути к изображению в ассетах
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Путь к изображению',
                  hintText: 'lib/images/cat7.jpg',
                  border: OutlineInputBorder(),
                  suffixIcon: IconButton(
                    icon: Icon(Icons.folder_open),
                    onPressed: _selectImage,
                  ),
                ),
                validator: (value) {
                  if (value == null || value.trim().isEmpty) {
                    return 'Пожалуйста, введите путь к изображению';
                  }
                  // Проверка, что путь начинается с 'lib/images/' и оканчивается на допустимое расширение
                  if (!value.trim().startsWith('lib/images/') ||
                      (!value.trim().endsWith('.png') &&
                          !value.trim().endsWith('.jpg') &&
                          !value.trim().endsWith('.jpeg') &&
                          !value.trim().endsWith('.gif'))) {
                    return 'Путь должен начинаться с "lib/images/" и оканчиваться на .png, .jpg, .jpeg или .gif';
                  }
                  return null;
                },
                onSaved: (value) {
                  _assetPath = value!.trim();
                },
              ),
              SizedBox(height: 8),
              Text(
                'Примечание: Добавленные изображения должны находиться в папке lib/images/ и быть перечислены в pubspec.yaml.',
                style: TextStyle(fontSize: 12, color: Colors.grey),
              ),
            ],
          ),
        ),
      ),
      actions: [
        TextButton(
          child: Text('Отмена'),
          onPressed: () => Navigator.of(context).pop(),
        ),
        ElevatedButton(
          child: Text('Добавить'),
          onPressed: _submit,
        ),
      ],
    );
  }
}

/// Страница с подробным просмотром изображения
class ImageDetailPage extends StatelessWidget {
  final ImageItem imageItem;

  ImageDetailPage({required this.imageItem});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(imageItem.title),
      ),
      body: Column(
        children: [
          Expanded(
            child: Center(
              child: Container(
                padding: EdgeInsets.all(16),
                child: Image.asset(
                  imageItem.assetPath,
                  fit: BoxFit.contain,
                  errorBuilder: (context, error, stackTrace) {
                    return Icon(
                      Icons.error,
                      color: Colors.red,
                      size: 60,
                    );
                  },
                ),
              ),
            ),
          ),
          Container(
            width: double.infinity,
            padding: EdgeInsets.all(16),
            color: Colors.teal.shade50,
            child: Text(
              imageItem.title,
              style: TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: Colors.teal.shade800,
              ),
              textAlign: TextAlign.center,
            ),
          ),
        ],
      ),
    );
  }
}

вот мой дарт код
вот моя ошибка: (исправь)

packages/flutter/src/widgets/binding.dart 1162:9                                drawFrame
binding.dart:1162
packages/flutter/src/rendering/binding.dart 468:5                               [_handlePersistentFrameCallback]
binding.dart:468
packages/flutter/src/scheduler/binding.dart 1397:7                              [_invokeFrameCallback]
binding.dart:1397
packages/flutter/src/scheduler/binding.dart 1318:9                              handleDrawFrame
binding.dart:1318
packages/flutter/src/scheduler/binding.dart 1176:5                              [_handleDrawFrame]
binding.dart:1176
lib/_engine/engine/platform_dispatcher.dart 1408:5                              invoke
platform_dispatcher.dart:1408
lib/_engine/engine/platform_dispatcher.dart 310:5                               invokeOnDrawFrame
platform_dispatcher.dart:310
lib/_engine/engine/initialization.dart 187:36                                   <fn>
initialization.dart:187
dart-sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart 188:27  _callDartFunctionFast1


пришли полностью новый переработанный код