Falotier Riverpod: a 'real life' state management PoC (Part 1)

Hi there! This is my first Flutter post, \(• ◡ •)/
Full app code here:
It's been several years now that I have started my Flutter journey, did some apps for clients, did some research too, and like everyone, I am on a quest.
I am a Riverpod
enthusiast, but coming from a MVVM oriented world, I had my share of doubts and interrogations. I read a lot of examples, but I couldn't find a sample app that covers the scenarios I always meet when I am building an app for a client.

The purpose of this Proof of Concept is to implement all real life app scenarios and see if the Riverpod
elegantly supports all the needed mutations (spoiler alert: it kind of does :).

S01E01.A.Falotier's.introduction.1080p.H264
There will be several posts on Falotier's implementation. I dunno how many for now, but here is my forecast:
- Falotier's introduction: description of the loading states (you are here)
- Architecture walkthrough
Loading from scratch
use case studyRefreshing
use case studyList update
use case studyItem details update
use case study- Design implementation
Falotier was the name given to the street lamp lighters in France.
Loading states
What I call loading states includes all the state transitions of the app. Since all those transitions include async calls, some of them are remote. It means we have to wait between transitions. Thus we need to give some UI feedback to the users.
It can be done with progress bar, refresher widget, saving overlay...But also with some animations.
For example when a falotier lights a lamp, the fire coming from the lamp will begin to grow when the remote call is done. Respectively, the fire will shrink when he'll turn off the lamp.
As a falotier:
- You can assign new streets to you by taping to the
Add Street
button, - You can lighten your burden by taping on the cross of an item,
- You must lit the street lamp when the night is coming by taping on the street lamp bulb,
- You must turn off the street lamp when the night is over with the same gesture.
Loading from scratch
The loading of an empty screen.
If the loading is successful, we display our result.
Or we display an informative message to the user and we give him the possibility to retry.

Refreshing
When an item is already loaded and we want to refresh it.
Typically the pull-to-refresh
of a list.
If the refresh is successful, we update our whole list.
It there is an error during the refresh, we show a SnackBar
.

List update
Adding a new item in the list
We tap on the FloatingActionButton
, it opens a modal displaying our available streets.
We select one, we call an update
method on our server side.
During the call, we show an overlay.
If the remote call is successful we update our list state and close the modal.
If there was a error during the call, we display a SnackBar
to our user.

Removing an item from a list
We tap on an item cross.
We call a remove
method on our server side.
During the call, we transform our cross icon to a loading widget.
If the remote call is successful we update our list state and the item is removed.
If there was a error during the call, we display a SnackBar
to our user.
add and remove a list item
Item details update
By taping to a list item, we navigate to a street.
By taping on the street lamp, we toggle its light.
This is calling a method on the server side.
During the remote call, we display an animation of the light which is growing or fading.
If it fails, the previous state is restored and we display a SnackBar
.

Our architecture must of course propagate the new immutable item to the item list.
The design
I implemented a theme with a separate flutter project called falotier_design.
It's like I had a design system and implemented it with a theme, giving semantics to colors, spaces, text, etc...
I also have a collection of Widgets
in this library that I use in my apps.
For this I followed Aloïs Deniel guidance.
Please have a look at this great video.
You can also check his repo.