{"id":26254349,"url":"https://github.com/strvcom/flutter-template","last_synced_at":"2025-03-13T18:27:49.834Z","repository":{"id":276281874,"uuid":"928794287","full_name":"strvcom/flutter-template","owner":"strvcom","description":null,"archived":false,"fork":false,"pushed_at":"2025-02-07T09:43:40.000Z","size":2015,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-02-07T10:24:42.060Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/strvcom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-07T08:54:03.000Z","updated_at":"2025-02-07T09:43:40.000Z","dependencies_parsed_at":"2025-02-07T10:35:35.856Z","dependency_job_id":null,"html_url":"https://github.com/strvcom/flutter-template","commit_stats":null,"previous_names":["strvcom/flutter-template"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strvcom%2Fflutter-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strvcom%2Fflutter-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strvcom%2Fflutter-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strvcom%2Fflutter-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/strvcom","download_url":"https://codeload.github.com/strvcom/flutter-template/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243457435,"owners_count":20294055,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-13T18:27:48.647Z","updated_at":"2025-03-13T18:27:49.814Z","avatar_url":"https://github.com/strvcom.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flutter Template\n- [Project notes](#project-notes)\n\n- [Our values](#our-values)\n\n- [First steps](#first-steps)\n\n- [Project](#project)\n    - [Project structure](#project-structure)\n    - [Supported platforms](#supported-platforms)\n    - [Project run](#project-run)\n        - [Linux](#linux)\n    - [Flavors](#flavors)\n\n- [Build and Distribution](#build-and-distribution)\n    - [Assembling the App](#assembling-the-app)\n    - [Deploying the app](#deploying-the-app)\n        - [Android](#android)\n            - [Manual](#manual)\n            - [Firebase App Distribution using GitHub Actions](#firebase-app-distribution-using-github-actions)\n            - [Google Play Distribution using GitHub Actions](#google-play-distribution-using-github-actions)\n        - [iOS](#ios)\n        - [Web](#web)\n    - [Versioning](#versioning)\n\n- [Implementation details](#implementation-details)\n    - [Architecture](#architecture)\n    - [Push Notifications](#push-notifications)\n    - [GIT](#git)\n    - [GitHub Actions](#github-actions)\n    - [Theming](#theming)\n    - [Social Logins](#social-logins)\n        - [Apple on Android](#apple-on-android)\n        - [Google on iOS](#google-on-ios)\n\n- [Testing](#testing)\n    - [Widgets Tests](#widget-tests)\n    - [Integration Tests](#integration-tests)\n\n- [Tooling](#tooling)\n    - [FVM](#fvm)\n    - [Application Rebranding](./project_setup/README.md#application-rebranding)\n    - [Icons generation](./project_setup/README.md#app-icon-generation)\n    - [Splash screen generation](./project_setup/README.md#splash-screen-generation)\n    - [Precompiling shaders](#precompiling-shaders)\n\n- [Services](#services)\n    - [Firebase setup](#firebase-setup)\n    - [Firebase hosting setup](#firebase-hosting-setup)\n\n- [Security](#security)\n    - [freeRASP](#freerasp)\n\n- [Authors](#authors)\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- #######           Project Notes            ####### --\u003e\n\u003c!-- ################################################## --\u003e\n# Project notes\n\n- Notes that could be benefitial to know during the development. \n- For example list of test accounts, required credentials, steps required to get testing account, etc.\n\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- #########           Our values            ######## --\u003e\n\u003c!-- ################################################## --\u003e\n# Our values\n\nThese are our four core values:\n- **User-Centric Approach** - Nothing is more important than our users. Keep the end-users in mind throughout the development process. Empathize with users' needs and pain points, and design Flutter applications that provide a great user experience. Regularly seek feedback and iterate based on user input.\n- **Quality Focus** - We should prioritize delivering high-quality code by adhering to best coding practices, following Flutter guidelines, and performing thorough testing when possible.\n- **Accountability** - We support responsibility and accountability among team members. Encourage individuals to take ownership of their tasks and deliverables, meet deadlines, and communicate effectively about progress and challenges.\n- **Innovation** - We encourage creativity and innovation within the Flutter team. Support an environment where team members feel comfortable suggesting new ideas, experimenting with different approaches, and finding new solutions to problems.\n\u003c!-- ################################################## --\u003e\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ########           First steps            ######## --\u003e\n\u003c!-- ################################################## --\u003e\n# First steps\n\n1. - [ ] Create a new repo from this template.\n2. - [ ] Set up the GIT settings according to your team's needs.\n3. - [ ] Clone created repository and open it trough File -\u003e Open Workspace from File... -\u003e `flutter.code-workspace`. Open.../Open folder... won't work ⚠️\n3. - [ ] Remove any unused platforms (Android, ios, web, Windows, Linux (+snap), macOS)\n    - Remove them from the folder structure of the template.\n    - Remove them from the `AppPlatform` class.\n    - When removing the `Web` platform, remove also `firebase.json` and `.firebaserc`, `web_setup.dart`, `flutter_web_plugins` and `universal_html` from the `pubspec.yaml` file.\n    - When removing all Desktop platforms, `window_manager` should be safe to remove from `pubspec.yaml` file.\n    - Fix all the reported issues that the change caused.\n4. - [ ] Update `.github/CODEOWNERS` file.\n5. - [ ] Change the package and application name. This process is described in the [Application Rebranding](#application-rebranding) section.\n6. - [ ] Change the app icon. This process is described in the [Icons generation](./project_setup/README.md#app-icon-generation) section.\n7. - [ ] Change the app splash screen. This process is described in the [Splash screen generation](./project_setup/README.md#splash-screen-generation) section.\n8. - [ ] Set up Firebase or remove it completely. This process is described in the [Firebase setup](#firebase-setup) section.\n9. - [ ] Go through all the ToDo's inside the project, and react to them.\n\u003c!-- ################################################## --\u003e\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########           Project            ########## --\u003e\n\u003c!-- ################################################## --\u003e\n# Project\n\n## Project structure\n- Our ideology is to combine feature and layer based architecture. Here is a short description of our folder structure you should follow.\n```\n‣ lib\n  ‣ app -\u003e Application class + Setup of Application class\n    ‣ configuration -\u003e Config files for different flavors\n    ‣ navigation -\u003e Setup of the App Navigation structure\n    ‣ setup -\u003e Classes to wrap up the Application setup\n    ‣ theme -\u003e Setup of the App theme\n  ‣ assets -\u003e Folder for generated assets code\n  ‣ common -\u003e Should contain code that is shared between features, and is closely bound to the state and UI of the app\n    ‣ animation -\u003e Animations used in features\n    ‣ component -\u003e Shared individual Widgets, like custom_app_bar\n    ‣ composition -\u003e Shared larger Widgets builds from smaller ones, like bottom sheet\n    ‣ data\n      ‣ dbo -\u003e Classes to transfer data over to the database \n      ‣ dto -\u003e Classes to transfer data over the network\n      ‣ enum -\u003e Enum classes used across the App\n      ‣ model -\u003e Model classes used across the App\n    ‣ extensions -\u003e Extension classes/methods over existing data types\n    ‣ provider -\u003e Global Services and manager providers, like Notification Service\n    ‣ usecase -\u003e Methods used to get/post data. Usually from/to network or local database\n    ‣ validator -\u003e Classes for text input validation\n  ‣ core -\u003e Should contain code that usually wraps some kind of outside service\n    ‣ analytics -\u003e Wrapper code for Analytics\n    ‣ database -\u003e Wrapper code for Local Storage layer\n    ‣ network -\u003e Wrapper code for the Network layer\n    ‣ riverpod -\u003e Riverpod related classes for easier state handling\n  ‣ features -\u003e Contains separate features\n```\n\u003c!-- ################################################## --\u003e\n\n## Supported platforms\n- Mobile (Android, iOS)\n- Web\n- Desktop (MacOS, Linux, Windows)\n\u003c!-- ################################################## --\u003e\n\n## Project run\n1. Run `flutter pub get`.\n2. Run `make install` to setup all project dependencies.\n3. Run `make gen` to generate files.\n4. Open the project in your favorite IDE and code 🎉.\n\nWhen you don't see generated files inside the project, first try to run `make gen`.\n\nYou can run following command in your terminal to constantly watch for any code-generation changes, and rebuilding the `.g.dart` files automatically.\n```\nflutter pub run build_runner watch --delete-conflicting-outputs\n```\n\nas an alternative you can just use:\n```\nmake build_runner\n```\n\n### Linux\nI personally had small issues getting the app run on Linux. I was missing `libstdc++-12-dev` installed.\nAnother problem was the App name inside `CMakeLists.txt`. It must not contain spaces.\n\u003c!-- ################################################## --\u003e\n\n## Flavors\nThere are 3 environments (Development, Staging, and Production) with 3 Flutter modes, which makes a total of 9 configurations. \n\nYou can read about flavors setup in the following tutorials:\n- 📱 [Android and iOS](https://docs.flutter.dev/deployment/flavors#launching-your-app-flavors)\n- 🌐 There are various ways how to support web configuration but for now, we don't need any.\n    - Copying files like scripts and `index.html` from different folder to web folder.\n    - Making class, where we can use `dart:html` and access dom at runtime.\n- 🖥️ [MacOS](https://docs.flutter.dev/deployment/macos) - Is not ready, but there is [merged PR](https://github.com/flutter/flutter/pull/119564) to master flutter branch, so hopefully, we will get support for flavors on macOS soon. If you want to test the app on macOS, you have to remove arguments from the `launch.json` configuration.\n- 🖥️ [Windows](https://docs.flutter.dev/deployment/windows) - Flavors are not supported yet.\n- 🖥️ [Linux](https://docs.flutter.dev/deployment/linux) - Flavors are not supported yet.\n\nIn case of using firebase with multiple flavors, you have to:\n- for iOS add custom build run script phase and copy appropriate `GoogleService-Info.plist` file. It's already prepared, you just need to uncomment it and add appropriate plists to destinations according to the script.\n\nFor Google sign in:\n- for iOS, you have to copy value from `REVERSED_CLIENT_ID` from `GoogleService-Info.plist` into `GOOGLE_REVERSED_CLIENT_ID` in build settings.\n\u003c!-- ################################################## --\u003e\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########    Build and Distribution    ########## --\u003e\n\u003c!-- ################################################## --\u003e\n# Build and Distribution\n## Assembling the App\n- As we are using flavors, we have to specify which flavor to build using `--flavor` argument, and also select a correct main file using `-t` argument.\n- One of the arguments you should use is `--obfuscate`. This makes reverse engineering harder. This has to be used also with `--split-debug-info` which should make the app smaller, and also specify the directory where the mapping file to read obfuscated stack trace is stored.\n- Optional step is to include precompiled Shaders. To do that you have to first [Precompile Shaders](#precompiling-shaders) and add `--bundle-sksl-path` argument.\n- In case we would like to build a Debugable version of the app, we have to add `--debug` argument.\n\nHere is an example of assembling an Android app bundle using all the commands:\n```\nflutter build appbundle \\\n    -t lib/main_production.dart --flavor production \\\n    --obfuscate --split-debug-info=build/app/outputs/symbols \\\n    --bundle-sksl-path flutter_01.sksl.json \\\n    --debug\n```\n\u003c!-- ################################################## --\u003e\n\n## Deploying the app\n### Android\n#### Manual\nTo deploy the app manually, you have to:\n1. Make sure you have your keystore configured and set up correctly. Check the [Keystore Readme](./android/extras/keystore/README.md)\n2. In the terminal run `flutter build appbundle -t lib/main_production.dart --flavor production --obfuscate --split-debug-info=build/app/outputs/symbols` for production release.\n3. After creating an app bundle, the mapping file will be included automatically, but the native symbols has to be added manually - it can be found in `build\\app\\intermediates\\merged_native_libs\\productionRelease\\out`.\n   Grab those generated folders, zip them and upload into Google Play console under the new build.\n   \n#### Firebase App Distribution using GitHub Actions\nAndroid app deployment can be done automatically when adding a tag to GitHub. The tag requirement is listed in `.github\\workflows\\android_firebase_app_distribution_develop.yml` or `production`. There is still some small setup needed for it to work.\n\nFirst, you need to create a new Service Account inside the Google Cloud console. Create the service account with a `Firebase App Distribution Admin` role. Then you need to generate new key for it. This key NEEDS to be converted to Base64. You can covert is using following command:\n```\nbase64 -i input.json \u003e output.json.b64\n```\n\nNow you need to set the Base64 string as a secret inside your GitHub. You should name it something like `FIREBASE_DEV_CREDENTIAL_FILE_CONTENT` and check that it has the same name inside the script. Also, do not forget to uncomment `apply plugin: 'com.google.gms.google-services'` at the end of the build.gradle file inside the Android app folder.\n\nNow you can use one of the actions we have. There should be at least two actions to build for the develop and for the production environment. You can launch those two by creating a tag on a commit with the name `*-develop` or `*-production`.\n\nAs an alternative, you can use `*-firebase-all` which will deploy both at the same time.\n\n#### Google Play Distribution using GitHub Actions\nWe also have a GitHub Action script for deploying to Google Play automatically. The tag requirement is listed in `.github\\workflows\\android_play_store_distribution.yml`.\n\nSteps on how to set up this GitHub action properly can be found in a separate [README.md](./.github/workflows/README.md) inside the workflows folder.\n\n#### Obfuscation\nIf an APK file is released (probably due to using Firebase App Distribution) a mapping file for obfuscation won't be included. To avoid obfuscation for crashlytics simply remove `--obfuscate` from the build command. \nThen the APK can be manually uploaded to Firebase and crashes will be readable. Do not remove it when releasing the app bundle via Google Play.\nAnother workaround would be uploading the mapping file you can get using `--split-debug-info`. To upload the file, you can use the following command:\n```\nfirebase crashlytics:symbols:upload --app=APP_ID build/app/outputs/symbols\n```\nAPP_ID can be found in the Firebase console.\n\u003c!-- ################################################## --\u003e\n\n### iOS\nThere is some basic setup needed before you are able to build IPA and continue with manual app distribution. First of all, open `Runner.xcworkspace` in `./ios` folder, and click on Runner. There you need to \"Signing \u0026 Capabilities\" tab. Here you have to check \"Automatically manage signing\" and select correct \"Team\" for both `Release-staging` and `Release-production` targets. For this you have to be added to the Team in App Store Connect and have the Certificates permissions.\n\nTo deploy the app, you have to:\n1. In the terminal (never in XCode) run `flutter build ipa -t lib/main_production.dart --flavor production --obfuscate --split-debug-info=build/app/outputs/symbols` for production release (or use makefile command `generateIosProductionIpa`).\n2. Open generated `./build/ios/ipa` folder and drag builded IPA file to `Transporter` application downloaded from AppStore. Wait for the upload and process to complete, and hit the `Deliver` button.\n3. Go to `./build/ios/archive` open the archive using finder, and go to `XXX` folder. Select all dSYM files, and compress them into single .zip file. Drag this .zip file to Firebase Crashlytics.\n4. After the build is validated, submit it to review by adding an external tester group.\n\u003c!-- ################################################## --\u003e\n\n### Web\nTo deploy the app, you have to:\n1. In the terminal run `make generateWebProduction` to build the web. Make sure you are using `canvaskit`` as a web-rendered. This fixes some rendering issues with fonts, etc. on mobile devices.\n2. In the terminal run `make deployWeb` to upload it to the currently set up firebase Web Hosting. More on the Firebase Hosting setup [here](#firebase-hosting-setup).\n\u003c!-- ################################################## --\u003e\n\n## Versioning\nFor now, the app versioning is done manually in the `pubspec.yaml` file where you have to update the `version` property. It is a good practice to also keep comments with the split build number so it is easier to read. For example:\n```\nversion: 1.2.3+10203000 #1 02 03 000\n```\n\u003c!-- ################################################## --\u003e\n\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########    Implementation Details    ########## --\u003e\n\u003c!-- ################################################## --\u003e\n# Implementation Details\n\n## Architecture\n### Tech stack\nHere are the list of libraries we are using for core functionality of our apps:\n- Riverpod (DI, State Management)\n- AutoRoute (Navigation)\n- Dio (Networking)\n- Firebase (Push notifications, Remote Config, Crashlytics, Analytics)\n- SharedPreferences (Local storage)\n- Freezed (Immutable data classes, sealed classes support)\n- ExtendedImage, FlutterSvg (displaying of local and network images)\n- FreeRasp (Basic security)\n- FlutterGen (Assets and localization handling)\n- Logger (Debuggable output logging)\n- Patrol (App testing)\n\n### Architecture ideology\nNote: We will describe our architecture ideology on a sample feature that would be called `user_detail`. Screen, that displays information about any user of the app.\n\nThe basic idea behind our architecture is that there should be one feature folder per application screen. In an ideal world, each feature should contain UI split into two files. The first file would be called for example `user_detail_page.dart`. This should be a wrapper around `user_detail_page_content.dart`, and should just wrap the content inside Scaffold. The rest should be implemented inside `content` file. The main idea behind this is the screen UI reusability. In some places, we may need to just use the whole screen content, without its AppBar for example. In some other places, on the other hand, we may need to open it as a standalone feature. \n\nWe covered the UI part, now we need to focus more on the app state and business handling logic. For this, we are using the Riverpod library. Each feature should contain a file ending with `_state.dart`. For example `user_detail_state.dart`. This file should then contain two classes. The first class is a `Freezed` class, which defines the state of the screen. It should hold all the data and state for the feature. As for the naming, the class name should end with the word `State`. For example `UserDetailState`.\nThe second class is `StateNotifier` class, annotated with `@riverpod` annotation. Rather than splitting the logic completely into small chunks, we believe that it is a good practice to usually have just one `StateNotifier`, providing the `State` for the feature. Naming should follow the same rules as the State class. For example: `UserDetailStateNotifier`. This class must override the `build` method. The State is built inside this method. This is a good place to for example call any necessary API calls, to get data, make some init logic for the feature, etc.. This class can also contain additional methods, to manipulate the State. For example method `updateUser` will update the state with `isUpdatingUser` to `true`, then update the user on the BE side and update the state again with progress set to `false``, and providing new user data. \nEven through we have just a single huge StateHandler, it is possible to observe just specific fields that are needed for building the UI. This way we can optimize the redrawing of the app when the state changes.\n\nThe last part is the solution, on how to communicate one-time events from `StateNotifier` back to the UI. For this, we are using a custom implementation of `EventNotifier` which extends `StateNotifier`. This part is implemented inside `*_event.dart` file. For example: `user_detail_event.dart`. Inside we can find the `Freezed` class defining the events (for example `error` event, `userUpdated` event). There is also a definition of an autodispose StateNotifierProvider, named by the feature. For example: `userDetailEventNotifierProvider`. We should then listen to all these defined events using `ref.listen()` inside our `*_page_content.dart` widget build method. \n\u003c!-- ################################################## --\u003e\n\n## Push Notifications\nTo correctly display push notifications on both Android and iOS, we need to first receive the correct FCM payload. The sample payload can be seen in the image below. The main idea is that the payload should not contain any `notification` field, so we can use the `data` field, and handle displaying notifications on Android manually.\n\nOn the iOS side, on the other hand, the notification will be always displayed by the system. For this, we need to send the `apns` field. The payload handling logic is also described in the image below.\n\n![Push Notifications Payload](docs/push_notifications_payload.jpg)\n\nAs for the handling of notifications of different types, we introduced `NotificationPayloadModel`, and `NotificationType`. These both define all the notifications types expected from BE, which the app will be able to handle. All the rest of the logic is handled inside `FirebaseMessagingService` and `NotificationsService` files.\n\n![Displaying Push Notifications](docs/displaying_push_notifications.jpg)\n\n![Opening Push Notifications](docs/opening_push_notifications.jpg)\n\u003c!-- ################################################## --\u003e\n\n## GIT\nWe have three main branches. `develop`, `staging`, and `master`. The most important and main branch for us would be `develop`. All pull requests are getting merged there. Once the new version is ready to go out, we merge `develop` into the `staging` branch. Once the app is ready to go to production, we merge `staging` into the `master` branch.\n\nWe also have a strict naming convention for branches, commit names, and PR names. Jira ticket is used only when there is any. We are using underscores, except in the Jira ticket name so the Jira automation works well.\nFor Branches: `{GithubUsername}/{chore/feat/fix/refactor}/{JiraTicketNumber}/{SomeBranchDetails}`\nExample: `helu/feat/MN-1726/sign_up`\n\nFor Commit and PR names: `{chore/feat/fix/refactor}: {Description}`\nExample: `feat: Sign up logic implementation`\n\nWhen making staging or production releases, you should also always create an appropriate tag on the commit merged to the `master` or `staging` branch. The tag always starts with the letter `v` followed by the version, and optionally by `-staging` flag.\n```\nExample tag on the master branch: v1.2.3\nExample tag on the staging branch: v1.2.3-staging\n```\n\u003c!-- ################################################## --\u003e\n\n## GitHub Actions\nWe are using GitHub actions mainly for checking the code style, and for deploying the app.\nAll GitHub action scripts can be found in the `.github/workflows/` folder.\n\nTo make sure we use consistent formatting and that the app is buildable, we run the following commands on each pull request:\n- `flutter analyze`\n- `flutter build apk`\nThis way we are ensuring that at least the Android version is buildable. We are also building only debug version of the app as the build is faster.\n\u003c!-- ################################################## --\u003e\n\n## Theming\nTheming is done inside `lib/core/themes/app_theme.dart`. Currently, we suggest using Material 3. The main setup is done in file `app_theme.dart`.\n\nThe main idea right now is to overwrite the whole `colorScheme` with an \"undefined\" pinkish color and to not use the default theme colorScheme anywhere in the app. Every widget like AppBar, EleveatedButton, TextField, etc. should have a custom implementation starting with the word `Custom` so it is easily recognizable. This Widget then should wrap the appropriate widget, and should utilize colors from `context.colorScheme`, which has an extension method, as is returning our own implementation of `CustomColorScheme`. All colors should be declared there.\n\nThe most tricky part of theming is to make sure that the app supports Edge-to-Edge, and that it has correct navigation and StatusBar colors set. To make this possible, we had to implement our own `CustomSystemBarsTheme` class. To use it properly, make sure you are calling `setupSystemBarsTheme` during the App startup. In case of the need of overriding the Brightness for a specific screen, there are two approaches. First, the simple one is to just use `CustomAppBar`, and set brightness to it. Second, wrap the whole Scaffold inside `CustomSystemBarsThemeWidget` and set Brightness to it.\n\u003c!-- ################################################## --\u003e\n\n## Social Logins\nMost social sign in methods work with current setup with minimal effort. We are using mix of Firebase Auth and specific libraries (google_sign_in and sign_in_with_apple) for social logins.\n\n### Apple on Android\nThis is a special use case, where we are not using `sign_in_with_apple` library, but rather plain `firebase_auth` as following: `FirebaseAuth.instance.signInWithProvider(AppleAuthProvider())`.\nThe `signInWithProvider` method could be used for other social logins too, but it takes user to a web view instead of nice native dialogs which would make the user experience worse.\nTo be able to use the firebase provider for Apple login, we need to do some configuration steps:\n\n- Register an App ID - this has to be done anyway if you want to use Apple login in your app. Developer -\u003e Certificates, Identifiers \u0026 Profiles -\u003e Identifiers -\u003e Sign In with Apple\n\n- Create a Service ID - this is the service that would provide sign in with apple. `Developer -\u003e Certificates, Identifiers \u0026 Profiles -\u003e Identifiers -\u003e Create new -\u003e Services IDs`\n    (note: to get into services there is a filter on Identifiers screen on right top where you can switch from identifiers to services.)\n    - Description will be visible to our users - e.g. WearTechClub\n    - Identifier - can be app/bundle ID `com.wearthech.club.develop` or simply `weartechclub-develop`\n    - Enable Sign in with Apple for the service \n        - Domains is url of your page e.g. `weartechclub.com`\n        - Return URL is crucial part - this will be taken from Firebase: Authentication -\u003e Sign-in method -\u003e Apple -\u003e callback URL\n\n- Create a key: `Developer -\u003e Certificates, Identifiers \u0026 Profiles -\u003e Keys -\u003e Create new`\n    (be aware once created you must download the key, it cannot be done later - this is one time action)\n    - Name - name like `Sign in with Apple key develop`, `Android sign in develop` etc.\n    - Enable Sign in with Apple and click Configure\n    - Primary App ID - select your App - in this case develop\n    - Save -\u003e Continue -\u003e Register -\u003e download the key\n\n- Firebase setup that will be done under `Authentication -\u003e Sign-in method -\u003e Apple`\n    - Services ID - this is the Identifier of a Service ID created in Apple Developer - `weartechclub-develop`\n    - Apple team Id from Developer (e.g. `965Y62DKGTU`)\n    - Key Id - generated when the key was created in previous step  (e.g. `798BRVKFKO`)\n    - Private key - when you created the key you downloaded the Private key as .p8 file\n    - Save it and check the `callback URL` - if it changed from what you have in your `Service ID` as `Return URL`, update it in Apple Developer\n\u003c!-- ################################################## --\u003e\n\n### Google on iOS\n- Make sure to add custom URL schemes to your Xcode project:\n    - Open your project configuration: click the project name in the left tree view. Select your app from the `TARGETS` section, then select the `Info` tab, and expand the `URL Types` section.\n    - Click the `+` button, and add a URL scheme for your reversed client ID.(If there are multiple development environments in the project, you can separate the values with commas in the URL Schemes field.)\n    - To find the reversed client ID, open the `GoogleService-Info.plist` configuration file, and look for the `REVERSED_CLIENT_ID` key. Copy the value of that key, and paste it into the URL Schemes box on the configuration page. Leave the other fields untouched.\n    - When completed, your configuration should look similar to the following (but with your application-specific values):\n    \n    ![Displaying Push Notifications](docs/google_on_ios_url_schemes.jpg)\n    \n    - The app will crash, and you will see the error message `[CustomException] Received error PlatformException(google_sign_in, Your app is missing support for the following URL schemes: com.googleusercontent.apps......` in the debug console if the custom URL schemes setup is incorrect after tapping the Google Auth button.\n\u003c!-- ################################################## --\u003e\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########           Testing            ########## --\u003e\n\u003c!-- ################################################## --\u003e\n# Testing\nFirst, you need to setup your environment. You will need to install patrol CLI using this command:\n```\nfvm dart pub global activate patrol_cli\n```\n\nor simply just by running:\n```\nmake install\n```\n\n## Widget tests\nAll widgets test should be put into `test/` folder.\n\nYou can run widget tests using:\n```\nflutter test\n```\n\nor simply just by running:\n```\nmake test\n```\n\n## Integration tests\nAll widgets test should be put into `integration_test/tests/` folder.\n\nYou can run integration tests using:\n```\npatrol test --flavor develop\n```\n\nor simply just by running:\n```\nmake integration_test\n```\n\u003c!-- ################################################## --\u003e\n\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########           Tooling            ########## --\u003e\n\u003c!-- ################################################## --\u003e\n# Tooling\n\n## FVM\nWe are using FVM on our projects to manage correct flutter version and make it more easy to switch between projects.\n\nTo install the FVM on your machine, please run:\n```\nmake install\n```\n\n\u003c!-- ################################################## --\u003e\n\n## Precompiling shaders\nRun the app with `--cache-sksl` turned on to capture shaders in **SkSL**:\n```\nflutter run --profile --cache-sksl --purge-persistent-cache\n```\n\nPress M (Shift + m) at the command line of flutter run to write the captured **SkSL** shaders into a file named something like `flutter_01.sksl.json`. For best results, capture **SkSL** shaders on actual Android and iOS devices separately.\n\u003c!-- ################################################## --\u003e\n\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########           Services            ######### --\u003e\n\u003c!-- ################################################## --\u003e\n# Services\n## Firebase setup\n### Installing dependencies\nFirst, there are some requirements. You have to have [Firebase CLI](https://firebase.google.com/docs/cli#setup_update_cli) installed. Second, you need to have flutterfire CLI.\n\nYou can install it using:\n```\nfvm dart pub global activate flutterfire_cli\n```\n\nor just by running:\n```\nmake install\n```\n\n### Configuring the app\nYou can now configure your project using:\n```\nflutterfire configure\n```\n\n#### Manual setup\n1. Go to Firebase Console and create the required Apps for the required platforms. Please consider following the naming of the apps. First, put their App name. Second, if there is a debug variant for the app, add `- Debug`. At last, add the platform to brackets. For example `(Android)`. Here is an example of how it could look like:\n```\nAppName (Android)\nAppName - Debug (Android)\nAppName (iOS)\nAppName (Web)\n```\n2. Now you have to download the `google-services.json` file for Android and place them in a specific folder. In case you support multiple flavors (like develop, staging or production), put them in appropriate folders in `android/app/src/{develop,staging,production}/`.\n3. Pretty much the same applies to the iOS too. You have to download `GoogleServices-Info.plist` files, and put them into `ios/Runner/config/{develop,staging,production}/`.\n\n## Firebase hosting setup\n1. Go to Firebase Console, under the `Build -\u003e Hosting` and enable Firebase Hosting for the app.\n2. Check and configure `deployWeb` task inside `makefile`.\n3. To build the Web app first run `make generateWebProduction`. You can then deploy the app by running `make deployWeb`.\n\n\u003c!-- ################################################## --\u003e\n\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########           Security            ######### --\u003e\n\u003c!-- ################################################## --\u003e\n# Security\n## FreeRASP\nIt is recommended to setup FreeRASP on the project. More info about the library [here](https://pub.dev/packages/freerasp).\n\nTalsec recommends adding the following statements to the Privacy Policy page dedicated to your app. Also, use the text below while filling in the Google Play Safety Section or similar for Apple App Store publishing.\n\n```\nFor the purpose of Fraud prevention, user safety, and compliance the dedicated App safety SDK needs to send the following anonymous diagnostic data off the device for detection of security issues. Thus the application collects the following data:\n- Category: App info and performance\n    - Data Type: Diagnostics\n    - Information about the integrity of the app and the operating system. For example, rooting, running in an emulator, hooking framework usage, etc...\n- Category: Device or other identifiers\n    - Data Type: Device or other identifiers\n    - Information that relates to an individual device. For example, a device model and anonymous identifier to control that app instance executed on the original device that it was initially installed on. It is needed to combat threats like bots and API abuse.\n```\n\u003c!-- ################################################## --\u003e\n\n\n\u003c!-- ################################################## --\u003e\n\u003c!-- ##########           Authors            ########## --\u003e\n\u003c!-- ################################################## --\u003e\n# Authors\n- [Lukáš Hermann](mailto:lukas.hermann@strv.com)\n- [Robert Oravec](mailto:robert.oravec@strv.com)\n- [Michal Urbánek](mailto:michal.urbanek@strv.com)\n\u003c!-- ################################################## --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrvcom%2Fflutter-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstrvcom%2Fflutter-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrvcom%2Fflutter-template/lists"}