Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #18

Merged
merged 51 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
0fa8ce7
build: install `g_recaptcha_v3`
felipecastrosales Mar 24, 2024
a90d2f8
feature: added recaptcha to integrate with new service, and keys to use
felipecastrosales Apr 9, 2024
0c7a5d1
feat: update to SES and testing
felipecastrosales Apr 9, 2024
5a306b1
feat: add error message
felipecastrosales Apr 10, 2024
0fc31ae
docs: revert for be equal
felipecastrosales Apr 15, 2024
f77e265
docs: update license
felipecastrosales Apr 15, 2024
5ce8268
docs: fix typo
felipecastrosales Apr 15, 2024
1e0a869
feat: change `emailjs` to `aws ses` for sending emails
felipecastrosales Apr 16, 2024
c863875
docs: removed references to email.js
felipecastrosales Apr 16, 2024
f997a5f
build: bump to 2.2.0
felipecastrosales Apr 16, 2024
c18b437
wip
felipecastrosales Apr 17, 2024
e13da16
chore: removed save and reset of form
felipecastrosales Apr 18, 2024
dca05a1
chore: add early return
felipecastrosales Apr 18, 2024
5a54ba4
chore: add headers
felipecastrosales Apr 18, 2024
0dceb84
chore: unused code
felipecastrosales Apr 22, 2024
5689d53
style: comment dart_code_metrics usage
felipecastrosales Apr 24, 2024
5aaa69f
fix: set primary as false to avoid error when typing form
felipecastrosales Apr 24, 2024
88bde04
chore: removed temp recaptcha, change http to dio and init to fix test
felipecastrosales Apr 24, 2024
a772562
chore: temporarily made recaptcha unavailable
felipecastrosales Apr 25, 2024
02e6371
chore: removed runZonedGuarded for prevent twice on app
felipecastrosales May 7, 2024
1ee7ffa
chore: fix overflow
felipecastrosales May 7, 2024
0cfa23c
refactor: removed help method
felipecastrosales May 7, 2024
301b559
build: add flutter_bloc
felipecastrosales May 7, 2024
afedae4
refactor!: change architecture to be more generic and make more imple…
felipecastrosales May 7, 2024
c8168f0
refactor: move Contact to inside specific feature
felipecastrosales May 7, 2024
5f821e6
feat: add result related (looks like dartz and fpdart - but native us…
felipecastrosales May 7, 2024
2130ab7
feat: init cubit construction and add equatable
felipecastrosales May 8, 2024
4abde1e
refactor!: apply clean architecture and separate better layers; also …
felipecastrosales May 8, 2024
b4ef9bd
feat: init to work with abstractions and complexities for ensure and …
felipecastrosales May 8, 2024
3a5b06f
chore: removed old ContactController
felipecastrosales May 12, 2024
d12547c
chore: removed deprecated properties
felipecastrosales May 12, 2024
44bb684
style: ignore only localizations
felipecastrosales May 12, 2024
ff4e89d
feat: enhance cubit with more control and models related for return t…
felipecastrosales May 12, 2024
98869c0
feat: update bloc and repository layers for better control
felipecastrosales May 12, 2024
a2cc20c
feat: add missing file
felipecastrosales May 15, 2024
9032cc2
feat: add global context for use in controllers
felipecastrosales May 16, 2024
229cdc2
chore: clear only after success
felipecastrosales May 16, 2024
946b6fc
chore: use WidgetState instead of MaterialState
felipecastrosales May 16, 2024
c9a21f0
feat: add messages and use
felipecastrosales May 18, 2024
cb46529
build: bump packages to latest version
felipecastrosales May 26, 2024
b35bb51
chore: optimizing build, using BlocListener instead of BlocConsumer
felipecastrosales May 26, 2024
49c3b32
build: bump web (index.html) to Flutter 3.22.0
felipecastrosales May 26, 2024
5c3811c
feat: enhance cubit and repository flow, and use get_it to control in…
felipecastrosales May 26, 2024
2f2a0ca
test: init to fix implementation tests
felipecastrosales May 27, 2024
b8ca9c0
chore: add stubs for test
felipecastrosales May 28, 2024
8233fd8
chore: removed unused injections
felipecastrosales May 28, 2024
a6220fc
test: add ContactCubit test and mocking AppLocalizations
felipecastrosales May 29, 2024
a5545dd
build: android bumps
felipecastrosales May 29, 2024
9830e36
fix: adjust for works in app and in test
felipecastrosales May 29, 2024
634bd42
chore: review and enhancing
felipecastrosales May 30, 2024
49d36b4
Merge pull request #16 from felipecastrosales/feature/add_recaptcha_ses
felipecastrosales Aug 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# You can get these keys from https://www.google.com/recaptcha/admin
RECAPTCHA_PUBLIC_KEY=your_public_key
RECAPTCHA_SECRET_KEY=your_secret_key

# Create your api key from AWS SES / API Gateway:
# - https://aws.amazon.com/ses/;
# - https://aws.amazon.com/api-gateway/
API_SEND_MAIL=your_api_send_mail
5 changes: 3 additions & 2 deletions .github/docs/WANTTODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ First, Follow the [🤔 How to Use](./README.md#-how-to-use) steps.
## Contact Form

- Related to Contact Form:
- Create your account inside `emailjs` and make your changes.
- You can see [this video](https://www.youtube.com/watch?v=9HW3MZ_tsdo), to help you on practice.
- Check my api [here](https://github.com/felipecastrosales/site-api) and make your changes.
- You need configurate your AWS SES, and put your credentials inside the `.env` file.
- After that, configure AWS Lambda and API Gateway, and deploy your API.

## Firebase

Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ firebase.json
firebase-config.js
.firebase
package.json

# Environment configuration
.env
lib/infra/env/env.g.dart
26 changes: 26 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "site",
"request": "launch",
"type": "dart",
"flutterMode": "debug"
},
{
"name": "site (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "site (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022-2023 Felipe Sales
Copyright (c) 2022-2024 Felipe Sales

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

With a single codebase, you can access this example from mobile, web and even desktop.

I'm sure this will be one of the best examples of the Flutter Web project in a completely open-source way and with the amout of features that exist.
I'm sure this will be one of the best examples of the Flutter Web project in a completely open-source way and with the amount of features that exist.

---

Expand Down Expand Up @@ -64,7 +64,7 @@ I'm sure this will be one of the best examples of the Flutter Web project in a c
- All of them using [`mocktail`](https://pub.dev/packages/mocktail).
- Internationalization:
- With support to 3 languages: English, Portuguese and Spanish;
- Feature to send an email to the user using [`emailjs API`](https://www.emailjs.com/);
- Feature to send an email to the user using [`AWS SES`](https://aws.amazon.com/ses/), [`AWS Lambda`](https://aws.amazon.com/lambda/) and [`AWS API Gateway`](https://aws.amazon.com/api-gateway/);
- Settings:
- Firebase Hosting;
- Google Domains;
Expand All @@ -88,7 +88,7 @@ Challenges are always an opportunity for growth, and in this project that became

One thing I realized was that Flutter Web still has a lot to evolve, but id does very well it proposes ([see here](https://docs.flutter.dev/development/platform-integration/web/faq#what-scenarios-are-ideal-for-flutter-on-the-web)). One of the main ones that still annoys me a little is the loading and rendering speed of the elements (there are some pre-load strategies, but that could be better and clearer IMHO.

I feel that the project can evolve a lot, and for that reason I was very carefull with its development. For it to be simple, scalable and capable of any developer, of any level, being able to use and understand it. Also, I'll always be on the lookout for issues and PRs to improve it. 🚀
I feel that the project can evolve a lot, and for that reason I was very carefully with its development. For it to be simple, scalable and capable of any developer, of any level, being able to use and understand it. Also, I'll always be on the lookout for issues and PRs to improve it. 🚀

This project took me out of my comfort zone, and I'm very happy with the result. Also, releasing it to the community did me a lot of good. Let's grow together, because the **Forge is Daily**. 🏆

Expand Down
60 changes: 30 additions & 30 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
include: package:flutter_lints/flutter.yaml

analyzer:
plugins:
- dart_code_metrics
# plugins:
# - dart_code_metrics
exclude:
- lib/generated_plugin_registrant.dart
- test/**
# - lib/generated_plugin_registrant.dart
# - test/**
- lib/app/core/l10n/localizations/** # Generated file
- lib/data/services/firebase/firebase_set_defaults.dart # To use dynamic type (because really need it)
# - lib/data/services/firebase/firebase_set_defaults.dart # To use dynamic type (because really need it)

linter:
rules:
Expand All @@ -28,28 +28,28 @@ linter:
- prefer_final_fields
- prefer_single_quotes

dart_code_metrics:
metrics:
cyclomatic-complexity: 20
number-of-parameters: 4
maximum-nesting-level: 5
metrics-exclude:
- test/**
rules:
- avoid-dynamic
- avoid-redundant-async
- avoid-passing-async-when-sync-expected
- avoid-redundant-async
- avoid-unnecessary-type-assertions
- avoid-unnecessary-type-casts
- avoid-unrelated-type-assertions
- avoid-unused-parameters
- avoid-nested-conditional-expressions
- newline-before-return
- no-boolean-literal-compare
- no-empty-block
- prefer-trailing-comma
- prefer-conditional-expressions
- no-equal-then-else
- prefer-moving-to-variable
- prefer-match-file-name
# dart_code_metrics:
# metrics:
# cyclomatic-complexity: 20
# number-of-parameters: 4
# maximum-nesting-level: 5
# metrics-exclude:
# - test/**
# rules:
# - avoid-dynamic
# - avoid-redundant-async
# - avoid-passing-async-when-sync-expected
# - avoid-redundant-async
# - avoid-unnecessary-type-assertions
# - avoid-unnecessary-type-casts
# - avoid-unrelated-type-assertions
# - avoid-unused-parameters
# - avoid-nested-conditional-expressions
# - newline-before-return
# - no-boolean-literal-compare
# - no-empty-block
# - prefer-trailing-comma
# - prefer-conditional-expressions
# - no-equal-then-else
# - prefer-moving-to-variable
# - prefer-match-file-name
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.felipecastrosales.site"
minSdkVersion 19
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand Down
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.6.21'
ext.kotlin_version = '1.9.24'
repositories {
google()
mavenCentral()
Expand Down Expand Up @@ -29,6 +29,6 @@ subprojects {
project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
15 changes: 8 additions & 7 deletions lib/app/app_widget.dart
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
import 'package:flutter/material.dart';

import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

import 'package:site/app/core/globals/globals.dart';
import 'package:site/app/core/injections/injections.dart';
import 'package:site/app/core/l10n/l10n.dart';
import 'package:site/app/core/themes/app_theme.dart';
import 'package:site/app/features/contact/contact.dart';
import 'package:site/app/features/home/home_page.dart';

class AppWidget extends StatelessWidget {
AppWidget({
super.key,
FirebaseRemoteConfig? firebaseRemoteConfig,
http.Client? httpClient,
ContactCubit? contactCubit,
}) : _firebaseRemoteConfig = firebaseRemoteConfig ?? getIt(),
_httpClient = httpClient ?? getIt();
_contactCubit = contactCubit ?? getIt();

final FirebaseRemoteConfig _firebaseRemoteConfig;
final http.Client _httpClient;
final ContactCubit _contactCubit;

@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: NavigationService.navigatorKey,
onGenerateTitle: (context) => AppTexts.get(context).projectTitle,
debugShowCheckedModeBanner: false,
theme: AppTheme.theme,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: HomePage(
firebaseRemoteConfig: _firebaseRemoteConfig,
httpClient: _httpClient,
contactCubit: _contactCubit,
),
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/app/core/globals/globals.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'navigation_service.dart';
6 changes: 6 additions & 0 deletions lib/app/core/globals/navigation_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'package:flutter/material.dart';

class NavigationService {
static final navigatorKey = GlobalKey<NavigatorState>();
static final navigatorKeyContext = navigatorKey.currentContext;
}
29 changes: 14 additions & 15 deletions lib/app/core/injections/injections.dart
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
import 'package:dio/dio.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:site/app/features/contact/contact.dart';
import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;

import 'package:site/data/repositories/contact/contact.dart';
import 'package:site/data/services/firebase/firebase.dart';

final getIt = GetIt.I;

void configureDependencies() {
if (!getIt.isRegistered<http.Client>()) {
getIt.registerSingleton<http.Client>(
http.Client(),
if (!getIt.isRegistered<Dio>()) {
getIt.registerSingleton<Dio>(
Dio(),
);
}
if (!getIt.isRegistered<FirebaseRemoteConfig>()) {
getIt.registerSingleton<FirebaseRemoteConfig>(
FirebaseRemoteConfig.instance,
);
}
if (!getIt.isRegistered<FirebaseService>()) {
getIt.registerSingleton<FirebaseService>(
FirebaseServiceImpl(),
);
}
if (!getIt.isRegistered<ContactRepository>()) {
getIt.registerSingleton<ContactRepository>(
ContactRepositoryImpl(
firebaseRemoteConfig: getIt(),
getIt.registerLazySingleton<ContactRepository>(
() => ContactRepositoryImpl(
httpClient: getIt(),
),
);
}
if (!getIt.isRegistered<ContactCubit>()) {
getIt.registerFactory<ContactCubit>(
() => ContactCubit(
contactRepository: getIt(),
),
);
}
}
24 changes: 24 additions & 0 deletions lib/app/core/l10n/localizations/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,30 @@ abstract class AppLocalizations {
/// **'E-mail enviado com sucesso!'**
String get emailSendedWithSuccess;

/// No description provided for @emailNotSended.
///
/// In pt, this message translates to:
/// **'Erro ao enviar e-mail!'**
String get emailNotSended;

/// No description provided for @emailTooManyRequests.
///
/// In pt, this message translates to:
/// **'Tente novamente mais tarde!'**
String get emailTooManyRequests;

/// No description provided for @emailUnauthorized.
///
/// In pt, this message translates to:
/// **'O envio não foi autorizado!'**
String get emailUnauthorized;

/// No description provided for @emailUnknowError.
///
/// In pt, this message translates to:
/// **'Tente enviar de outra forma!'**
String get emailUnknowError;

/// No description provided for @letsChatCallMe.
///
/// In pt, this message translates to:
Expand Down
12 changes: 12 additions & 0 deletions lib/app/core/l10n/localizations/app_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get emailSendedWithSuccess => 'Email sent successfully!';

@override
String get emailNotSended => 'Error to send email';

@override
String get emailTooManyRequests => 'Please try again later!';

@override
String get emailUnauthorized => 'Sending was not authorized!';

@override
String get emailUnknowError => 'Try sending in another way!';

@override
String get letsChatCallMe => 'Let\'s chat, call me:';

Expand Down
12 changes: 12 additions & 0 deletions lib/app/core/l10n/localizations/app_localizations_es.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ class AppLocalizationsEs extends AppLocalizations {
@override
String get emailSendedWithSuccess => '¡Email enviado exitosamente!';

@override
String get emailNotSended => '¡Error al enviar el email!';

@override
String get emailTooManyRequests => '¡Inténtalo de nuevo más tarde!';

@override
String get emailUnauthorized => '¡El envío no fue autorizado!';

@override
String get emailUnknowError => '¡Intenta enviar de otra manera!';

@override
String get letsChatCallMe => 'Hablemos, llámame:';

Expand Down
12 changes: 12 additions & 0 deletions lib/app/core/l10n/localizations/app_localizations_pt.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ class AppLocalizationsPt extends AppLocalizations {
@override
String get emailSendedWithSuccess => 'E-mail enviado com sucesso!';

@override
String get emailNotSended => 'Erro ao enviar e-mail!';

@override
String get emailTooManyRequests => 'Tente novamente mais tarde!';

@override
String get emailUnauthorized => 'O envio não foi autorizado!';

@override
String get emailUnknowError => 'Tente enviar de outra forma!';

@override
String get letsChatCallMe => 'Vamos bater um papo, me chame:';

Expand Down
Loading
Loading