From 95c64ce1cd3e82f75425c0a6bdfbf8bc1c7194bb Mon Sep 17 00:00:00 2001 From: Alma Alexyz Date: Mon, 31 Aug 2026 15:30:41 +0500 Subject: [PATCH] clean: remove catalog tab, keeping 2 pure tabs (Oracle and History) --- lib/main.dart | 15 +- lib/screens/catalog_screen.dart | 313 -------------------------------- test/widget_test.dart | 3 +- 3 files changed, 5 insertions(+), 326 deletions(-) delete mode 100644 lib/screens/catalog_screen.dart diff --git a/lib/main.dart b/lib/main.dart index eefde01..c3de5e3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'screens/catalog_screen.dart'; import 'screens/history_screen.dart'; import 'screens/home_search_screen.dart'; import 'services/words_repository.dart'; @@ -57,19 +56,19 @@ class _Words999AppState extends State { ), ), navigationBarTheme: NavigationBarThemeData( - backgroundColor: const Color(0xFF101322), + backgroundColor: const Color(0xFF101222), indicatorColor: const Color(0xFF2A2D4A), labelTextStyle: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return const TextStyle( - color: Color(0xFFFFD54F), + color: Color(0xFFFFF9C4), fontWeight: FontWeight.bold, fontSize: 12, ); } return const TextStyle( - color: Color(0xFF9FA8DA), - fontSize: 11, + color: Color(0xFF8C93B8), + fontSize: 12, ); }), ), @@ -91,7 +90,6 @@ class _MainNavigationContainerState extends State { final List _screens = const [ HomeSearchScreen(), - CatalogScreen(), HistoryScreen(), ]; @@ -114,11 +112,6 @@ class _MainNavigationContainerState extends State { selectedIcon: GradientStar(size: 22), label: 'Оракул', ), - NavigationDestination( - icon: Icon(Icons.menu_book_outlined), - selectedIcon: GradientStar(size: 22), - label: 'Каталог 999', - ), NavigationDestination( icon: Icon(Icons.history_rounded), selectedIcon: GradientStar(size: 22), diff --git a/lib/screens/catalog_screen.dart b/lib/screens/catalog_screen.dart deleted file mode 100644 index 0686ac6..0000000 --- a/lib/screens/catalog_screen.dart +++ /dev/null @@ -1,313 +0,0 @@ -import 'package:flutter/material.dart'; -import '../models/word_model.dart'; -import '../services/words_repository.dart'; -import '../widgets/gradient_star_badge.dart'; -import '../widgets/word_card_widget.dart'; - -class CatalogScreen extends StatefulWidget { - const CatalogScreen({super.key}); - - @override - State createState() => _CatalogScreenState(); -} - -class _CatalogScreenState extends State { - final _repo = WordsRepository(); - final _searchController = TextEditingController(); - String _selectedCategory = 'Все'; - String _sortBy = 'id'; // 'id', 'alpha' - - List _filteredWords = []; - - @override - void initState() { - super.initState(); - _applyFilter(); - _searchController.addListener(_applyFilter); - } - - @override - void dispose() { - _searchController.removeListener(_applyFilter); - _searchController.dispose(); - super.dispose(); - } - - void _applyFilter() { - final query = _searchController.text.trim(); - List list; - - if (query.isEmpty) { - list = _repo.allWords; - } else { - list = _repo.search(query); - } - - if (_selectedCategory != 'Все') { - list = list - .where((w) => w.partOfSpeech == _selectedCategory || w.category == _selectedCategory) - .toList(); - } - - if (_sortBy == 'alpha') { - list = List.of(list)..sort((a, b) => a.word.compareTo(b.word)); - } else { - // By session number - list = List.of(list)..sort((a, b) => a.sessionNumber.compareTo(b.sessionNumber)); - } - - setState(() { - _filteredWords = list; - }); - } - - void _showWordDetails(WordItem word) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => StatefulBuilder( - builder: (context, setSheetState) { - return Container( - padding: const EdgeInsets.only(top: 12), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.vertical(top: Radius.circular(28)), - ), - child: SafeArea( - child: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 40, - height: 4, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.outlineVariant, - borderRadius: BorderRadius.circular(2), - ), - ), - const SizedBox(height: 12), - WordCardWidget( - word: word, - onNext: () { - final next = _repo.getNextWord(word.sessionNumber); - Navigator.pop(context); - _showWordDetails(next); - }, - onPrevious: () { - final prev = _repo.getPreviousWord(word.sessionNumber); - Navigator.pop(context); - _showWordDetails(prev); - }, - onRandom: () { - final rnd = _repo.getRandomWord(); - Navigator.pop(context); - _showWordDetails(rnd); - }, - ), - ], - ), - ), - ), - ); - }, - ), - ); - } - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final isDark = theme.brightness == Brightness.dark; - final categories = _repo.getPartsOfSpeech(); - - return Scaffold( - appBar: AppBar( - title: const Row( - children: [ - GradientStar(size: 22), - SizedBox(width: 8), - Text( - 'Каталог 999 символов', - style: TextStyle(fontWeight: FontWeight.w900), - ), - ], - ), - actions: [ - PopupMenuButton( - tooltip: 'Сортировка', - icon: const Icon(Icons.sort_rounded), - initialValue: _sortBy, - onSelected: (val) { - setState(() { - _sortBy = val; - _applyFilter(); - }); - }, - itemBuilder: (context) => [ - const PopupMenuItem( - value: 'id', - child: Row( - children: [ - Icon(Icons.format_list_numbered, size: 20), - SizedBox(width: 8), - Text('По номеру сессии (#000..#999)'), - ], - ), - ), - const PopupMenuItem( - value: 'alpha', - child: Row( - children: [ - Icon(Icons.sort_by_alpha, size: 20), - SizedBox(width: 8), - Text('По алфавиту (А..Я)'), - ], - ), - ), - ], - ), - ], - ), - body: Column( - children: [ - // Search input - Padding( - padding: const EdgeInsets.fromLTRB(16, 8, 16, 8), - child: TextField( - controller: _searchController, - decoration: InputDecoration( - hintText: 'Поиск по слову, номеру или смыслу...', - prefixIcon: const Padding( - padding: EdgeInsets.symmetric(horizontal: 10), - child: GradientStar(size: 16), - ), - suffixIcon: _searchController.text.isNotEmpty - ? IconButton( - icon: const Icon(Icons.clear), - onPressed: () => _searchController.clear(), - ) - : null, - filled: true, - fillColor: isDark - ? const Color(0xFF1B1D30) - : theme.colorScheme.surfaceContainerHighest.withValues(alpha: 0.4), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(16), - borderSide: BorderSide( - color: const Color(0xFFFFD54F).withValues(alpha: 0.3), - ), - ), - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - ), - ), - ), - - // Categories Filter Chips - SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), - child: Row( - children: categories.map((cat) { - final isSelected = _selectedCategory == cat; - return Padding( - padding: const EdgeInsets.only(right: 6), - child: FilterChip( - label: Text(cat), - selected: isSelected, - onSelected: (selected) { - setState(() { - _selectedCategory = cat; - _applyFilter(); - }); - }, - selectedColor: const Color(0xFF2A2D4A), - checkmarkColor: const Color(0xFFFFD54F), - labelStyle: TextStyle( - color: isSelected ? const Color(0xFFFFF9C4) : null, - fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, - ), - ), - ); - }).toList(), - ), - ), - - // Stats Bar - Padding( - padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 6), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Найдено: ${_filteredWords.length}', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: theme.colorScheme.outline, - ), - ), - Text( - 'Всего знаков: ${_repo.totalWords}', - style: TextStyle( - fontSize: 12, - color: theme.colorScheme.outline, - ), - ), - ], - ), - ), - - const Divider(height: 1), - - // Words List - Expanded( - child: _filteredWords.isEmpty - ? const Center( - child: Text('Ничего не найдено'), - ) - : ListView.separated( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - itemCount: _filteredWords.length, - separatorBuilder: (_, _) => const Divider(height: 1, indent: 64), - itemBuilder: (context, index) { - final item = _filteredWords[index]; - - return ListTile( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - leading: GradientStarBadge( - text: '#${item.formattedSessionNumber}', - size: 14, - ), - title: Text( - item.word.toUpperCase(), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16, - letterSpacing: 0.5, - ), - ), - subtitle: Text( - item.description, - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12, - color: theme.colorScheme.onSurfaceVariant, - ), - ), - trailing: const Icon(Icons.chevron_right_rounded, size: 20), - onTap: () => _showWordDetails(item), - ); - }, - ), - ), - ], - ), - ); - } -} diff --git a/test/widget_test.dart b/test/widget_test.dart index 9cf917a..772d972 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -11,10 +11,9 @@ void main() { await tester.pump(); await tester.pump(const Duration(milliseconds: 300)); - // Verify app title and 3 unified destinations + // Verify app title and 2 destinations expect(find.text('Оракул 999'), findsOneWidget); expect(find.text('Оракул'), findsOneWidget); - expect(find.text('Каталог 999'), findsOneWidget); expect(find.text('История'), findsOneWidget); }); }