From d8928b9d4e3e535cc32ebbb563a1b44513158bc2 Mon Sep 17 00:00:00 2001 From: Craftplacer <22963120+Craftplacer@users.noreply.github.com> Date: Sun, 31 Dec 2023 20:02:09 +0100 Subject: [PATCH] refactor: use dedicated MediaQuery methods instead of depending on all MediaQuery data --- .../dialogs/dynamic_dialog_container.dart | 2 +- src/kaiteki/lib/ui/user/user_screen.dart | 8 ++- src/kaiteki_lints/lib/kaiteki_lints.dart | 3 + .../lib/rules/prefer_media_query_aspects.dart | 66 +++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 src/kaiteki_lints/lib/rules/prefer_media_query_aspects.dart diff --git a/src/kaiteki/lib/ui/shared/dialogs/dynamic_dialog_container.dart b/src/kaiteki/lib/ui/shared/dialogs/dynamic_dialog_container.dart index 3dbba23d..c54a971c 100644 --- a/src/kaiteki/lib/ui/shared/dialogs/dynamic_dialog_container.dart +++ b/src/kaiteki/lib/ui/shared/dialogs/dynamic_dialog_container.dart @@ -34,7 +34,7 @@ class DynamicDialogContainer extends StatelessWidget { curve: Curves.easeOutQuad, child: Padding( padding: fullscreen - ? MediaQuery.of(context).viewInsets + ? MediaQuery.viewInsetsOf(context) : EdgeInsets.zero, child: Material( borderRadius: borderRadius, diff --git a/src/kaiteki/lib/ui/user/user_screen.dart b/src/kaiteki/lib/ui/user/user_screen.dart index df9b7b1d..b5e8cbf4 100644 --- a/src/kaiteki/lib/ui/user/user_screen.dart +++ b/src/kaiteki/lib/ui/user/user_screen.dart @@ -123,7 +123,9 @@ class _UserScreenState extends ConsumerState { const a = avatarSize * 0.5; final primaryButton = buildPrimaryButton( user, - MediaQuery.of(context).size.width < 840, + MediaQuery + .sizeOf(context) + .width < 840, ); return Scaffold( backgroundColor: _getBackgroundColor(context), @@ -146,7 +148,9 @@ class _UserScreenState extends ConsumerState { // recommended side pane width is 360dp, we use what is lower of // width and a third of the screen, so the content pane doesn't get // too squished. - width: min(MediaQuery.of(context).size.width / 3, 360), + width: min(MediaQuery + .sizeOf(context) + .width / 3, 360), child: SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Column( diff --git a/src/kaiteki_lints/lib/kaiteki_lints.dart b/src/kaiteki_lints/lib/kaiteki_lints.dart index 11217b5b..18b0f7bc 100644 --- a/src/kaiteki_lints/lib/kaiteki_lints.dart +++ b/src/kaiteki_lints/lib/kaiteki_lints.dart @@ -1,6 +1,8 @@ import 'package:custom_lint_builder/custom_lint_builder.dart'; import 'rules/l10n.dart'; +import 'rules/prefer_media_query_aspects.dart'; +import 'rules/prefer_widget_classes.dart'; PluginBase createPlugin() => _KaitekiLinter(); @@ -9,6 +11,7 @@ class _KaitekiLinter extends PluginBase { List getLintRules(CustomLintConfigs configs) { return [ const LocalizationRule(), + const PreferMediaQueryAspectsRule(), ]; } } diff --git a/src/kaiteki_lints/lib/rules/prefer_media_query_aspects.dart b/src/kaiteki_lints/lib/rules/prefer_media_query_aspects.dart new file mode 100644 index 00000000..2ceb9a5a --- /dev/null +++ b/src/kaiteki_lints/lib/rules/prefer_media_query_aspects.dart @@ -0,0 +1,66 @@ +import 'package:analyzer/error/error.dart'; +import 'package:analyzer/error/listener.dart'; +import 'package:custom_lint_builder/custom_lint_builder.dart'; + +const _typeChecker = + TypeChecker.fromName('MediaQueryData', packageName: 'flutter'); + +class PreferMediaQueryAspectsRule extends DartLintRule { + const PreferMediaQueryAspectsRule() : super(code: _code); + + static const _code = LintCode( + name: 'prefer_media_query_aspects', + problemMessage: + 'Prefer calling MediaQuery method that depend on only one aspect', + ); + + static const mediaQueryAspects = { + "size": "sizeOf", + "orientation": "orientationOf", + "devicePixelRatio": "devicePixelRatioOf", + "textScaler": "textScalerOf", + "textScaleFactor": "textScaleFactorOf", + "platformBrightness": "platformBrightnessOf", + "boldText": "boldTextOf", + "highContrast": "highContrastOf", + "disableAnimations": "disableAnimationsOf", + "invertColors": "invertColorsOf", + "alwaysUse24HourFormat": "alwaysUse24HourFormatOf", + "accessibleNavigation": "accessibleNavigationOf", + "navigationMode": "navigationModeOf", + "displayFeatures": "displayFeaturesOf", + "gestureSettings": "gestureSettingsOf", + "viewPadding": "viewPaddingOf", + "systemGestureInsets": "systemGestureInsetsOf", + "viewInsets": "viewInsetsOf", + "padding": "paddingOf", + }; + + @override + void run( + CustomLintResolver resolver, + ErrorReporter reporter, + CustomLintContext context, + ) { + // Detect access to e.g. MediaQuery.of(context).size and prompt to use MediaQuery.sizeOf(context) instead. + context.registry.addPropertyAccess((node) { + var propertyName = node.propertyName.name; + final methodName = mediaQueryAspects[propertyName]; + if (methodName == null) return; + + final targetType = node.target?.staticType; + if (targetType == null) return; + if (!_typeChecker.isAssignableFromType(targetType)) return; + + reporter.reportErrorForNode( + LintCode( + name: 'prefer_media_query_aspects', + problemMessage: + 'Prefer calling MediaQuery.$methodName(context) instead of MediaQuery.of(context).$propertyName', + errorSeverity: ErrorSeverity.WARNING, + ), + node, + ); + }); + } +}