Developer Documentation - coi-dev/flutter-deltachat-core GitHub Wiki
The Flutter Delta Chat Core plugin is a Flutter plugin (https://flutter.io/docs/development/packages-and-plugins/developing-packages) which provides IMAP/SMTP chat functionality by using the Delta Chat Core (https://github.com/deltachat/deltachat-core) and providing an API for consuming Flutter clients.
The DCC is integrated as a sub module within the Delta Chat Core Plugin. Right now a fork of the main project of DCC is used (https://github.com/open-xchange/deltachat-core-rust). The latest develop version is used.
To upgrade the core perform the following actions:
- Every core update should have a corresponding GitHub ticket
- Update the submodule
- Build the core
- Verify the app + plugin are still working as intended
- As soon as everything is working, commit and push to the Flutter Delta Chat Core Plugin repository
This area covers the API provided by the plugin. General structure and flow
The plugin supports two general flows:
- The active requesting / setting of information via MethodChannels leading to a "direct" but async response
- The registering of listeners via EventChannels which produces a stream of response events
Further information regarding the general Flutter approach to handle Flutter to native (Android / iOS) communication can be found in the official documentation (https://flutter.io/docs/development/platform-integration/platform-channels).
If the app needs to get or set information in the Delta Chat Core (DCC) it calls one of the provided plugin methods. Every call related to a MethodChannels (https://docs.flutter.io/flutter/services/MethodChannel-class.html) is async and has to be handled that way (https://www.dartlang.org/guides/language/language-tour#asynchrony-support). For visualization please see the diagrams area below.
- A method call always produces an answer, but it can be null. Answers for e.g. setters will be
Future<void>and should be ignored by the caller- Returning a value is mandatory to provide the information to the caller that the async call is finished
- MethodChannels should use the following MessageCodecs
- StringCodec: If only single Strings should be transferred (https://docs.flutter.io/flutter/services/StringCodec-class.html)
- StandardMessageCodec: If any default data type should be transferred. This type is also used for multiple values (e.g. List or Map) if no nesting is performed (https://docs.flutter.io/flutter/services/StandardMessageCodec-class.html)
- JSONMessageCodec: If complex data set with nesting is transferred (https://docs.flutter.io/flutter/services/JSONMessageCodec-class.html)
- Adding new methods required the following steps:
- Implement the call in Dart
- Implement the call in Java / Swift
- Verify the JNI call + dc_wrapper entry / Swift call against the DCC is existing and working
- For now only the existing MethodChannel should get used, no new channels should get created
- All calls require matching constants on the Dart and native side, to connect the calls. Avoid using inline Strings.
- General functionality (e.g. error handling) should be added in the AbstractCallHandler.java / Method.swift or a similar helper / class in the Dart part
- For error checks or other often needed helper methods look into those classes instead of re-implementing functionality
If the app needs continuous information about data, e.g. for incoming new mails or to keep track of the login progress, EventChannels should get used. See (https://docs.flutter.io/flutter/services/EventChannel-class.html) for more information. For visualization please see the diagrams area below.
- Calling the
addListenermethod on the plugin registers a listener / listeners for a given event type- The plugin keeps track of the StreamController registrations and delegates only relevant events (filtered by id) to the caller
- The native plugin part pushes all upcoming events to the EventChannel
- Calling the removeListener method on the plugin removes the listener
- The app should call
removeListenerin the dispose method of the listening component (https://docs.flutter.io/flutter/widgets/State/dispose.html)
- The app should call
- The Dart part manages the listeners, while the native part only delegates events
- The native parts only delegate events to the EventChannel, the actual filtering is done within the Dart part
- Dart manages listeners from the calling app, to receive EventChannel events and push them back to interested callers
- Every pushed event is from Type
Eventand contains:-
integer eventIdallows the verification of event relevance for a caller -
object data1main payload object which carries most of the relevant information (exist nearly always) -
object data2secondary payload object which contains additional information if existing (exists only some times)
-
- The EventChannel normally shouldn't need further extensions in the plugin part, as it written in a generic way
This diagram describes the used colors in the following diagrams.

Simplified version of the MethodChannel flow provided by the plugin.

Simplified version of the EventChannel flow provided by the plugin.
