From 83eba7ff54b6d43c627915e1938a60ffe83269e2 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Wed, 9 Sep 2026 16:54:56 +0200 Subject: [PATCH] Editeurs de traduction : le curseur ne saute plus a chaque frappe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `QuillEditor.basic` fabrique un `FocusNode` et un `ScrollController` neufs a chaque construction quand on ne lui en passe pas. Or chaque frappe reconstruit ces widgets — compteur de caracteres, pastilles du rail de langues — donc l'editeur perdait le focus des le premier caractere saisi. Les deux conteneurs creent desormais leurs noeuds une fois, dans `initState`, un par langue, et les liberent au `dispose`. Co-Authored-By: Claude Opus 5 (1M context) --- ...nslation_input_and_resource_container.dart | 22 ++++++++++++++++++ .../translation_input_container.dart | 23 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lib/Components/translation_input_and_resource_container.dart b/lib/Components/translation_input_and_resource_container.dart index 85ab47f..8c625af 100644 --- a/lib/Components/translation_input_and_resource_container.dart +++ b/lib/Components/translation_input_and_resource_container.dart @@ -41,6 +41,12 @@ class TranslationInputAndResourceContainer extends StatefulWidget { class _TranslationInputAndResourceContainerState extends State { late Map _controllers; + + /// Meme piege que dans `translation_input_container` : sans `focusNode` ni + /// `scrollController`, `QuillEditor.basic` en cree de neufs a chaque + /// construction et le champ perd le curseur des qu'un rebuild survient. + late Map _focusNodes; + late Map _editorScrollControllers; int _selected = 0; bool _isEnforcingLimit = false; bool _isTranslating = false; @@ -50,6 +56,14 @@ class _TranslationInputAndResourceContainerState void initState() { super.initState(); _controllers = _buildControllers(); + _focusNodes = { + for (final translation in widget.newValues) + translation.language!: FocusNode(), + }; + _editorScrollControllers = { + for (final translation in widget.newValues) + translation.language!: ScrollController(), + }; } static const _emptyDelta = [{'insert': '\n'}]; @@ -172,6 +186,12 @@ class _TranslationInputAndResourceContainerState for (final c in _controllers.values) { c.dispose(); } + for (final node in _focusNodes.values) { + node.dispose(); + } + for (final c in _editorScrollControllers.values) { + c.dispose(); + } super.dispose(); } @@ -396,6 +416,8 @@ class _TranslationInputAndResourceContainerState ), child: QuillEditor.basic( controller: controller, + focusNode: _focusNodes[lang], + scrollController: _editorScrollControllers[lang], config: const QuillEditorConfig( scrollable: true, expands: false, diff --git a/lib/Components/translation_input_container.dart b/lib/Components/translation_input_container.dart index 0dfc76b..74a0d99 100644 --- a/lib/Components/translation_input_container.dart +++ b/lib/Components/translation_input_container.dart @@ -47,6 +47,13 @@ class TranslationInputContainer extends StatefulWidget { class _TranslationInputContainerState extends State { late Map _controllers; late Map _textControllers; + + /// `QuillEditor.basic` fabrique un `FocusNode` et un `ScrollController` neufs + /// a chaque construction quand on ne lui en passe pas : le curseur sautait de + /// l'editeur des la premiere frappe, puisque chaque frappe reconstruit ce + /// widget (compteur de caracteres, pastilles du rail). + late Map _focusNodes; + late Map _editorScrollControllers; int _selected = 0; bool _isEnforcingLimit = false; bool _isTranslating = false; @@ -57,6 +64,14 @@ class _TranslationInputContainerState extends State { super.initState(); _controllers = widget.isHTML ? _buildControllers() : {}; _textControllers = widget.isHTML ? {} : _buildTextControllers(); + _focusNodes = { + for (final translation in widget.newValues) + translation.language!: FocusNode(), + }; + _editorScrollControllers = { + for (final translation in widget.newValues) + translation.language!: ScrollController(), + }; } Map _buildTextControllers() { @@ -207,6 +222,12 @@ class _TranslationInputContainerState extends State { for (final c in _textControllers.values) { c.dispose(); } + for (final node in _focusNodes.values) { + node.dispose(); + } + for (final c in _editorScrollControllers.values) { + c.dispose(); + } super.dispose(); } @@ -467,6 +488,8 @@ class _TranslationInputContainerState extends State { ), child: QuillEditor.basic( controller: controller, + focusNode: _focusNodes[lang], + scrollController: _editorScrollControllers[lang], config: const QuillEditorConfig( scrollable: true, expands: false,