From 943e9fa0af67d1f65ceb4075cc9159d4a9bb18c2 Mon Sep 17 00:00:00 2001 From: Ellet Date: Thu, 5 Sep 2024 19:38:24 +0300 Subject: [PATCH 1/3] chore: improve platform check by using constants and defaultTargetPlatform --- .../lib/screens/quill/my_quill_editor.dart | 18 +- .../lib/screens/quill/my_quill_toolbar.dart | 11 +- .../settings/widgets/settings_screen.dart | 6 - .../screens/shared/widgets/dialog_action.dart | 45 +---- .../lib/src/editor/image/image_menu.dart | 2 +- .../image/models/image_configurations.dart | 6 +- .../toolbar/camera/select_camera_action.dart | 4 +- .../toolbar/image/select_image_source.dart | 4 +- .../toolbar/video/select_video_source.dart | 4 +- lib/extensions.dart | 4 + lib/src/common/utils/platform.dart | 191 ++++++++---------- lib/src/editor/editor.dart | 30 +-- .../editor/raw_editor/raw_editor_state.dart | 14 +- lib/src/editor/widgets/cursor.dart | 2 +- lib/src/editor/widgets/default_styles.dart | 7 +- lib/src/editor/widgets/delegate.dart | 2 +- lib/src/editor/widgets/text/text_line.dart | 8 +- .../toolbar/buttons/search/search_dialog.dart | 2 +- test/common/utils/platform_test.dart | 132 ++---------- 19 files changed, 148 insertions(+), 344 deletions(-) diff --git a/example/lib/screens/quill/my_quill_editor.dart b/example/lib/screens/quill/my_quill_editor.dart index a1d4c764f..505a9a09c 100644 --- a/example/lib/screens/quill/my_quill_editor.dart +++ b/example/lib/screens/quill/my_quill_editor.dart @@ -3,9 +3,9 @@ import 'dart:io' as io show Directory, File; import 'package:cached_network_image/cached_network_image.dart' show CachedNetworkImageProvider; import 'package:desktop_drop/desktop_drop.dart' show DropTarget; +import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; -import 'package:flutter_quill/extensions.dart' - show isAndroid, isDesktop, isIOS, isWeb; +import 'package:flutter_quill/extensions.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; // ignore: implementation_imports @@ -65,7 +65,7 @@ class MyQuillEditor extends StatelessWidget { placeholder: 'Start writing your notes...', padding: const EdgeInsets.all(16), onImagePaste: (imageBytes) async { - if (isWeb()) { + if (kIsWeb) { return null; } // We will save it to system temporary files @@ -81,7 +81,7 @@ class MyQuillEditor extends StatelessWidget { return file.path; }, onGifPaste: (gifBytes) async { - if (isWeb()) { + if (kIsWeb) { return null; } // We will save it to system temporary files @@ -96,7 +96,7 @@ class MyQuillEditor extends StatelessWidget { return file.path; }, embedBuilders: [ - ...(isWeb() + ...(kIsWeb ? FlutterQuillEmbeds.editorWebBuilders() : FlutterQuillEmbeds.editorBuilders( imageEmbedConfigurations: QuillEditorImageEmbedConfigurations( @@ -110,9 +110,7 @@ class MyQuillEditor extends StatelessWidget { // only for Android, iOS and web // We will use it only if image from network - if (isAndroid(supportWeb: false) || - isIOS(supportWeb: false) || - isWeb()) { + if (isAndroidApp || isIosApp || kIsWeb) { if (isHttpBasedUrl(imageUrl)) { return CachedNetworkImageProvider( imageUrl, @@ -132,7 +130,7 @@ class MyQuillEditor extends StatelessWidget { videoEmbedConfigurations: QuillEditorVideoEmbedConfigurations( // Loading YouTube videos on Desktop is not supported yet // when using iframe platform view - youtubeVideoSupportMode: isDesktop(supportWeb: false) + youtubeVideoSupportMode: isDesktopApp ? YoutubeVideoSupportMode.customPlayerWithDownloadUrl : YoutubeVideoSupportMode.iframeView, ), @@ -141,7 +139,7 @@ class MyQuillEditor extends StatelessWidget { ], builder: (context, rawEditor) { // The `desktop_drop` plugin doesn't support iOS platform for now - if (isIOS(supportWeb: false)) { + if (isIosApp) { return rawEditor; } return DropTarget( diff --git a/example/lib/screens/quill/my_quill_toolbar.dart b/example/lib/screens/quill/my_quill_toolbar.dart index 6ea80d44d..ef42c03cc 100644 --- a/example/lib/screens/quill/my_quill_toolbar.dart +++ b/example/lib/screens/quill/my_quill_toolbar.dart @@ -1,8 +1,9 @@ import 'dart:io' as io show File; +import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_quill/extensions.dart' show isAndroid, isIOS, isWeb; +import 'package:flutter_quill/extensions.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -65,7 +66,7 @@ class MyQuillToolbar extends StatelessWidget { if (newImage == null) { return; } - if (isWeb()) { + if (kIsWeb) { controller.insertImageBlock(imageSource: newImage); return; } @@ -74,7 +75,7 @@ class MyQuillToolbar extends StatelessWidget { } Future onImageInsert(String image, QuillController controller) async { - if (isWeb() || isHttpBasedUrl(image)) { + if (kIsWeb || isHttpBasedUrl(image)) { controller.insertImageBlock(imageSource: image); return; } @@ -295,9 +296,7 @@ class MyQuillToolbar extends StatelessWidget { embedButtons: FlutterQuillEmbeds.toolbarButtons( imageButtonOptions: QuillToolbarImageButtonOptions( imageButtonConfigurations: QuillToolbarImageConfigurations( - onImageInsertCallback: isAndroid(supportWeb: false) || - isIOS(supportWeb: false) || - isWeb() + onImageInsertCallback: isAndroidApp || isIosApp || kIsWeb ? (image, controller) => onImageInsertWithCropping(image, controller, context) : onImageInsert, diff --git a/example/lib/screens/settings/widgets/settings_screen.dart b/example/lib/screens/settings/widgets/settings_screen.dart index 49ffa4568..3bee862f3 100644 --- a/example/lib/screens/settings/widgets/settings_screen.dart +++ b/example/lib/screens/settings/widgets/settings_screen.dart @@ -77,12 +77,6 @@ class SettingsScreen extends StatelessWidget { actions: [ AppDialogAction( onPressed: () => Navigator.of(context).pop(null), - options: const DialogActionOptions( - cupertinoDialogActionOptions: - CupertinoDialogActionOptions( - isDefaultAction: true, - ), - ), child: const Text('Cancel'), ), ], diff --git a/example/lib/screens/shared/widgets/dialog_action.dart b/example/lib/screens/shared/widgets/dialog_action.dart index 0761e0664..74d19840a 100644 --- a/example/lib/screens/shared/widgets/dialog_action.dart +++ b/example/lib/screens/shared/widgets/dialog_action.dart @@ -1,62 +1,23 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_quill/extensions.dart'; - -@immutable -final class CupertinoDialogActionOptions { - const CupertinoDialogActionOptions({ - this.isDefaultAction = false, - }); - - final bool isDefaultAction; -} - -@immutable -final class MaterialDialogActionOptions { - const MaterialDialogActionOptions({ - this.textStyle, - }); - - final ButtonStyle? textStyle; -} - -@immutable -class DialogActionOptions { - const DialogActionOptions({ - this.cupertinoDialogActionOptions, - this.materialDialogActionOptions, - }); - - final CupertinoDialogActionOptions? cupertinoDialogActionOptions; - final MaterialDialogActionOptions? materialDialogActionOptions; -} class AppDialogAction extends StatelessWidget { const AppDialogAction({ required this.child, required this.onPressed, - this.options, + this.textStyle, super.key, }); final VoidCallback? onPressed; final Widget child; - final DialogActionOptions? options; + final ButtonStyle? textStyle; @override Widget build(BuildContext context) { - if (isAppleOS(supportWeb: true)) { - return CupertinoDialogAction( - onPressed: onPressed, - isDefaultAction: - options?.cupertinoDialogActionOptions?.isDefaultAction ?? false, - child: child, - ); - } return TextButton( onPressed: onPressed, - style: options?.materialDialogActionOptions?.textStyle, + style: textStyle, child: child, ); } diff --git a/flutter_quill_extensions/lib/src/editor/image/image_menu.dart b/flutter_quill_extensions/lib/src/editor/image/image_menu.dart index f031a19c2..c0efff770 100644 --- a/flutter_quill_extensions/lib/src/editor/image/image_menu.dart +++ b/flutter_quill_extensions/lib/src/editor/image/image_menu.dart @@ -168,7 +168,7 @@ class ImageOptionsMenu extends StatelessWidget { localizations.savedUsingLocalStorage, }; - if (isDesktop(supportWeb: false)) { + if (isDesktopApp) { message = localizations.theImageHasBeenSavedAt(imageSource); } diff --git a/flutter_quill_extensions/lib/src/editor/image/models/image_configurations.dart b/flutter_quill_extensions/lib/src/editor/image/models/image_configurations.dart index 3bb0c4a8b..f8edcf0a7 100644 --- a/flutter_quill_extensions/lib/src/editor/image/models/image_configurations.dart +++ b/flutter_quill_extensions/lib/src/editor/image/models/image_configurations.dart @@ -1,7 +1,7 @@ import 'dart:io' show File; +import 'package:flutter/foundation.dart'; import 'package:flutter_quill/extensions.dart'; -import 'package:meta/meta.dart' show immutable; import '../image_embed_types.dart'; @@ -108,11 +108,11 @@ class QuillEditorImageEmbedConfigurations { static ImageEmbedBuilderOnRemovedCallback get defaultOnImageRemovedCallback { return (imageUrl) async { - if (isWeb()) { + if (kIsWeb) { return; } - final mobile = isMobile(supportWeb: false); + final mobile = isMobileApp; // If the platform is not mobile, return void; // Since the mobile OS gives us a copy of the image diff --git a/flutter_quill_extensions/lib/src/toolbar/camera/select_camera_action.dart b/flutter_quill_extensions/lib/src/toolbar/camera/select_camera_action.dart index c20670280..28e66da66 100644 --- a/flutter_quill_extensions/lib/src/toolbar/camera/select_camera_action.dart +++ b/flutter_quill_extensions/lib/src/toolbar/camera/select_camera_action.dart @@ -21,7 +21,7 @@ class SelectCameraActionDialog extends StatelessWidget { context.loc.takeAPhotoUsingYourCamera, ), leading: const Icon(Icons.photo_sharp), - enabled: !isDesktop(supportWeb: false), + enabled: !isDesktopApp, onTap: () => Navigator.of(context).pop(CameraAction.image), ), ListTile( @@ -30,7 +30,7 @@ class SelectCameraActionDialog extends StatelessWidget { context.loc.recordAVideoUsingYourCamera, ), leading: const Icon(Icons.camera), - enabled: !isDesktop(supportWeb: false), + enabled: !isDesktopApp, onTap: () => Navigator.of(context).pop(CameraAction.video), ), ], diff --git a/flutter_quill_extensions/lib/src/toolbar/image/select_image_source.dart b/flutter_quill_extensions/lib/src/toolbar/image/select_image_source.dart index bd1fbb465..d67d11125 100644 --- a/flutter_quill_extensions/lib/src/toolbar/image/select_image_source.dart +++ b/flutter_quill_extensions/lib/src/toolbar/image/select_image_source.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_quill/extensions.dart' show isDesktop; +import 'package:flutter_quill/extensions.dart' show isDesktopApp; import 'package:flutter_quill/translations.dart'; import '../../editor/image/image_embed_types.dart'; @@ -29,7 +29,7 @@ class SelectImageSourceDialog extends StatelessWidget { context.loc.takeAPhotoUsingYourCamera, ), leading: const Icon(Icons.camera), - enabled: !isDesktop(supportWeb: false), + enabled: !isDesktopApp, onTap: () => Navigator.of(context).pop(InsertImageSource.camera), ), ListTile( diff --git a/flutter_quill_extensions/lib/src/toolbar/video/select_video_source.dart b/flutter_quill_extensions/lib/src/toolbar/video/select_video_source.dart index d4c9479c9..0c3126ef0 100644 --- a/flutter_quill_extensions/lib/src/toolbar/video/select_video_source.dart +++ b/flutter_quill_extensions/lib/src/toolbar/video/select_video_source.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_quill/extensions.dart' show isDesktop; +import 'package:flutter_quill/extensions.dart' show isDesktopApp; import 'package:flutter_quill/translations.dart'; import 'models/video.dart'; @@ -27,7 +27,7 @@ class SelectVideoSourceDialog extends StatelessWidget { title: Text(context.loc.camera), subtitle: Text(context.loc.recordAVideoUsingYourCamera), leading: const Icon(Icons.camera), - enabled: !isDesktop(supportWeb: false), + enabled: !isDesktopApp, onTap: () => Navigator.of(context).pop(InsertVideoSource.camera), ), ListTile( diff --git a/lib/extensions.dart b/lib/extensions.dart index dd0632234..002d1bd9e 100644 --- a/lib/extensions.dart +++ b/lib/extensions.dart @@ -1,5 +1,9 @@ library flutter_quill.extensions; +// This file contains exports that are meant to be used +// internally and are not part of the public API as +// breaking changes can happen + export 'src/common/utils/platform.dart'; export 'src/common/utils/string.dart'; export 'src/common/utils/widgets.dart'; diff --git a/lib/src/common/utils/platform.dart b/lib/src/common/utils/platform.dart index d248b3698..3d94a5605 100644 --- a/lib/src/common/utils/platform.dart +++ b/lib/src/common/utils/platform.dart @@ -2,118 +2,25 @@ import 'dart:io' show Platform; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart' - show TargetPlatform, defaultTargetPlatform, kIsWeb, visibleForTesting; - -/// If you want to override the [kIsWeb] use [overrideIsWeb] but it's only -/// for testing -bool isWeb({ - @visibleForTesting bool? overrideIsWeb, -}) { - return overrideIsWeb ?? kIsWeb; -} + show TargetPlatform, defaultTargetPlatform, kDebugMode, kIsWeb; +import 'package:flutter/material.dart'; -/// [supportWeb] is a parameter that ask you if we should care about web support -/// if the value is true then we will return the result no matter if we are -/// on web or using a native app to run the flutter app -bool isMobile({ - required bool supportWeb, - TargetPlatform? platform, - bool? overrideIsWeb, -}) { - if (isWeb(overrideIsWeb: overrideIsWeb) && !supportWeb) return false; - platform ??= defaultTargetPlatform; - return {TargetPlatform.iOS, TargetPlatform.android}.contains(platform); -} +// Android -/// [supportWeb] is a parameter that ask you if we should care about web support -/// if the value is true then we will return the result no matter if we are -/// on web or using a native app to run the flutter app -bool isDesktop({ - required bool supportWeb, - TargetPlatform? platform, - bool? overrideIsWeb, -}) { - if (isWeb(overrideIsWeb: overrideIsWeb) && !supportWeb) return false; - platform ??= defaultTargetPlatform; - return {TargetPlatform.macOS, TargetPlatform.linux, TargetPlatform.windows} - .contains(platform); -} +@pragma('vm:platform-const-if', !kDebugMode) +bool get isAndroidApp => + !kIsWeb && defaultTargetPlatform == TargetPlatform.android; -/// [supportWeb] is a parameter that ask you if we should care about web support -/// if the value is true then we will return the result no matter if we are -/// on web or using a native app to run the flutter app -bool isKeyboardOS({ - required bool supportWeb, - TargetPlatform? platform, - bool? overrideIsWeb, -}) { - platform ??= defaultTargetPlatform; - return isDesktop( - platform: platform, - supportWeb: supportWeb, - overrideIsWeb: overrideIsWeb) || - platform == TargetPlatform.fuchsia; -} +// iOS -/// [supportWeb] is a parameter that ask you if we should care about web support -/// if the value is true then we will return the result no matter if we are -/// on web or using a native app to run the flutter app -bool isAppleOS({ - required bool supportWeb, - TargetPlatform? platform, - bool? overrideIsWeb, -}) { - if (isWeb(overrideIsWeb: overrideIsWeb) && !supportWeb) return false; - platform ??= defaultTargetPlatform; - return { - TargetPlatform.macOS, - TargetPlatform.iOS, - }.contains(platform); -} +@pragma('vm:platform-const-if', !kDebugMode) +bool get isIos => defaultTargetPlatform == TargetPlatform.iOS; -/// [supportWeb] is a parameter that ask you if we should care about web support -/// if the value is true then we will return the result no matter if we are -/// on web or using a native app to run the flutter app -bool isMacOS({ - required bool supportWeb, - TargetPlatform? platform, - bool? overrideIsWeb, -}) { - if (isWeb(overrideIsWeb: overrideIsWeb) && !supportWeb) return false; - platform ??= defaultTargetPlatform; - return TargetPlatform.macOS == platform; -} +@pragma('vm:platform-const-if', !kDebugMode) +bool get isIosApp => !kIsWeb && defaultTargetPlatform == TargetPlatform.android; -/// [supportWeb] is a parameter that ask you if we should care about web support -/// if the value is true then we will return the result no matter if we are -/// on web or using a native app to run the flutter app -bool isIOS({ - required bool supportWeb, - TargetPlatform? platform, - bool? overrideIsWeb, -}) { - if (isWeb(overrideIsWeb: overrideIsWeb) && !supportWeb) return false; - platform ??= defaultTargetPlatform; - return TargetPlatform.iOS == platform; -} - -/// [supportWeb] is a parameter that ask you if we should care about web support -/// if the value is true then we will return the result no matter if we are -/// on web or using a native app to run the flutter app -bool isAndroid({ - required bool supportWeb, - TargetPlatform? platform, - bool? overrideIsWeb, -}) { - if (isWeb(overrideIsWeb: overrideIsWeb) && !supportWeb) return false; - platform ??= defaultTargetPlatform; - return TargetPlatform.android == platform; -} - -Future isIOSSimulator({ - bool? overrideIsWeb, -}) async { - if (!isAppleOS(supportWeb: false, overrideIsWeb: overrideIsWeb)) { +Future isIOSSimulator() async { + if (kIsWeb || defaultTargetPlatform != TargetPlatform.iOS) { return false; } @@ -128,9 +35,73 @@ Future isIOSSimulator({ return false; } -bool isFlutterTest({ - bool? overrideIsWeb, -}) { - if (isWeb(overrideIsWeb: overrideIsWeb)) return false; +// Mobile + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isMobile => + defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.android; + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isMobileApp => + !kIsWeb && + (defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.android); + +// Destkop + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isDesktop => + defaultTargetPlatform == TargetPlatform.linux || + defaultTargetPlatform == TargetPlatform.macOS || + defaultTargetPlatform == TargetPlatform.windows; + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isDesktopApp => + !kIsWeb && + (defaultTargetPlatform == TargetPlatform.linux || + defaultTargetPlatform == TargetPlatform.macOS || + defaultTargetPlatform == TargetPlatform.windows); + +// macOS + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isMacOS => defaultTargetPlatform == TargetPlatform.macOS; + +// AppleOS + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isAppleOS => + defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.macOS; + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isAppleOSApp => + !kIsWeb && + (defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.macOS); + +// Keyboard + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isKeyboardOS => + isDesktop || defaultTargetPlatform == TargetPlatform.fuchsia; + +extension PlatformThemeCheckExtension on ThemeData { + bool get isMaterial => platform == TargetPlatform.android; + bool get isCupertino => platform == TargetPlatform.iOS; +} + +/// Should check if [kIsWeb] is `false` before checking if +/// this is a test. +bool get isFlutterTest { + assert(() { + if (kIsWeb) { + throw FlutterError( + 'The getter `isFlutterTest` should not be used in web', + ); + } + return true; + }()); return Platform.environment.containsKey('FLUTTER_TEST'); } diff --git a/lib/src/editor/editor.dart b/lib/src/editor/editor.dart index 649176b08..e1afa8145 100644 --- a/lib/src/editor/editor.dart +++ b/lib/src/editor/editor.dart @@ -3,7 +3,7 @@ import 'dart:math' as math; import 'package:flutter/cupertino.dart' show CupertinoTheme, cupertinoTextSelectionControls; import 'package:flutter/foundation.dart' - show ValueListenable, defaultTargetPlatform; + show ValueListenable, defaultTargetPlatform, kIsWeb; import 'package:flutter/gestures.dart' show PointerDeviceKind, @@ -263,10 +263,7 @@ class QuillEditorState extends State Color selectionColor; Radius? cursorRadius; - if (isAppleOS( - platform: theme.platform, - supportWeb: true, - )) { + if (theme.isCupertino) { final cupertinoTheme = CupertinoTheme.of(context); textSelectionControls = cupertinoTextSelectionControls; paintCursorAboveText = true; @@ -316,10 +313,7 @@ class QuillEditorState extends State ? (configurations.contextMenuBuilder ?? QuillRawEditorConfigurations.defaultContextMenuBuilder) : null, - showSelectionHandles: isMobile( - platform: theme.platform, - supportWeb: true, - ), + showSelectionHandles: isMobile, showCursor: configurations.showCursor ?? true, cursorStyle: CursorStyle( color: cursorColor, @@ -381,7 +375,7 @@ class QuillEditorState extends State ) : child; - if (isWeb()) { + if (kIsWeb) { // Intercept RawKeyEvent on Web to prevent it from propagating to parents // that might interfere with the editor key behavior, such as // SingleChildScrollView. Thanks to @wliumelb for the workaround. @@ -477,11 +471,7 @@ class _QuillEditorSelectionGestureDetectorBuilder return; } - final platform = Theme.of(_state.context).platform; - if (isAppleOS( - platform: platform, - supportWeb: true, - )) { + if (Theme.of(_state.context).isCupertino) { renderEditor!.selectPositionAt( from: details.globalPosition, cause: SelectionChangedCause.longPress, @@ -554,9 +544,7 @@ class _QuillEditorSelectionGestureDetectorBuilder try { if (delegate.selectionEnabled && !_isPositionSelected(details)) { - final platform = Theme.of(_state.context).platform; - if (isAppleOS(platform: platform, supportWeb: true) || - isDesktop(platform: platform, supportWeb: true)) { + if (isAppleOS || isDesktop) { // added isDesktop() to enable extend selection in Windows platform switch (details.kind) { case PointerDeviceKind.mouse: @@ -619,11 +607,7 @@ class _QuillEditorSelectionGestureDetectorBuilder } if (delegate.selectionEnabled) { - final platform = Theme.of(_state.context).platform; - if (isAppleOS( - platform: platform, - supportWeb: true, - )) { + if (Theme.of(_state.context).isCupertino) { renderEditor!.selectPositionAt( from: details.globalPosition, cause: SelectionChangedCause.longPress, diff --git a/lib/src/editor/raw_editor/raw_editor_state.dart b/lib/src/editor/raw_editor/raw_editor_state.dart index ef9fed206..0d7408945 100644 --- a/lib/src/editor/raw_editor/raw_editor_state.dart +++ b/lib/src/editor/raw_editor/raw_editor_state.dart @@ -513,11 +513,7 @@ class QuillRawEditorState extends EditorState maxHeight: widget.configurations.maxHeight ?? double.infinity, ); - // Please notice that this change will make the check fixed - // so if we ovveride the platform in material app theme data - // it will not depend on it and doesn't change here but I don't think - // we need to - final isDesktopMacOS = isMacOS(supportWeb: true); + final isDesktopMacOS = isMacOS; return TextFieldTapRegion( enabled: widget.configurations.isOnTapOutsideEnabled, @@ -1191,9 +1187,9 @@ class QuillRawEditorState extends EditorState _floatingCursorResetController = AnimationController(vsync: this); _floatingCursorResetController.addListener(onFloatingCursorResetTick); - if (isKeyboardOS(supportWeb: true)) { + if (isKeyboardOS) { _keyboardVisible = true; - } else if (!isWeb() && isFlutterTest()) { + } else if (!kIsWeb && isFlutterTest) { // treat tests like a keyboard OS _keyboardVisible = true; } else { @@ -1356,7 +1352,7 @@ class QuillRawEditorState extends EditorState } void _didChangeTextEditingValue([bool ignoreFocus = false]) { - if (isWeb()) { + if (kIsWeb) { _onChangeTextEditingValue(ignoreFocus); if (!ignoreFocus) { requestKeyboard(); @@ -1576,7 +1572,7 @@ class QuillRawEditorState extends EditorState // toolbar: copy, paste, select, cut. It might also provide additional // functionality depending on the browser (such as translate). Due to this // we should not show a Flutter toolbar for the editable text elements. - if (isWeb()) { + if (kIsWeb) { return false; } diff --git a/lib/src/editor/widgets/cursor.dart b/lib/src/editor/widgets/cursor.dart index 5b2fa21e8..e89df9e81 100644 --- a/lib/src/editor/widgets/cursor.dart +++ b/lib/src/editor/widgets/cursor.dart @@ -291,7 +291,7 @@ class CursorPainter { final caretHeight = editable!.getFullHeightForCaret(position); if (caretHeight != null) { - if (isAppleOS(supportWeb: false)) { + if (isAppleOSApp) { // Center the caret vertically along the text. caretRect = Rect.fromLTWH( caretRect.left, diff --git a/lib/src/editor/widgets/default_styles.dart b/lib/src/editor/widgets/default_styles.dart index 8ae38d0d6..0d55366e7 100644 --- a/lib/src/editor/widgets/default_styles.dart +++ b/lib/src/editor/widgets/default_styles.dart @@ -256,12 +256,7 @@ class DefaultStyles { ); const baseHorizontalSpacing = HorizontalSpacing(0, 0); const baseVerticalSpacing = VerticalSpacing(6, 0); - String fontFamily; - if (isAppleOS(platform: themeData.platform, supportWeb: true)) { - fontFamily = 'Menlo'; - } else { - fontFamily = 'Roboto Mono'; - } + final fontFamily = themeData.isCupertino ? 'Menlo' : 'Roboto Mono'; final inlineCodeStyle = TextStyle( fontSize: 14, diff --git a/lib/src/editor/widgets/delegate.dart b/lib/src/editor/widgets/delegate.dart index b8d133813..836e7e37b 100644 --- a/lib/src/editor/widgets/delegate.dart +++ b/lib/src/editor/widgets/delegate.dart @@ -975,7 +975,7 @@ class EditorTextSelectionGestureDetectorBuilder { void onDragSelectionEnd(TapDragEndDetails details) { // if (editor?.textEditingValue.selection.isCollapsed == false) return; renderEditor!.handleDragEnd(details); - if (isDesktop(supportWeb: true) && + if (isDesktop && delegate.selectionEnabled && checkSelectionToolbarShouldShow(isAdditionalAction: false)) { // added to show selection copy/paste toolbar after drag to select diff --git a/lib/src/editor/widgets/text/text_line.dart b/lib/src/editor/widgets/text/text_line.dart index 266b4be82..597741209 100644 --- a/lib/src/editor/widgets/text/text_line.dart +++ b/lib/src/editor/widgets/text/text_line.dart @@ -86,7 +86,7 @@ class _TextLineState extends State { // Desktop platforms (macOS, Linux, Windows): // only allow Meta (Control) + Click combinations - if (isDesktop(supportWeb: false)) { + if (isDesktopApp) { return _metaOrControlPressed; } // Mobile platforms (ios, android): always allow but we install a @@ -541,7 +541,7 @@ class _TextLineState extends State { } if (isLink && canLaunchLinks) { - if (isDesktop(supportWeb: true) || widget.readOnly) { + if (isDesktop || widget.readOnly) { _linkRecognizers[segment] = TapGestureRecognizer() ..onTap = () => _tapNodeLink(segment); } else { @@ -1016,9 +1016,7 @@ class RenderEditableTextLine extends RenderEditableBox { /// of the cursor for iOS is approximate and obtained through an eyeball /// comparison. void _computeCaretPrototype() { - // If the cursor is taller only on iOS and not AppleOS then we should check - // only for iOS instead of AppleOS (macOS for example) - if (isIOS(supportWeb: true)) { + if (isIos) { _caretPrototype = Rect.fromLTWH(0, 0, cursorWidth, cursorHeight + 2); } else { _caretPrototype = Rect.fromLTWH(0, 2, cursorWidth, cursorHeight - 4.0); diff --git a/lib/src/toolbar/buttons/search/search_dialog.dart b/lib/src/toolbar/buttons/search/search_dialog.dart index a5cc7f7f8..72d959ef1 100644 --- a/lib/src/toolbar/buttons/search/search_dialog.dart +++ b/lib/src/toolbar/buttons/search/search_dialog.dart @@ -111,7 +111,7 @@ class QuillToolbarSearchDialogState extends State { final searchBarAtBottom = (searchBarAlignment == Alignment.bottomCenter) || (searchBarAlignment == Alignment.bottomLeft) || (searchBarAlignment == Alignment.bottomRight); - final addBottomPadding = searchBarAtBottom && isMobile(supportWeb: true); + final addBottomPadding = searchBarAtBottom && isMobile; var matchShown = ''; if (_text.isNotEmpty) { if (_offsets.isEmpty) { diff --git a/test/common/utils/platform_test.dart b/test/common/utils/platform_test.dart index 496514049..ece4c516e 100644 --- a/test/common/utils/platform_test.dart +++ b/test/common/utils/platform_test.dart @@ -1,17 +1,15 @@ -import 'package:flutter/foundation.dart' show TargetPlatform; +import 'package:flutter/foundation.dart' + show TargetPlatform, debugDefaultTargetPlatformOverride; import 'package:flutter_quill/src/common/utils/platform.dart'; import 'package:test/test.dart'; void main() { group('Test platform checking logic', () { - var platform = TargetPlatform.linux; - test('Check isDesktop()', () { - platform = TargetPlatform.android; + debugDefaultTargetPlatformOverride = TargetPlatform.linux; + test('Check isDesktop', () { + debugDefaultTargetPlatformOverride = TargetPlatform.android; expect( - isDesktop( - platform: platform, - supportWeb: true, - ), + isDesktop, false, ); @@ -20,41 +18,23 @@ void main() { TargetPlatform.linux, TargetPlatform.windows ]) { + debugDefaultTargetPlatformOverride = desktopPlatform; expect( - isDesktop( - supportWeb: false, - overrideIsWeb: false, - platform: desktopPlatform, - ), + isDesktopApp, true, ); + debugDefaultTargetPlatformOverride = null; expect( - isDesktop( - supportWeb: false, - overrideIsWeb: true, - platform: desktopPlatform, - ), + isDesktopApp, false, ); - - expect( - isDesktop( - supportWeb: true, - overrideIsWeb: true, - platform: desktopPlatform, - ), - true, - ); } }); - test('Check isMobile()', () { - platform = TargetPlatform.macOS; + test('Check isMobile', () { + debugDefaultTargetPlatformOverride = TargetPlatform.macOS; expect( - isMobile( - platform: platform, - supportWeb: true, - ), + isMobile, false, ); @@ -62,95 +42,19 @@ void main() { TargetPlatform.android, TargetPlatform.iOS, ]) { + debugDefaultTargetPlatformOverride = mobilePlatform; expect( - isMobile( - platform: mobilePlatform, - supportWeb: false, - overrideIsWeb: false, - ), + isMobile, true, ); - expect( - isMobile( - platform: mobilePlatform, - supportWeb: false, - overrideIsWeb: true, - ), - false, - ); + debugDefaultTargetPlatformOverride = TargetPlatform.windows; expect( - isMobile( - supportWeb: true, - overrideIsWeb: true, - platform: mobilePlatform, - ), - true, + isMobile, + false, ); } }); - test( - 'Check supportWeb parameter when using desktop platform on web', - () { - platform = TargetPlatform.macOS; - expect( - isDesktop( - platform: platform, - supportWeb: true, - ), - true, - ); - expect( - isDesktop( - platform: platform, - supportWeb: false, - overrideIsWeb: false, - ), - true, - ); - - expect( - isDesktop( - platform: platform, - supportWeb: false, - overrideIsWeb: true, - ), - false, - ); - }, - ); - - test( - 'Check supportWeb parameter when using mobile platform on web', - () { - platform = TargetPlatform.android; - expect( - isMobile( - platform: platform, - supportWeb: true, - overrideIsWeb: true, - ), - true, - ); - expect( - isMobile( - platform: platform, - supportWeb: false, - overrideIsWeb: false, - ), - true, - ); - - expect( - isMobile( - platform: platform, - supportWeb: false, - overrideIsWeb: true, - ), - false, - ); - }, - ); }); } From b869dce9ca674a284de01dcfaeed267921f805bf Mon Sep 17 00:00:00 2001 From: Ellet Date: Fri, 6 Sep 2024 14:56:40 +0300 Subject: [PATCH 2/3] chore: update isMaterial and isCupertino to support other platforms --- lib/src/common/utils/platform.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/common/utils/platform.dart b/lib/src/common/utils/platform.dart index 3d94a5605..bf2b5a584 100644 --- a/lib/src/common/utils/platform.dart +++ b/lib/src/common/utils/platform.dart @@ -88,8 +88,9 @@ bool get isKeyboardOS => isDesktop || defaultTargetPlatform == TargetPlatform.fuchsia; extension PlatformThemeCheckExtension on ThemeData { - bool get isMaterial => platform == TargetPlatform.android; - bool get isCupertino => platform == TargetPlatform.iOS; + bool get isMaterial => !isCupertino; + bool get isCupertino => + {TargetPlatform.iOS, TargetPlatform.macOS}.contains(platform); } /// Should check if [kIsWeb] is `false` before checking if From fb16b77e4bc11181456989ec6f15e73f6d646d57 Mon Sep 17 00:00:00 2001 From: Ellet Date: Fri, 6 Sep 2024 16:10:32 +0300 Subject: [PATCH 3/3] chore: add isMacOSApp and isAndroidApp --- lib/src/common/utils/platform.dart | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/lib/src/common/utils/platform.dart b/lib/src/common/utils/platform.dart index bf2b5a584..60c8a0b17 100644 --- a/lib/src/common/utils/platform.dart +++ b/lib/src/common/utils/platform.dart @@ -8,8 +8,10 @@ import 'package:flutter/material.dart'; // Android @pragma('vm:platform-const-if', !kDebugMode) -bool get isAndroidApp => - !kIsWeb && defaultTargetPlatform == TargetPlatform.android; +bool get isAndroid => defaultTargetPlatform == TargetPlatform.android; + +@pragma('vm:platform-const-if', !kDebugMode) +bool get isAndroidApp => !kIsWeb && isAndroid; // iOS @@ -17,7 +19,7 @@ bool get isAndroidApp => bool get isIos => defaultTargetPlatform == TargetPlatform.iOS; @pragma('vm:platform-const-if', !kDebugMode) -bool get isIosApp => !kIsWeb && defaultTargetPlatform == TargetPlatform.android; +bool get isIosApp => !kIsWeb && isIos; Future isIOSSimulator() async { if (kIsWeb || defaultTargetPlatform != TargetPlatform.iOS) { @@ -43,10 +45,7 @@ bool get isMobile => defaultTargetPlatform == TargetPlatform.android; @pragma('vm:platform-const-if', !kDebugMode) -bool get isMobileApp => - !kIsWeb && - (defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.android); +bool get isMobileApp => !kIsWeb && isMobile; // Destkop @@ -57,17 +56,16 @@ bool get isDesktop => defaultTargetPlatform == TargetPlatform.windows; @pragma('vm:platform-const-if', !kDebugMode) -bool get isDesktopApp => - !kIsWeb && - (defaultTargetPlatform == TargetPlatform.linux || - defaultTargetPlatform == TargetPlatform.macOS || - defaultTargetPlatform == TargetPlatform.windows); +bool get isDesktopApp => !kIsWeb && isDesktop; // macOS @pragma('vm:platform-const-if', !kDebugMode) bool get isMacOS => defaultTargetPlatform == TargetPlatform.macOS; +@pragma('vm:platform-const-if', !kDebugMode) +bool get isMacOSApp => !kIsWeb && isMacOS; + // AppleOS @pragma('vm:platform-const-if', !kDebugMode) @@ -76,10 +74,7 @@ bool get isAppleOS => defaultTargetPlatform == TargetPlatform.macOS; @pragma('vm:platform-const-if', !kDebugMode) -bool get isAppleOSApp => - !kIsWeb && - (defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.macOS); +bool get isAppleOSApp => !kIsWeb && isAppleOS; // Keyboard