fix(store): localised docs, debounced typing, explicit-submit always AI
Some checks failed
Security / Security check (push) Failing after 1s
Some checks failed
Security / Security check (push) Failing after 1s
Three Stefan-found bugs in one pass: 1. Documentation rendered in English even when Studio was set to German. _loadDocs now passes Localizations.localeOf(...) to fetchModuleDocs(); the hub tries README.de.md before README.md when locale='de'. 2. 'Keine Treffer' flickered on every keystroke. _onAskTyping used to call _runSearch synchronously per character — a short 2-3-letter substring matched nothing, so the empty- state showed for a frame, then the next character revealed results. Add a 250ms typing debounce (Timer + cancel on dispose) so the search only re-runs once typing pauses. 3. Submit button did substring search even when System-AI was enabled — the _looksLikeQuestion heuristic only routed 4+-word / question-mark queries through the LLM. The user reasonably expected an explicit submit (with the AI-icon showing on the button) to actually use AI. New behaviour: when system-AI is enabled, the submit button always calls _runAiQuery; live-typing keeps substring filtering. The heuristic helper was removed (now unused). Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
ec7417fef5
commit
98a6414eaa
2 changed files with 35 additions and 17 deletions
|
|
@ -5,6 +5,7 @@
|
|||
// renders the full bilingual description, requires-list, and
|
||||
// repository link.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -74,6 +75,11 @@ class _StorePageState extends State<StorePage> {
|
|||
List<_AiMatch>? _aiMatches;
|
||||
Set<String>? _aiMatchedNames;
|
||||
String? _aiError;
|
||||
/// Debounce-Timer für Such-Filterung beim Tippen. Ohne
|
||||
/// Debounce flackert "Keine Treffer" zwischen Buchstaben
|
||||
/// (für 2-3 Buchstaben matched z.B. nichts, das nächste
|
||||
/// dann doch). 250ms ist comfortable für Tippen.
|
||||
Timer? _typingDebounce;
|
||||
/// Whether the operator has a System-AI configured. Drives
|
||||
/// the Ask-bar hint copy and disables the AI path when off.
|
||||
bool _systemAiEnabled = false;
|
||||
|
|
@ -105,6 +111,7 @@ class _StorePageState extends State<StorePage> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
_typingDebounce?.cancel();
|
||||
_queryCtrl.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
|
@ -442,7 +449,6 @@ class _StorePageState extends State<StorePage> {
|
|||
/// operator submits — otherwise typing "ein Modul, das …"
|
||||
/// wipes the visible result set with every space.
|
||||
void _onAskTyping(String value) {
|
||||
final trimmed = value.trim();
|
||||
if (_aiAnswer != null || _aiMatches != null) {
|
||||
setState(() {
|
||||
_aiAnswer = null;
|
||||
|
|
@ -451,17 +457,35 @@ class _StorePageState extends State<StorePage> {
|
|||
_aiError = null;
|
||||
});
|
||||
}
|
||||
if (_systemAiEnabled && _looksLikeQuestion(trimmed)) return;
|
||||
_runSearch();
|
||||
// Tippen läuft IMMER nur durch die lokale Substring-Suche.
|
||||
// Die KI-Suche kostet einen LLM-Roundtrip und gehört hinter
|
||||
// den expliziten Submit-Knopf — sonst feuern wir pro
|
||||
// Keystroke einen Prompt. Debounce verhindert "Keine
|
||||
// Treffer" zwischen Buchstaben.
|
||||
_typingDebounce?.cancel();
|
||||
_typingDebounce = Timer(const Duration(milliseconds: 250), () {
|
||||
if (!mounted) return;
|
||||
_runSearch();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _onAskSubmit() async {
|
||||
// Pending typing-debounce abbrechen — wir submitten jetzt
|
||||
// explizit und wollen nicht hinterher nochmal substring-
|
||||
// filter laufen lassen.
|
||||
_typingDebounce?.cancel();
|
||||
final q = _queryCtrl.text.trim();
|
||||
if (q.isEmpty) {
|
||||
_clearQuery();
|
||||
return;
|
||||
}
|
||||
if (_systemAiEnabled && _looksLikeQuestion(q)) {
|
||||
// Wenn System-AI verfügbar ist, geht der explizite Submit
|
||||
// IMMER über die KI-Suche — egal ob die Eingabe wie eine
|
||||
// Frage aussieht. Das war der Bug: Nutzer tippt "tabellen"
|
||||
// + klick Suchen, erwartet KI, bekommt Substring-Filter.
|
||||
// Substring-Filter passiert weiter live beim Tippen
|
||||
// (siehe _onAskTyping).
|
||||
if (_systemAiEnabled) {
|
||||
await _runAiQuery(q);
|
||||
} else {
|
||||
_runSearch();
|
||||
|
|
@ -479,16 +503,6 @@ class _StorePageState extends State<StorePage> {
|
|||
_runSearch();
|
||||
}
|
||||
|
||||
/// Heuristic question detector — kept generous so a sentence
|
||||
/// "modul für tabellen lesen" triggers the LLM path even
|
||||
/// without a question mark. Single-word and two-word inputs
|
||||
/// stay on substring search where they belong.
|
||||
bool _looksLikeQuestion(String q) {
|
||||
if (q.endsWith('?')) return true;
|
||||
final words = q.split(RegExp(r'\s+'));
|
||||
return words.length >= 4;
|
||||
}
|
||||
|
||||
Future<void> _runAiQuery(String query) async {
|
||||
setState(() {
|
||||
_aiThinking = true;
|
||||
|
|
@ -1922,10 +1936,14 @@ class _StoreDetailSheetState extends State<_StoreDetailSheet> {
|
|||
|
||||
void _loadDocs() {
|
||||
if (_docsLoaded) return;
|
||||
// Sprache vom aktuellen Studio-Locale ans Hub weitergeben,
|
||||
// damit `README.de.md` zuerst probiert wird wenn Studio auf
|
||||
// Deutsch steht.
|
||||
final locale = Localizations.localeOf(context).languageCode;
|
||||
setState(() {
|
||||
_docsLoaded = true;
|
||||
_docsFuture =
|
||||
HubService.instance.fetchModuleDocs(widget.item.name);
|
||||
HubService.instance.fetchModuleDocs(widget.item.name, locale: locale);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue