Refactor using platform helper

pull/602/head
X Code 3 years ago
parent 6b9c85f7cc
commit 53507416d0
  1. 23
      lib/src/utils/platform_helper.dart
  2. 49
      lib/src/widgets/cursor.dart
  3. 20
      lib/src/widgets/default_styles.dart
  4. 185
      lib/src/widgets/editor.dart
  5. 35
      lib/src/widgets/raw_editor.dart
  6. 24
      lib/src/widgets/text_line.dart

@ -5,8 +5,21 @@ bool isMobile([TargetPlatform? targetPlatform]) {
return {TargetPlatform.iOS, TargetPlatform.android}.contains(targetPlatform); return {TargetPlatform.iOS, TargetPlatform.android}.contains(targetPlatform);
} }
bool get isDesktop => { bool isDesktop([TargetPlatform? targetPlatform]) {
TargetPlatform.macOS, targetPlatform ??= defaultTargetPlatform;
TargetPlatform.linux, return {TargetPlatform.macOS, TargetPlatform.linux, TargetPlatform.windows}
TargetPlatform.windows .contains(targetPlatform);
}.contains(defaultTargetPlatform); }
bool isKeyboardOS([TargetPlatform? targetPlatform]) {
targetPlatform ??= defaultTargetPlatform;
return isDesktop(targetPlatform) || targetPlatform == TargetPlatform.fuchsia;
}
bool isAppleOS([TargetPlatform? targetPlatform]) {
targetPlatform ??= defaultTargetPlatform;
return {
TargetPlatform.macOS,
TargetPlatform.iOS,
}.contains(targetPlatform);
}

@ -1,8 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import '../utils/platform_helper.dart';
import 'box.dart'; import 'box.dart';
/// Style properties of editing cursor. /// Style properties of editing cursor.
@ -287,33 +287,26 @@ class CursorPainter {
final caretHeight = editable!.getFullHeightForCaret(position); final caretHeight = editable!.getFullHeightForCaret(position);
if (caretHeight != null) { if (caretHeight != null) {
switch (defaultTargetPlatform) { if (isKeyboardOS()) {
case TargetPlatform.android: // Override the height to take the full height of the glyph at the
case TargetPlatform.fuchsia: // TextPosition when not on iOS. iOS has special handling that
case TargetPlatform.linux: // creates a taller caret.
case TargetPlatform.windows: caretRect = Rect.fromLTWH(
// Override the height to take the full height of the glyph at the caretRect.left,
// TextPosition when not on iOS. iOS has special handling that caretRect.top - 2.0,
// creates a taller caret. caretRect.width,
caretRect = Rect.fromLTWH( caretHeight,
caretRect.left, );
caretRect.top - 2.0, } else if (isAppleOS()) {
caretRect.width, // Center the caret vertically along the text.
caretHeight, caretRect = Rect.fromLTWH(
); caretRect.left,
break; caretRect.top + (caretHeight - caretRect.height) / 2,
case TargetPlatform.iOS: caretRect.width,
case TargetPlatform.macOS: caretRect.height,
// Center the caret vertically along the text. );
caretRect = Rect.fromLTWH( } else {
caretRect.left, throw UnimplementedError();
caretRect.top + (caretHeight - caretRect.height) / 2,
caretRect.width,
caretRect.height,
);
break;
default:
throw UnimplementedError();
} }
} }

@ -3,6 +3,7 @@ import 'package:tuple/tuple.dart';
import '../../flutter_quill.dart'; import '../../flutter_quill.dart';
import '../../models/documents/style.dart'; import '../../models/documents/style.dart';
import '../utils/platform_helper.dart';
class QuillStyles extends InheritedWidget { class QuillStyles extends InheritedWidget {
const QuillStyles({ const QuillStyles({
@ -192,19 +193,12 @@ class DefaultStyles {
); );
const baseSpacing = Tuple2<double, double>(6, 0); const baseSpacing = Tuple2<double, double>(6, 0);
String fontFamily; String fontFamily;
switch (themeData.platform) { if (isAppleOS(themeData.platform)) {
case TargetPlatform.iOS: fontFamily = 'Menlo';
case TargetPlatform.macOS: } else if (isKeyboardOS(themeData.platform)) {
fontFamily = 'Menlo'; fontFamily = 'Roboto Mono';
break; } else {
case TargetPlatform.android: throw UnimplementedError();
case TargetPlatform.fuchsia:
case TargetPlatform.windows:
case TargetPlatform.linux:
fontFamily = 'Roboto Mono';
break;
default:
throw UnimplementedError();
} }
final inlineCodeStyle = TextStyle( final inlineCodeStyle = TextStyle(

@ -398,34 +398,26 @@ class _QuillEditorState extends State<QuillEditor>
Color selectionColor; Color selectionColor;
Radius? cursorRadius; Radius? cursorRadius;
switch (theme.platform) { if (isKeyboardOS(theme.platform)) {
case TargetPlatform.android: textSelectionControls = materialTextSelectionControls;
case TargetPlatform.fuchsia: paintCursorAboveText = false;
case TargetPlatform.linux: cursorOpacityAnimates = false;
case TargetPlatform.windows: cursorColor ??= selectionTheme.cursorColor ?? theme.colorScheme.primary;
textSelectionControls = materialTextSelectionControls; selectionColor = selectionTheme.selectionColor ??
paintCursorAboveText = false; theme.colorScheme.primary.withOpacity(0.40);
cursorOpacityAnimates = false; } else if (isAppleOS(theme.platform)) {
cursorColor ??= selectionTheme.cursorColor ?? theme.colorScheme.primary; final cupertinoTheme = CupertinoTheme.of(context);
selectionColor = selectionTheme.selectionColor ?? textSelectionControls = cupertinoTextSelectionControls;
theme.colorScheme.primary.withOpacity(0.40); paintCursorAboveText = true;
break; cursorOpacityAnimates = true;
case TargetPlatform.iOS: cursorColor ??= selectionTheme.cursorColor ?? cupertinoTheme.primaryColor;
case TargetPlatform.macOS: selectionColor = selectionTheme.selectionColor ??
final cupertinoTheme = CupertinoTheme.of(context); cupertinoTheme.primaryColor.withOpacity(0.40);
textSelectionControls = cupertinoTextSelectionControls; cursorRadius ??= const Radius.circular(2);
paintCursorAboveText = true; cursorOffset = Offset(
cursorOpacityAnimates = true; iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio, 0);
cursorColor ??= } else {
selectionTheme.cursorColor ?? cupertinoTheme.primaryColor; throw UnimplementedError();
selectionColor = selectionTheme.selectionColor ??
cupertinoTheme.primaryColor.withOpacity(0.40);
cursorRadius ??= const Radius.circular(2);
cursorOffset = Offset(
iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio, 0);
break;
default:
throw UnimplementedError();
} }
final child = RawEditor( final child = RawEditor(
@ -524,26 +516,21 @@ class _QuillEditorSelectionGestureDetectorBuilder
if (!delegate.selectionEnabled) { if (!delegate.selectionEnabled) {
return; return;
} }
switch (Theme.of(_state.context).platform) {
case TargetPlatform.iOS: final _platform = Theme.of(_state.context).platform;
case TargetPlatform.macOS: if (isAppleOS(_platform)) {
renderEditor!.selectPositionAt( renderEditor!.selectPositionAt(
from: details.globalPosition, from: details.globalPosition,
cause: SelectionChangedCause.longPress, cause: SelectionChangedCause.longPress,
); );
break; } else if (isKeyboardOS(_platform)) {
case TargetPlatform.android: renderEditor!.selectWordsInRange(
case TargetPlatform.fuchsia: details.globalPosition - details.offsetFromOrigin,
case TargetPlatform.linux: details.globalPosition,
case TargetPlatform.windows: SelectionChangedCause.longPress,
renderEditor!.selectWordsInRange( );
details.globalPosition - details.offsetFromOrigin, } else {
details.globalPosition, throw UnimplementedError();
SelectionChangedCause.longPress,
);
break;
default:
throw 'Invalid platform';
} }
} }
@ -599,52 +586,40 @@ class _QuillEditorSelectionGestureDetectorBuilder
final positionSelected = _isPositionSelected(details); final positionSelected = _isPositionSelected(details);
if (delegate.selectionEnabled && !positionSelected) { if (delegate.selectionEnabled && !positionSelected) {
switch (Theme.of(_state.context).platform) { final _platform = Theme.of(_state.context).platform;
case TargetPlatform.iOS: if (isAppleOS(_platform)) {
case TargetPlatform.macOS: switch (details.kind) {
switch (details.kind) { case PointerDeviceKind.mouse:
case PointerDeviceKind.mouse: case PointerDeviceKind.stylus:
case PointerDeviceKind.stylus: case PointerDeviceKind.invertedStylus:
case PointerDeviceKind.invertedStylus: // Precise devices should place the cursor at a precise position.
// Precise devices should place the cursor at a precise position. // If `Shift` key is pressed then
// If `Shift` key is pressed then // extend current selection instead.
// extend current selection instead. if (isShiftClick(details.kind)) {
if (isShiftClick(details.kind)) { renderEditor!
renderEditor! ..extendSelection(details.globalPosition,
..extendSelection(details.globalPosition, cause: SelectionChangedCause.tap)
cause: SelectionChangedCause.tap) ..onSelectionCompleted();
..onSelectionCompleted(); } else {
} else { renderEditor!
renderEditor! ..selectPosition(cause: SelectionChangedCause.tap)
..selectPosition(cause: SelectionChangedCause.tap) ..onSelectionCompleted();
..onSelectionCompleted(); }
}
break;
break; case PointerDeviceKind.touch:
case PointerDeviceKind.touch: case PointerDeviceKind.unknown:
case PointerDeviceKind.unknown: // On macOS/iOS/iPadOS a touch tap places the cursor at the edge
// On macOS/iOS/iPadOS a touch tap places the cursor at the edge // of the word.
// of the word.
try {
renderEditor!
..selectWordEdge(SelectionChangedCause.tap)
..onSelectionCompleted();
} finally {
break;
}
}
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
try {
renderEditor! renderEditor!
..selectPosition(cause: SelectionChangedCause.tap) ..selectWordEdge(SelectionChangedCause.tap)
..onSelectionCompleted(); ..onSelectionCompleted();
} finally {
break; break;
} }
} else if (isKeyboardOS(_platform)) {
renderEditor!
..selectPosition(cause: SelectionChangedCause.tap)
..onSelectionCompleted();
} }
} }
_state._requestKeyboard(); _state._requestKeyboard();
@ -661,23 +636,17 @@ class _QuillEditorSelectionGestureDetectorBuilder
} }
if (delegate.selectionEnabled) { if (delegate.selectionEnabled) {
switch (Theme.of(_state.context).platform) { final _platform = Theme.of(_state.context).platform;
case TargetPlatform.iOS: if (isAppleOS(_platform)) {
case TargetPlatform.macOS: renderEditor!.selectPositionAt(
renderEditor!.selectPositionAt( from: details.globalPosition,
from: details.globalPosition, cause: SelectionChangedCause.longPress,
cause: SelectionChangedCause.longPress, );
); } else if (isKeyboardOS(_platform)) {
break; renderEditor!.selectWord(SelectionChangedCause.longPress);
case TargetPlatform.android: Feedback.forLongPress(_state.context);
case TargetPlatform.fuchsia: } else {
case TargetPlatform.linux: throw UnimplementedError();
case TargetPlatform.windows:
renderEditor!.selectWord(SelectionChangedCause.longPress);
Feedback.forLongPress(_state.context);
break;
default:
throw 'Invalid platform';
} }
} }
} }

@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -16,6 +17,7 @@ import '../models/documents/attribute.dart';
import '../models/documents/document.dart'; import '../models/documents/document.dart';
import '../models/documents/nodes/block.dart'; import '../models/documents/nodes/block.dart';
import '../models/documents/nodes/line.dart'; import '../models/documents/nodes/line.dart';
import '../utils/platform_helper.dart';
import 'controller.dart'; import 'controller.dart';
import 'cursor.dart'; import 'cursor.dart';
import 'default_styles.dart'; import 'default_styles.dart';
@ -524,10 +526,7 @@ class RawEditorState extends EditorState
_floatingCursorResetController = AnimationController(vsync: this); _floatingCursorResetController = AnimationController(vsync: this);
_floatingCursorResetController.addListener(onFloatingCursorResetTick); _floatingCursorResetController.addListener(onFloatingCursorResetTick);
if (defaultTargetPlatform == TargetPlatform.windows || if (isKeyboardOS()) {
defaultTargetPlatform == TargetPlatform.macOS ||
defaultTargetPlatform == TargetPlatform.linux ||
defaultTargetPlatform == TargetPlatform.fuchsia) {
_keyboardVisible = true; _keyboardVisible = true;
} else { } else {
_keyboardVisibilityController = KeyboardVisibilityController(); _keyboardVisibilityController = KeyboardVisibilityController();
@ -852,24 +851,16 @@ class RawEditorState extends EditorState
bringIntoView(textEditingValue.selection.extent); bringIntoView(textEditingValue.selection.extent);
hideToolbar(false); hideToolbar(false);
switch (defaultTargetPlatform) { if (isKeyboardOS() || Platform.isAndroid) {
case TargetPlatform.iOS: // Collapse the selection and hide the toolbar and handles.
break; userUpdateTextEditingValue(
case TargetPlatform.macOS: TextEditingValue(
case TargetPlatform.android: text: textEditingValue.text,
case TargetPlatform.fuchsia: selection:
case TargetPlatform.linux: TextSelection.collapsed(offset: textEditingValue.selection.end),
case TargetPlatform.windows: ),
// Collapse the selection and hide the toolbar and handles. SelectionChangedCause.toolbar,
userUpdateTextEditingValue( );
TextEditingValue(
text: textEditingValue.text,
selection: TextSelection.collapsed(
offset: textEditingValue.selection.end),
),
SelectionChangedCause.toolbar,
);
break;
} }
} }
} }

@ -1,7 +1,6 @@
import 'dart:collection'; import 'dart:collection';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
@ -81,7 +80,7 @@ class _TextLineState extends State<TextLine> {
// Desktop platforms (macos, linux, windows): // Desktop platforms (macos, linux, windows):
// only allow Meta(Control)+Click combinations // only allow Meta(Control)+Click combinations
if (isDesktop) { if (isDesktop()) {
return _metaOrControlPressed; return _metaOrControlPressed;
} }
// Mobile platforms (ios, android): always allow but we install a // Mobile platforms (ios, android): always allow but we install a
@ -376,7 +375,7 @@ class _TextLineState extends State<TextLine> {
return _linkRecognizers[segment]!; return _linkRecognizers[segment]!;
} }
if (isDesktop || widget.readOnly) { if (isDesktop() || widget.readOnly) {
_linkRecognizers[segment] = TapGestureRecognizer() _linkRecognizers[segment] = TapGestureRecognizer()
..onTap = () => _tapNodeLink(segment); ..onTap = () => _tapNodeLink(segment);
} else { } else {
@ -854,19 +853,12 @@ class RenderEditableTextLine extends RenderEditableBox {
/// of the cursor for iOS is approximate and obtained through an eyeball /// of the cursor for iOS is approximate and obtained through an eyeball
/// comparison. /// comparison.
void _computeCaretPrototype() { void _computeCaretPrototype() {
switch (defaultTargetPlatform) { if (isAppleOS()) {
case TargetPlatform.iOS: _caretPrototype = Rect.fromLTWH(0, 0, cursorWidth, cursorHeight + 2);
case TargetPlatform.macOS: } else if (isKeyboardOS()) {
_caretPrototype = Rect.fromLTWH(0, 0, cursorWidth, cursorHeight + 2); _caretPrototype = Rect.fromLTWH(0, 2, cursorWidth, cursorHeight - 4.0);
break; } else {
case TargetPlatform.android: throw UnimplementedError();
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
_caretPrototype = Rect.fromLTWH(0, 2, cursorWidth, cursorHeight - 4.0);
break;
default:
throw 'Invalid platform';
} }
} }

Loading…
Cancel
Save