diff --git a/packages/flutter_markdown/CHANGELOG.md b/packages/flutter_markdown/CHANGELOG.md index 8feeca4bdae2..9d901df3fa72 100644 --- a/packages/flutter_markdown/CHANGELOG.md +++ b/packages/flutter_markdown/CHANGELOG.md @@ -1,6 +1,10 @@ -## NEXT +## 0.6.20 -* Updates minimum supported SDK version to Flutter 3.13/Dart 3.1. +* Adds `textScaler` to `MarkdownStyleSheet`, and deprecates `textScaleFactor`. + * Clients using `textScaleFactor: someFactor` should replace it with + `TextScaler.linear(someFactor)` to preserve behavior. +* Removes use of deprecated Flutter framework `textScaleFactor` methods. +* Updates minimum supported SDK version to Flutter 3.16. ## 0.6.19 @@ -44,7 +48,7 @@ * Introduces a new `MarkdownElementBuilder.visitElementAfterWithContext()` method passing the widget `BuildContext` and the parent text's `TextStyle`. - + ## 0.6.16 * Adds `tableVerticalAlignment` property to allow aligning table cells vertically. diff --git a/packages/flutter_markdown/example/pubspec.yaml b/packages/flutter_markdown/example/pubspec.yaml index a904473786a4..c536ac0ce8d5 100644 --- a/packages/flutter_markdown/example/pubspec.yaml +++ b/packages/flutter_markdown/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the flutter_markdown package. publish_to: none environment: - sdk: ^3.1.0 - flutter: ">=3.13.0" + sdk: ^3.2.0 + flutter: ">=3.16.0" dependencies: flutter: diff --git a/packages/flutter_markdown/lib/src/_functions_io.dart b/packages/flutter_markdown/lib/src/_functions_io.dart index 81fd5b8f22b6..b3020573e165 100644 --- a/packages/flutter_markdown/lib/src/_functions_io.dart +++ b/packages/flutter_markdown/lib/src/_functions_io.dart @@ -64,7 +64,7 @@ final MarkdownStyleSheet Function(BuildContext, MarkdownStyleSheetBaseTheme?) } return result.copyWith( - textScaleFactor: MediaQuery.textScaleFactorOf(context), + textScaler: MediaQuery.textScalerOf(context), ); }; diff --git a/packages/flutter_markdown/lib/src/_functions_web.dart b/packages/flutter_markdown/lib/src/_functions_web.dart index 62692236a21e..7adf81654bed 100644 --- a/packages/flutter_markdown/lib/src/_functions_web.dart +++ b/packages/flutter_markdown/lib/src/_functions_web.dart @@ -66,7 +66,7 @@ final MarkdownStyleSheet Function(BuildContext, MarkdownStyleSheetBaseTheme?) } return result.copyWith( - textScaleFactor: MediaQuery.textScaleFactorOf(context), + textScaler: MediaQuery.textScalerOf(context), ); }; diff --git a/packages/flutter_markdown/lib/src/builder.dart b/packages/flutter_markdown/lib/src/builder.dart index 659df8ae6fc7..5d3cb10a8e43 100644 --- a/packages/flutter_markdown/lib/src/builder.dart +++ b/packages/flutter_markdown/lib/src/builder.dart @@ -867,7 +867,7 @@ class MarkdownBuilder implements md.NodeVisitor { if (selectable) { return SelectableText.rich( text!, - textScaleFactor: styleSheet.textScaleFactor, + textScaler: styleSheet.textScaler, textAlign: textAlign ?? TextAlign.start, onTap: onTapText, key: k, @@ -875,7 +875,7 @@ class MarkdownBuilder implements md.NodeVisitor { } else { return Text.rich( text!, - textScaleFactor: styleSheet.textScaleFactor, + textScaler: styleSheet.textScaler, textAlign: textAlign ?? TextAlign.start, key: k, ); diff --git a/packages/flutter_markdown/lib/src/style_sheet.dart b/packages/flutter_markdown/lib/src/style_sheet.dart index 8d73d318aa9c..7fc16d9881e0 100644 --- a/packages/flutter_markdown/lib/src/style_sheet.dart +++ b/packages/flutter_markdown/lib/src/style_sheet.dart @@ -59,8 +59,19 @@ class MarkdownStyleSheet { this.orderedListAlign = WrapAlignment.start, this.blockquoteAlign = WrapAlignment.start, this.codeblockAlign = WrapAlignment.start, - this.textScaleFactor, - }) : _styles = { + @Deprecated('Use textScaler instead.') this.textScaleFactor, + TextScaler? textScaler, + }) : assert( + textScaler == null || textScaleFactor == null, + 'textScaleFactor is deprecated and cannot be specified when textScaler is specified.', + ), + textScaler = textScaler ?? + // Internally, only textScaler is used, so convert the scale factor + // to a linear scaler. + (textScaleFactor == null + ? null + : TextScaler.linear(textScaleFactor)), + _styles = { 'a': a, 'p': p, 'li': p, @@ -380,8 +391,19 @@ class MarkdownStyleSheet { WrapAlignment? orderedListAlign, WrapAlignment? blockquoteAlign, WrapAlignment? codeblockAlign, - double? textScaleFactor, + @Deprecated('Use textScaler instead.') double? textScaleFactor, + TextScaler? textScaler, }) { + assert( + textScaler == null || textScaleFactor == null, + 'textScaleFactor is deprecated and cannot be specified when textScaler is specified.', + ); + // If either of textScaler or textScaleFactor is non-null, pass null for the + // other instead of the previous value, since only one is allowed. + final TextScaler? newTextScaler = + textScaler ?? (textScaleFactor == null ? this.textScaler : null); + final double? nextTextScaleFactor = + textScaleFactor ?? (textScaler == null ? this.textScaleFactor : null); return MarkdownStyleSheet( a: a ?? this.a, p: p ?? this.p, @@ -435,7 +457,8 @@ class MarkdownStyleSheet { orderedListAlign: orderedListAlign ?? this.orderedListAlign, blockquoteAlign: blockquoteAlign ?? this.blockquoteAlign, codeblockAlign: codeblockAlign ?? this.codeblockAlign, - textScaleFactor: textScaleFactor ?? this.textScaleFactor, + textScaler: newTextScaler, + textScaleFactor: nextTextScaleFactor, ); } @@ -497,6 +520,11 @@ class MarkdownStyleSheet { blockquoteAlign: other.blockquoteAlign, codeblockAlign: other.codeblockAlign, textScaleFactor: other.textScaleFactor, + // Only one of textScaler and textScaleFactor can be passed. If + // other.textScaleFactor is non-null, then the sheet was created with a + // textScaleFactor and the textScaler was derived from that, so should be + // ignored so that the textScaleFactor continues to be set. + textScaler: other.textScaleFactor == null ? other.textScaler : null, ); } @@ -650,7 +678,14 @@ class MarkdownStyleSheet { /// The [WrapAlignment] to use for a code block. Defaults to start. final WrapAlignment codeblockAlign; - /// The text scale factor to use in textual elements + /// The text scaler to use in textual elements. + final TextScaler? textScaler; + + /// The text scale factor to use in textual elements. + /// + /// This will be non-null only if the sheet was created with the deprecated + /// [textScaleFactor] instead of [textScaler]. + @Deprecated('Use textScaler instead.') final double? textScaleFactor; /// A [Map] from element name to the corresponding [TextStyle] object. @@ -717,7 +752,7 @@ class MarkdownStyleSheet { other.orderedListAlign == orderedListAlign && other.blockquoteAlign == blockquoteAlign && other.codeblockAlign == codeblockAlign && - other.textScaleFactor == textScaleFactor; + other.textScaler == textScaler; } @override @@ -774,6 +809,7 @@ class MarkdownStyleSheet { orderedListAlign, blockquoteAlign, codeblockAlign, + textScaler, textScaleFactor, ]); } diff --git a/packages/flutter_markdown/pubspec.yaml b/packages/flutter_markdown/pubspec.yaml index c3732a5c2cb8..0a3c89d24e77 100644 --- a/packages/flutter_markdown/pubspec.yaml +++ b/packages/flutter_markdown/pubspec.yaml @@ -4,11 +4,11 @@ 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.6.19 +version: 0.6.20 environment: - sdk: ^3.1.0 - flutter: ">=3.13.0" + sdk: ^3.2.0 + flutter: ">=3.16.0" dependencies: flutter: diff --git a/packages/flutter_markdown/test/all.dart b/packages/flutter_markdown/test/all.dart index 44387e0afe9c..28338dbdcf30 100644 --- a/packages/flutter_markdown/test/all.dart +++ b/packages/flutter_markdown/test/all.dart @@ -18,7 +18,7 @@ import 'selection_area_compatibility_test.dart' as selection_area_test; import 'style_sheet_test.dart' as style_sheet_test; import 'table_test.dart' as table_test; import 'text_alignment_test.dart' as text_alignment_test; -import 'text_scale_factor_test.dart' as text_scale_factor; +import 'text_scaler_test.dart' as text_scaler; import 'text_test.dart' as text_test; import 'uri_test.dart' as uri_test; @@ -40,6 +40,6 @@ void main() { table_test.defineTests(); text_test.defineTests(); text_alignment_test.defineTests(); - text_scale_factor.defineTests(); + text_scaler.defineTests(); uri_test.defineTests(); } diff --git a/packages/flutter_markdown/test/style_sheet_test.dart b/packages/flutter_markdown/test/style_sheet_test.dart index ad8c1f0c695b..b48465a415a0 100644 --- a/packages/flutter_markdown/test/style_sheet_test.dart +++ b/packages/flutter_markdown/test/style_sheet_test.dart @@ -398,5 +398,65 @@ void defineTests() { ); }, ); + + testWidgets( + 'deprecated textScaleFactor is converted to linear scaler', + (WidgetTester tester) async { + const double scaleFactor = 2.0; + final MarkdownStyleSheet style = MarkdownStyleSheet( + textScaleFactor: scaleFactor, + ); + + expect(style.textScaler, const TextScaler.linear(scaleFactor)); + expect(style.textScaleFactor, scaleFactor); + }, + ); + + testWidgets( + 'deprecated textScaleFactor is null when a scaler is provided', + (WidgetTester tester) async { + const TextScaler scaler = TextScaler.linear(2.0); + final MarkdownStyleSheet style = MarkdownStyleSheet( + textScaler: scaler, + ); + + expect(style.textScaler, scaler); + expect(style.textScaleFactor, null); + }, + ); + + testWidgets( + 'copyWith textScaler overwrites both textScaler and textScaleFactor', + (WidgetTester tester) async { + final MarkdownStyleSheet original = MarkdownStyleSheet( + textScaleFactor: 2.0, + ); + + const TextScaler newScaler = TextScaler.linear(3.0); + final MarkdownStyleSheet copy = original.copyWith( + textScaler: newScaler, + ); + + expect(copy.textScaler, newScaler); + expect(copy.textScaleFactor, null); + }, + ); + + testWidgets( + 'copyWith textScaleFactor overwrites both textScaler and textScaleFactor', + (WidgetTester tester) async { + final MarkdownStyleSheet original = MarkdownStyleSheet( + textScaleFactor: 2.0, + ); + + const double newScaleFactor = 3.0; + final MarkdownStyleSheet copy = original.copyWith( + textScaleFactor: newScaleFactor, + ); + + expect(copy.textScaler, const TextScaler.linear(newScaleFactor)); + expect(copy.textScaleFactor, newScaleFactor); + }, + ); }); } diff --git a/packages/flutter_markdown/test/text_scale_factor_test.dart b/packages/flutter_markdown/test/text_scaler_test.dart similarity index 69% rename from packages/flutter_markdown/test/text_scale_factor_test.dart rename to packages/flutter_markdown/test/text_scaler_test.dart index 3710b3e0a62e..bc3ff911ef4e 100644 --- a/packages/flutter_markdown/test/text_scale_factor_test.dart +++ b/packages/flutter_markdown/test/text_scaler_test.dart @@ -10,33 +10,35 @@ import 'utils.dart'; void main() => defineTests(); void defineTests() { - group('Text Scale Factor', () { + group('Text Scaler', () { testWidgets( - 'should use style textScaleFactor in RichText', + 'should use style textScaler in RichText', (WidgetTester tester) async { + const TextScaler scaler = TextScaler.linear(2.0); const String data = 'Hello'; await tester.pumpWidget( boilerplate( MarkdownBody( - styleSheet: MarkdownStyleSheet(textScaleFactor: 2.0), + styleSheet: MarkdownStyleSheet(textScaler: scaler), data: data, ), ), ); final RichText richText = tester.widget(find.byType(RichText)); - expect(richText.textScaleFactor, 2.0); + expect(richText.textScaler, scaler); }, ); testWidgets( - 'should use MediaQuery textScaleFactor in RichText', + 'should use MediaQuery textScaler in RichText', (WidgetTester tester) async { + const TextScaler scaler = TextScaler.linear(2.0); const String data = 'Hello'; await tester.pumpWidget( boilerplate( const MediaQuery( - data: MediaQueryData(textScaleFactor: 2.0), + data: MediaQueryData(textScaler: scaler), child: MarkdownBody( data: data, ), @@ -45,18 +47,19 @@ void defineTests() { ); final RichText richText = tester.widget(find.byType(RichText)); - expect(richText.textScaleFactor, 2.0); + expect(richText.textScaler, scaler); }, ); testWidgets( - 'should use MediaQuery textScaleFactor in SelectableText.rich', + 'should use MediaQuery textScaler in SelectableText.rich', (WidgetTester tester) async { + const TextScaler scaler = TextScaler.linear(2.0); const String data = 'Hello'; await tester.pumpWidget( boilerplate( const MediaQuery( - data: MediaQueryData(textScaleFactor: 2.0), + data: MediaQueryData(textScaler: scaler), child: MarkdownBody( data: data, selectable: true, @@ -67,7 +70,7 @@ void defineTests() { final SelectableText selectableText = tester.widget(find.byType(SelectableText)); - expect(selectableText.textScaleFactor, 2.0); + expect(selectableText.textScaler, scaler); }, ); }); diff --git a/packages/flutter_markdown/test/utils.dart b/packages/flutter_markdown/test/utils.dart index 1cd902c30022..2d1a4ff27de5 100644 --- a/packages/flutter_markdown/test/utils.dart +++ b/packages/flutter_markdown/test/utils.dart @@ -169,7 +169,7 @@ void expectLinkTap(MarkdownLink? actual, MarkdownLink expected) { } String dumpRenderView() { - return WidgetsBinding.instance.renderViewElement!.toStringDeep().replaceAll( + return WidgetsBinding.instance.rootElement!.toStringDeep().replaceAll( RegExp(r'SliverChildListDelegate#\d+', multiLine: true), 'SliverChildListDelegate', );