Kaynağa Gözat

Merge pull request #75 from memspace/autofocus-fix

Fix for autofocus not working
Anatoly Pulyaevskiy 6 yıl önce
ebeveyn
işleme
03d95a582b
No account linked to committer's email address

+ 4
- 0
packages/zefyr/CHANGELOG.md Dosyayı Görüntüle

@@ -1,3 +1,7 @@
1
+## Unreleased
2
+
3
+- Fixed autofocus not being triggered when set to `true` for the first time.
4
+
1 5
 ## 0.3.0
2 6
 
3 7
 This version introduces new widget `ZefyrScaffold` which allows embedding Zefyr in custom

+ 1
- 1
packages/zefyr/example/lib/src/form.dart Dosyayı Görüntüle

@@ -56,7 +56,7 @@ class _FormEmbeddedScreenState extends State<FormEmbeddedScreen> {
56 56
         decoration: InputDecoration(labelText: 'Description'),
57 57
         controller: _controller,
58 58
         focusNode: _focusNode,
59
-        autofocus: false,
59
+        autofocus: true,
60 60
         imageDelegate: new CustomImageDelegate(),
61 61
         physics: ClampingScrollPhysics(),
62 62
       ),

+ 1
- 1
packages/zefyr/example/lib/src/full_page.dart Dosyayı Görüntüle

@@ -31,7 +31,7 @@ final doc =
31 31
     r'g":2}},{"insert":"Of course:\nimport ‘package:flutter/material.dart’;"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"import ‘package:zefyr/zefyr.dart’;"},{"insert":"\n\n","attributes":{"block":"code"}},{"insert":"void main() {"},{"insert":"\n","attributes":{"block":"code"}},{"insert":" runApp(MyZefyrApp());"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"}"},{"insert":"\n","attributes":{"block":"code"}},{"insert":"\n\n\n"}]';
32 32
 
33 33
 Delta getDelta() {
34
-  return Delta.fromJson(json.decode(doc));
34
+  return Delta.fromJson(json.decode(doc) as List);
35 35
 }
36 36
 
37 37
 class _FullPageEditorScreenState extends State<FullPageEditorScreen> {

+ 18
- 8
packages/zefyr/lib/src/widgets/editable_text.dart Dosyayı Görüntüle

@@ -119,6 +119,17 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>
119 119
       FocusScope.of(context).requestFocus(focusNode);
120 120
   }
121 121
 
122
+  void focusOrUnfocusIfNeeded() {
123
+    if (!_didAutoFocus && widget.autofocus && widget.enabled) {
124
+      FocusScope.of(context).autofocus(focusNode);
125
+      _didAutoFocus = true;
126
+    }
127
+    if (!widget.enabled && focusNode.hasFocus) {
128
+      _didAutoFocus = false;
129
+      focusNode.unfocus();
130
+    }
131
+  }
132
+
122 133
   //
123 134
   // Overridden members of State
124 135
   //
@@ -169,14 +180,13 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>
169 180
   void didUpdateWidget(ZefyrEditableText oldWidget) {
170 181
     super.didUpdateWidget(oldWidget);
171 182
     _updateSubscriptions(oldWidget);
172
-    if (!_didAutoFocus && widget.autofocus && widget.enabled) {
173
-      FocusScope.of(context).autofocus(focusNode);
174
-      _didAutoFocus = true;
175
-    }
176
-    if (!widget.enabled && focusNode.hasFocus) {
177
-      _didAutoFocus = false;
178
-      focusNode.unfocus();
179
-    }
183
+    focusOrUnfocusIfNeeded();
184
+  }
185
+
186
+  @override
187
+  void didChangeDependencies() {
188
+    super.didChangeDependencies();
189
+    focusOrUnfocusIfNeeded();
180 190
   }
181 191
 
182 192
   @override

+ 20
- 3
packages/zefyr/test/testing.dart Dosyayı Görüntüle

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

+ 12
- 12
packages/zefyr/test/widgets/buttons_test.dart Dosyayı Görüntüle

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

+ 1
- 1
packages/zefyr/test/widgets/code_test.dart Dosyayı Görüntüle

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

+ 13
- 1
packages/zefyr/test/widgets/editable_text_test.dart Dosyayı Görüntüle

@@ -11,11 +11,23 @@ void main() {
11 11
   group('$ZefyrEditableText', () {
12 12
     testWidgets('user input', (tester) async {
13 13
       final editor = new EditorSandBox(tester: tester);
14
-      await editor.tapEditor();
14
+      await editor.pumpAndTap();
15 15
       final currentValue = editor.document.toPlainText();
16 16
       await enterText(tester, 'Added $currentValue');
17 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 Dosyayı Görüntüle

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

+ 4
- 4
packages/zefyr/test/widgets/horizontal_rule_test.dart Dosyayı Görüntüle

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

+ 4
- 4
packages/zefyr/test/widgets/image_test.dart Dosyayı Görüntüle

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

+ 1
- 1
packages/zefyr/test/widgets/list_test.dart Dosyayı Görüntüle

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

+ 1
- 1
packages/zefyr/test/widgets/quote_test.dart Dosyayı Görüntüle

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

+ 4
- 4
packages/zefyr/test/widgets/selection_test.dart Dosyayı Görüntüle

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