From 66ba3c52476eaa378f9e05eebe2b11b198598f50 Mon Sep 17 00:00:00 2001 From: Alma Alexyz Date: Mon, 31 Aug 2026 14:34:49 +0500 Subject: [PATCH] clean: remove pre-filled search bar clutter and unify direct d10 dice input on home screen --- lib/screens/home_search_screen.dart | 227 +++++----------------------- 1 file changed, 41 insertions(+), 186 deletions(-) diff --git a/lib/screens/home_search_screen.dart b/lib/screens/home_search_screen.dart index 48d4e71..eb2c3f0 100644 --- a/lib/screens/home_search_screen.dart +++ b/lib/screens/home_search_screen.dart @@ -17,72 +17,21 @@ class HomeSearchScreen extends StatefulWidget { class _HomeSearchScreenState extends State { final _repo = WordsRepository(); - final _searchController = TextEditingController(); final _questionController = TextEditingController(); - final _focusNode = FocusNode(); final _diceRollerKey = GlobalKey(); WordItem? _currentWord; String? _activeHistoryId; - List _searchResults = []; bool _showKeypad = true; - String _currentDigits = ''; // Tracks 0..3 digits input for d10 dice cleromancy - - @override - void initState() { - super.initState(); - _searchController.addListener(_onSearchChanged); - } + String _currentDigits = ''; // Tracks 0..3 digits input: e.g. "", "7", "74", "742" @override void dispose() { - _searchController.removeListener(_onSearchChanged); - _searchController.dispose(); _questionController.dispose(); - _focusNode.dispose(); super.dispose(); } - void _onSearchChanged() { - final query = _searchController.text.trim(); - if (query.isEmpty) { - setState(() { - _searchResults = []; - _currentDigits = ''; - }); - return; - } - - final isNumeric = int.tryParse(query) != null; - - if (isNumeric) { - setState(() { - _currentDigits = query; - }); - // In Cleromancy, exactly 3 digits (d10x3) are required to resolve a number 000..999 - if (query.length >= 3) { - final num = int.tryParse(query); - if (num != null && num <= 999) { - final word = _repo.getWordBySessionNumber(num); - if (word != null) { - _setWord(word, recordHistory: true); - } - } - } - } else { - // Text search by word - final results = _repo.search(query); - setState(() { - _searchResults = results; - _currentDigits = ''; - if (results.isNotEmpty) { - _setWord(results.first, recordHistory: true); - } - }); - } - } - - Future _setWord(WordItem word, {bool updateText = false, bool recordHistory = true}) async { + Future _setWord(WordItem word, {bool recordHistory = true}) async { final question = _questionController.text.trim(); String? newHistId; @@ -105,71 +54,78 @@ class _HomeSearchScreenState extends State { _currentWord = word; _activeHistoryId = newHistId ?? _activeHistoryId; _currentDigits = word.formattedSessionNumber; - if (updateText) { - _searchController.text = word.formattedSessionNumber; - } }); HapticFeedback.selectionClick(); } void _onKeypadTap(String val) { HapticFeedback.lightImpact(); - String currentText = _searchController.text; if (val == 'C') { - _searchController.clear(); - setState(() => _currentDigits = ''); + setState(() { + _currentDigits = ''; + }); return; } if (val == '⌫') { - if (currentText.isNotEmpty) { - _searchController.text = currentText.substring(0, currentText.length - 1); - _searchController.selection = TextSelection.fromPosition( - TextPosition(offset: _searchController.text.length), - ); + if (_currentDigits.isNotEmpty) { + setState(() { + _currentDigits = _currentDigits.substring(0, _currentDigits.length - 1); + }); } return; } - // In Cleromancy, append digit up to 3 digits - if (currentText.length >= 3) { - _searchController.text = val; + // Append digit up to 3 digits (1st d10, 2nd d10, 3rd d10) + String newDigits; + if (_currentDigits.length >= 3) { + newDigits = val; } else { - _searchController.text = currentText + val; + newDigits = _currentDigits + val; } - _searchController.selection = TextSelection.fromPosition( - TextPosition(offset: _searchController.text.length), - ); + setState(() { + _currentDigits = newDigits; + }); + + // Only resolve word when all 3 digits are provided! + if (newDigits.length == 3) { + final num = int.tryParse(newDigits); + if (num != null && num <= 999) { + final word = _repo.getWordBySessionNumber(num); + if (word != null) { + _setWord(word, recordHistory: true); + } + } + } } void _onVirtualRollCompleted(int finalNumber) { final word = _repo.getWordBySessionNumber(finalNumber); if (word != null) { - _setWord(word, updateText: true, recordHistory: true); + _setWord(word, recordHistory: true); } } void _resetToWelcome() { setState(() { _currentWord = null; - _searchController.clear(); - _searchResults = []; _currentDigits = ''; + _activeHistoryId = null; }); } void _goToNext() { if (_currentWord == null) return; final next = _repo.getNextWord(_currentWord!.sessionNumber); - _setWord(next, updateText: true, recordHistory: false); + _setWord(next, recordHistory: false); } void _goToPrevious() { if (_currentWord == null) return; final prev = _repo.getPreviousWord(_currentWord!.sessionNumber); - _setWord(prev, updateText: true, recordHistory: false); + _setWord(prev, recordHistory: false); } void _reshuffleSession() { @@ -289,7 +245,7 @@ class _HomeSearchScreenState extends State { const SizedBox(height: 12), - // D10 Dice Roller Slots Widget + // D10 Dice Roller Slots Widget (Clean & without prefilled junk) D10DiceRollerWidget( key: _diceRollerKey, digits: _currentDigits, @@ -298,109 +254,6 @@ class _HomeSearchScreenState extends State { onRollCompleted: _onVirtualRollCompleted, ), - const SizedBox(height: 10), - - // Search & Direct Number Input Bar - TextField( - controller: _searchController, - focusNode: _focusNode, - keyboardType: TextInputType.text, - decoration: InputDecoration( - labelText: 'Введите число (#000..#999) или слово', - hintText: 'Например: 777 или огонь', - prefixIcon: const Padding( - padding: EdgeInsets.symmetric(horizontal: 12), - child: GradientStar(size: 18), - ), - suffixIcon: _searchController.text.isNotEmpty - ? IconButton( - icon: const Icon(Icons.clear_rounded), - onPressed: () { - _searchController.clear(); - _focusNode.unfocus(); - setState(() => _currentDigits = ''); - }, - ) - : null, - filled: true, - fillColor: isDark - ? const Color(0xFF1B1D30) - : theme.colorScheme.surfaceContainerHighest.withValues(alpha: 0.4), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(18), - borderSide: BorderSide( - color: const Color(0xFFFFD54F).withValues(alpha: 0.3), - ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(18), - borderSide: BorderSide( - color: const Color(0xFFFFD54F).withValues(alpha: 0.25), - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(18), - borderSide: const BorderSide( - color: Color(0xFFFFD54F), - width: 1.8, - ), - ), - ), - ), - - // Search matches dropdown list (for text search) - if (_searchResults.length > 1 && _searchController.text.isNotEmpty && int.tryParse(_searchController.text) == null) ...[ - const SizedBox(height: 8), - Container( - constraints: const BoxConstraints(maxHeight: 140), - decoration: BoxDecoration( - color: isDark ? const Color(0xFF161828) : theme.colorScheme.surface, - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: const Color(0xFFFFD54F).withValues(alpha: 0.3), - ), - ), - child: ListView.separated( - shrinkWrap: true, - padding: const EdgeInsets.symmetric(vertical: 4), - itemCount: _searchResults.length > 10 ? 10 : _searchResults.length, - separatorBuilder: (_, _) => const Divider(height: 1), - itemBuilder: (context, idx) { - final item = _searchResults[idx]; - final isSelected = item.sessionNumber == _currentWord?.sessionNumber; - return ListTile( - dense: true, - selected: isSelected, - leading: GradientStarBadge( - text: '#${item.formattedSessionNumber}', - size: 14, - ), - title: Text( - item.word.toUpperCase(), - style: const TextStyle(fontWeight: FontWeight.bold), - ), - subtitle: Text( - item.description, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle(fontSize: 11), - ), - trailing: Text( - item.partOfSpeech, - style: TextStyle( - fontSize: 11, - color: theme.colorScheme.outline, - ), - ), - onTap: () { - _setWord(item, updateText: true, recordHistory: true); - }, - ); - }, - ), - ), - ], - const SizedBox(height: 14), // Welcome Idle State OR Active Word Card @@ -439,7 +292,7 @@ class _HomeSearchScreenState extends State { ), const SizedBox(height: 8), Text( - 'Сформулируйте вопрос, затем совершите 3 броска кубика d10 кнопкой выше или введите 3 выпавших числа (Сотни, Десятки, Единицы).', + 'Сформулируйте вопрос, затем совершите 3 броска кубика d10 кнопкой выше или наберите 3 выпавших грани на панели.', textAlign: TextAlign.center, style: TextStyle( fontSize: 13, @@ -501,7 +354,7 @@ class _HomeSearchScreenState extends State { const SizedBox(height: 14), - // Interactive Numeric Keypad + // Interactive Numeric Keypad (Directly maps to 3 d10 dice slots) if (_showKeypad) ...[ Container( padding: const EdgeInsets.all(12), @@ -524,7 +377,7 @@ class _HomeSearchScreenState extends State { Icon(Icons.casino_outlined, size: 15, color: Color(0xFFFFD54F)), SizedBox(width: 6), Text( - 'Ввод граней d10 (3 цифры):', + 'Ввод граней d10:', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w700, @@ -534,9 +387,11 @@ class _HomeSearchScreenState extends State { ], ), Text( - _currentDigits.length == 3 - ? 'Код: #$_currentDigits' - : 'Введено: ${_currentDigits.length} из 3', + _currentDigits.isEmpty + ? 'Ожидание 3 цифр' + : (_currentDigits.length == 3 + ? 'Код: #$_currentDigits' + : 'Введено: ${_currentDigits.length} из 3'), style: TextStyle( fontSize: 11, fontWeight: FontWeight.bold,