Browse Source

Added documentation about embedding images

Anatoly Pulyaevskiy 6 years ago
parent
commit
0d6010c302
3 changed files with 128 additions and 0 deletions
  1. 2
    0
      README.md
  2. 12
    0
      doc/heuristics.md
  3. 114
    0
      doc/images.md

+ 2
- 0
README.md View File

17
 * [Data Format and Document Model][data_and_document]
17
 * [Data Format and Document Model][data_and_document]
18
 * [Style attributes][attributes]
18
 * [Style attributes][attributes]
19
 * [Heuristic rules][heuristics]
19
 * [Heuristic rules][heuristics]
20
+* [Images][images]
20
 * [FAQ][faq]
21
 * [FAQ][faq]
21
 
22
 
22
 [quick_start]: /doc/quick_start.md
23
 [quick_start]: /doc/quick_start.md
23
 [data_and_document]: /doc/data_and_document.md
24
 [data_and_document]: /doc/data_and_document.md
24
 [attributes]: /doc/attributes.md
25
 [attributes]: /doc/attributes.md
25
 [heuristics]: /doc/heuristics.md
26
 [heuristics]: /doc/heuristics.md
27
+[images]: /doc/images.md
26
 [faq]: /doc/faq.md
28
 [faq]: /doc/faq.md
27
 
29
 
28
 ## Clean and modern look
30
 ## Clean and modern look

+ 12
- 0
doc/heuristics.md View File

87
 sure to use `ChangeSource.remote` when calling `compose()`. This allows
87
 sure to use `ChangeSource.remote` when calling `compose()`. This allows
88
 you to distinguish such changes from local changes made by the user
88
 you to distinguish such changes from local changes made by the user
89
 when listening on `NotusDocument.changes` stream.
89
 when listening on `NotusDocument.changes` stream.
90
+
91
+### Next up
92
+
93
+* [Images][images]
94
+
95
+[images]: /doc/images.md
96
+
97
+### Previous
98
+
99
+* [Style attributes][attributes]
100
+
101
+[attributes]: /doc/attributes.md

+ 114
- 0
doc/images.md View File

1
+## Images
2
+
3
+> Note that described API is considered experimental and is likely to be
4
+> changed in backward incompatible ways. If this happens all changes will be
5
+> described in detail in the changelog to simplify upgrading.
6
+
7
+Zefyr (and Notus) supports embedded images. In order to handle images in
8
+your application you need to implement `ZefyrImageDelegate` interface which
9
+looks like this:
10
+
11
+```dart
12
+abstract class ZefyrImageDelegate<S> {
13
+  /// Builds image widget for specified [imageSource] and [context].
14
+  Widget buildImage(BuildContext context, String imageSource);
15
+
16
+  /// Picks an image from specified [source].
17
+  ///
18
+  /// Returns unique string key for the selected image. Returned key is stored
19
+  /// in the document.
20
+  Future<String> pickImage(S source);
21
+}
22
+```
23
+
24
+Zefyr comes with default implementation which exists mostly to provide an
25
+example and a starting point for your own version.
26
+
27
+It is recommended to always have your own implementation specific to your
28
+application.
29
+
30
+### Implementing ZefyrImageDelegate
31
+
32
+Let's start from the `pickImage` method:
33
+
34
+```dart
35
+// Currently Zefyr depends on image_picker plugin to show camera or image gallery.
36
+// (note that in future versions this may change so that users can choose their
37
+// own plugin and define custom sources)
38
+import 'package:image_picker/image_picker.dart';
39
+
40
+class MyAppZefyrImageDelegate implements ZefyrImageDelegate<ImageSource> {
41
+  @override
42
+  Future<String> pickImage(ImageSource source) async {
43
+    final file = await ImagePicker.pickImage(source: source);
44
+    if (file == null) return null;
45
+    // We simply return the absolute path to selected file.
46
+    return file.uri.toString();
47
+  }
48
+}
49
+```
50
+
51
+This method is responsible for initiating image selection flow (either using
52
+camera or gallery), handling result of selection and returning a string value
53
+which essentially serves as an identifier for the image.
54
+
55
+Returned value is stored in the document Delta and later on used to build the
56
+appropriate `Widget`.
57
+
58
+It is up to the developer to define what this value represents.
59
+
60
+In the above example we simply return a full path to the file on user's device,
61
+e.g. `file:///Users/something/something/image.jpg`. Some other examples
62
+may include a web link, `https://myapp.com/images/some.jpg` or just some
63
+arbitrary string like an ID.
64
+
65
+For instance, if you upload files to your server you can initiate this task
66
+in `pickImage`, for instance:
67
+
68
+```dart
69
+class MyAppZefyrImageDelegate implements ZefyrImageDelegate<ImageSource> {
70
+  final MyFileStorage storage;
71
+  MyAppZefyrImageDelegate(this.storage);
72
+
73
+  @override
74
+  Future<String> pickImage(ImageSource source) async {
75
+    final file = await ImagePicker.pickImage(source: source);
76
+    if (file == null) return null;
77
+    // Use my storage service to upload selected file. The uploadImage method
78
+    // returns unique ID of newly uploaded image on my server.
79
+    final String imageId = await storage.uploadImage(file);
80
+    return imageId;
81
+  }
82
+}
83
+```
84
+
85
+Next we need to implement `buildImage`. This method takes `imageSource` argument
86
+which contains that same string you returned from `pickImage`. Here you can
87
+use this value to create a Flutter `Widget` which renders the image. Normally
88
+you would return the standard `Image` widget from this method, but it is not
89
+a requirement. You are free to create a custom widget which, for instance,
90
+shows progress of upload operation that you initiated in the `pickImage` call.
91
+
92
+Assuming our first example where we returned full path to the image file on
93
+user's device, our `buildImage` method can be as simple as following:
94
+
95
+```dart
96
+class MyAppZefyrImageDelegate implements ZefyrImageDelegate<ImageSource> {
97
+  // ...
98
+
99
+  @override
100
+  Widget buildImage(BuildContext context, String imageSource) {
101
+    final file = new File.fromUri(Uri.parse(imageSource));
102
+    /// Create standard [FileImage] provider. If [imageSource] was an HTTP link
103
+    /// we could use [NetworkImage] instead.
104
+    final image = new FileImage(file);
105
+    return new Image(image: image);
106
+  }
107
+}
108
+```
109
+
110
+### Previous
111
+
112
+* [Heuristics][heuristics]
113
+
114
+[heuristics]: /doc/heuristics.md