From 48ad8060876782cd7d7eed0df8cd3562fc056af9 Mon Sep 17 00:00:00 2001 From: Andrew Wilson Date: Mon, 10 Jun 2024 16:52:52 -0700 Subject: [PATCH] Ensure each code block specified in the markdown uses its own ScrollController. --- packages/flutter_markdown/CHANGELOG.md | 4 +++ .../flutter_markdown/lib/src/builder.dart | 6 ++-- packages/flutter_markdown/pubspec.yaml | 2 +- .../test/scrollable_test.dart | 28 +++++++++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/flutter_markdown/CHANGELOG.md b/packages/flutter_markdown/CHANGELOG.md index b550b9a29fdb..c7e29128abd8 100644 --- a/packages/flutter_markdown/CHANGELOG.md +++ b/packages/flutter_markdown/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.7.2 + +* Multiple code blocks within a single markdown will now use separate ScrollControllers. + ## 0.7.1 * Allows for choosing a custom font feature to create superscript in footnotes when the font does not support the `supr` font feature. diff --git a/packages/flutter_markdown/lib/src/builder.dart b/packages/flutter_markdown/lib/src/builder.dart index b89ef2e70354..fff7f393089c 100644 --- a/packages/flutter_markdown/lib/src/builder.dart +++ b/packages/flutter_markdown/lib/src/builder.dart @@ -174,7 +174,6 @@ class MarkdownBuilder implements md.NodeVisitor { final List<_TableElement> _tables = <_TableElement>[]; final List<_InlineElement> _inlines = <_InlineElement>[]; final List _linkHandlers = []; - final ScrollController _preScrollController = ScrollController(); String? _currentBlockTag; String? _lastVisitedTag; bool _isInBlockquote = false; @@ -347,10 +346,11 @@ class MarkdownBuilder implements md.NodeVisitor { child = builders[_blocks.last.tag!]! .visitText(text, styleSheet.styles[_blocks.last.tag!]); } else if (_blocks.last.tag == 'pre') { + final ScrollController preScrollController = ScrollController(); child = Scrollbar( - controller: _preScrollController, + controller: preScrollController, child: SingleChildScrollView( - controller: _preScrollController, + controller: preScrollController, scrollDirection: Axis.horizontal, padding: styleSheet.codeblockPadding, child: _buildRichText(delegate.formatText(styleSheet, text.text)), diff --git a/packages/flutter_markdown/pubspec.yaml b/packages/flutter_markdown/pubspec.yaml index 04d24132024a..0336c962d17b 100644 --- a/packages/flutter_markdown/pubspec.yaml +++ b/packages/flutter_markdown/pubspec.yaml @@ -4,7 +4,7 @@ description: A Markdown renderer for Flutter. Create rich text output, formatted with simple Markdown tags. repository: https://github.com/flutter/packages/tree/main/packages/flutter_markdown issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_markdown%22 -version: 0.7.1 +version: 0.7.2 environment: sdk: ^3.3.0 diff --git a/packages/flutter_markdown/test/scrollable_test.dart b/packages/flutter_markdown/test/scrollable_test.dart index ef8e9096766f..23092328f00d 100644 --- a/packages/flutter_markdown/test/scrollable_test.dart +++ b/packages/flutter_markdown/test/scrollable_test.dart @@ -34,6 +34,34 @@ void defineTests() { }, ); + testWidgets( + 'two code blocks use different scroll controllers', + (WidgetTester tester) async { + const String data = + "```\nvoid main() {\n print('Hello World!');\n}\n```" + '\n' + "```\nvoid main() {\n print('Hello World!');\n}\n```"; + + await tester.pumpWidget( + boilerplate( + const MediaQuery( + data: MediaQueryData(), + child: MarkdownBody(data: data), + ), + ), + ); + + final Iterable widgets = tester.allWidgets; + final Iterable scrollViews = + widgets.whereType(); + expect(scrollViews, hasLength(2)); + expect(scrollViews.first.controller, isNotNull); + expect(scrollViews.last.controller, isNotNull); + expect(scrollViews.first.controller, + isNot(equals(scrollViews.last.controller))); + }, + ); + testWidgets( 'controller', (WidgetTester tester) async {