瀏覽代碼

Basic working image support

Anatoly Pulyaevskiy 6 年之前
父節點
當前提交
6e47d641ac

+ 6
- 0
packages/zefyr/example/ios/Podfile.lock 查看文件

@@ -1,20 +1,26 @@
1 1
 PODS:
2 2
   - Flutter (1.0.0)
3
+  - image_picker (0.0.1):
4
+    - Flutter
3 5
   - url_launcher (0.0.1):
4 6
     - Flutter
5 7
 
6 8
 DEPENDENCIES:
7 9
   - Flutter (from `.symlinks/flutter/ios`)
10
+  - image_picker (from `.symlinks/plugins/image_picker/ios`)
8 11
   - url_launcher (from `.symlinks/plugins/url_launcher/ios`)
9 12
 
10 13
 EXTERNAL SOURCES:
11 14
   Flutter:
12 15
     :path: ".symlinks/flutter/ios"
16
+  image_picker:
17
+    :path: ".symlinks/plugins/image_picker/ios"
13 18
   url_launcher:
14 19
     :path: ".symlinks/plugins/url_launcher/ios"
15 20
 
16 21
 SPEC CHECKSUMS:
17 22
   Flutter: 9d0fac939486c9aba2809b7982dfdbb47a7b0296
23
+  image_picker: ee00aab0487cedc80a304085219503cc6d0f2e22
18 24
   url_launcher: 92b89c1029a0373879933c21642958c874539095
19 25
 
20 26
 PODFILE CHECKSUM: 1e5af4103afd21ca5ead147d7b81d06f494f51a2

+ 16
- 4
packages/zefyr/lib/src/widgets/buttons.dart 查看文件

@@ -3,8 +3,9 @@
3 3
 // BSD-style license that can be found in the LICENSE file.
4 4
 import 'package:flutter/material.dart';
5 5
 import 'package:flutter/services.dart';
6
-import 'package:url_launcher/url_launcher.dart';
6
+import 'package:image_picker/image_picker.dart';
7 7
 import 'package:notus/notus.dart';
8
+import 'package:url_launcher/url_launcher.dart';
8 9
 
9 10
 import 'editor.dart';
10 11
 import 'theme.dart';
@@ -246,7 +247,7 @@ class ImageButton extends StatefulWidget {
246 247
   _ImageButtonState createState() => _ImageButtonState();
247 248
 }
248 249
 
249
-class _ImageButtonState extends State<HeadingButton> {
250
+class _ImageButtonState extends State<ImageButton> {
250 251
   @override
251 252
   Widget build(BuildContext context) {
252 253
     final toolbar = ZefyrToolbar.of(context);
@@ -276,8 +277,19 @@ class _ImageButtonState extends State<HeadingButton> {
276 277
     return ZefyrToolbarScaffold(body: buttons);
277 278
   }
278 279
 
279
-  void _pickFromCamera() {}
280
-  void _pickFromGallery() {}
280
+  void _pickFromCamera() async {
281
+    final editor = ZefyrEditor.of(context);
282
+    final image = await editor.imageDelegate.pickImage(ImageSource.camera);
283
+    if (image != null)
284
+      editor.formatSelection(NotusAttribute.embed.image(image));
285
+  }
286
+
287
+  void _pickFromGallery() async {
288
+    final editor = ZefyrEditor.of(context);
289
+    final image = await editor.imageDelegate.pickImage(ImageSource.gallery);
290
+    if (image != null)
291
+      editor.formatSelection(NotusAttribute.embed.image(image));
292
+  }
281 293
 }
282 294
 
283 295
 class LinkButton extends StatefulWidget {

+ 11
- 3
packages/zefyr/lib/src/widgets/common.dart 查看文件

@@ -6,9 +6,10 @@ import 'package:flutter/widgets.dart';
6 6
 import 'package:notus/notus.dart';
7 7
 
8 8
 import 'editable_box.dart';
9
-import 'editable_rich_text.dart';
10 9
 import 'editable_text.dart';
11 10
 import 'horizontal_rule.dart';
11
+import 'image.dart';
12
+import 'rich_text.dart';
12 13
 import 'theme.dart';
13 14
 
14 15
 /// Raw widget representing a single line of rich text document in Zefyr editor.
@@ -154,8 +155,15 @@ class _RawZefyrLineState extends State<RawZefyrLine> {
154 155
         selectionColor: theme.selectionColor,
155 156
       );
156 157
     } else if (embed.type == EmbedType.image) {
157
-      // TODO: implement image embeds.
158
-      return null;
158
+      return new EditableBox(
159
+        child: ImageEmbed(node: node, delegate: editable.imageDelegate),
160
+        node: widget.node,
161
+        layerLink: _link,
162
+        renderContext: editable.renderContext,
163
+        showCursor: editable.showCursor,
164
+        selection: editable.selection,
165
+        selectionColor: theme.selectionColor,
166
+      );
159 167
     } else {
160 168
       throw new UnimplementedError('Unimplemented embed type ${embed.type}');
161 169
     }

+ 7
- 0
packages/zefyr/lib/src/widgets/editable_text.dart 查看文件

@@ -13,6 +13,7 @@ import 'common.dart';
13 13
 import 'controller.dart';
14 14
 import 'editable_box.dart';
15 15
 import 'editor.dart';
16
+import 'image.dart';
16 17
 import 'input.dart';
17 18
 import 'list.dart';
18 19
 import 'paragraph.dart';
@@ -31,12 +32,14 @@ class ZefyrEditableText extends StatefulWidget {
31 32
     Key key,
32 33
     @required this.controller,
33 34
     @required this.focusNode,
35
+    @required this.imageDelegate,
34 36
     this.autofocus: true,
35 37
     this.enabled: true,
36 38
   }) : super(key: key);
37 39
 
38 40
   final ZefyrController controller;
39 41
   final FocusNode focusNode;
42
+  final ZefyrImageDelegate imageDelegate;
40 43
   final bool autofocus;
41 44
   final bool enabled;
42 45
 
@@ -60,18 +63,21 @@ class ZefyrEditableTextScope extends InheritedWidget {
60 63
     @required this.selection,
61 64
     @required this.showCursor,
62 65
     @required this.renderContext,
66
+    @required this.imageDelegate,
63 67
   })  : _activeBoxes = new Set.from(renderContext.active),
64 68
         super(key: key, child: child);
65 69
 
66 70
   final TextSelection selection;
67 71
   final ValueNotifier<bool> showCursor;
68 72
   final ZefyrRenderContext renderContext;
73
+  final ZefyrImageDelegate imageDelegate;
69 74
   final Set<RenderEditableBox> _activeBoxes;
70 75
 
71 76
   @override
72 77
   bool updateShouldNotify(ZefyrEditableTextScope oldWidget) {
73 78
     return selection != oldWidget.selection ||
74 79
         showCursor != oldWidget.showCursor ||
80
+        imageDelegate != oldWidget.imageDelegate ||
75 81
         !_kEquality.equals(_activeBoxes, oldWidget._activeBoxes);
76 82
   }
77 83
 }
@@ -138,6 +144,7 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>
138 144
       selection: selection,
139 145
       showCursor: showCursor,
140 146
       renderContext: renderContext,
147
+      imageDelegate: widget.imageDelegate,
141 148
       child: Stack(fit: StackFit.expand, children: layers),
142 149
     );
143 150
   }

+ 14
- 1
packages/zefyr/lib/src/widgets/editor.dart 查看文件

@@ -6,6 +6,7 @@ import 'package:notus/notus.dart';
6 6
 
7 7
 import 'controller.dart';
8 8
 import 'editable_text.dart';
9
+import 'image.dart';
9 10
 import 'theme.dart';
10 11
 import 'toolbar.dart';
11 12
 
@@ -19,6 +20,7 @@ class ZefyrEditor extends StatefulWidget {
19 20
     this.enabled: true,
20 21
     this.padding: const EdgeInsets.symmetric(horizontal: 16.0),
21 22
     this.toolbarDelegate,
23
+    this.imageDelegate,
22 24
   }) : super(key: key);
23 25
 
24 26
   final ZefyrController controller;
@@ -26,6 +28,7 @@ class ZefyrEditor extends StatefulWidget {
26 28
   final bool autofocus;
27 29
   final bool enabled;
28 30
   final ZefyrToolbarDelegate toolbarDelegate;
31
+  final ZefyrImageDelegate imageDelegate;
29 32
 
30 33
   /// Padding around editable area.
31 34
   final EdgeInsets padding;
@@ -47,6 +50,7 @@ class ZefyrEditorScope extends InheritedWidget {
47 50
   final TextSelection selection;
48 51
   final FocusOwner focusOwner;
49 52
   final FocusNode toolbarFocusNode;
53
+  final ZefyrImageDelegate imageDelegate;
50 54
   final ZefyrController _controller;
51 55
   final FocusNode _focusNode;
52 56
 
@@ -57,6 +61,7 @@ class ZefyrEditorScope extends InheritedWidget {
57 61
     @required this.selection,
58 62
     @required this.focusOwner,
59 63
     @required this.toolbarFocusNode,
64
+    @required this.imageDelegate,
60 65
     @required ZefyrController controller,
61 66
     @required FocusNode focusNode,
62 67
   })  : _controller = controller,
@@ -84,7 +89,8 @@ class ZefyrEditorScope extends InheritedWidget {
84 89
   bool updateShouldNotify(ZefyrEditorScope oldWidget) {
85 90
     return (selectionStyle != oldWidget.selectionStyle ||
86 91
         selection != oldWidget.selection ||
87
-        focusOwner != oldWidget.focusOwner);
92
+        focusOwner != oldWidget.focusOwner ||
93
+        imageDelegate != oldWidget.imageDelegate);
88 94
   }
89 95
 }
90 96
 
@@ -94,6 +100,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
94 100
   NotusStyle _selectionStyle;
95 101
   TextSelection _selection;
96 102
   FocusOwner _focusOwner;
103
+  ZefyrImageDelegate _imageDelegate;
97 104
 
98 105
   FocusOwner getFocusOwner() {
99 106
     if (widget.focusNode.hasFocus) {
@@ -111,6 +118,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
111 118
     _selectionStyle = widget.controller.getSelectionStyle();
112 119
     _selection = widget.controller.selection;
113 120
     _focusOwner = getFocusOwner();
121
+    _imageDelegate = widget.imageDelegate ?? new ZefyrDefaultImageDelegate();
114 122
     widget.controller.addListener(_handleControllerChange);
115 123
     _toolbarFocusNode.addListener(_handleFocusChange);
116 124
     widget.focusNode.addListener(_handleFocusChange);
@@ -129,6 +137,9 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
129 137
       _selectionStyle = widget.controller.getSelectionStyle();
130 138
       _selection = widget.controller.selection;
131 139
     }
140
+    if (widget.imageDelegate != oldWidget.imageDelegate) {
141
+      _imageDelegate = widget.imageDelegate ?? new ZefyrDefaultImageDelegate();
142
+    }
132 143
   }
133 144
 
134 145
   @override
@@ -145,6 +156,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
145 156
     Widget editable = new ZefyrEditableText(
146 157
       controller: widget.controller,
147 158
       focusNode: widget.focusNode,
159
+      imageDelegate: _imageDelegate,
148 160
       autofocus: widget.autofocus,
149 161
       enabled: widget.enabled,
150 162
     );
@@ -173,6 +185,7 @@ class _ZefyrEditorState extends State<ZefyrEditor> {
173 185
         selectionStyle: _selectionStyle,
174 186
         focusOwner: _focusOwner,
175 187
         toolbarFocusNode: _toolbarFocusNode,
188
+        imageDelegate: _imageDelegate,
176 189
         controller: widget.controller,
177 190
         focusNode: widget.focusNode,
178 191
         child: Column(children: children),

+ 58
- 25
packages/zefyr/lib/src/widgets/image.dart 查看文件

@@ -91,8 +91,8 @@ class _ImageEmbedState extends State<ImageEmbed> {
91 91
   @override
92 92
   Widget build(BuildContext context) {
93 93
     return _EditableImage(
94
+      child: new RawImage(image: _imageInfo?.image),
94 95
       node: widget.node,
95
-      image: _imageInfo?.image,
96 96
     );
97 97
   }
98 98
 
@@ -112,15 +112,16 @@ class _ImageEmbedState extends State<ImageEmbed> {
112 112
   }
113 113
 }
114 114
 
115
-class _EditableImage extends LeafRenderObjectWidget {
116
-  _EditableImage({@required this.node, this.image}) : assert(node != null);
115
+class _EditableImage extends SingleChildRenderObjectWidget {
116
+  _EditableImage({@required Widget child, @required this.node})
117
+      : assert(node != null),
118
+        super(child: child);
117 119
 
118 120
   final EmbedNode node;
119
-  final ui.Image image;
120 121
 
121 122
   @override
122 123
   RenderEditableImage createRenderObject(BuildContext context) {
123
-    return new RenderEditableImage(node: node, image: image);
124
+    return new RenderEditableImage(node: node);
124 125
   }
125 126
 
126 127
   @override
@@ -130,14 +131,19 @@ class _EditableImage extends LeafRenderObjectWidget {
130 131
   }
131 132
 }
132 133
 
133
-class RenderEditableImage extends RenderImage implements RenderEditableBox {
134
+class RenderEditableImage extends RenderBox
135
+    with
136
+        RenderObjectWithChildMixin<RenderImage>,
137
+        RenderProxyBoxMixin<RenderImage>
138
+    implements RenderEditableBox {
139
+  static const kPaddingBottom = 24.0;
140
+
134 141
   RenderEditableImage({
135
-    ui.Image image,
142
+    RenderImage child,
136 143
     @required EmbedNode node,
137
-  })  : _node = node,
138
-        super(
139
-          image: image,
140
-        );
144
+  }) : _node = node {
145
+    this.child = child;
146
+  }
141 147
 
142 148
   @override
143 149
   EmbedNode get node => _node;
@@ -150,7 +156,7 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
150 156
   double get preferredLineHeight => size.height;
151 157
 
152 158
   @override
153
-  SelectionOrder get selectionOrder => SelectionOrder.foreground;
159
+  SelectionOrder get selectionOrder => SelectionOrder.background;
154 160
 
155 161
   @override
156 162
   TextSelection getLocalSelection(TextSelection documentSelection) {
@@ -165,24 +171,36 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
165 171
   }
166 172
 
167 173
   @override
168
-  List<TextBox> getEndpointsForSelection(TextSelection selection) {
174
+  List<ui.TextBox> getEndpointsForSelection(TextSelection selection) {
169 175
     TextSelection local = getLocalSelection(selection);
170 176
     if (local.isCollapsed) {
177
+      final dx = local.extentOffset == 0 ? 0.0 : size.width;
171 178
       return [
172
-        new TextBox.fromLTRBD(0.0, 0.0, 0.0, size.height, TextDirection.ltr),
179
+        new ui.TextBox.fromLTRBD(dx, 0.0, dx, size.height, TextDirection.ltr),
173 180
       ];
174 181
     }
175 182
 
176 183
     return [
177
-      new TextBox.fromLTRBD(0.0, 0.0, 0.0, size.height, TextDirection.ltr),
178
-      new TextBox.fromLTRBD(
184
+      new ui.TextBox.fromLTRBD(0.0, 0.0, 0.0, size.height, TextDirection.ltr),
185
+      new ui.TextBox.fromLTRBD(
179 186
           size.width, 0.0, size.width, size.height, TextDirection.ltr),
180 187
     ];
181 188
   }
182 189
 
183 190
   @override
184 191
   TextPosition getPositionForOffset(Offset offset) {
185
-    return new TextPosition(offset: node.documentOffset);
192
+    int position = _node.documentOffset;
193
+
194
+    if (offset.dx > size.width / 2) {
195
+      position++;
196
+    }
197
+    return new TextPosition(offset: position);
198
+  }
199
+
200
+  @override
201
+  TextRange getWordBoundary(TextPosition position) {
202
+    final start = _node.documentOffset;
203
+    return new TextRange(start: start, end: start + 1);
186 204
   }
187 205
 
188 206
   @override
@@ -193,13 +211,7 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
193 211
   }
194 212
 
195 213
   @override
196
-  TextRange getWordBoundary(ui.TextPosition position) {
197
-    return new TextRange(start: position.offset, end: position.offset + 1);
198
-  }
199
-
200
-  @override
201
-  ui.Offset getOffsetForCaret(
202
-      ui.TextPosition position, ui.Rect caretPrototype) {
214
+  Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) {
203 215
     final pos = position.offset - node.documentOffset;
204 216
     Offset caretOffset = Offset.zero;
205 217
     if (pos == 1) {
@@ -211,6 +223,27 @@ class RenderEditableImage extends RenderImage implements RenderEditableBox {
211 223
   @override
212 224
   void paintSelection(PaintingContext context, ui.Offset offset,
213 225
       TextSelection selection, ui.Color selectionColor) {
214
-    // TODO: implement paintSelection
226
+    final localSelection = getLocalSelection(selection);
227
+    assert(localSelection != null);
228
+    if (!localSelection.isCollapsed) {
229
+      final Paint paint = new Paint()..color = selectionColor;
230
+      final rect = new Rect.fromLTWH(0.0, 0.0, size.width, size.height);
231
+      context.canvas.drawRect(rect.shift(offset), paint);
232
+    }
233
+  }
234
+
235
+  @override
236
+  void performLayout() {
237
+    assert(constraints.hasBoundedWidth);
238
+    if (child != null) {
239
+      // Make constraints use 16:9 aspect ratio.
240
+      final childConstraints = constraints.copyWith(
241
+        maxHeight: (constraints.maxWidth * 9 / 16).floorToDouble(),
242
+      );
243
+      child.layout(childConstraints, parentUsesSize: true);
244
+      size = new Size(child.size.width, child.size.height + kPaddingBottom);
245
+    } else {
246
+      performResize();
247
+    }
215 248
   }
216 249
 }

packages/zefyr/lib/src/widgets/editable_rich_text.dart → packages/zefyr/lib/src/widgets/rich_text.dart 查看文件


+ 1
- 0
packages/zefyr/lib/src/widgets/toolbar.dart 查看文件

@@ -264,6 +264,7 @@ class ZefyrToolbarState extends State<ZefyrToolbar>
264 264
       buildButton(context, ZefyrToolbarAction.quote),
265 265
       buildButton(context, ZefyrToolbarAction.code),
266 266
       buildButton(context, ZefyrToolbarAction.horizontalRule),
267
+      ImageButton(),
267 268
     ];
268 269
     return buttons;
269 270
   }

+ 0
- 18
packages/zefyr/lib/widgets.dart 查看文件

@@ -1,18 +0,0 @@
1
-// Copyright (c) 2018, the Zefyr project authors.  Please see the AUTHORS file
2
-// for details. All rights reserved. Use of this source code is governed by a
3
-// BSD-style license that can be found in the LICENSE file.
4
-library zefyr.widgets;
5
-
6
-export 'src/widgets/buttons.dart' hide HeadingButton, LinkButton;
7
-export 'src/widgets/code.dart';
8
-export 'src/widgets/common.dart';
9
-export 'src/widgets/controller.dart';
10
-export 'src/widgets/editable_text.dart';
11
-export 'src/widgets/editor.dart';
12
-export 'src/widgets/list.dart';
13
-export 'src/widgets/paragraph.dart';
14
-export 'src/widgets/quote.dart';
15
-//export 'src/widgets/render_context.dart';
16
-export 'src/widgets/selection.dart' hide SelectionHandleDriver;
17
-export 'src/widgets/theme.dart';
18
-export 'src/widgets/toolbar.dart';

+ 15
- 7
packages/zefyr/lib/zefyr.dart 查看文件

@@ -5,14 +5,22 @@
5 5
 /// Zefyr widgets and document model.
6 6
 ///
7 7
 /// To use, `import 'package:zefyr/zefyr.dart';`.
8
-///
9
-/// See also:
10
-///
11
-///   * [Quick start]()
12
-///   * [NotusDocument], model for Zefyr documents.
13
-///   * [ZefyrEditor], widget for editing Zefyr documents.
14 8
 library zefyr;
15 9
 
16 10
 export 'package:notus/notus.dart';
17 11
 
18
-export 'widgets.dart';
12
+export 'src/widgets/buttons.dart' hide HeadingButton, LinkButton;
13
+export 'src/widgets/code.dart';
14
+export 'src/widgets/common.dart';
15
+export 'src/widgets/controller.dart';
16
+export 'src/widgets/editable_text.dart';
17
+export 'src/widgets/editor.dart';
18
+export 'src/widgets/image.dart';
19
+export 'src/widgets/list.dart';
20
+export 'src/widgets/paragraph.dart';
21
+export 'src/widgets/quote.dart';
22
+export 'src/widgets/selection.dart' hide SelectionHandleDriver;
23
+export 'src/widgets/theme.dart';
24
+export 'src/widgets/toolbar.dart';
25
+//export 'src/widgets/render_context.dart';
26
+

+ 1
- 1
packages/zefyr/test/rendering/render_editable_paragraph_test.dart 查看文件

@@ -6,8 +6,8 @@ import 'dart:ui';
6 6
 import 'package:flutter/material.dart';
7 7
 import 'package:flutter/rendering.dart';
8 8
 import 'package:flutter_test/flutter_test.dart';
9
-import 'package:zefyr/src/widgets/editable_rich_text.dart';
10 9
 import 'package:zefyr/src/widgets/render_context.dart';
10
+import 'package:zefyr/src/widgets/rich_text.dart';
11 11
 import 'package:zefyr/zefyr.dart';
12 12
 
13 13
 void main() {

+ 1
- 1
packages/zefyr/test/widgets/editable_paragraph_test.dart 查看文件

@@ -5,7 +5,7 @@ import 'dart:ui';
5 5
 
6 6
 import 'package:flutter/material.dart';
7 7
 import 'package:flutter_test/flutter_test.dart';
8
-import 'package:zefyr/src/widgets/editable_rich_text.dart';
8
+import 'package:zefyr/src/widgets/rich_text.dart';
9 9
 import 'package:zefyr/zefyr.dart';
10 10
 
11 11
 void main() {

+ 16
- 0
packages/zefyr/test/widgets/editable_text_scope_test.dart 查看文件

@@ -57,6 +57,20 @@ void main() {
57 57
       widget2 = createScope(renderingContext: context, showCursor: showCursor);
58 58
       expect(widget2.updateShouldNotify(widget1), isTrue);
59 59
     });
60
+
61
+    test('updateShouldNotify for imageDelegate changes', () {
62
+      var context = new ZefyrRenderContext();
63
+      var delegate = new ZefyrDefaultImageDelegate();
64
+      var widget1 =
65
+          createScope(renderingContext: context, imageDelegate: delegate);
66
+      var widget2 =
67
+          createScope(renderingContext: context, imageDelegate: delegate);
68
+
69
+      expect(widget2.updateShouldNotify(widget1), isFalse);
70
+      delegate = new ZefyrDefaultImageDelegate();
71
+      widget2 = createScope(renderingContext: context, imageDelegate: delegate);
72
+      expect(widget2.updateShouldNotify(widget1), isTrue);
73
+    });
60 74
   });
61 75
 }
62 76
 
@@ -64,11 +78,13 @@ ZefyrEditableTextScope createScope({
64 78
   @required ZefyrRenderContext renderingContext,
65 79
   TextSelection selection,
66 80
   ValueNotifier<bool> showCursor,
81
+  ZefyrImageDelegate imageDelegate,
67 82
 }) {
68 83
   return ZefyrEditableTextScope(
69 84
     renderContext: renderingContext,
70 85
     selection: selection,
71 86
     showCursor: showCursor,
87
+    imageDelegate: imageDelegate,
72 88
     child: null,
73 89
   );
74 90
 }

+ 1
- 1
packages/zefyr/test/widgets/editor_test.dart 查看文件

@@ -4,7 +4,7 @@
4 4
 import 'package:flutter/material.dart';
5 5
 import 'package:flutter_test/flutter_test.dart';
6 6
 import 'package:quill_delta/quill_delta.dart';
7
-import 'package:zefyr/src/widgets/editable_rich_text.dart';
7
+import 'package:zefyr/src/widgets/rich_text.dart';
8 8
 import 'package:zefyr/zefyr.dart';
9 9
 
10 10
 import '../testing.dart';

+ 1
- 1
packages/zefyr/test/widgets/selection_test.dart 查看文件

@@ -3,7 +3,7 @@
3 3
 // BSD-style license that can be found in the LICENSE file.
4 4
 import 'package:flutter/material.dart';
5 5
 import 'package:flutter_test/flutter_test.dart';
6
-import 'package:zefyr/src/widgets/editable_rich_text.dart';
6
+import 'package:zefyr/src/widgets/rich_text.dart';
7 7
 import 'package:zefyr/zefyr.dart';
8 8
 
9 9
 import '../testing.dart';