fix(editor): le champ suit le curseur pendant la frappe (#447 point 1)#449
Merged
Conversation
…int 1) Le champ en scroll externe (#422/#434) ne demandait jamais au scrollable ancêtre de suivre le caret en frappe — Compose ne câble ce suivi que quand le TextField possède son propre scroll interne. Retour bêta-dev v123 de Dintr-un lemn (post #2787456). - BbcodeFieldImpl réécrit : BasicTextField (overload TextFieldValue, qui expose onTextLayout — M3 OutlinedTextField ne l'expose pas) + OutlinedTextFieldDefaults.DecorationBox pour la parité visuelle (label flottant, bordure focus, couleurs M3). - BringIntoViewRequester attaché au nœud texte INTERNE (le caret rect de TextLayoutResult.getCursorRect est dans son espace de coordonnées, pas celui de la boîte décorée), déclenché sur (focus, sélection, layout) — jamais sur value.text seul (layout périmé). - Parité M3 répliquée : semantics(mergeDescendants) + padding(top=8.dp) (réserve la moitié haute du label flottant — vérifié rogné sans), textStyle onSurface, caret primary, capitalisation Sentences. - Test Robolectric : sélection déplacée en fin de contenu long → le viewport scrolle (>0) pour révéler le caret. Vérifié sur émulateur : 30 lignes tapées, le viewport suit et le caret reste visible au-dessus de l'IME ; label flottant entier. Le point 2 de #447 (drag-to-scroll de sélection) reste ouvert — structurellement plus coûteux, traité séparément. Demandé par @xatrix Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 IMPORTANT + 1 MINOR de la review Codex sur #449 : - L'assertion « scrollAfter > scrollBefore » prouvait un scroll, pas la révélation du caret : un requester accroché au mauvais ancêtre (ou un rect lu dans l'espace de la boîte décorée) sous-scrollerait d'un offset constant et passait quand même. Caret en DERNIÈRE ligne => assert scrollAfter >= 95% du maxValue du range. - Le mode défaut (fillViewport=false dans un verticalScroll externe, layout TopicFormScreen) n'était pas couvert : 2e test avec Column scrollable externe taguée, même contrat. - Commentaires resserrés : le wrapper Box du requester est offset-free PAR CONTRAT (son origine coïncide avec celle du layout texte). 5/5 tests BbcodeTextFieldViewportTest verts + detektAll. Demandé par @xatrix Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
refs-#447 (point 1 — le point 2, drag-to-scroll de sélection, reste ouvert et sera traité séparément). Retour bêta-dev v123 de Dintr-un lemn (post #2787456).
Problème
Depuis le passage du champ en scroll externe (#422/#434), Compose ne suit plus le caret pendant la frappe : ce suivi n'est câblé nativement que quand le TextField possède son propre scroll interne. Quand la frappe fait descendre le caret sous la zone visible (clavier ouvert), il fallait scroller à la main.
Solution
BbcodeFieldImplréécrit :BasicTextField(overloadTextFieldValue, qui exposeonTextLayout— M3OutlinedTextFieldne l'expose pas) habillé parOutlinedTextFieldDefaults.DecorationBoxpour la parité visuelle (label flottant, bordure focus, couleurs M3). APIs vérifiées dans les artefacts réels du cache Gradle : DecorationBox stable en M3 1.4.0, BringIntoViewRequester stable en foundation 1.11.2.BringIntoViewRequesterattaché au nœud texte interne (le rect deTextLayoutResult.getCursorRectest dans son espace de coordonnées, pas celui de la boîte décorée), déclenché parLaunchedEffect(isFocused, selection, textLayout)— jamais survalue.textseul, qui ferait viser le layout périmé du texte précédent.semantics(mergeDescendants)+padding(top = 8.dp)(réserve la moitié haute du label flottant — vérifié rogné sans, screenshot émulateur),textStyleonSurface, caret primary, capitalisationSentences(Phase 2F — Éditeur : pas de capitalisation auto en début de phrase (Gboard) vs RF1 #237 conservé).Validation
detektAll test :app:assembleProdDebugpuis:app:lintProdDebug— verts (re-run incrémental après le fix padding : 4/4 testsBbcodeTextFieldViewportTestdont le nouveau).🤖 Generated with Claude Code