Build coverage Android iTunes App Store Web Flutter Version

Table of Contents

The AEGEE-Leiden App

Introduction

The AEGEE-Leiden App is a mobile application designed for members of AEGEE-Leiden, a European student organization. This app provides users with easy access to events, news, and other important information related to the organization. It is available on both Android and iOS platforms, as well as a web version for broader accessibility.

Features

  • Members: Members can create an account and customize their profile with personal information.
  • Events: View upcoming events in the calendar and get detailed information about each event. Admins can create and manage events.
  • Posts: Stay up-to-date with the latest news and announcements from AEGEE-Leiden in the feed. All members can create posts, but only admins can publish them.
  • Interactions: Members can comment on posts and events and let others know to which events they are going.
  • Resources: Access important documents and resources related to the organization, such as photo albums, Eurokeys editions, booklets, and ALV documents.
  • Notifications: Receive push notifications for new posts, comments, and events.
  • Admin Panel: Admins have access to an admin panel where they can manage new users and posts, as well as send custom push notifications.
  • External Links: Links and resources not integrated into the app can be accessed through the links section of the app's sidebar.
  • Settings: Users can customize their app experience by changing the theme, language, and notification settings.

Documentation

Both the functional and technical documentation can be found on the automatically generated Docs page. To board members, the site may seem daunting at first, but most of the important information for board members can be found in the 'Topics' section of the side menu, which contains descriptions to all the different pages in the app as well as a topic called Services which contains information about the different (external) services the app uses. For one service, being the Cloud Functions, there is a dedicated topic page. This is because the service covers a lot of functionality that are not immediately clear to regular app users (such as how new activities in the app are automatically added to the AEGEE Google Calendar). with If any information is missing or unclear, please let us know so we can improve the documentation.

Development

This section is intended for developers who want to contribute to the app. If you are a board member or user of the app, you can ignore this section.

Ecosystem

Before starting out, it is important to understand all the different services, tools, and platforms that are relevant to the development process. The app is built using the following technologies:

  • Development Platform: The app's code is hosted on our GitHub repository, where we manage issues, pull requests, and releases.
  • Environments: The app has two environments: dev and prod. The dev environment is used for development and testing, while the prod environment is used for the production version of the app.
  • Frontend: The app is built using the Flutter framework, which allows for cross-platform app development. The app is written in Dart.
  • Backend: The app uses Firebase for most of its backend services. Developers can request access to the Production Firebase Project and Development Firebase Project. Aside from Firebase, some of the cloud computing aspects of the app are handled on the somewhat related Google Cloud Platform. Here, too, we have a Production GCP Project and a Development GCP Project. The features that we use are:
    • Authentication: Firebase Authentication is used for user authentication.
    • Firestore: Firestore is used as the database for storing posts, events, and other information.
    • Storage: Firebase Storage is used for storing images such as event banners and user profile pictures.
    • Cloud Messaging: Firebase Cloud Messaging is used to enable push notifications.
    • Functions: Firebase Functions are used for server-side logic, such as sending push notifications on specific events and executing more sensitive operations such as deleting users and giving users admin rights. It is this aspect of the app that is most closely related to the Google Cloud Platform, as the functions are written in Node.js and run on Google's servers. Additionally, we have some service accounts set up for a variety of tasks, such as adding new events to the AEGEE-Leiden Google Calendar and fetching data from the AEGEE-Leiden Google Drive.
    • Hosting: Firebase Hosting is used to host the web version of the app, which is accessible at app.aegee-leiden.nl.
    • Extensions: We use the 'Resize Images' extension to resize images uploaded by users to allow for thumbnails and a consistent format.
    • Remote Config: Remote Config is used to store configuration values that can be updated without updating the app. Currently, this is only used for providing the latest app version and the links to 'quick access' items on the ALV page.
  • Content Management: Aside from data stored in Firestore and Firebase Storage, the app also uses Google Drive to store some resources. These are organised as follows:
    • Intranet Drive: This drive contains everything that is displayed on the resources page of the app. This includes photo albums, Eurokeys editions, booklets, and ALV documents.
    • AppTeam Drive: The cms folder in this drive contains the Terms and Conditions of the App as well as the 'Discounts' document that can be accessed from the 'Links' section of the app.
  • App Stores: The app is available on both the Google Play Store and the Apple App Store. Publishing Android apps is done through the Google Play Console, while publishing iOS apps is done through App Store Connect.
  • CI/CD: The app uses GitHub Actions for various CI/CD tasks, although this is still a work in progress. The workflows can be found in the workflows folder of the repository.
  • Testing: While some tests have been written for the app, there is not yet a comprehensive testing strategy in place. The tests can be found in the test folder of the repository and are run using the flutter test command.
  • Local Storage: The app uses the shared_preferences package to store user preferences locally on the device. While only a few preferences are currently stored, is is good to be aware of this functionality.
  • Secrets: The app uses a variety of secrets, such as API keys and service account credentials. You can download these secrets from the keys folder in the AppTeam Drive. Which keys you need depends on the kind of tasks that you are working on, but having the .env file in the root folder is one of the most important things to get started.

Getting Started

To get started with the development of the app, you will need to set up your development environment. This includes installing Flutter, cloning the project, and configuring your IDE. For a more detailed guide on how to get started, please refer to the wiki.

Once you have set up your development environment, you can start working on the app. Here are some common commands that you will need to use:

  1. Install dependencies: Before you can run the app, you need to install the dependencies. You can do this by running flutter pub get in the root folder of the project.
  2. Generate code: The app uses code generation for various tasks, such as generating models and routes. You can run the code generators by running dart run build_runner build in the root folder of the project. You can also use dart run build_runner watch to rerun the generator on file changes, but if you are not actively working on the generators, it is better to run the build command only when needed.
  3. Run the app: You can run the app on an emulator or a physical device. Ensure you have build flavors set up correctly. Then run the app using flutter run --flavor dev --dart-define=IS_DEV=true for the development version of the app.

Contributing

We use issues and branches for development. These are merged into the master branch with pull requests. Releases are preserved on the stable channel.

Commit messages

We follow the Angular Commit Message Guidelines. Commits should be in the format

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

Where type is any of the following:

  • feat: A new feature
  • fix: A bug fix
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • refactor: A code change that neither fixes a bug nor adds a feature
  • perf: A code change that improves performance
  • test: Adding missing or correcting existing tests
  • chore: Changes to the build process or auxiliary tools and libraries such as documentation generation

Tools and tips

To make development easier, you can use the following tools and tips. Some assume you are using Visual Studio Code as your IDE, although other IDEs may have similar functionality.

  • Flutter and Dart extensions: Install the Flutter and Dart extensions in Visual Studio Code for better support for Flutter development.
  • GitHub Copilot: Install the GitHub Copilot extension in Visual Studio Code for AI-powered code suggestions.
  • Flutter Riverpod Snippets: Install the Flutter Riverpod Snippets extension in Visual Studio Code for easy access to common Riverpod snippets.
  • FVM: Use FVM to manage Flutter versions. This allows you to switch between Flutter versions easily and avoid conflicts between projects.
  • File Nesting: In the VS Code settings, enable the Explorer>File Nesting setting to group related files together in the file explorer. You can add your own nesting rules in the settings. The following are recommended:
    • Item:*.dart, value: ${capture}.g.dart,${capture}.freezed.dart, for generated files.
    • Item:pubspec.yaml, value: pubspec.lock,.packages,.flutter-plugins,.flutter-plugins-dependencies,.metadata,*.yaml,*.yml,*.log,.fvmrc,upload_keystore.jks, for a cleaner project root.

Testing

The app has a few tests that can be run using the flutter test --dart-define=IS_DEV=true command. Currently, not all tests are passing.

Libraries

screens/settings/local_widgets/about
screens/userProfile/local_widgets/actions
screens/activity/local_widgets/actions
screens/activity/activity
widgets/activity/activityBuilder
widgets/activity/activityCategory
services/firebase/firestore/local/activityFunctions
models/activityModel
providers/activityProvider
widgets/activity/activityTile
screens/calendar/local_widgets/activityTileList
screens/admin/admin
services/firebase/functions/local/adminFunctions
screens/resources/alv/alv
screens/navigationShell/local_widgets/appBar
screens/navigationShell/local_widgets/appBarActions
services/firebase/authentication/authExceptionHandler
services/firebase/authentication/authService
services/firebase/authentication/authStatus
services/firebase/authentication/local/authStream
services/navigation/authStream
utils/blurhashFunctions
screens/createActivity/local_widgets/body
screens/resources/booklets/booklets
screens/calendar/calendar
screens/calendar/calendarModel
services/calendar/calendarService
screens/calendar/local_widgets/calendarViewSelectionBar
screens/createPost/local_widgets/callToActionButton
screens/userProfile/local_widgets/chips
services/firebase/cloudMessaging/cloudMessagingService
screens/createActivity/local_widgets/color
widgets/comment/commentForm
widgets/comment/commentFormProvider
services/firebase/firestore/local/commentFunctions
models/commentModel
widgets/comment/commentSection
widgets/comment/commentSectionProvider
widgets/comment/commentTile
screens/confidentialBody/confidentialBody
services/connectivity/connectivityService
screens/createActivity/createActivity
screens/createActivity/createActivityProvider
widgets/activity/createActivityResult
services/firebase/authentication/local/createDeleteFunctions
screens/createPost/createPost
screens/createPost/createPostProvider
screens/createPost/local_widgets/createPostResult
screens/navigationShell/local_widgets/currentRouteTitle
providers/currentUserProvider
utils/custom_icons
models/customClaimsModel
screens/admin/local_widgets/customNotificationPage
utils/customQuillEditors
screens/createActivity/local_widgets/dateTimePicker
screens/sidebar/local_widgets/destinations
utils/dialogs
screens/admin/local_widgets/disabledUsersList
services/drive/driveApiService
screens/resources/driveFileModel
screens/userProfile/local_widgets/editableBirthday
screens/userProfile/local_widgets/editablePhoneNumber
widgets/post/editDeleteMenu
screens/settings/local_widgets/emailResetForm
screens/settings/local_widgets/emailResetTile
env/env
screens/resources/eurokeys/euroKeys
screens/activity/local_widgets/europeanEventDescription
utils/extensions
screens/feed/feed
services/drive/local/fetchFunctions
screens/resources/local_widgets/fileTile
screens/resources/local_widgets/fileTree
screens/calendar/filterModel
utils/firestoreConverters
services/firebase/firestore/firestoreService
screens/home/local_widgets/floatingActionButton
screens/resources/local_widgets/folderExpansionTile
screens/landing/local_widgets/formSwitcher
services/firebase/functions/functionService
services/firebase/remoteConfig/local/getConfigFunctions
screens/calendar/local_widgets/getOlderActivitiesButton
screens/home/home
screens/home/homeModel
utils/imagePickerAndCropper
screens/inbox/inbox
screens/inbox/inboxData
services/firebase/firestore/local/inboxFunctions
screens/inbox/inboxModel
services/localNotifications/local/initializationSettings
providers/isInAsyncProvider
screens/landing/landing
screens/landing/local_widgets/landingButton
screens/landing/local_widgets/landingFormField
screens/landing/landingModel
screens/sidebar/local_widgets/linkDestination
screens/createPost/local_widgets/linkedActivityMenu
screens/createActivity/local_widgets/linkedUrl
screens/calendar/local_widgets/listCalendarView
screens/settings/local_widgets/localePreferenceTile
services/localNotifications/localNotification
screens/activity/local_widgets/localParticipantsSection
services/localStorage/localStorage
screens/createActivity/local_widgets/location
screens/landing/login/login
services/firebase/authentication/local/logInOrOutFunctions
main
screens/confidentialBody/local_widgets/memberInfo
screens/members/members
widgets/user/nameTag
screens/navigationShell/local_widgets/narrowViewAppBarLeading
screens/feed/local_widgets/newEventTile
widgets/user/noAvatarTile
screens/resources/local_widgets/node
screens/createActivity/local_widgets/notificationCheckbox
services/firebase/cloudMessaging/local/notificationFunctions
screens/navigationShell/local_widgets/notificationInboxIcon
screens/settings/local_widgets/notificationOptions
services/navigation/notificationRedirectStream
screens/inbox/local_widgets/notificationTile
screens/settings/local_widgets/notificationToggles
widgets/user/offlineNameTag
widgets/user/offlineProfilePicture
services/firebase/firestore/local/participantFunctions
screens/activity/local_widgets/participantsModel
screens/activity/local_widgets/participantType
screens/activity/local_widgets/participateSection
screens/landing/passwordReset/passwordReset
screens/settings/local_widgets/passwordResetTile
services/localNotifications/local/permissionFunctions
screens/navigationShell/local_widgets/photoAlbumButton
screens/createActivity/local_widgets/photoAlbumCheckbox
screens/resources/photos/photos
screens/resources/local_widgets/photoUpload
screens/createActivity/local_widgets/pickBannerButton
utils/pluralResolver
screens/post/post
screens/createPost/local_widgets/postBody
widgets/post/postCard
screens/feed/postCreationDateModel
services/firebase/firestore/local/postFunctions
screens/post/postModel
models/postModel
screens/settings/local_widgets/privacyStatement
services/firebase/functions/local/profileFunctions
widgets/user/profilePicture
utils/providerObserver
screens/sidebar/local_widgets/quickLinksDialog
services/localNotifications/local/receivedNotificationFunctions
screens/activity/local_widgets/referencedPostPage
screens/landing/register/register
services/firebase/remoteConfig/remoteConfigService
screens/userProfile/local_widgets/renameUserPage
screens/resources/resources
screens/resources/resourcesModel
screens/resources/local_widgets/resourceType
services/firebase/functions/local/retrieverFunctions
services/navigation/router
services/navigation/routerNotifier
services/navigation/routes
screens/createActivity/local_widgets/saveButton
screens/createPost/local_widgets/savePostButton
services/localNotifications/local/scheduleAndCancelFunctions
screens/members/local_widgets/searchFormAndList
screens/settings/settings
screens/navigationShell/local_widgets/shareButton
screens/settings/local_widgets/signOutListTile
screens/splash/splash
services/firebase/storage/storageService
l10n/strings.g
services/firebase/cloudMessaging/local/subscriptionFunctions
screens/calendar/local_widgets/tableCalendarView
screens/calendar/local_widgets/tableCalendarwithBuilders
screens/settings/local_widgets/termsOfService
utils/themeData
screens/settings/local_widgets/themeSwitcherTile
utils/timeAgo
screens/createActivity/local_widgets/title
utils/typedefs
screens/admin/unapprovedPostProvider
screens/admin/local_widgets/unapprovedPostsList
screens/admin/local_widgets/unapprovedPostWithButtons
services/firebase/authentication/local/updateFunctions
services/firebase/storage/local/uploadAndDeleteFunctions
services/drive/local/uploadFunctions
screens/userProfile/local_widgets/userInfoRow
widgets/user/userListTile
models/userModel
screens/userProfile/userProfile
screens/userProfile/local_widgets/userProfileName
screens/userProfile/local_widgets/userProfilePicture
providers/userProvider
services/firebase/storage/utils
utils/validators