Skip to content

Latest commit

 

History

History
125 lines (100 loc) · 7.9 KB

project-overview.md

File metadata and controls

125 lines (100 loc) · 7.9 KB

In-depth project overview

The project starts with the main.dart file, which configures all necessary services (e.g supabase) and runs the Points widget inside. Because the Project uses the repository pattern and because all repositories need a SupabaseClient, this client is injected into all repositories using the singleton from supabase_flutter. The Points widget first provides the AuthRepository and MetadataRepository to the widget tree, which are both needed in the top Cubit, the AuthCubit, which is placed above the (first) Navigator, the AuthNavigator, which listens to the AuthCubit.

Diagram for the different UI pages (and delegates) (red), state management (orange) and repositories (yellow)

Authentication

The AuthCubit first tries to auto log in using the persisted credentials by an injected hive 'Box'. While the AuthNavigator is waiting for the auto log in to complete, it shows the AuthInitialPage. If not logged in the AuthPage is shown. The AuthCubit also handles errors, as all Cubits report errors to the AuthCubit. If an error occurs the AuthNavigator shows the ConnectionLostPage, which lets the user decide if they want to retry the connection or log out. When the user is finally logged in, the HomeNavigator is shown, with all other repositories and shared cubits that need the supabase client to be logged in.

Home and navigation

The HomeNavigator first includes the NotificationDelegate, which listens to the NotificationCubit, to display in app notifications in front of all pages using in_app_notifications. For in_app_notifications to work the InAppNotification had to also be placed in the Points widget.

The HomeNavigator does not listen to any Cubit, instead it just provides all routes in the onGenerateRoute callback and all navigation occurs in the children of the HomeNavigator, by calling its pushNamed method. Some routes also accept a parameter, for example to open an example friend (by their id), call e.g: Navigator.pushNamed(context, "/friend/033d628a-bf96-4edd-add7-e10cc197032e. The initial page on the navigator is the HomePage, it has a button to access the GivePointsPage, a button to access the NotificationsPage and a menu to access the UserDiscoveryPage, ProfilePage, and InfoDialog.

The HomePage also listens to different Cubits to display the points, gives and number of notifications in realtime in the app bar. The actual content of the HomePage however is the RelationsSubPage, which shows an in realtime updated list of the friends, friend requests sent to the user, friend requests from the user, blocked users, and others that have blocked the user. If clicked on a friend, a FriendPage for that user is opened. From the FriendPage the ChatPage or the GiveFriendPointsDialog.

Project structure

All repositories are in packages/, in different separated dart packages, while the state management is in lib/state_management and the pages are in lib/pages, the other directories in lib/ are: lib/helpers, lib/theme and lib/widgets (for widgets shared between pages).

Supabase (and other) configurations

As previously mentioned, points uses the supabase_flutter singleton, which is configured in the supabase_configuration.dart file, which is called in main.dart. The supabase_configuration.dart file, uses the dotenv package, to read the .env file, which contains the url and the supabase anon key.

The configure_package_info.dart file configures the package_info_plus package to read the current version of the program, which happens in the InfoDialog widget. It is also called in the main.dart file.

Supabase and PostgreSQL

The sql files needed in a points supabase project are found in supabase/ and a guide to configure a supabase project for points is found here.

In points the different repositories use their injected SupabaseClient to interface with supabase, in points the tables profiles, relations, chats, messages, and notifications, which are defined in main.sql, are all queried and listened to directly, without anything in between.

It is made sure via RLS, that the user can only query/listen to the table that they are allowed to. A user can query all profiles, but they are only allowed to query their own relations, notifications, and chats/messages.

To however update the tables, for example send a friend request to a user, the repositories cannot directly update the tables. Updating a profile, getting a profile from an email, managing relations (accepting/rejecting a request, blocking, etc.). and even complex queries like searching for users or querying all relations, are done via functions. These functions are are defined inside of functions.sql.

It is also notable, that the authentication is from supabase. For every new signed up user, supabase adds a new row to auth.users and then via a trigger, a new profile is inserted into the profile table of points. To redistribute the points at the end of the day, a crontab is used, it is also defined inside of main.sql.

App icon and splash screen

The points icon is three different svgs in the icons folder. The generate-icons.sh script then uses imagemagick to convert these svgs into three different pngs, which are then used by flutter_native_splash and flutter_launcher_icons to put in the correct directories in the ios and android folders. The configuration (path to the generated pngs, as well as colors) for these two packages is in pubspec.yaml.

Testing and GitHub Actions

At the moment only tests for the repositories have been written. These are executed in GitHub Actions by .github/workflows/testing.yml.

The other file .github/workflows/analyze.yml, runs the dart analyze and dart format commands, to statically analyze the project and format it.

Design, fonts and theming

The flutter_neumorphic library was used to achieve a neumorphic design. However, lots of custom widgets still needed to be made, because of the relatively limited library. The colors and theme (the app does not include support for white mode) for the app are located in lib/theme/. These are all put together inside the Points widget. For the font Courier Prime is used, which is configured via the google_fonts package.