Portrait of Patrice GADEGBEPatrice GADEGBE

Flutter packages

Three private Flutter packages gather what my applications had in common: a generic bloc state and a few widgets, the sign-in screen and session, the theme and language settings.

Role
Sole author
Period
July 2025, with a touch-up in January 2026
Status
In service. Used by two applications, Tontini and Soccercup
Technologies
Flutter, Dart, flutter_bloc, hydrated_bloc, dio, retrofit
Repositories
Three
Dependencies of the shared Flutter packagesThe Tontini and Soccercup applications depend on the settings and sign-in packages, which themselves depend on the base package.ApplicationsTontiniSoccercupcofinger_settingstheme, language, profilecofinger_loginscreen, session, tokencofinger_corebloc state, messagesform widgetsdepends ondepends on
Figure 1. Dependencies between the applications and the three packages. The settings also rely on the sign-in, whose session they read.

Context

Tontini and Soccercup were developed the same year from the same template, and both repeated the same sign-in, the same settings and the same way of representing the state of a screen. The three packages were born in July 2025 from the extraction of that common code, and not from a prior design.

Problem

Each cubit redeclared its loading, success and failure states, and a fix made to the sign-in screen of one application had to be carried over by hand to the other. The shared code also had to avoid imposing its appearance, since the two applications each have their own colours.

Answer

An extraction from two applications in service

The day after the packages were created, Tontini deleted its own bloc state, its sign-in cubits and several widgets, that is 1,665 lines removed; Soccercup followed ten days later, with 1,240 lines removed. The packages therefore contain only code that had already been in use.

A single shape of state for all screens

The generic state carries a type, namely idle, loading, loaded, empty or failure, and an optional piece of data for each. An alias hides the four type parameters that most screens do not use, and it is the most reused piece: it appears 131 times in Soccercup and 45 times in Tontini.

typedef SimpleBlocState<T> = BlocState<T, void, void, void, dynamic>;

class BlocState<T, Tidle, Tloading, Tempty, Tfailure> extends Equatable {
  const BlocState({
    required this.type,
    this.loadingData,
    this.loadedData,
    this.idleData,
    this.emptyData,
    this.failureData,
  });
Listing 1. The generic bloc state and the alias that makes it short to write.

A sign-in grafted onto the host’s client

The host application passes its own HTTP client to the sign-in package, which adds an interceptor to it: the interceptor attaches the token to each request and signs the user out when the server answers that they are no longer authorised. The theme and the language, for their part, are a persisted state, which the application applies to its interface itself; the shared widgets read the colours of the current theme, so that each application keeps its identity. Finally, the messages intended for the user go through a single bus, which one component alone is responsible for displaying.

Limits and outlook

The applications reference the packages by their path on disk and not by a version, which speeds up work across three repositories but lets incompatible changes through without a number or a warning, and requires each application to be cloned next to the packages. The tests amount to no more than the original template.

The sign-in also fixes the server’s contract, namely four paths and a token scheme, and therefore suits only the APIs that expose it identically; the interceptor further assumes that the host has stored the session in a precise form, which no documentation states. Finally, reuse is limited to two applications, and the Flutter work on Sanu, which is more recent, does not rely on these packages.

Back to the other projects