Browse Source

Merged in changes from beta channel, resolved conflicts

Anatoly Pulyaevskiy 6 years ago
parent
commit
8ecb5970b2

+ 5
- 0
packages/zefyr/CHANGELOG.md View File

11
 * Breaking change: removed `ZefyrEditor.of` and `ZefyrEditableText.of` static methods.
11
 * Breaking change: removed `ZefyrEditor.of` and `ZefyrEditableText.of` static methods.
12
   Use `ZefyrScope.of` instead.
12
   Use `ZefyrScope.of` instead.
13
 
13
 
14
+## 0.3.1
15
+
16
+- Fixed autofocus not being triggered when set to `true` for the first time.
17
+- Allow customizing cursor color via ZefyrTheme.
18
+
14
 ## 0.3.0
19
 ## 0.3.0
15
 
20
 
16
 This version introduces new widget `ZefyrScaffold` which allows embedding Zefyr in custom
21
 This version introduces new widget `ZefyrScaffold` which allows embedding Zefyr in custom

+ 1
- 1
packages/zefyr/example/lib/src/form.dart View File

56
         decoration: InputDecoration(labelText: 'Description'),
56
         decoration: InputDecoration(labelText: 'Description'),
57
         controller: _controller,
57
         controller: _controller,
58
         focusNode: _focusNode,
58
         focusNode: _focusNode,
59
-        autofocus: false,
59
+        autofocus: true,
60
         imageDelegate: new CustomImageDelegate(),
60
         imageDelegate: new CustomImageDelegate(),
61
         physics: ClampingScrollPhysics(),
61
         physics: ClampingScrollPhysics(),
62
       ),
62
       ),

+ 1
- 0
packages/zefyr/example/lib/src/full_page.dart View File

59
   @override
59
   @override
60
   Widget build(BuildContext context) {
60
   Widget build(BuildContext context) {
61
     final theme = new ZefyrThemeData(
61
     final theme = new ZefyrThemeData(
62
+      cursorColor: Colors.blue,
62
       toolbarTheme: ZefyrToolbarTheme.fallback(context).copyWith(
63
       toolbarTheme: ZefyrToolbarTheme.fallback(context).copyWith(
63
         color: Colors.grey.shade800,
64
         color: Colors.grey.shade800,
64
         toggleColor: Colors.grey.shade900,
65
         toggleColor: Colors.grey.shade900,

+ 14
- 2
packages/zefyr/lib/src/widgets/caret.dart View File

5
 
5
 
6
 import 'package:flutter/material.dart';
6
 import 'package:flutter/material.dart';
7
 
7
 
8
-class CaretPainter {
8
+/// Helper class responsible for cursor layout and painting.
9
+class CursorPainter {
9
   static const double _kCaretHeightOffset = 2.0; // pixels
10
   static const double _kCaretHeightOffset = 2.0; // pixels
10
   static const double _kCaretWidth = 1.0; // pixels
11
   static const double _kCaretWidth = 1.0; // pixels
11
 
12
 
14
         0.0, 0.0, _kCaretWidth, lineHeight - _kCaretHeightOffset);
15
         0.0, 0.0, _kCaretWidth, lineHeight - _kCaretHeightOffset);
15
   }
16
   }
16
 
17
 
18
+  CursorPainter(Color color)
19
+      : assert(color != null),
20
+        _color = color;
21
+
17
   Rect _prototype;
22
   Rect _prototype;
18
 
23
 
19
   Rect get prototype => _prototype;
24
   Rect get prototype => _prototype;
20
 
25
 
26
+  Color _color;
27
+  Color get color => _color;
28
+  set color(Color value) {
29
+    assert(value != null);
30
+    _color = value;
31
+  }
32
+
21
   void layout(double lineHeight) {
33
   void layout(double lineHeight) {
22
     _prototype = buildPrototype(lineHeight);
34
     _prototype = buildPrototype(lineHeight);
23
   }
35
   }
24
 
36
 
25
   void paint(Canvas canvas, Offset offset) {
37
   void paint(Canvas canvas, Offset offset) {
26
-    final Paint paint = new Paint()..color = Colors.black;
38
+    final Paint paint = new Paint()..color = _color;
27
     final Rect caretRect = _prototype.shift(offset);
39
     final Rect caretRect = _prototype.shift(offset);
28
     canvas.drawRect(caretRect, paint);
40
     canvas.drawRect(caretRect, paint);
29
   }
41
   }

+ 1
- 0
packages/zefyr/lib/src/widgets/common.dart View File

69
         showCursor: scope.showCursor,
69
         showCursor: scope.showCursor,
70
         selection: scope.selection,
70
         selection: scope.selection,
71
         selectionColor: theme.selectionColor,
71
         selectionColor: theme.selectionColor,
72
+        cursorColor: theme.cursorColor,
72
       );
73
       );
73
       content = CompositedTransformTarget(link: _link, child: content);
74
       content = CompositedTransformTarget(link: _link, child: content);
74
     }
75
     }

+ 21
- 8
packages/zefyr/lib/src/widgets/editable_box.dart View File

20
     @required this.showCursor,
20
     @required this.showCursor,
21
     @required this.selection,
21
     @required this.selection,
22
     @required this.selectionColor,
22
     @required this.selectionColor,
23
+    @required this.cursorColor,
23
   }) : super(child: child);
24
   }) : super(child: child);
24
 
25
 
25
   final ContainerNode node;
26
   final ContainerNode node;
28
   final ValueNotifier<bool> showCursor;
29
   final ValueNotifier<bool> showCursor;
29
   final TextSelection selection;
30
   final TextSelection selection;
30
   final Color selectionColor;
31
   final Color selectionColor;
32
+  final Color cursorColor;
31
 
33
 
32
   @override
34
   @override
33
   RenderEditableProxyBox createRenderObject(BuildContext context) {
35
   RenderEditableProxyBox createRenderObject(BuildContext context) {
38
       showCursor: showCursor,
40
       showCursor: showCursor,
39
       selection: selection,
41
       selection: selection,
40
       selectionColor: selectionColor,
42
       selectionColor: selectionColor,
43
+      cursorColor: cursorColor,
41
     );
44
     );
42
   }
45
   }
43
 
46
 
50
       ..renderContext = renderContext
53
       ..renderContext = renderContext
51
       ..showCursor = showCursor
54
       ..showCursor = showCursor
52
       ..selection = selection
55
       ..selection = selection
53
-      ..selectionColor = selectionColor;
56
+      ..selectionColor = selectionColor
57
+      ..cursorColor = cursorColor;
54
   }
58
   }
55
 }
59
 }
56
 
60
 
67
     @required ValueNotifier<bool> showCursor,
71
     @required ValueNotifier<bool> showCursor,
68
     @required TextSelection selection,
72
     @required TextSelection selection,
69
     @required Color selectionColor,
73
     @required Color selectionColor,
74
+    @required Color cursorColor,
70
   })  : _node = node,
75
   })  : _node = node,
71
         _layerLink = layerLink,
76
         _layerLink = layerLink,
72
         _renderContext = renderContext,
77
         _renderContext = renderContext,
75
         _selectionColor = selectionColor,
80
         _selectionColor = selectionColor,
76
         super() {
81
         super() {
77
     this.child = child;
82
     this.child = child;
83
+    _cursorPainter = CursorPainter(cursorColor);
84
+  }
85
+
86
+  CursorPainter _cursorPainter;
87
+
88
+  set cursorColor(Color value) {
89
+    if (_cursorPainter.color != value) {
90
+      _cursorPainter.color = value;
91
+      markNeedsPaint();
92
+    }
78
   }
93
   }
79
 
94
 
80
   bool _isDirty = true;
95
   bool _isDirty = true;
182
   @mustCallSuper
197
   @mustCallSuper
183
   void performLayout() {
198
   void performLayout() {
184
     super.performLayout();
199
     super.performLayout();
185
-    _caretPainter.layout(preferredLineHeight);
200
+    _cursorPainter.layout(preferredLineHeight);
186
     // Indicate to render context that this object can be used by other
201
     // Indicate to render context that this object can be used by other
187
     // layers (selection overlay, for instance).
202
     // layers (selection overlay, for instance).
188
     _isDirty = false;
203
     _isDirty = false;
207
       paintSelection(context, offset, selection, selectionColor);
222
       paintSelection(context, offset, selection, selectionColor);
208
     }
223
     }
209
     if (isCaretVisible) {
224
     if (isCaretVisible) {
210
-      _paintCaret(context, offset);
225
+      _paintCursor(context, offset);
211
     }
226
     }
212
   }
227
   }
213
 
228
 
214
-  final CaretPainter _caretPainter = new CaretPainter();
215
-
216
-  void _paintCaret(PaintingContext context, Offset offset) {
229
+  void _paintCursor(PaintingContext context, Offset offset) {
217
     Offset caretOffset =
230
     Offset caretOffset =
218
-        getOffsetForCaret(_selection.extent, _caretPainter.prototype);
219
-    _caretPainter.paint(context.canvas, caretOffset + offset);
231
+        getOffsetForCaret(_selection.extent, _cursorPainter.prototype);
232
+    _cursorPainter.paint(context.canvas, caretOffset + offset);
220
   }
233
   }
221
 
234
 
222
   @override
235
   @override

+ 13
- 8
packages/zefyr/lib/src/widgets/editable_text.dart View File

82
       FocusScope.of(context).requestFocus(focusNode);
82
       FocusScope.of(context).requestFocus(focusNode);
83
   }
83
   }
84
 
84
 
85
+  void focusOrUnfocusIfNeeded() {
86
+    if (!_didAutoFocus && widget.autofocus && widget.enabled) {
87
+      FocusScope.of(context).autofocus(focusNode);
88
+      _didAutoFocus = true;
89
+    }
90
+    if (!widget.enabled && focusNode.hasFocus) {
91
+      _didAutoFocus = false;
92
+      focusNode.unfocus();
93
+    }
94
+  }
95
+
85
   //
96
   //
86
   // Overridden members of State
97
   // Overridden members of State
87
   //
98
   //
125
   void didUpdateWidget(ZefyrEditableText oldWidget) {
136
   void didUpdateWidget(ZefyrEditableText oldWidget) {
126
     super.didUpdateWidget(oldWidget);
137
     super.didUpdateWidget(oldWidget);
127
     _updateSubscriptions(oldWidget);
138
     _updateSubscriptions(oldWidget);
128
-    if (!_didAutoFocus && widget.autofocus && widget.enabled) {
129
-      FocusScope.of(context).autofocus(focusNode);
130
-      _didAutoFocus = true;
131
-    }
132
-    if (!widget.enabled && focusNode.hasFocus) {
133
-      _didAutoFocus = false;
134
-      focusNode.unfocus();
135
-    }
139
+    focusOrUnfocusIfNeeded();
136
   }
140
   }
137
 
141
 
138
   @override
142
   @override
149
       _cursorTimer = scope.cursorTimer;
153
       _cursorTimer = scope.cursorTimer;
150
       _cursorTimer.startOrStop(focusNode, selection);
154
       _cursorTimer.startOrStop(focusNode, selection);
151
     }
155
     }
156
+    focusOrUnfocusIfNeeded();
152
   }
157
   }
153
 
158
 
154
   @override
159
   @override

+ 1
- 1
packages/zefyr/lib/src/widgets/rich_text.dart View File

128
   List<ui.TextBox> getEndpointsForSelection(TextSelection selection) {
128
   List<ui.TextBox> getEndpointsForSelection(TextSelection selection) {
129
     TextSelection local = getLocalSelection(selection);
129
     TextSelection local = getLocalSelection(selection);
130
     if (local.isCollapsed) {
130
     if (local.isCollapsed) {
131
-      final caret = CaretPainter.buildPrototype(preferredLineHeight);
131
+      final caret = CursorPainter.buildPrototype(preferredLineHeight);
132
       final offset = getOffsetForCaret(local.extent, caret);
132
       final offset = getOffsetForCaret(local.extent, caret);
133
       return [
133
       return [
134
         new ui.TextBox.fromLTRBD(
134
         new ui.TextBox.fromLTRBD(

+ 6
- 0
packages/zefyr/lib/src/widgets/theme.dart View File

60
   final HeadingTheme headingTheme;
60
   final HeadingTheme headingTheme;
61
   final BlockTheme blockTheme;
61
   final BlockTheme blockTheme;
62
   final Color selectionColor;
62
   final Color selectionColor;
63
+  final Color cursorColor;
63
 
64
 
64
   /// Size of indentation for blocks.
65
   /// Size of indentation for blocks.
65
   final double indentSize;
66
   final double indentSize;
88
       headingTheme: new HeadingTheme.fallback(),
89
       headingTheme: new HeadingTheme.fallback(),
89
       blockTheme: new BlockTheme.fallback(),
90
       blockTheme: new BlockTheme.fallback(),
90
       selectionColor: Colors.lightBlueAccent.shade100,
91
       selectionColor: Colors.lightBlueAccent.shade100,
92
+      cursorColor: Colors.black,
91
       indentSize: 16.0,
93
       indentSize: 16.0,
92
       toolbarTheme: new ZefyrToolbarTheme.fallback(context),
94
       toolbarTheme: new ZefyrToolbarTheme.fallback(context),
93
     );
95
     );
101
     this.headingTheme,
103
     this.headingTheme,
102
     this.blockTheme,
104
     this.blockTheme,
103
     this.selectionColor,
105
     this.selectionColor,
106
+    this.cursorColor,
104
     this.indentSize,
107
     this.indentSize,
105
     this.toolbarTheme,
108
     this.toolbarTheme,
106
   });
109
   });
114
     HeadingTheme headingTheme,
117
     HeadingTheme headingTheme,
115
     BlockTheme blockTheme,
118
     BlockTheme blockTheme,
116
     Color selectionColor,
119
     Color selectionColor,
120
+    Color cursorColor,
117
     double indentSize,
121
     double indentSize,
118
     ZefyrToolbarTheme toolbarTheme,
122
     ZefyrToolbarTheme toolbarTheme,
119
   }) {
123
   }) {
125
       headingTheme: headingTheme ?? this.headingTheme,
129
       headingTheme: headingTheme ?? this.headingTheme,
126
       blockTheme: blockTheme ?? this.blockTheme,
130
       blockTheme: blockTheme ?? this.blockTheme,
127
       selectionColor: selectionColor ?? this.selectionColor,
131
       selectionColor: selectionColor ?? this.selectionColor,
132
+      cursorColor: cursorColor ?? this.cursorColor,
128
       indentSize: indentSize ?? this.indentSize,
133
       indentSize: indentSize ?? this.indentSize,
129
       toolbarTheme: toolbarTheme ?? this.toolbarTheme,
134
       toolbarTheme: toolbarTheme ?? this.toolbarTheme,
130
     );
135
     );
139
       headingTheme: other.headingTheme,
144
       headingTheme: other.headingTheme,
140
       blockTheme: other.blockTheme,
145
       blockTheme: other.blockTheme,
141
       selectionColor: other.selectionColor,
146
       selectionColor: other.selectionColor,
147
+      cursorColor: other.cursorColor,
142
       indentSize: other.indentSize,
148
       indentSize: other.indentSize,
143
       toolbarTheme: other.toolbarTheme,
149
       toolbarTheme: other.toolbarTheme,
144
     );
150
     );

+ 1
- 1
packages/zefyr/pubspec.yaml View File

1
 name: zefyr
1
 name: zefyr
2
 description: Clean, minimalistic and collaboration-ready rich text editor for Flutter.
2
 description: Clean, minimalistic and collaboration-ready rich text editor for Flutter.
3
-version: 0.3.0
3
+version: 0.3.1
4
 author: Anatoly Pulyaevskiy <anatoly.pulyaevskiy@gmail.com>
4
 author: Anatoly Pulyaevskiy <anatoly.pulyaevskiy@gmail.com>
5
 homepage: https://github.com/memspace/zefyr
5
 homepage: https://github.com/memspace/zefyr
6
 
6
 

+ 4
- 3
packages/zefyr/test/painting/caret_painter_test.dart View File

3
 // BSD-style license that can be found in the LICENSE file.
3
 // BSD-style license that can be found in the LICENSE file.
4
 import 'dart:ui';
4
 import 'dart:ui';
5
 
5
 
6
+import 'package:flutter/material.dart';
6
 import 'package:flutter_test/flutter_test.dart';
7
 import 'package:flutter_test/flutter_test.dart';
7
 import 'package:zefyr/src/widgets/caret.dart';
8
 import 'package:zefyr/src/widgets/caret.dart';
8
 
9
 
9
 void main() {
10
 void main() {
10
-  group('$CaretPainter', () {
11
+  group('$CursorPainter', () {
11
     test('prototype is null before layout', () {
12
     test('prototype is null before layout', () {
12
-      var painter = new CaretPainter();
13
+      var painter = new CursorPainter(Colors.black);
13
       expect(painter.prototype, isNull);
14
       expect(painter.prototype, isNull);
14
     });
15
     });
15
 
16
 
16
     test('prototype is set after layout', () {
17
     test('prototype is set after layout', () {
17
-      var painter = new CaretPainter();
18
+      var painter = new CursorPainter(Colors.black);
18
       painter.layout(16.0);
19
       painter.layout(16.0);
19
       expect(painter.prototype, new Rect.fromLTWH(0.0, 0.0, 1.0, 14.0));
20
       expect(painter.prototype, new Rect.fromLTWH(0.0, 0.0, 1.0, 14.0));
20
     });
21
     });

+ 1
- 0
packages/zefyr/test/rendering/render_editable_proxy_box_test.dart View File

36
         showCursor: ValueNotifier<bool>(true),
36
         showCursor: ValueNotifier<bool>(true),
37
         selection: TextSelection.collapsed(offset: 0),
37
         selection: TextSelection.collapsed(offset: 0),
38
         selectionColor: Color(0),
38
         selectionColor: Color(0),
39
+        cursorColor: Color(0),
39
       );
40
       );
40
     });
41
     });
41
 
42
 

+ 20
- 3
packages/zefyr/test/testing.dart View File

21
     FocusNode focusNode,
21
     FocusNode focusNode,
22
     NotusDocument document,
22
     NotusDocument document,
23
     ZefyrThemeData theme,
23
     ZefyrThemeData theme,
24
+    bool autofocus: false,
24
   }) {
25
   }) {
25
     focusNode ??= FocusNode();
26
     focusNode ??= FocusNode();
26
     document ??= NotusDocument.fromDelta(delta);
27
     document ??= NotusDocument.fromDelta(delta);
27
     var controller = ZefyrController(document);
28
     var controller = ZefyrController(document);
28
 
29
 
29
-    Widget widget = _ZefyrSandbox(controller: controller, focusNode: focusNode);
30
+    Widget widget = _ZefyrSandbox(
31
+      controller: controller,
32
+      focusNode: focusNode,
33
+      autofocus: autofocus,
34
+    );
35
+
30
     if (theme != null) {
36
     if (theme != null) {
31
       widget = ZefyrTheme(data: theme, child: widget);
37
       widget = ZefyrTheme(data: theme, child: widget);
32
     }
38
     }
60
     return tester.pumpAndSettle();
66
     return tester.pumpAndSettle();
61
   }
67
   }
62
 
68
 
63
-  Future<void> tapEditor() async {
69
+  Future<void> pump() async {
64
     await tester.pumpWidget(widget);
70
     await tester.pumpWidget(widget);
71
+  }
72
+
73
+  Future<void> tap() async {
65
     await tester.tap(find.byType(ZefyrParagraph).first);
74
     await tester.tap(find.byType(ZefyrParagraph).first);
66
     await tester.pumpAndSettle();
75
     await tester.pumpAndSettle();
67
     expect(focusNode.hasFocus, isTrue);
76
     expect(focusNode.hasFocus, isTrue);
68
   }
77
   }
69
 
78
 
79
+  Future<void> pumpAndTap() async {
80
+    await pump();
81
+    await tap();
82
+  }
83
+
70
   Future<void> tapHideKeyboardButton() async {
84
   Future<void> tapHideKeyboardButton() async {
71
     await tapButtonWithIcon(Icons.keyboard_hide);
85
     await tapButtonWithIcon(Icons.keyboard_hide);
72
   }
86
   }
101
 }
115
 }
102
 
116
 
103
 class _ZefyrSandbox extends StatefulWidget {
117
 class _ZefyrSandbox extends StatefulWidget {
104
-  const _ZefyrSandbox({Key key, this.controller, this.focusNode})
118
+  const _ZefyrSandbox(
119
+      {Key key, this.controller, this.focusNode, this.autofocus})
105
       : super(key: key);
120
       : super(key: key);
106
   final ZefyrController controller;
121
   final ZefyrController controller;
107
   final FocusNode focusNode;
122
   final FocusNode focusNode;
123
+  final bool autofocus;
108
 
124
 
109
   @override
125
   @override
110
   _ZefyrSandboxState createState() => _ZefyrSandboxState();
126
   _ZefyrSandboxState createState() => _ZefyrSandboxState();
119
       controller: widget.controller,
135
       controller: widget.controller,
120
       focusNode: widget.focusNode,
136
       focusNode: widget.focusNode,
121
       enabled: _enabled,
137
       enabled: _enabled,
138
+      autofocus: widget.autofocus,
122
     );
139
     );
123
   }
140
   }
124
 
141
 

+ 12
- 12
packages/zefyr/test/widgets/buttons_test.dart View File

13
   group('$ZefyrButton', () {
13
   group('$ZefyrButton', () {
14
     testWidgets('toggle style', (tester) async {
14
     testWidgets('toggle style', (tester) async {
15
       final editor = new EditorSandBox(tester: tester);
15
       final editor = new EditorSandBox(tester: tester);
16
-      await editor.tapEditor();
16
+      await editor.pumpAndTap();
17
       await editor.updateSelection(base: 5, extent: 10);
17
       await editor.updateSelection(base: 5, extent: 10);
18
       await editor.tapButtonWithIcon(Icons.format_bold);
18
       await editor.tapButtonWithIcon(Icons.format_bold);
19
 
19
 
31
     testWidgets('toggle state for different styles of the same attribute',
31
     testWidgets('toggle state for different styles of the same attribute',
32
         (tester) async {
32
         (tester) async {
33
       final editor = new EditorSandBox(tester: tester);
33
       final editor = new EditorSandBox(tester: tester);
34
-      await editor.tapEditor();
34
+      await editor.pumpAndTap();
35
 
35
 
36
       await editor.tapButtonWithIcon(Icons.format_list_bulleted);
36
       await editor.tapButtonWithIcon(Icons.format_list_bulleted);
37
       expect(editor.document.root.children.first, isInstanceOf<BlockNode>());
37
       expect(editor.document.root.children.first, isInstanceOf<BlockNode>());
46
   group('$HeadingButton', () {
46
   group('$HeadingButton', () {
47
     testWidgets('toggle menu', (tester) async {
47
     testWidgets('toggle menu', (tester) async {
48
       final editor = new EditorSandBox(tester: tester);
48
       final editor = new EditorSandBox(tester: tester);
49
-      await editor.tapEditor();
49
+      await editor.pumpAndTap();
50
       await editor.tapButtonWithIcon(Icons.format_size);
50
       await editor.tapButtonWithIcon(Icons.format_size);
51
 
51
 
52
       expect(find.text('H1'), findsOneWidget);
52
       expect(find.text('H1'), findsOneWidget);
60
 
60
 
61
     testWidgets('toggle styles', (tester) async {
61
     testWidgets('toggle styles', (tester) async {
62
       final editor = new EditorSandBox(tester: tester);
62
       final editor = new EditorSandBox(tester: tester);
63
-      await editor.tapEditor();
63
+      await editor.pumpAndTap();
64
       await editor.tapButtonWithIcon(Icons.format_size);
64
       await editor.tapButtonWithIcon(Icons.format_size);
65
       await editor.tapButtonWithText('H3');
65
       await editor.tapButtonWithText('H3');
66
       LineNode line = editor.document.root.children.first;
66
       LineNode line = editor.document.root.children.first;
71
 
71
 
72
     testWidgets('close overlay', (tester) async {
72
     testWidgets('close overlay', (tester) async {
73
       final editor = new EditorSandBox(tester: tester);
73
       final editor = new EditorSandBox(tester: tester);
74
-      await editor.tapEditor();
74
+      await editor.pumpAndTap();
75
       await editor.tapButtonWithIcon(Icons.format_size);
75
       await editor.tapButtonWithIcon(Icons.format_size);
76
       expect(find.text('H1'), findsOneWidget);
76
       expect(find.text('H1'), findsOneWidget);
77
       await editor.tapButtonWithIcon(Icons.close);
77
       await editor.tapButtonWithIcon(Icons.close);
82
   group('$LinkButton', () {
82
   group('$LinkButton', () {
83
     testWidgets('disabled when selection is collapsed', (tester) async {
83
     testWidgets('disabled when selection is collapsed', (tester) async {
84
       final editor = new EditorSandBox(tester: tester);
84
       final editor = new EditorSandBox(tester: tester);
85
-      await editor.tapEditor();
85
+      await editor.pumpAndTap();
86
       await editor.tapButtonWithIcon(Icons.link);
86
       await editor.tapButtonWithIcon(Icons.link);
87
       expect(find.byIcon(Icons.link_off), findsNothing);
87
       expect(find.byIcon(Icons.link_off), findsNothing);
88
     });
88
     });
90
     testWidgets('enabled and toggles menu with non-empty selection',
90
     testWidgets('enabled and toggles menu with non-empty selection',
91
         (tester) async {
91
         (tester) async {
92
       final editor = new EditorSandBox(tester: tester);
92
       final editor = new EditorSandBox(tester: tester);
93
-      await editor.tapEditor();
93
+      await editor.pumpAndTap();
94
       await editor.updateSelection(base: 5, extent: 10);
94
       await editor.updateSelection(base: 5, extent: 10);
95
       await editor.tapButtonWithIcon(Icons.link);
95
       await editor.tapButtonWithIcon(Icons.link);
96
       expect(find.byIcon(Icons.link_off), findsOneWidget);
96
       expect(find.byIcon(Icons.link_off), findsOneWidget);
98
 
98
 
99
     testWidgets('auto cancels edit on selection update', (tester) async {
99
     testWidgets('auto cancels edit on selection update', (tester) async {
100
       final editor = new EditorSandBox(tester: tester);
100
       final editor = new EditorSandBox(tester: tester);
101
-      await editor.tapEditor();
101
+      await editor.pumpAndTap();
102
       await editor.updateSelection(base: 5, extent: 10);
102
       await editor.updateSelection(base: 5, extent: 10);
103
       await editor.tapButtonWithIcon(Icons.link);
103
       await editor.tapButtonWithIcon(Icons.link);
104
       await tester
104
       await tester
111
 
111
 
112
     testWidgets('editing link', (tester) async {
112
     testWidgets('editing link', (tester) async {
113
       final editor = new EditorSandBox(tester: tester);
113
       final editor = new EditorSandBox(tester: tester);
114
-      await editor.tapEditor();
114
+      await editor.pumpAndTap();
115
       await editor.updateSelection(base: 5, extent: 10);
115
       await editor.updateSelection(base: 5, extent: 10);
116
 
116
 
117
       await editor.tapButtonWithIcon(Icons.link);
117
       await editor.tapButtonWithIcon(Icons.link);
160
 
160
 
161
     testWidgets('toggle overlay', (tester) async {
161
     testWidgets('toggle overlay', (tester) async {
162
       final editor = new EditorSandBox(tester: tester);
162
       final editor = new EditorSandBox(tester: tester);
163
-      await editor.tapEditor();
163
+      await editor.pumpAndTap();
164
       await editor.tapButtonWithIcon(Icons.photo);
164
       await editor.tapButtonWithIcon(Icons.photo);
165
 
165
 
166
       expect(find.byIcon(Icons.photo_camera), findsOneWidget);
166
       expect(find.byIcon(Icons.photo_camera), findsOneWidget);
170
 
170
 
171
     testWidgets('pick from camera', (tester) async {
171
     testWidgets('pick from camera', (tester) async {
172
       final editor = new EditorSandBox(tester: tester);
172
       final editor = new EditorSandBox(tester: tester);
173
-      await editor.tapEditor();
173
+      await editor.pumpAndTap();
174
       await editor.tapButtonWithIcon(Icons.photo);
174
       await editor.tapButtonWithIcon(Icons.photo);
175
       await editor.tapButtonWithIcon(Icons.photo_camera);
175
       await editor.tapButtonWithIcon(Icons.photo_camera);
176
       expect(log, hasLength(1));
176
       expect(log, hasLength(1));
189
 
189
 
190
     testWidgets('pick from gallery', (tester) async {
190
     testWidgets('pick from gallery', (tester) async {
191
       final editor = new EditorSandBox(tester: tester);
191
       final editor = new EditorSandBox(tester: tester);
192
-      await editor.tapEditor();
192
+      await editor.pumpAndTap();
193
       await editor.tapButtonWithIcon(Icons.photo);
193
       await editor.tapButtonWithIcon(Icons.photo);
194
       await editor.tapButtonWithIcon(Icons.photo_library);
194
       await editor.tapButtonWithIcon(Icons.photo_library);
195
       expect(log, hasLength(1));
195
       expect(log, hasLength(1));

+ 1
- 1
packages/zefyr/test/widgets/code_test.dart View File

11
   group('$ZefyrCode', () {
11
   group('$ZefyrCode', () {
12
     testWidgets('format as code', (tester) async {
12
     testWidgets('format as code', (tester) async {
13
       final editor = new EditorSandBox(tester: tester);
13
       final editor = new EditorSandBox(tester: tester);
14
-      await editor.tapEditor();
14
+      await editor.pumpAndTap();
15
       await editor.tapButtonWithIcon(Icons.code);
15
       await editor.tapButtonWithIcon(Icons.code);
16
 
16
 
17
       BlockNode block = editor.document.root.children.first;
17
       BlockNode block = editor.document.root.children.first;

+ 13
- 1
packages/zefyr/test/widgets/editable_text_test.dart View File

11
   group('$ZefyrEditableText', () {
11
   group('$ZefyrEditableText', () {
12
     testWidgets('user input', (tester) async {
12
     testWidgets('user input', (tester) async {
13
       final editor = new EditorSandBox(tester: tester);
13
       final editor = new EditorSandBox(tester: tester);
14
-      await editor.tapEditor();
14
+      await editor.pumpAndTap();
15
       final currentValue = editor.document.toPlainText();
15
       final currentValue = editor.document.toPlainText();
16
       await enterText(tester, 'Added $currentValue');
16
       await enterText(tester, 'Added $currentValue');
17
       expect(editor.document.toPlainText(), 'Added This House Is A Circus\n');
17
       expect(editor.document.toPlainText(), 'Added This House Is A Circus\n');
18
     });
18
     });
19
+
20
+    testWidgets('autofocus', (tester) async {
21
+      final editor = new EditorSandBox(tester: tester, autofocus: true);
22
+      await editor.pump();
23
+      expect(editor.focusNode.hasFocus, isTrue);
24
+    });
25
+
26
+    testWidgets('no autofocus', (tester) async {
27
+      final editor = new EditorSandBox(tester: tester);
28
+      await editor.pump();
29
+      expect(editor.focusNode.hasFocus, isFalse);
30
+    });
19
   });
31
   });
20
 }
32
 }
21
 
33
 

+ 3
- 3
packages/zefyr/test/widgets/editor_test.dart View File

22
       var theme = ZefyrThemeData(linkStyle: TextStyle(color: Colors.red));
22
       var theme = ZefyrThemeData(linkStyle: TextStyle(color: Colors.red));
23
       var editor =
23
       var editor =
24
           new EditorSandBox(tester: tester, document: doc, theme: theme);
24
           new EditorSandBox(tester: tester, document: doc, theme: theme);
25
-      await editor.tapEditor();
25
+      await editor.pumpAndTap();
26
       // TODO: figure out why this extra pump is needed here
26
       // TODO: figure out why this extra pump is needed here
27
       await tester.pumpAndSettle();
27
       await tester.pumpAndSettle();
28
       ZefyrRichText p = tester.widget(find.byType(ZefyrRichText).first);
28
       ZefyrRichText p = tester.widget(find.byType(ZefyrRichText).first);
31
 
31
 
32
     testWidgets('collapses selection when unfocused', (tester) async {
32
     testWidgets('collapses selection when unfocused', (tester) async {
33
       final editor = new EditorSandBox(tester: tester);
33
       final editor = new EditorSandBox(tester: tester);
34
-      await editor.tapEditor();
34
+      await editor.pumpAndTap();
35
       await editor.updateSelection(base: 0, extent: 3);
35
       await editor.updateSelection(base: 0, extent: 3);
36
       expect(editor.findSelectionHandle(), findsNWidgets(2));
36
       expect(editor.findSelectionHandle(), findsNWidgets(2));
37
       await editor.tapHideKeyboardButton();
37
       await editor.tapHideKeyboardButton();
41
 
41
 
42
     testWidgets('toggle enabled state', (tester) async {
42
     testWidgets('toggle enabled state', (tester) async {
43
       final editor = new EditorSandBox(tester: tester);
43
       final editor = new EditorSandBox(tester: tester);
44
-      await editor.tapEditor();
44
+      await editor.pumpAndTap();
45
       await editor.updateSelection(base: 0, extent: 3);
45
       await editor.updateSelection(base: 0, extent: 3);
46
       await editor.disable();
46
       await editor.disable();
47
       ZefyrEditor widget = tester.widget(find.byType(ZefyrEditor));
47
       ZefyrEditor widget = tester.widget(find.byType(ZefyrEditor));

+ 4
- 4
packages/zefyr/test/widgets/horizontal_rule_test.dart View File

11
   group('$ZefyrHorizontalRule', () {
11
   group('$ZefyrHorizontalRule', () {
12
     testWidgets('format as horizontal rule', (tester) async {
12
     testWidgets('format as horizontal rule', (tester) async {
13
       final editor = new EditorSandBox(tester: tester);
13
       final editor = new EditorSandBox(tester: tester);
14
-      await editor.tapEditor();
14
+      await editor.pumpAndTap();
15
       await editor.tapButtonWithIcon(Icons.remove);
15
       await editor.tapButtonWithIcon(Icons.remove);
16
 
16
 
17
       LineNode line = editor.document.root.children.last;
17
       LineNode line = editor.document.root.children.last;
21
     testWidgets('tap left side of horizontal rule puts caret before it',
21
     testWidgets('tap left side of horizontal rule puts caret before it',
22
         (tester) async {
22
         (tester) async {
23
       final editor = new EditorSandBox(tester: tester);
23
       final editor = new EditorSandBox(tester: tester);
24
-      await editor.tapEditor();
24
+      await editor.pumpAndTap();
25
       await editor.tapButtonWithIcon(Icons.remove);
25
       await editor.tapButtonWithIcon(Icons.remove);
26
       await editor.updateSelection(base: 0, extent: 0);
26
       await editor.updateSelection(base: 0, extent: 0);
27
 
27
 
35
     testWidgets('tap right side of horizontal rule puts caret after it',
35
     testWidgets('tap right side of horizontal rule puts caret after it',
36
         (tester) async {
36
         (tester) async {
37
       final editor = new EditorSandBox(tester: tester);
37
       final editor = new EditorSandBox(tester: tester);
38
-      await editor.tapEditor();
38
+      await editor.pumpAndTap();
39
       await editor.tapButtonWithIcon(Icons.remove);
39
       await editor.tapButtonWithIcon(Icons.remove);
40
       await editor.updateSelection(base: 0, extent: 0);
40
       await editor.updateSelection(base: 0, extent: 0);
41
 
41
 
51
     testWidgets('selects on long press',
51
     testWidgets('selects on long press',
52
         (tester) async {
52
         (tester) async {
53
       final editor = new EditorSandBox(tester: tester);
53
       final editor = new EditorSandBox(tester: tester);
54
-      await editor.tapEditor();
54
+      await editor.pumpAndTap();
55
       await editor.tapButtonWithIcon(Icons.remove);
55
       await editor.tapButtonWithIcon(Icons.remove);
56
       await editor.updateSelection(base: 0, extent: 0);
56
       await editor.updateSelection(base: 0, extent: 0);
57
 
57
 

+ 4
- 4
packages/zefyr/test/widgets/image_test.dart View File

47
 
47
 
48
     testWidgets('embed image', (tester) async {
48
     testWidgets('embed image', (tester) async {
49
       final editor = new EditorSandBox(tester: tester);
49
       final editor = new EditorSandBox(tester: tester);
50
-      await editor.tapEditor();
50
+      await editor.pumpAndTap();
51
       await editor.tapButtonWithIcon(Icons.photo);
51
       await editor.tapButtonWithIcon(Icons.photo);
52
       await editor.tapButtonWithIcon(Icons.photo_camera);
52
       await editor.tapButtonWithIcon(Icons.photo_camera);
53
       LineNode line = editor.document.root.children.last;
53
       LineNode line = editor.document.root.children.last;
63
     testWidgets('tap on left side of image puts caret before it',
63
     testWidgets('tap on left side of image puts caret before it',
64
         (tester) async {
64
         (tester) async {
65
       final editor = new EditorSandBox(tester: tester);
65
       final editor = new EditorSandBox(tester: tester);
66
-      await editor.tapEditor();
66
+      await editor.pumpAndTap();
67
       await editor.tapButtonWithIcon(Icons.photo);
67
       await editor.tapButtonWithIcon(Icons.photo);
68
       await editor.tapButtonWithIcon(Icons.photo_camera);
68
       await editor.tapButtonWithIcon(Icons.photo_camera);
69
       await editor.updateSelection(base: 0, extent: 0);
69
       await editor.updateSelection(base: 0, extent: 0);
78
     testWidgets('tap right side of image puts caret after it',
78
     testWidgets('tap right side of image puts caret after it',
79
         (tester) async {
79
         (tester) async {
80
       final editor = new EditorSandBox(tester: tester);
80
       final editor = new EditorSandBox(tester: tester);
81
-      await editor.tapEditor();
81
+      await editor.pumpAndTap();
82
       await editor.tapButtonWithIcon(Icons.photo);
82
       await editor.tapButtonWithIcon(Icons.photo);
83
       await editor.tapButtonWithIcon(Icons.photo_camera);
83
       await editor.tapButtonWithIcon(Icons.photo_camera);
84
       await editor.updateSelection(base: 0, extent: 0);
84
       await editor.updateSelection(base: 0, extent: 0);
94
 
94
 
95
     testWidgets('selects on long press', (tester) async {
95
     testWidgets('selects on long press', (tester) async {
96
       final editor = new EditorSandBox(tester: tester);
96
       final editor = new EditorSandBox(tester: tester);
97
-      await editor.tapEditor();
97
+      await editor.pumpAndTap();
98
       await editor.tapButtonWithIcon(Icons.photo);
98
       await editor.tapButtonWithIcon(Icons.photo);
99
       await editor.tapButtonWithIcon(Icons.photo_camera);
99
       await editor.tapButtonWithIcon(Icons.photo_camera);
100
       await editor.updateSelection(base: 0, extent: 0);
100
       await editor.updateSelection(base: 0, extent: 0);

+ 1
- 1
packages/zefyr/test/widgets/list_test.dart View File

11
   group('$ZefyrList', () {
11
   group('$ZefyrList', () {
12
     testWidgets('format as list', (tester) async {
12
     testWidgets('format as list', (tester) async {
13
       final editor = new EditorSandBox(tester: tester);
13
       final editor = new EditorSandBox(tester: tester);
14
-      await editor.tapEditor();
14
+      await editor.pumpAndTap();
15
       await editor.tapButtonWithIcon(Icons.format_list_bulleted);
15
       await editor.tapButtonWithIcon(Icons.format_list_bulleted);
16
       BlockNode block = editor.document.root.children.first;
16
       BlockNode block = editor.document.root.children.first;
17
       expect(block.style.get(NotusAttribute.block),
17
       expect(block.style.get(NotusAttribute.block),

+ 1
- 1
packages/zefyr/test/widgets/quote_test.dart View File

11
   group('$ZefyrQuote', () {
11
   group('$ZefyrQuote', () {
12
     testWidgets('format as quote', (tester) async {
12
     testWidgets('format as quote', (tester) async {
13
       final editor = new EditorSandBox(tester: tester);
13
       final editor = new EditorSandBox(tester: tester);
14
-      await editor.tapEditor();
14
+      await editor.pumpAndTap();
15
       await editor.tapButtonWithIcon(Icons.format_quote);
15
       await editor.tapButtonWithIcon(Icons.format_quote);
16
 
16
 
17
       BlockNode block = editor.document.root.children.first;
17
       BlockNode block = editor.document.root.children.first;

+ 1
- 0
packages/zefyr/test/widgets/render_context_test.dart View File

85
     showCursor: showCursor,
85
     showCursor: showCursor,
86
     selection: selection,
86
     selection: selection,
87
     selectionColor: selectionColor,
87
     selectionColor: selectionColor,
88
+    cursorColor: Color(0),
88
   );
89
   );
89
 }
90
 }

+ 4
- 4
packages/zefyr/test/widgets/selection_test.dart View File

12
   group('$ZefyrSelectionOverlay', () {
12
   group('$ZefyrSelectionOverlay', () {
13
     testWidgets('double tap caret shows toolbar', (tester) async {
13
     testWidgets('double tap caret shows toolbar', (tester) async {
14
       final editor = new EditorSandBox(tester: tester);
14
       final editor = new EditorSandBox(tester: tester);
15
-      await editor.tapEditor();
15
+      await editor.pumpAndTap();
16
 
16
 
17
       RenderZefyrParagraph renderObject =
17
       RenderZefyrParagraph renderObject =
18
           tester.firstRenderObject(find.byType(ZefyrRichText));
18
           tester.firstRenderObject(find.byType(ZefyrRichText));
27
 
27
 
28
     testWidgets('hides when editor lost focus', (tester) async {
28
     testWidgets('hides when editor lost focus', (tester) async {
29
       final editor = new EditorSandBox(tester: tester);
29
       final editor = new EditorSandBox(tester: tester);
30
-      await editor.tapEditor();
30
+      await editor.pumpAndTap();
31
       await editor.updateSelection(base: 0, extent: 5);
31
       await editor.updateSelection(base: 0, extent: 5);
32
       expect(editor.findSelectionHandle(), findsNWidgets(2));
32
       expect(editor.findSelectionHandle(), findsNWidgets(2));
33
       await editor.unfocus();
33
       await editor.unfocus();
36
 
36
 
37
     testWidgets('tap on padding area finds closest paragraph', (tester) async {
37
     testWidgets('tap on padding area finds closest paragraph', (tester) async {
38
       final editor = new EditorSandBox(tester: tester);
38
       final editor = new EditorSandBox(tester: tester);
39
-      await editor.tapEditor();
39
+      await editor.pumpAndTap();
40
       editor.controller
40
       editor.controller
41
           .updateSelection(new TextSelection.collapsed(offset: 10));
41
           .updateSelection(new TextSelection.collapsed(offset: 10));
42
       await tester.pumpAndSettle();
42
       await tester.pumpAndSettle();
54
 
54
 
55
     testWidgets('tap on empty space finds closest paragraph', (tester) async {
55
     testWidgets('tap on empty space finds closest paragraph', (tester) async {
56
       final editor = new EditorSandBox(tester: tester);
56
       final editor = new EditorSandBox(tester: tester);
57
-      await editor.tapEditor();
57
+      await editor.pumpAndTap();
58
       editor.controller.replaceText(10, 1, '\n',
58
       editor.controller.replaceText(10, 1, '\n',
59
           selection: new TextSelection.collapsed(offset: 0));
59
           selection: new TextSelection.collapsed(offset: 0));
60
       await tester.pumpAndSettle();
60
       await tester.pumpAndSettle();