diff --git a/.fvmrc b/.fvmrc new file mode 100644 index 0000000..c6c5344 --- /dev/null +++ b/.fvmrc @@ -0,0 +1,3 @@ +{ + "flutter": "3.41.3" +} \ No newline at end of file diff --git a/.github/workflows/sonar-qube-scann.yml b/.github/workflows/sonar-qube-scann.yml index 6acffaa..0d0468d 100644 --- a/.github/workflows/sonar-qube-scann.yml +++ b/.github/workflows/sonar-qube-scann.yml @@ -1,64 +1,67 @@ -# name: sonarqube +name: sonarqube -# # ──────────────────────────────────────────────────────────────── -# # CI TRIGGERS -# # · push on main → historical baseline -# # · pull_request PRs → quality gate before merge -# # ──────────────────────────────────────────────────────────────── -# on: -# push: -# branches: [main] -# pull_request: -# types: [opened, synchronize, reopened] +# ──────────────────────────────────────────────────────────────── +# CI TRIGGERS +# · push on main → historical baseline +# · pull_request PRs → quality gate before merge +# ──────────────────────────────────────────────────────────────── +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize, reopened] -# jobs: -# sonarQubeTrigger: -# name: Sonarqube Trigger -# runs-on: ubuntu-latest +jobs: + sonarQubeTrigger: + name: Sonarqube Trigger + runs-on: ubuntu-latest -# steps: -# # 1 — Checkout the repo -# - name: Checkout code -# uses: actions/checkout@v3 + steps: + # 1 — Checkout the repo + - name: Checkout code + uses: actions/checkout@v4 -# # 2 — SSH agent for any Git-based pub dependencies -# - name: Start ssh-agent -# uses: webfactory/ssh-agent@v0.9.0 -# with: -# ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + # 2 — SSH agent for any Git-based pub dependencies + - name: Start ssh-agent + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} -# # 3 — Install Dart SDK -# - uses: dart-lang/setup-dart@v1 + # 3 — Read the pinned Flutter version from .fvmrc + - name: Read Flutter version + id: fvm + run: echo "version=$(jq -r '.flutter' .fvmrc)" >> "$GITHUB_OUTPUT" -# # 4 — Install Flutter SDK -# - name: Set up Flutter -# uses: subosito/flutter-action@v2 -# with: -# channel: stable -# flutter-version: 3.24.3 + # 4 — Install Flutter SDK at the pinned version + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + channel: stable + flutter-version: ${{ steps.fvm.outputs.version }} -# # 5 — Install all pub packages (app + each module) -# - name: Get pub packages -# run: | -# set -e -# for dir in app modules/*; do -# if [ -f "$dir/pubspec.yaml" ]; then -# echo "▶ flutter pub get --directory $dir" -# flutter pub get --directory "$dir" -# fi -# done + # 5 — Install Melos + - name: Install Melos + run: dart pub global activate melos -# # 6 — Static analysis (kept exactly as before) -# - name: Analyze App -# run: flutter analyze + # 6 — Resolve workspace dependencies + - name: Bootstrap workspace + run: melos bootstrap -# # 7 — Install SonarScanner CLI (needed by full_coverage.py) -# - name: Setup Sonarqube Scanner -# uses: warchant/setup-sonar-scanner@v8 + # 7 — Static analysis + - name: Analyze + run: melos run analyze -# # 8 — Run tests, build combined lcov.info and upload to SonarQube -# - name: Generate coverage & run SonarQube -# run: python3 coverage/full_coverage.py --ci -# env: -# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} -# SONAR_URL: ${{ secrets.SONAR_URL }} + # 8 — Run tests (each package) + - name: Run tests + run: melos exec --dir-exists=test -- flutter test + + # 9 — Install SonarScanner CLI (needed by full_coverage.py) + - name: Setup Sonarqube Scanner + uses: warchant/setup-sonar-scanner@v8 + + # 10 — Generate coverage & run SonarQube + - name: Generate coverage & run SonarQube + run: python3 coverage/full_coverage.py --ci + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_URL: ${{ secrets.SONAR_URL }} diff --git a/.gitignore b/.gitignore index e160594..ea51e0b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,11 @@ .classpath .project .settings/ -.vscode/ +.vscode/* +!.vscode/settings.json + +# FVM (Flutter Version Management) +.fvm/ # Flutter repo-specific /bin/cache/ @@ -110,7 +114,7 @@ unlinked_spec.ds # Coverage coverage/ -+!coverage/full_coverage.py +!coverage/full_coverage.py # Symbols app.*.symbols @@ -129,4 +133,4 @@ app.*.symbols /modules/data/.flutter-plugins-dependencies /modules/domain/.flutter-plugins /modules/domain/.flutter-plugins-dependencies -/.idea/ +/.idea/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f9953fe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "dart.flutterSdkPath": ".fvm/flutter_sdk", + "search.exclude": { + "**/.fvm": true + }, + "files.watcherExclude": { + "**/.fvm": true + } +} diff --git a/README.md b/README.md index 93f6c8a..b59e99c 100644 --- a/README.md +++ b/README.md @@ -28,14 +28,45 @@ This template comes with: ![template](app/template.png) 2. Clone your new repo. -3. Install [Melos](https://melos.invertase.dev/getting-started) globally executing: `dart pub global activate melos`. -4. test: `melos -v` * note: if your terminal don't recognize melos command, you can add the following line to your .zshrc or .bashrc file:* +3. Install [FVM](https://fvm.app) (Flutter Version Management): +```text + dart pub global activate fvm +``` +4. Install the Flutter SDK version pinned in `.fvmrc`: +```text + fvm install +``` + This downloads the exact Flutter version the repo is pinned to and links it at `.fvm/flutter_sdk`. All contributors and CI use the same version. +5. Run Flutter commands through FVM: +```text + fvm flutter +``` + Optionally add a shell alias (`alias flutter='fvm flutter'`) so you can keep typing `flutter ...`. +6. Install [Melos](https://melos.invertase.dev/getting-started) 7.x globally: +```text + dart pub global activate melos +``` +7. Verify melos is on the path: `melos --version`. If your shell does not find the command, add `pub-cache` to `PATH` (e.g. in `~/.zshrc` or `~/.bashrc`): ```text export PATH="$PATH":"$HOME/.pub-cache/bin" -``` -5. Run `melos doctor`. -6. Run `melos pub:get`. -7. Setup Android: +``` +8. Bootstrap the workspace (downloads packages for every workspace member): +```text + melos bootstrap +``` +9. Run `melos doctor` to verify the setup. + +> Melos 7 uses [Dart pub workspaces](https://dart.dev/tools/pub/workspaces). The workspace is declared in the root `pubspec.yaml`, each package sets `resolution: workspace`, and there is a single shared `pubspec.lock` at the repo root. + +### Upgrading the pinned Flutter version + +When the team agrees to move to a new Flutter version, run `fvm use ` at the repo root and commit the updated `.fvmrc`. CI reads the pinned version from `.fvmrc`, so the change propagates automatically. + +### IDE setup + +- **VS Code**: settings are already wired in `.vscode/settings.json` — the Dart extension picks up `.fvm/flutter_sdk` automatically. +- **Android Studio / IntelliJ**: open `Preferences → Languages & Frameworks → Flutter` and set the SDK path to `/.fvm/flutter_sdk`. +10. Setup Android: - Add to the build.properties file (and update when needed): ```text flutter.versionName=1.0.0 @@ -46,7 +77,7 @@ This template comes with: flutter.targetSdkVersion=33 ``` -8. Android SignIn +11. Android SignIn - Create your release Key Store: ```text @@ -62,7 +93,7 @@ This template comes with: storeFile= ``` -9. Add your env vars, create a config file for each env: +12. Add your env vars, create a config file for each env: ![me](env_config_files.png) - add the env config, i.e: diff --git a/app/analysis_options.yaml b/app/analysis_options.yaml index 605d338..cd6fba3 100644 --- a/app/analysis_options.yaml +++ b/app/analysis_options.yaml @@ -1,98 +1,11 @@ # This file configures the analyzer, which statically analyzes Dart code to # check for errors, warnings, and lints. # -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. +# Lint rules come from `package:flutter_lints/flutter.yaml`. To customize, add +# entries under `linter.rules` below. include: package:flutter_lints/flutter.yaml linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at - # https://dart-lang.github.io/linter/lints/index.html. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. rules: # avoid_print: false # Uncomment to disable the `avoid_print` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule -analyzer: - plugins: - - dart_code_metrics -dart_code_metrics: - anti-patterns: - - long-parameter-list - metrics: - cyclomatic-complexity: 20 - maximum-nesting-level: 5 - number-of-parameters: 4 - source-lines-of-code: 15 - metrics-exclude: - - test/** - rules: - - avoid-nested-conditional-expressions: - acceptable-level: 2 - - prefer-correct-identifier-length: - max-identifier-length: 30 - min-identifier-length: 2 - - no-equal-arguments: - ignored-parameters: - - height - - width - - backspaceColor - - skinToneIndicatorColor - - enabled - - fontFamily - - color - - focusedBorder - - enabledBorder - - subtitle2 - - subtitle1 - - overline - - headline4 - - bodyText1 - - bodyText2 - - button - - caption - - headline1 - - headline2 - - headline3 - - headline5 - - headline6 - - verticalPadding - - horizontalPadding - - topRightRadius - - topLeftRadius - - bottomRightRadius - - bottomLeftRadius - - topLeft - - bottomLeft - - contentBorderColor - - no-boolean-literal-compare - - no-empty-block - - no-equal-then-else - - avoid-missing-enum-constant-in-map - - avoid-non-null-assertion - - avoid-unnecessary-type-assertions - - avoid-unnecessary-type-casts - - double-literal-format - - no-equal-then-else - - no-magic-number - - no-object-declaration - - prefer-async-await - - prefer-first - - prefer-immediate-return - - prefer-last - - prefer-match-file-name - - prefer-trailing-comma - - avoid-border-all - - avoid-wrapping-in-padding - - prefer-const-border-radius diff --git a/app/lib/main/init.dart b/app/lib/main/init.dart index 7be81c9..f8b29f1 100644 --- a/app/lib/main/init.dart +++ b/app/lib/main/init.dart @@ -8,7 +8,6 @@ import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; - void init() async { WidgetsFlutterBinding.ensureInitialized(); usePathUrlStrategy(); diff --git a/app/lib/presentation/resources/custom_network_image.dart b/app/lib/presentation/resources/custom_network_image.dart index 503640a..9b9afca 100644 --- a/app/lib/presentation/resources/custom_network_image.dart +++ b/app/lib/presentation/resources/custom_network_image.dart @@ -56,7 +56,9 @@ class CustomNetworkImage extends StatelessWidget { imageUrl ?? "", width: width, height: height, - colorFilter: color != null ? ColorFilter.mode(svgIconColor!, BlendMode.srcIn) : null, + colorFilter: color != null + ? ColorFilter.mode(svgIconColor!, BlendMode.srcIn) + : null, ), ) : Container( diff --git a/app/lib/presentation/resources/images.dart b/app/lib/presentation/resources/images.dart index f963dfa..1ca7915 100644 --- a/app/lib/presentation/resources/images.dart +++ b/app/lib/presentation/resources/images.dart @@ -106,7 +106,8 @@ class _SvgImage { width: width, height: height, fit: fit, - colorFilter: color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null, + colorFilter: + color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null, alignment: alignment, semanticsLabel: semanticLabel, package: package, diff --git a/app/lib/presentation/resources/locale/generated/intl/messages_en.dart b/app/lib/presentation/resources/locale/generated/intl/messages_en.dart index f7ead05..e307e61 100644 --- a/app/lib/presentation/resources/locale/generated/intl/messages_en.dart +++ b/app/lib/presentation/resources/locale/generated/intl/messages_en.dart @@ -25,92 +25,95 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { - "appName": MessageLookupByLibrary.simpleMessage("Flutter Target"), - "cookiesAcceptCTA": MessageLookupByLibrary.simpleMessage("Accept"), - "cookiesBody": MessageLookupByLibrary.simpleMessage( - "We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you’ve provided to them or that they’ve collected from your use of their services.", - ), - "cookiesTitle": MessageLookupByLibrary.simpleMessage( - "This website uses cookies", - ), - "ctaLogin": MessageLookupByLibrary.simpleMessage("Login"), - "ctaSignUp": MessageLookupByLibrary.simpleMessage("Sign Up"), - "debugModeCancel": MessageLookupByLibrary.simpleMessage("Cancel"), - "debugModeConfirm": MessageLookupByLibrary.simpleMessage("Confirm"), - "debugModeLabel": MessageLookupByLibrary.simpleMessage("DEV"), - "debugModeResetApp": MessageLookupByLibrary.simpleMessage("RESET"), - "debugModeResetAppMessage": MessageLookupByLibrary.simpleMessage( - "Are you sure you want to reset the app?", - ), - "debugModeResetAppTitle": MessageLookupByLibrary.simpleMessage("Reset App"), - "errorEmailInvalid": MessageLookupByLibrary.simpleMessage( - "Please enter a valid email address.", - ), - "errorEmailRequired": MessageLookupByLibrary.simpleMessage( - "Email is required.", - ), - "errorPasswordRequired": MessageLookupByLibrary.simpleMessage( - "Password is required.", - ), - "errorPasswordWeak": MessageLookupByLibrary.simpleMessage( - "Password is too weak.", - ), - "errorPasswordsDoNotMatch": MessageLookupByLibrary.simpleMessage( - "Passwords do not match.", - ), - "hintTermsAndConditions": MessageLookupByLibrary.simpleMessage( - "This should open the terms and conditions URL.", - ), - "labelAgreeToTerms": MessageLookupByLibrary.simpleMessage( - "I agree to the Terms and Conditions", - ), - "labelConfirmPassword": MessageLookupByLibrary.simpleMessage( - "Confirm Password", - ), - "labelEmail": MessageLookupByLibrary.simpleMessage("Email"), - "labelPassword": MessageLookupByLibrary.simpleMessage("Password"), - "loginErrorInvalidCredentials": MessageLookupByLibrary.simpleMessage( - "Invalid email or password.", - ), - "noConnection": MessageLookupByLibrary.simpleMessage("No connection"), - "onboardingBack": MessageLookupByLibrary.simpleMessage("Back"), - "onboardingNext": MessageLookupByLibrary.simpleMessage("Next"), - "onboardingPage1Description": MessageLookupByLibrary.simpleMessage( - "This is the first page of the onboarding flow", - ), - "onboardingPage1Title": MessageLookupByLibrary.simpleMessage("Welcome"), - "onboardingPage2Description": MessageLookupByLibrary.simpleMessage( - "This is the second page of the onboarding flow", - ), - "onboardingPage2Title": MessageLookupByLibrary.simpleMessage("Discover"), - "onboardingPage3Description": MessageLookupByLibrary.simpleMessage( - "This is the third page of the onboarding flow", - ), - "onboardingPage3Title": MessageLookupByLibrary.simpleMessage("Connect"), - "onboardingPage4Description": MessageLookupByLibrary.simpleMessage( - "This is the fourth page of the onboarding flow", - ), - "onboardingPage4Title": MessageLookupByLibrary.simpleMessage("Get Started"), - "onboardingPageIndicator": m0, - "onboardingStart": MessageLookupByLibrary.simpleMessage("Start"), - "passwordInstructions": MessageLookupByLibrary.simpleMessage( - "Min 8 characters long: 1 uppercase letter, 1 lowercase letter, 1 number, and 1 special character.", - ), - "pleaseTryAgainLaterWeArenworkingToFixTheIssue": - MessageLookupByLibrary.simpleMessage( + "appName": MessageLookupByLibrary.simpleMessage("Flutter Target"), + "cookiesAcceptCTA": MessageLookupByLibrary.simpleMessage("Accept"), + "cookiesBody": MessageLookupByLibrary.simpleMessage( + "We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you’ve provided to them or that they’ve collected from your use of their services.", + ), + "cookiesTitle": MessageLookupByLibrary.simpleMessage( + "This website uses cookies", + ), + "ctaLogin": MessageLookupByLibrary.simpleMessage("Login"), + "ctaSignUp": MessageLookupByLibrary.simpleMessage("Sign Up"), + "debugModeCancel": MessageLookupByLibrary.simpleMessage("Cancel"), + "debugModeConfirm": MessageLookupByLibrary.simpleMessage("Confirm"), + "debugModeLabel": MessageLookupByLibrary.simpleMessage("DEV"), + "debugModeResetApp": MessageLookupByLibrary.simpleMessage("RESET"), + "debugModeResetAppMessage": MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset the app?", + ), + "debugModeResetAppTitle": + MessageLookupByLibrary.simpleMessage("Reset App"), + "errorEmailInvalid": MessageLookupByLibrary.simpleMessage( + "Please enter a valid email address.", + ), + "errorEmailRequired": MessageLookupByLibrary.simpleMessage( + "Email is required.", + ), + "errorPasswordRequired": MessageLookupByLibrary.simpleMessage( + "Password is required.", + ), + "errorPasswordWeak": MessageLookupByLibrary.simpleMessage( + "Password is too weak.", + ), + "errorPasswordsDoNotMatch": MessageLookupByLibrary.simpleMessage( + "Passwords do not match.", + ), + "hintTermsAndConditions": MessageLookupByLibrary.simpleMessage( + "This should open the terms and conditions URL.", + ), + "labelAgreeToTerms": MessageLookupByLibrary.simpleMessage( + "I agree to the Terms and Conditions", + ), + "labelConfirmPassword": MessageLookupByLibrary.simpleMessage( + "Confirm Password", + ), + "labelEmail": MessageLookupByLibrary.simpleMessage("Email"), + "labelPassword": MessageLookupByLibrary.simpleMessage("Password"), + "loginErrorInvalidCredentials": MessageLookupByLibrary.simpleMessage( + "Invalid email or password.", + ), + "noConnection": MessageLookupByLibrary.simpleMessage("No connection"), + "onboardingBack": MessageLookupByLibrary.simpleMessage("Back"), + "onboardingNext": MessageLookupByLibrary.simpleMessage("Next"), + "onboardingPage1Description": MessageLookupByLibrary.simpleMessage( + "This is the first page of the onboarding flow", + ), + "onboardingPage1Title": MessageLookupByLibrary.simpleMessage("Welcome"), + "onboardingPage2Description": MessageLookupByLibrary.simpleMessage( + "This is the second page of the onboarding flow", + ), + "onboardingPage2Title": + MessageLookupByLibrary.simpleMessage("Discover"), + "onboardingPage3Description": MessageLookupByLibrary.simpleMessage( + "This is the third page of the onboarding flow", + ), + "onboardingPage3Title": MessageLookupByLibrary.simpleMessage("Connect"), + "onboardingPage4Description": MessageLookupByLibrary.simpleMessage( + "This is the fourth page of the onboarding flow", + ), + "onboardingPage4Title": + MessageLookupByLibrary.simpleMessage("Get Started"), + "onboardingPageIndicator": m0, + "onboardingStart": MessageLookupByLibrary.simpleMessage("Start"), + "passwordInstructions": MessageLookupByLibrary.simpleMessage( + "Min 8 characters long: 1 uppercase letter, 1 lowercase letter, 1 number, and 1 special character.", + ), + "pleaseTryAgainLaterWeArenworkingToFixTheIssue": + MessageLookupByLibrary.simpleMessage( "Please try again later, we are\nworking to fix the issue.", ), - "retry": MessageLookupByLibrary.simpleMessage("Retry"), - "sorryWeDidntFindAnyProduct": MessageLookupByLibrary.simpleMessage( - "Sorry we didn\'t find any product", - ), - "titleLogin": MessageLookupByLibrary.simpleMessage("Login"), - "titleLoginSubtitle": MessageLookupByLibrary.simpleMessage( - "Use your email and password to login to your account.", - ), - "titleSignUp": MessageLookupByLibrary.simpleMessage("Sign Up"), - "titleSignUpSubtitle": MessageLookupByLibrary.simpleMessage( - "Create an account using your email and password.", - ), - }; + "retry": MessageLookupByLibrary.simpleMessage("Retry"), + "sorryWeDidntFindAnyProduct": MessageLookupByLibrary.simpleMessage( + "Sorry we didn\'t find any product", + ), + "titleLogin": MessageLookupByLibrary.simpleMessage("Login"), + "titleLoginSubtitle": MessageLookupByLibrary.simpleMessage( + "Use your email and password to login to your account.", + ), + "titleSignUp": MessageLookupByLibrary.simpleMessage("Sign Up"), + "titleSignUpSubtitle": MessageLookupByLibrary.simpleMessage( + "Create an account using your email and password.", + ), + }; } diff --git a/app/lib/presentation/resources/locale/generated/intl/messages_es.dart b/app/lib/presentation/resources/locale/generated/intl/messages_es.dart index 6d8e904..88e7cbb 100644 --- a/app/lib/presentation/resources/locale/generated/intl/messages_es.dart +++ b/app/lib/presentation/resources/locale/generated/intl/messages_es.dart @@ -25,94 +25,99 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { - "appName": MessageLookupByLibrary.simpleMessage("Flutter Target"), - "cookiesAcceptCTA": MessageLookupByLibrary.simpleMessage("Aceptar"), - "cookiesBody": MessageLookupByLibrary.simpleMessage( - "Usamos cookies para personalizar el contenido y los anuncios, proporcionar funciones de redes sociales y analizar nuestro tráfico. También compartimos información sobre el uso que haces de nuestro sitio con nuestros socios de redes sociales, publicidad y análisis, quienes pueden combinarla con otra información que les hayas proporcionado o que hayan recopilado a partir del uso que haces de sus servicios.", - ), - "cookiesTitle": MessageLookupByLibrary.simpleMessage( - "Este sitio web utiliza cookies", - ), - "ctaLogin": MessageLookupByLibrary.simpleMessage("Iniciar sesión"), - "ctaSignUp": MessageLookupByLibrary.simpleMessage("Registrarse"), - "debugModeCancel": MessageLookupByLibrary.simpleMessage("Cancelar"), - "debugModeConfirm": MessageLookupByLibrary.simpleMessage("Confirmar"), - "debugModeLabel": MessageLookupByLibrary.simpleMessage("DEV"), - "debugModeResetApp": MessageLookupByLibrary.simpleMessage("RESET"), - "debugModeResetAppMessage": MessageLookupByLibrary.simpleMessage( - "¿Estás seguro de que deseas resetear la aplicación?", - ), - "debugModeResetAppTitle": MessageLookupByLibrary.simpleMessage( - "Resetear App", - ), - "errorEmailInvalid": MessageLookupByLibrary.simpleMessage( - "Por favor ingresa un correo electrónico válido.", - ), - "errorEmailRequired": MessageLookupByLibrary.simpleMessage( - "El correo electrónico es obligatorio.", - ), - "errorPasswordRequired": MessageLookupByLibrary.simpleMessage( - "La contraseña es obligatoria.", - ), - "errorPasswordWeak": MessageLookupByLibrary.simpleMessage( - "La contraseña es demasiado débil.", - ), - "errorPasswordsDoNotMatch": MessageLookupByLibrary.simpleMessage( - "Las contraseñas no coinciden.", - ), - "hintTermsAndConditions": MessageLookupByLibrary.simpleMessage( - "Esto debería abrir la URL de términos y condiciones.", - ), - "labelAgreeToTerms": MessageLookupByLibrary.simpleMessage( - "Acepto los Términos y Condiciones", - ), - "labelConfirmPassword": MessageLookupByLibrary.simpleMessage( - "Confirmar contraseña", - ), - "labelEmail": MessageLookupByLibrary.simpleMessage("Correo electrónico"), - "labelPassword": MessageLookupByLibrary.simpleMessage("Contraseña"), - "loginErrorInvalidCredentials": MessageLookupByLibrary.simpleMessage( - "Correo electrónico o contraseña incorrectos.", - ), - "noConnection": MessageLookupByLibrary.simpleMessage("Sin conexión"), - "onboardingBack": MessageLookupByLibrary.simpleMessage("Atrás"), - "onboardingNext": MessageLookupByLibrary.simpleMessage("Siguiente"), - "onboardingPage1Description": MessageLookupByLibrary.simpleMessage( - "Esta es la primera página del flujo de incorporación", - ), - "onboardingPage1Title": MessageLookupByLibrary.simpleMessage("Bienvenido"), - "onboardingPage2Description": MessageLookupByLibrary.simpleMessage( - "Esta es la segunda página del flujo de incorporación", - ), - "onboardingPage2Title": MessageLookupByLibrary.simpleMessage("Descubrir"), - "onboardingPage3Description": MessageLookupByLibrary.simpleMessage( - "Esta es la tercera página del flujo de incorporación", - ), - "onboardingPage3Title": MessageLookupByLibrary.simpleMessage("Conectar"), - "onboardingPage4Description": MessageLookupByLibrary.simpleMessage( - "Esta es la cuarta página del flujo de incorporación", - ), - "onboardingPage4Title": MessageLookupByLibrary.simpleMessage("Comenzar"), - "onboardingPageIndicator": m0, - "onboardingStart": MessageLookupByLibrary.simpleMessage("Comenzar"), - "passwordInstructions": MessageLookupByLibrary.simpleMessage( - "Mínimo 8 caracteres: 1 mayúscula, 1 minúscula, 1 número y 1 carácter especial.", - ), - "pleaseTryAgainLaterWeArenworkingToFixTheIssue": - MessageLookupByLibrary.simpleMessage( + "appName": MessageLookupByLibrary.simpleMessage("Flutter Target"), + "cookiesAcceptCTA": MessageLookupByLibrary.simpleMessage("Aceptar"), + "cookiesBody": MessageLookupByLibrary.simpleMessage( + "Usamos cookies para personalizar el contenido y los anuncios, proporcionar funciones de redes sociales y analizar nuestro tráfico. También compartimos información sobre el uso que haces de nuestro sitio con nuestros socios de redes sociales, publicidad y análisis, quienes pueden combinarla con otra información que les hayas proporcionado o que hayan recopilado a partir del uso que haces de sus servicios.", + ), + "cookiesTitle": MessageLookupByLibrary.simpleMessage( + "Este sitio web utiliza cookies", + ), + "ctaLogin": MessageLookupByLibrary.simpleMessage("Iniciar sesión"), + "ctaSignUp": MessageLookupByLibrary.simpleMessage("Registrarse"), + "debugModeCancel": MessageLookupByLibrary.simpleMessage("Cancelar"), + "debugModeConfirm": MessageLookupByLibrary.simpleMessage("Confirmar"), + "debugModeLabel": MessageLookupByLibrary.simpleMessage("DEV"), + "debugModeResetApp": MessageLookupByLibrary.simpleMessage("RESET"), + "debugModeResetAppMessage": MessageLookupByLibrary.simpleMessage( + "¿Estás seguro de que deseas resetear la aplicación?", + ), + "debugModeResetAppTitle": MessageLookupByLibrary.simpleMessage( + "Resetear App", + ), + "errorEmailInvalid": MessageLookupByLibrary.simpleMessage( + "Por favor ingresa un correo electrónico válido.", + ), + "errorEmailRequired": MessageLookupByLibrary.simpleMessage( + "El correo electrónico es obligatorio.", + ), + "errorPasswordRequired": MessageLookupByLibrary.simpleMessage( + "La contraseña es obligatoria.", + ), + "errorPasswordWeak": MessageLookupByLibrary.simpleMessage( + "La contraseña es demasiado débil.", + ), + "errorPasswordsDoNotMatch": MessageLookupByLibrary.simpleMessage( + "Las contraseñas no coinciden.", + ), + "hintTermsAndConditions": MessageLookupByLibrary.simpleMessage( + "Esto debería abrir la URL de términos y condiciones.", + ), + "labelAgreeToTerms": MessageLookupByLibrary.simpleMessage( + "Acepto los Términos y Condiciones", + ), + "labelConfirmPassword": MessageLookupByLibrary.simpleMessage( + "Confirmar contraseña", + ), + "labelEmail": + MessageLookupByLibrary.simpleMessage("Correo electrónico"), + "labelPassword": MessageLookupByLibrary.simpleMessage("Contraseña"), + "loginErrorInvalidCredentials": MessageLookupByLibrary.simpleMessage( + "Correo electrónico o contraseña incorrectos.", + ), + "noConnection": MessageLookupByLibrary.simpleMessage("Sin conexión"), + "onboardingBack": MessageLookupByLibrary.simpleMessage("Atrás"), + "onboardingNext": MessageLookupByLibrary.simpleMessage("Siguiente"), + "onboardingPage1Description": MessageLookupByLibrary.simpleMessage( + "Esta es la primera página del flujo de incorporación", + ), + "onboardingPage1Title": + MessageLookupByLibrary.simpleMessage("Bienvenido"), + "onboardingPage2Description": MessageLookupByLibrary.simpleMessage( + "Esta es la segunda página del flujo de incorporación", + ), + "onboardingPage2Title": + MessageLookupByLibrary.simpleMessage("Descubrir"), + "onboardingPage3Description": MessageLookupByLibrary.simpleMessage( + "Esta es la tercera página del flujo de incorporación", + ), + "onboardingPage3Title": + MessageLookupByLibrary.simpleMessage("Conectar"), + "onboardingPage4Description": MessageLookupByLibrary.simpleMessage( + "Esta es la cuarta página del flujo de incorporación", + ), + "onboardingPage4Title": + MessageLookupByLibrary.simpleMessage("Comenzar"), + "onboardingPageIndicator": m0, + "onboardingStart": MessageLookupByLibrary.simpleMessage("Comenzar"), + "passwordInstructions": MessageLookupByLibrary.simpleMessage( + "Mínimo 8 caracteres: 1 mayúscula, 1 minúscula, 1 número y 1 carácter especial.", + ), + "pleaseTryAgainLaterWeArenworkingToFixTheIssue": + MessageLookupByLibrary.simpleMessage( "Por favor intenta nuevamente más tarde,\nestamos trabajando para solucionar el problema.", ), - "retry": MessageLookupByLibrary.simpleMessage("Reintentar"), - "sorryWeDidntFindAnyProduct": MessageLookupByLibrary.simpleMessage( - "Lo sentimos, no encontramos ningún producto", - ), - "titleLogin": MessageLookupByLibrary.simpleMessage("Iniciar sesión"), - "titleLoginSubtitle": MessageLookupByLibrary.simpleMessage( - "Usa tu correo electrónico y contraseña para iniciar sesión en tu cuenta.", - ), - "titleSignUp": MessageLookupByLibrary.simpleMessage("Registrarse"), - "titleSignUpSubtitle": MessageLookupByLibrary.simpleMessage( - "Crea una cuenta usando tu correo electrónico y contraseña.", - ), - }; + "retry": MessageLookupByLibrary.simpleMessage("Reintentar"), + "sorryWeDidntFindAnyProduct": MessageLookupByLibrary.simpleMessage( + "Lo sentimos, no encontramos ningún producto", + ), + "titleLogin": MessageLookupByLibrary.simpleMessage("Iniciar sesión"), + "titleLoginSubtitle": MessageLookupByLibrary.simpleMessage( + "Usa tu correo electrónico y contraseña para iniciar sesión en tu cuenta.", + ), + "titleSignUp": MessageLookupByLibrary.simpleMessage("Registrarse"), + "titleSignUpSubtitle": MessageLookupByLibrary.simpleMessage( + "Crea una cuenta usando tu correo electrónico y contraseña.", + ), + }; } diff --git a/app/lib/presentation/resources/locale/generated/l10n.dart b/app/lib/presentation/resources/locale/generated/l10n.dart index d3696f8..6b038cc 100644 --- a/app/lib/presentation/resources/locale/generated/l10n.dart +++ b/app/lib/presentation/resources/locale/generated/l10n.dart @@ -28,10 +28,9 @@ class S { static const AppLocalizationDelegate delegate = AppLocalizationDelegate(); static Future load(Locale locale) { - final name = - (locale.countryCode?.isEmpty ?? false) - ? locale.languageCode - : locale.toString(); + final name = (locale.countryCode?.isEmpty ?? false) + ? locale.languageCode + : locale.toString(); final localeName = Intl.canonicalizedLocale(name); return initializeMessages(localeName).then((_) { Intl.defaultLocale = localeName; diff --git a/app/lib/presentation/themes/resources/dark_theme_colors.dart b/app/lib/presentation/themes/resources/dark_theme_colors.dart index d4a5746..94d2f0f 100644 --- a/app/lib/presentation/themes/resources/dark_theme_colors.dart +++ b/app/lib/presentation/themes/resources/dark_theme_colors.dart @@ -95,7 +95,8 @@ class DarkThemeColors implements ThemeColors { @override MaterialColor get neutral => const MaterialColor(0xFF1C1B1F, { 0: Color(0xFF000000), // shadow / scrim - 10: Color(0xFFE6E1E5), // onSurface - Main text color in dark (light color) + 10: Color( + 0xFFE6E1E5), // onSurface - Main text color in dark (light color) 20: Color(0xFFF4EFF4), // inverseSurface (light color) 30: Color(0xFFAEAAAE), 40: Color(0xFF939094), @@ -118,7 +119,8 @@ class DarkThemeColors implements ThemeColors { 0: Color(0xFF000000), 10: Color(0xFFF5EEFA), 20: Color(0xFFE7E0EC), - 30: Color(0xFFC9C5D0), // onSurfaceVariant - Secondary text (lighter in dark) + 30: Color( + 0xFFC9C5D0), // onSurfaceVariant - Secondary text (lighter in dark) 40: Color(0xFFAEA9B4), 50: Color(0xFF938F99), // outline - Borders, dividers 60: Color(0xFF79747E), diff --git a/app/lib/presentation/ui/base/tracked_page.dart b/app/lib/presentation/ui/base/tracked_page.dart index e65a000..e677dc4 100644 --- a/app/lib/presentation/ui/base/tracked_page.dart +++ b/app/lib/presentation/ui/base/tracked_page.dart @@ -6,23 +6,26 @@ import 'package:flutter/material.dart'; /// A base class for pages that are tracked for analytics purposes. /// This class can be extended to implement specific tracking logic /// for different pages in the application. +/// +/// ```dart /// class HomePage extends TrackedPage { -/// const HomePage({super.key}); -/// @override -/// String get trackingName => "home_page"; -/// @override -/// Map? get trackingProperties => { -/// 'userType': 'guest', -/// 'origin': 'splash_screen', -/// }; -/// @override -/// Widget buildPage(BuildContext context) { -/// return Scaffold( -/// appBar: AppBar(title: const Text("Home")), -/// body: const Center(child: Text("Welcome")), -/// ); -/// } -///} +/// const HomePage({super.key}); +/// @override +/// String get trackingName => "home_page"; +/// @override +/// Map? get trackingProperties => { +/// 'userType': 'guest', +/// 'origin': 'splash_screen', +/// }; +/// @override +/// Widget buildPage(BuildContext context) { +/// return Scaffold( +/// appBar: AppBar(title: const Text("Home")), +/// body: const Center(child: Text("Welcome")), +/// ); +/// } +/// } +/// ``` abstract class TrackedPage extends StatefulWidget { const TrackedPage({super.key}); diff --git a/app/lib/presentation/ui/custom/debug_banner.dart b/app/lib/presentation/ui/custom/debug_banner.dart index dec65b3..96d26b5 100644 --- a/app/lib/presentation/ui/custom/debug_banner.dart +++ b/app/lib/presentation/ui/custom/debug_banner.dart @@ -92,6 +92,7 @@ class DebugBanner extends StatelessWidget { onPressed: () async { Navigator.of(dialogContext).pop(); await context.read().resetApp(); + if (!context.mounted) return; await context.read().logOut(); }, child: Text(S.of(context).debugModeConfirm), diff --git a/app/lib/presentation/ui/custom/failure_widget.dart b/app/lib/presentation/ui/custom/failure_widget.dart index f853e02..c34efb7 100644 --- a/app/lib/presentation/ui/custom/failure_widget.dart +++ b/app/lib/presentation/ui/custom/failure_widget.dart @@ -8,7 +8,8 @@ class FailureWidget extends StatelessWidget { final Failure? failure; final VoidCallback onRetry; - const FailureWidget({super.key, required this.failure, required this.onRetry}); + const FailureWidget( + {super.key, required this.failure, required this.onRetry}); @override Widget build(BuildContext context) { diff --git a/app/lib/presentation/ui/pages/main/home/home_view.dart b/app/lib/presentation/ui/pages/main/home/home_view.dart index 74f5daf..87fc75c 100644 --- a/app/lib/presentation/ui/pages/main/home/home_view.dart +++ b/app/lib/presentation/ui/pages/main/home/home_view.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; class HomeView extends StatelessWidget { /// Given this is a global cubit, we can access it directly from getIt - /// otherwise use context.read() to read the Cubit under that context + /// otherwise use `context.read()` to read the Cubit under that context AuthCubit get _authCubit => getIt(); const HomeView({super.key}); diff --git a/app/lib/presentation/ui/pages/onboarding/onboarding_page.dart b/app/lib/presentation/ui/pages/onboarding/onboarding_page.dart index cdb131b..7bac335 100644 --- a/app/lib/presentation/ui/pages/onboarding/onboarding_page.dart +++ b/app/lib/presentation/ui/pages/onboarding/onboarding_page.dart @@ -200,8 +200,10 @@ class _OnboardingPageState extends State { Text( description, style: Theme.of(context).textTheme.bodyLarge?.copyWith( - color: - Theme.of(context).colorScheme.onSurface.withOpacity(0.6), + color: Theme.of(context) + .colorScheme + .onSurface + .withValues(alpha: 0.6), ), textAlign: TextAlign.center, ), diff --git a/app/lib/presentation/ui/pages/splash/splash_page.dart b/app/lib/presentation/ui/pages/splash/splash_page.dart index 9b8f1f4..95ba5fd 100644 --- a/app/lib/presentation/ui/pages/splash/splash_page.dart +++ b/app/lib/presentation/ui/pages/splash/splash_page.dart @@ -12,7 +12,7 @@ class SplashPage extends StatefulWidget { class _SplashPageState extends State { /// Given this is a global cubit, we can access it directly from getIt - /// otherwise use context.read() to read the Cubit under that context + /// otherwise use `context.read()` to read the Cubit under that context AuthCubit get _authCubit => getIt(); @override diff --git a/app/lib/presentation/utils/lang_extensions.dart b/app/lib/presentation/utils/lang_extensions.dart index 3391874..595604e 100644 --- a/app/lib/presentation/utils/lang_extensions.dart +++ b/app/lib/presentation/utils/lang_extensions.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:domain/models/app_lang.dart'; import 'package:app/presentation/resources/locale/generated/l10n.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; + extension LangExtensions on AppLang { static const supportedLang = [ Locale('en', ''), // English, no country code diff --git a/app/melos.yaml b/app/melos.yaml deleted file mode 100644 index 0923c00..0000000 --- a/app/melos.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: one_time_chat - -packages: - - app - - modules/* - -scripts: - lint:all: - run: melos run analyze && melos run format - description: Run all static analysis checks. - analyze: - run: | - melos exec -c 1 -- \ - dart analyze . --fatal-infos - description: | - Run `dart analyze` in all packages. - - Note: you can also rely on your IDEs Dart Analysis / Issues window. - pub:get: - exec: flutter pub get - description: Run `flutter pub get` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib - pub:runner: - exec: flutter pub run build_runner build --delete-conflicting-outputs - description: Run ` pub run build_runner` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib - pub:upgrade: - exec: flutter pub upgrade - description: Run `dart pub upgrade` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib - doctor: - exec: flutter doctor - description: Run `dart doctor` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 8f38ac4..9d2b9bd 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -1,6 +1,8 @@ name: app description: A new Flutter project. +resolution: workspace + # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: "none" # Remove this line if you wish to publish to pub.dev @@ -18,7 +20,8 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=3.0.0 <4.0.0" + sdk: ">=3.6.0 <4.0.0" + flutter: ">=3.41.0" dependencies: flutter: @@ -26,19 +29,18 @@ dependencies: flutter_svg: ^2.2.0 shared_preferences: ^2.5.3 intl: ^0.20.2 - intl_utils: ^2.8.7 + intl_utils: ^2.8.14 cupertino_icons: ^1.0.5 - dio: ^5.1.2 + dio: ^5.8.0 async: ^2.11.0 - flutter_bloc: ^8.1.2 - get_it: ^7.6.0 + flutter_bloc: ^9.0.0 + get_it: ^8.0.0 package_info_plus: ^8.3.0 - permission_handler: ^11.4.0 - universal_html: ^2.2.2 - go_router: ^17.0.0 - equatable: ^2.0.5 - firebase_core: ^3.13.0 - url_strategy: ^0.2.0 + permission_handler: ^12.0.0 + universal_html: ^2.2.4 + go_router: ^17.2.3 + equatable: ^2.0.7 + firebase_core: ^3.15.0 flutter_localizations: sdk: flutter domain: @@ -48,9 +50,6 @@ dependencies: data: path: ../modules/data - http: ^1.5.0 - melos: ^3.4.0 - dev: ^1.0.0 flutter_dotenv: ^5.2.1 flutter_web_plugins: sdk: flutter @@ -58,14 +57,13 @@ dependencies: gap: ^3.0.1 dev_dependencies: - bloc_test: ^9.0.2 - build_runner: ^2.4.9 + bloc_test: ^10.0.0 + build_runner: ^2.15.0 flutter_gen: flutter_test: sdk: flutter - mockito: ^5.4.4 - mocktail: ^1.0.3 - flutter_lints: ^3.0.2 + mocktail: ^1.0.4 + flutter_lints: ^5.0.0 flutter_intl: enabled: true # Required. Must be set to true to activate the package. Default: false diff --git a/app/test/widget_test.dart b/app/test/widget_test.dart deleted file mode 100644 index 9ab4255..0000000 --- a/app/test/widget_test.dart +++ /dev/null @@ -1,25 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..620e46e --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/melos.yaml b/melos.yaml deleted file mode 100644 index 10d1409..0000000 --- a/melos.yaml +++ /dev/null @@ -1,45 +0,0 @@ -name: one_time_chat - -packages: - - app - - modules/* - -scripts: - run:web: - description: Run the app in development mode for web. - run: melos exec --scope="app" -- \ - flutter run -t lib/main.dart --dart-define-from-file=env/.dev -d chrome - lint:all: - run: melos run analyze && melos run format - description: Run all static analysis checks. - analyze: - run: | - melos exec -c 1 -- \ - dart analyze . --fatal-infos - description: | - Run `dart analyze` in all packages. - - Note: you can also rely on your IDEs Dart Analysis / Issues window. - pub:get: - exec: flutter pub get - description: Run `flutter pub get` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib - pub:runner: - exec: flutter pub run build_runner build --delete-conflicting-outputs - description: Run ` pub run build_runner` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib - pub:upgrade: - exec: flutter pub upgrade - description: Run `dart pub upgrade` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib - doctor: - exec: flutter doctor - description: Run `dart doctor` in selected or all packages. Includes prompt for packages. - packageFilters: - dirExists: - - lib diff --git a/modules/common/lib/core/failure/failure.dart b/modules/common/lib/core/failure/failure.dart index b246d79..6fd533e 100644 --- a/modules/common/lib/core/failure/failure.dart +++ b/modules/common/lib/core/failure/failure.dart @@ -5,11 +5,11 @@ sealed class Failure implements Exception { } class ConnectionFailure extends Failure { - ConnectionFailure([String? message]) : super(message); + ConnectionFailure([super.message]); } class SocketTimeOutFailure extends Failure { - SocketTimeOutFailure([String? message]) : super(message); + SocketTimeOutFailure([super.message]); } class HttpFailure extends Failure { @@ -19,5 +19,5 @@ class HttpFailure extends Failure { } class UnexpectedFailure extends Failure { - UnexpectedFailure([String? message]) : super(message); + UnexpectedFailure([super.message]); } diff --git a/modules/common/lib/core/mixins/cancelable_cubit_mixin.dart b/modules/common/lib/core/mixins/cancelable_cubit_mixin.dart index 7e518f1..a530b08 100644 --- a/modules/common/lib/core/mixins/cancelable_cubit_mixin.dart +++ b/modules/common/lib/core/mixins/cancelable_cubit_mixin.dart @@ -17,4 +17,4 @@ mixin CancelableCubitMixin on Cubit { } return super.close(); } -} \ No newline at end of file +} diff --git a/modules/common/lib/ui/responsive.dart b/modules/common/lib/ui/responsive.dart index 1690f7c..a614312 100644 --- a/modules/common/lib/ui/responsive.dart +++ b/modules/common/lib/ui/responsive.dart @@ -11,11 +11,11 @@ class ResponsiveBuilder extends StatelessWidget { final AppPlatform _platform = getIt.get(); ResponsiveBuilder({ - Key? key, + super.key, required this.small, required this.big, this.medium, - }) : super(key: key); + }); Orientation _screenOrientation(BuildContext context) => MediaQuery.orientationOf(context); diff --git a/modules/common/pubspec.yaml b/modules/common/pubspec.yaml index 0b3ad3f..1564241 100644 --- a/modules/common/pubspec.yaml +++ b/modules/common/pubspec.yaml @@ -2,30 +2,32 @@ name: common description: A new Flutter package project. version: 0.0.1 +resolution: workspace + environment: - sdk: '>=3.0.1 <4.0.0' - flutter: ">=1.17.0" + sdk: ">=3.6.0 <4.0.0" + flutter: ">=3.41.0" dependencies: flutter: sdk: flutter intl: ^0.20.2 - intl_utils: ^2.8.6 + intl_utils: ^2.8.14 cupertino_icons: ^1.0.5 async: ^2.11.0 - flutter_bloc: ^8.1.2 - get_it: ^7.6.0 + flutter_bloc: ^9.0.0 + get_it: ^8.0.0 package_info_plus: ^8.3.0 - permission_handler: ^11.4.0 - universal_html: ^2.2.2 - dio: ^5.1.2 + permission_handler: ^12.0.0 + universal_html: ^2.2.4 + dio: ^5.8.0 flutter_localizations: sdk: flutter dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^5.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/modules/data/lib/init.dart b/modules/data/lib/init.dart index 00f3b99..af0612e 100644 --- a/modules/data/lib/init.dart +++ b/modules/data/lib/init.dart @@ -21,18 +21,22 @@ class DataInit { getIt.registerSingleton(PreferencesImpl(getIt())); // Network - getIt.registerLazySingleton(() => AuthTokenInterceptor(getIt())); + getIt.registerLazySingleton( + () => AuthTokenInterceptor(getIt())); getIt.registerLazySingleton(() => NetworkConfig.provideDio(getIt())); - getIt.registerLazySingleton(() => EnvironmentServiceImpl(getIt())); + getIt.registerLazySingleton( + () => EnvironmentServiceImpl(getIt())); // Data Sources // Repositories getIt.registerLazySingleton( - () => AuthRepositoryImpl(getIt(),), + () => AuthRepositoryImpl( + getIt(), + ), ); getIt.registerLazySingleton( - () => CommonRepositoryImpl(getIt()), + () => CommonRepositoryImpl(getIt()), ); } } diff --git a/modules/data/lib/network/config/network_constants.dart b/modules/data/lib/network/config/network_constants.dart index c4a3581..16ec30d 100644 --- a/modules/data/lib/network/config/network_constants.dart +++ b/modules/data/lib/network/config/network_constants.dart @@ -3,7 +3,8 @@ class NetworkConstants { static const receiveTimeout = 2; //static const baseUrl = String.fromEnvironment('API_URL', defaultValue: "NA"); static const productsPath = "/products"; - static const baseUrl = "http://www.example.com"; // To get started: comment this and uncomment line 4 + static const baseUrl = + "http://www.example.com"; // To get started: comment this and uncomment line 4 static const tokenHeader = "token"; static const unauthorizedStatusCode = 401; static const forbiddenStatusCode = 403; diff --git a/modules/data/pubspec.yaml b/modules/data/pubspec.yaml index 7e8c992..1ab3654 100644 --- a/modules/data/pubspec.yaml +++ b/modules/data/pubspec.yaml @@ -3,19 +3,21 @@ description: A new Flutter package project. version: 0.0.1 publish_to: none +resolution: workspace + environment: - sdk: '>=3.0.1 <4.0.0' - flutter: ">=1.17.0" + sdk: ">=3.6.0 <4.0.0" + flutter: ">=3.41.0" dependencies: flutter: sdk: flutter - shared_preferences: ^2.1.1 - dio: ^5.1.2 + shared_preferences: ^2.5.3 + dio: ^5.8.0 async: ^2.11.0 - flutter_bloc: ^8.1.2 - get_it: ^7.6.0 - equatable: ^2.0.5 + flutter_bloc: ^9.0.0 + get_it: ^8.0.0 + equatable: ^2.0.7 flutter_localizations: sdk: flutter domain: @@ -26,7 +28,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^5.0.0 + mocktail: ^1.0.4 #connectivity_plus: ^5.0.2. Steps to add connectivity plus: #Add platform :ios, '12.0' in ios/Podfile and check no new crashings are in ios 16 diff --git a/modules/domain/lib/init.dart b/modules/domain/lib/init.dart index 95f04fa..076ceed 100644 --- a/modules/domain/lib/init.dart +++ b/modules/domain/lib/init.dart @@ -7,7 +7,7 @@ class DomainInit { static Future initialize(GetIt getIt) async { //Services getIt.registerLazySingleton(() => AuthService(getIt())); - + //Global Cubits getIt.registerSingleton(AppCubit(getIt())); getIt.registerSingleton(AuthCubit(getIt())); diff --git a/modules/domain/pubspec.yaml b/modules/domain/pubspec.yaml index 9da14e6..bb89432 100644 --- a/modules/domain/pubspec.yaml +++ b/modules/domain/pubspec.yaml @@ -3,18 +3,19 @@ description: A new Flutter package project. version: 0.0.1 publish_to: none +resolution: workspace + environment: - sdk: '>=3.0.1 <4.0.0' - flutter: ">=1.17.0" + sdk: ">=3.6.0 <4.0.0" + flutter: ">=3.41.0" dependencies: flutter: sdk: flutter async: ^2.11.0 - flutter_bloc: ^8.1.2 - get_it: ^7.6.0 - equatable: ^2.0.5 - url_strategy: ^0.2.0 + flutter_bloc: ^9.0.0 + get_it: ^8.0.0 + equatable: ^2.0.7 flutter_dotenv: ^5.2.1 flutter_localizations: sdk: flutter @@ -24,8 +25,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 - mocktail: ^1.0.0 + flutter_lints: ^5.0.0 + mocktail: ^1.0.4 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/pubspec.yaml b/pubspec.yaml index b25738f..1db00ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,22 +1,46 @@ -# This config file is for Sonarqube only -name: Sonar -description: Sonar +name: flutter_base_workspace +description: Melos workspace root. Real packages live under app/ and modules/*. publish_to: "none" version: 0.0.1+1 environment: - sdk: '>=3.0.0 <4.0.0' + sdk: ">=3.6.0 <4.0.0" + flutter: ">=3.41.0" -dependencies: - flutter: - sdk: flutter - app_links: ^6.4.1 +workspace: + - app + - modules/common + - modules/data + - modules/domain dev_dependencies: - flutter_test: - sdk: flutter + melos: ^7.0.0 -flutter: - generate: true - uses-material-design: true \ No newline at end of file +melos: + sdkPath: .fvm/flutter_sdk + scripts: + run:web: + description: Run the app in development mode for web. + run: melos exec --scope="app" -- flutter run -t lib/main.dart --dart-define-from-file=env/.dev -d chrome + lint:all: + run: melos run analyze && melos run format + description: Run all static analysis checks. + analyze: + description: Run `dart analyze` in all packages. + run: melos exec -c 1 -- dart analyze . --fatal-infos + format: + description: Run `dart format` in all packages. + run: melos exec -c 1 -- dart format --set-exit-if-changed . + pub:runner: + description: Run `pub run build_runner` in selected or all packages. + run: melos exec -- dart run build_runner build --delete-conflicting-outputs + packageFilters: + dirExists: + - lib + doctor: + description: Run `flutter doctor`. + run: melos exec -- flutter doctor + packageFilters: + dirExists: + - lib