diff --git a/lib/main.dart b/lib/main.dart index f0d0d1c..21876b5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,5 @@ +// ignore_for_file: unnecessary_string_escapes + import 'package:flutter/material.dart'; void main() { @@ -20,21 +22,19 @@ class MyApp extends StatelessWidget { } } -// Enum +// Enum для управления состоянием сообщений enum MessageType { noQuotes, newQuoteAdded } // Модель цитаты class Quote { final String text; final String author; - Quote(this.text, this.author); } - +// Главный экран class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); - final String title; @override @@ -42,51 +42,22 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - List _quotes = []; // Generics List<> - MessageType _messageType = MessageType.noQuotes; // Enum для состояния + final List _quotes = []; + MessageType _messageType = MessageType.noQuotes; - // Добавление новой цитаты + // Метод добавления цитаты Future _addQuote() async { final result = await showDialog?>( context: context, - builder: (BuildContext context) { - final TextEditingController quoteController = TextEditingController(); - final TextEditingController authorController = TextEditingController(); - - return AlertDialog( - title: const Text('Добавить цитату'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextField( - controller: quoteController, - decoration: const InputDecoration(labelText: 'Цитата'), - ), - TextField( - controller: authorController, - decoration: const InputDecoration(labelText: 'Автор'), - ), - ], - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop({ - 'quote': quoteController.text, - 'author': authorController.text, - }), // Анонимная функция - child: const Text('Добавить'), - ), - ], - ); - }, + builder: (BuildContext context) => const AddQuoteDialog(), ); if (result != null && result['quote'] != '' && result['author'] != '') { setState(() { _quotes.add( - Quote(result['quote']!.addQuotesIfMissing(), result['author']!.capitalize()), // Применение расширения + Quote(result['quote']!.addQuotesIfMissing(), result['author']!.capitalize()), ); - _messageType = MessageType.newQuoteAdded; // Изменение состояния на "новая цитата добавлена" + _messageType = MessageType.newQuoteAdded; }); } } @@ -102,53 +73,13 @@ class _MyHomePageState extends State { children: [ Center( child: _messageType == MessageType.noQuotes - ? const Text( - 'Нет добавленных цитат. Добавь первую!.', - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18, color: Colors.grey), - ) - : ListView.builder( - itemCount: _quotes.length, - itemBuilder: (context, index) { - return ListTile( - title: Text( - _quotes[index].text, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - ), - ), - subtitle: Text('- ${_quotes[index].author}'), - ); - }, - ), + ? const NoQuotesMessage() + : QuoteList(quotes: _quotes), ), Align( alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.all(30.0), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 10), // Отступы внутри контейнера - decoration: BoxDecoration( - color: Colors.grey, // Полупрозрачный чёрный фон - borderRadius: BorderRadius.circular(15), // Закругленные углы - border: Border.all(//Граница - color: Colors.black.withOpacity(0.2), - width: 1, - ), - ), - child: Text( - 'Количество цитат: ${_quotes.length}', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.black.withOpacity(0.5), - ), - ), - ), - ), + child: QuoteCounter(count: _quotes.length), ), - ], ), floatingActionButton: FloatingActionButton( @@ -160,9 +91,109 @@ class _MyHomePageState extends State { } } +// Виджет списка цитат +class QuoteList extends StatelessWidget { + final List quotes; + const QuoteList({super.key, required this.quotes}); + + @override + Widget build(BuildContext context) { + return ListView.builder( + itemCount: quotes.length, + itemBuilder: (context, index) { + return ListTile( + title: Text( + quotes[index].text, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500), + ), + subtitle: Text('- ${quotes[index].author}'), + ); + }, + ); + } +} + +// Виджет сообщения "нет цитат" +class NoQuotesMessage extends StatelessWidget { + const NoQuotesMessage({super.key}); + + @override + Widget build(BuildContext context) { + return const Text( + 'Нет добавленных цитат. Добавь первую!', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18, color: Colors.grey), + ); + } +} + +// Виджет счетчика цитат +class QuoteCounter extends StatelessWidget { + final int count; + const QuoteCounter({super.key, required this.count}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(30.0), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + decoration: BoxDecoration( + color: Colors.grey.withOpacity(0.7), + borderRadius: BorderRadius.circular(15), + border: Border.all( + color: Colors.black.withOpacity(0.2), + width: 1, + ), + ), + child: Text( + 'Количество цитат: $count', + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.black), + ), + ), + ); + } +} + +// Диалоговое окно добавления цитаты +class AddQuoteDialog extends StatelessWidget { + const AddQuoteDialog({super.key}); + + @override + Widget build(BuildContext context) { + final TextEditingController quoteController = TextEditingController(); + final TextEditingController authorController = TextEditingController(); + + return AlertDialog( + title: const Text('Добавить цитату'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: quoteController, + decoration: const InputDecoration(labelText: 'Цитата'), + ), + TextField( + controller: authorController, + decoration: const InputDecoration(labelText: 'Автор'), + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop({ + 'quote': quoteController.text, + 'author': authorController.text, + }), + child: const Text('Добавить'), + ), + ], + ); + } +} + // Расширение для форматирования текста extension StringExtension on String { - // Метод для заглавной буквы у каждого слова String capitalize() { return split(' ').map((word) { if (word.isNotEmpty) { @@ -171,19 +202,11 @@ extension StringExtension on String { return word; }).join(' '); } - // Метод для добавления кавычек, если их нет или они размещены некорректно + String addQuotesIfMissing() { - if (startsWith('\"') && endsWith('\"')) { - return this; - } - // Если начинается с кавычки, но не заканчивается на неё - if (startsWith('\"') && !endsWith('\"')) { - return '$this\"'; - } - // Если заканчивается на кавычку, но не начинается с неё - if (endsWith('\"') && !startsWith('\"')) { - return '\"$this'; - } + if (startsWith('\"') && endsWith('\"')) return this; + if (startsWith('\"') && !endsWith('\"')) return '$this\"'; + if (endsWith('\"') && !startsWith('\"')) return '\"$this'; return '\"$this\"'; } }