Fedi — Flutter open-source social network client. Part 4. Used packages.

Yevhenii Zapletin
11 min readJul 21, 2021

--

List of packages used by Fedi with examples and notes: provider, hive, moor, easy_dispose, intl, logging, and much more.

Fedi is an open-source client for Pleroma and Mastodon social networks written using Flutter available on iOS(Beta) and Android(Beta)

Series:

In this part:

· Intro
Specify version numbers without bounds
Outdated packages
How to find new packages
· Packages
build_runner — code generator
provider — dependency injection
intl — localization with code generation
fluttericon.com — icon font generator
moor — SQLite ORM
hive — key-value storage
panache & flex_color_scheme — color schemes
easy_dispose — dispose and clean up resources
url_launcher & uni_links — OAuth login
Working with files on devices
overlay_support — in-app overlay toasts
firebase_messaging & awesome_notifications — rich push notifications
json_serializable
nested_scroll_controller & extended_nested_scroll_view — ScrollView in ScrollView
video_player
cached_network_image
package_info_plus — build details at Runtime
flutter_html — render HTML
permission_handler
web_socket_channel — WebSockets API
share_plus — share to other apps
receive_sharing_intent — receive shares from other apps
collection — null-safety collection extension
extended_text_field — highlight mentions in text field
flutter_slidable — list view item actions on slide
flutter_keyboard_visibility
flutter_reorderable_list
scrollable_positioned_list — ListView with scrollToItem()
logging — log support
jiffy & timeago — DateTime & Duration utils

Intro

You can find up-to-date packages list in Fedi pubspec.yaml with a single-line comment about why these packages are used.

Specify version numbers without bounds

When you import a package from pub.dev you usually use ^1.0.0 notation. Which actually means >=1.0.0 <2.0.0. That means that any version above and equal to 1.0.0 and below 2.0.0 is acceptable. See version constraints in official docs.

It should be OK to use ^1.0.0 because all versions before major 2.0.0update should have backward compatibility (no API changes, only mark as deprecated is possible).

Unfortunately, not all package authors follow backward compatibility and you may have issues when the version will be upgraded. Additionally, sometimes even minor version updates may add bugs to the package.

So, a simple pub get run even without changes in pubspec.yaml or cloning repo to another machine may add unexpected errors.

Solution: Fedi uses only explicit versions like 1.0.0 to avoid backward compatibility issues. This may cause versions conflict which you should manually fix. So it is not acceptable for packages published on pub.dev(because other people depend on them) but is OK for applications like Fedi.

Outdated packages

Flutter development is under active development and sometimes community creates new better packages which completely replace old solutions. So I suggest always check package Github page to understand package development activity.

How to find new packages

Packages

build_runner — code generator

Is used to run code generations tasks for moor, json_serializable, mockito etc

provider — dependency injection

The most popular dependency injection framework for Flutter. It is used everywhere in Fedi.

Extended with easy_dispose_provider package.

intl — localization with code generation

Localization via .arb(looks like json) files with .dart code generation.

Localization context is injected on the app level, so you should re-run app to change locale.

Generated .dart classes provide cool features:

  • IDE autocomplete
  • bugfree — you always know that specified keys exist

By default, you should apply intl-utils package from the command line to re-generate .dart classes. However, you can use Intl Android Studio Plugin to achieve automated code generation.

You can learn more about localization from official docs

Weblate

Open-source(free self-hosted or paid cloud) localization web application with .arb files support. It has modern features(screenshot attachment to key to show context, git integration, ready for crowd translations) and easy to use.

You can see how Fedi Weblate project looks.

fluttericon.com — icon font generator

In order to turn SVG into icon font, you should make Compound Path. It is possible with Adobe Illustrator or Inkscape.

In Adobe Illustrator you can follow the next steps:

  1. Select all
  2. Ungroup
  3. Outline stroke(optional) — sometimes making a compound path is not possible without this and outline stroke can modify original shapes
  4. Make compound path

You can find config using by Fedi in icons_export folder

You can use font_awesome_flutter font if you don’t need custom icons

moor — SQLite ORM

It’s like Room for Android.

Pros:

  • Dart query builder with autocomplete & suggestions
  • Have database version migration mechanism;
  • You can watch() data for Select query. So you will have Stream which updates every time when the database is updated.
  • Almost all SQLite features like indexes, foreign keys, transactions etc are supported
  • There is moor_inspector

Cons:

  • It is not possible to implement all possible SQL operations with dart query builder. Sometimes you should use raw SQL queries and integrate them with moor(tell which data is updated);
  • You should use .moor files(just contains SQL queries) for some things. For example, Fedi uses it to create indexes;
  • Strange bug: If DAO is used in .moor you shouldn’t add it in @Database annotation: app_database.dart

Usage in Fedi:

moor_flutter — extension to use moor with flutter

moor_inspector is dart package and Android Studio plugin to view moor databases.

You can connect and view the database in Android Studio when app is running.

Dump DB from Android Emulator

hive — key-value storage

It’s like shared_preferences, but even better.

Pros:

  • Fast;
  • Secure.

Cons:

  • You should annotate all data classes and register adapters;
  • Adapters Ids implementation is really strange. You should put global id in data classes annotation. You should remember the last used id and increment it each time;
  • Only for simple key-value, SQLite is better for complex data structures.

Usage in Fedi:

hive_flutter — required extension to work with flutter

panache & flex_color_scheme — color schemes

Fedi uses custom design with day/night themes support.

However, previously Fedi had used themes generated with panache. It is a cool web application to generate Dart theme code.

Unfortunately, panache hasn’t been receiving updates for a long time, so generated code needs small manual changes to work with Flutter 2. You can also use forks or another similar solution of flex_color_scheme

easy_dispose — dispose and clean up resources

easy_dispose, easy_dispose_flutter, easy_dispose_provider, easy_dispose_rxdart packages were part of Fedi but now they are separated to own packages

Example from easy_dispose. You can explore specific packages for more details and examples.

Almost all Provider are DisposableProvider and dispose themselves when needed.

url_launcher & uni_links — OAuth login

Fedi uses OAuth to login to different instances.

To implement OAuth, you should launch OAuth URL via url_launcher (custom) and handle redirect URL with uni_links.

Different browsers work in different ways. For example, Chrome on Android just brings the app to foreground and uni_links linkStream is fired. However, Firefox on Android fully restart apps and you should handle getInitialUri() from uni_link.

You can see pleroma_api_oauth_service_impl.dart file for details.

There is uni_links2 package, which is a fork of uni_links and was created due to long uni_links inactivity. However, currently, uni_links is under active development. uni_links2 also supports reading NFC tags by default so iOS Review team will ask you why you use NFC.

Working with files on devices

Picking and saving files in Flutter is not simple due to differences in Android and iOS. Even more, different OS versions have different behavior and you(or packages you use) should support all variants.

photo_manager

Fetch albums and photos from device. See/lib/media/device

file_picker

A package that allows you to use the native file explorer to pick single or multiple files, with extensions filtering support.

Usage in Fedi:

post_message_select_media_attachment_type_to_pick_widget.dart

image_picker

A Flutter plugin for iOS and Android for picking images from the image library and taking new pictures with the camera.

It is sed to pick image from Camera: camera_media_service_impl.dart

flutter_image_compress

When you pick image from iOS gallery it may be picked in .heic format which is usually not supported in other softwear, so you need to re-compress the image

Usage in Fedi — photo_manager/photo_manager_media_device_file_model.dart

gallery_saver

Saves images and videos from the network or temporary files to external storage.

Usage in Fedi — media_attachment_add_to_gallery_helper.dart

overlay_support — in-app overlay toasts

Sometimes you want to display notifications when an app is on the foreground

Usage in Fedi — overlay_notification_service_impl.dart

Why not Snackbar?

Because overlay_support is more customizable

firebase_messaging & awesome_notifications — rich push notifications

By default, firebase_messaging displays a simple(just title and body) notification from FCM notification message:

  • You should localize messages on the server-side;
  • You can’t add actions like ‘Reply’ to notifications;
  • You can’t customize notification layout like ‘Big Picture’;
  • You can’t run custom code and modify notification content before display.

To fix all issues mentioned above Fedi uses awesome_notifications. However currently(during the migrating period) Fedi supports both push notification delivery approaches. Check Readme for details.

Note: awesome_notifications version is under 1.0.0 right now and that is a problem. API may be changed several times before the 1.0.0 stable release. Think twice before taking risks.

Usage in Fedi:

json_serializable

Most popular package to parse Map from JSON String and vice versa.

explicitToJson

This option is disabled by default, however, you must enable it if you want to include nested objects with toJson. Otherwise nested objects will be included via toString()

nested_scroll_controller & extended_nested_scroll_view — ScrollView in ScrollView

Almost all timelines in Fedi are actually tabs with ScrollView inside another ScrollView.

Additionally Fedi show/hide some UI elements depending on scroll and this requires additional tricks. nested_scroll_controller & extended_nested_scroll_view help implement such things

Usage in Fedi:

video_player

A Flutter plugin for iOS, Android and Web for playing back video on a Widget surface.

Currently, Fedi has custom UI for Video/Audio players. Previously Fedi had used chewie and chewie_audio UI. Another good UI is better_player

wakelock

This is a Package that allows you to keep the device screen awake, i.e. prevent the screen from sleeping

Usage in Fedi — /lib/media/player

cached_network_image

A flutter library to show images from the internet and keep them in the cache directory.

flutter_cache_manager

Used internally by cached_network_image and imported manually to control cache config.

Usage in Fedi: files_cache_service_impl.dart

package_info_plus — build details at Runtime

This Flutter plugin provides an API for querying information about an application package.

Displays version number on splash screen: config_service_impl.dart

flutter_html — render HTML

A lot of text in Fedi may have html tags and flutter_html helps with that.

Pros:

  • Good performance.

Cons:

  • Doesn’t support text selection (only partial selection in the latest updates).

Usage in Fedi: html_text_widget.dart

html

Helps to transform text with HTML tags to raw text

permission_handler

This plugin provides a cross-platform (iOS, Android) API to request permissions and check their status. You can also open the device’s app settings so users can grant permission.

In Fedi each permission have own bloc: /lib/permission

web_socket_channel — WebSockets API

In addition to push notifications, Fedi can receive updates via WebSockets API provided by Pleroma and Mastodon.

Notes:

  • WebSockets drain battery. Always provide an option to disable features that may cause problems for use;
  • It is not possible to handle WebSockets updates in background. iOS doesn’t have API to run tasks in background.

Usage in Fedi: web_sockets_channel_source_impl.dart

share_plus — share to other apps

Share content from Fedi to other apps

Usage in Fedi: external_share_service_impl.dart

receive_sharing_intent — receive shares from other apps

Receive share intents from other apps to Fedi

Pros:

  • Only one package to receive sharing intents on Flutter right now.

Cons

Usage in Fedi: external_share_service_impl.dart

collection — null-safety collection extension

Useful IterableExtension

  • firstOrNull
  • whereNotNull

extended_text_field — highlight mentions in text field

Extended official text field to build special text like inline image, @somebody, custom background etc.

Is used to highlight @user mentions in text field

flutter_slidable — list view item actions on slide

A Flutter implementation of slidable list item with directional slide actions that can be dismissed.

Usage in Fedi — notification_list_item_widget.dart

flutter_keyboard_visibility

React to keyboard visibility changes.

Usage in Fedi — upload_media_attachment_list_all_widget.dart

flutter_reorderable_list

Reorderable list with animations

Usage in Fedi — timelines_home_tab_storage_widget.dart

scrollable_positioned_list — ListView with scrollToItem()

Flutter ListView doesn’t have scrollToItem() and scrollable_positioned_list does

Usage in Fedi — status_thread_widget.dart

logging — log support

Logging library from dart.dev team.

  • Fedi prints a lot of messages to log each second;
  • Grep Console Android Studio Plugin helps filter messages which you really need right now;
  • Don’t forget to disable log in production builds, because many print() calls may highly decrease performance. Additionally, you may put sensitive data in the console which is not good

Pros:

  • Supports Log Tag
  • Supports putting error and stackTrace from catch
  • Supports printing via functions(see example) and via simple String

Cons:

  • Nested Log tags is not supported
  • Strange(as for me ) log levels like fine, finer, finest

Prefer log with anonymous function instead of raw string.

It doesn’t have any sense while logging is enabled.

However, it does have a sense when you disable log in release builds by simple disabling print() calls somewhere in one place (like logging/logging_service_impl.dart in Fedi).

Benefits(when log is disabled):

  • You may use function/getter which calculates something for log which will be not executed in disabled state
  • Don’t create new String objects and don’t clean up them with Garbage Collector. I don’t know how actually GC works in Flutter, but in Android this have a sense

jiffy & timeago — DateTime & Duration utils

jiffy

Jiffy is a Flutter (Android, IOS and Web) date time package inspired by moment.js for parsing, manipulating, querying and formatting dates

Usage in Fedi — duration_date_time_form_field_row_widget.dart

timeago

This library is useful for creating fuzzy timestamps. (e.g. “5 minutes ago”)

Usage in Fedi — date_time_dynamic_time_ago_widget.dart

Final Words

Feel free to comment and fill issue if you don’t agree with something or have suggestions.

Next partPart 5. Android Studio Plugins & Feature Plans.

Start using Pleroma and Mastodon with Fedi if you still not in Fediverse: iOS(Beta) and Android(Beta). Any feedback is welcome.

If you are interested in Fedi and want to help to develop it you can start from Readme.

--

--