Compare commits

...
Author SHA1 Message Date
hugo c945cd435e chore(release): publish packages
- wyatt_authentication_bloc@0.4.0
 - wyatt_form_bloc@0.2.0
2022-11-16 16:03:13 -05:00
hugo 852d29ef0a refactor(auth): update example with new input builders 2022-11-16 16:02:18 -05:00
hugo 08383ec03b refactor(form)!: input builders provides FormInput 2022-11-16 16:00:13 -05:00
hugo ee8ce76839 fix(form): disable status selection and rebuild SubmitBuilder on every state changes #28 2022-11-16 15:51:34 -05:00
hugo f05f2230e9 fix(auth): add initial null account event in stream in the mock authentication 2022-11-16 15:46:07 -05:00
hugo 54002beaab test(auth): add tests for the SignUpCubit update method 2022-11-16 15:45:11 -05:00
hugo d5698fbffc test(form): add formReplace test case #27 2022-11-16 15:43:52 -05:00
hugo 31ad460757 fix(auth)!: add signInWithEmailAndPassword and signInAnonymously methods in SignInCubit #26 2022-11-15 19:25:20 -05:00
hugo 4fd2a2a16c chore(auth): remove old example and rename actual 2022-11-15 18:52:10 -05:00
hugo 6eb40de72c feat(form): add metadata tag to bypass validation #29 2022-11-15 18:48:02 -05:00
hugo cecbc94a95 chore(auth): add global vscode folder symlink 2022-11-15 18:13:56 -05:00
hugo 3820fc4764 chore(auth): remove local vscode folder 2022-11-15 18:13:30 -05:00
hugo 1b893a5b84 test(form): add some tests 2022-11-15 18:10:50 -05:00
hugo 72661a343f fix(form): fix set operations behaviors 2022-11-15 18:10:30 -05:00
hugo 9ebe8e21dc fix(form): add nullable validator on boolean value 2022-11-15 18:09:39 -05:00
hugo 141f15b444 feat(form): add shorthands to access validator status 2022-11-15 18:09:13 -05:00
hugo 3a8a604a48 chore(form): add vscode folder symlink 2022-11-15 18:06:13 -05:00
hugo 41493207b3 chore(form): remove local vscode folder 2022-11-15 18:05:18 -05:00
hugo cbc4a2e149 chore: change vscode global settings 2022-11-15 18:03:30 -05:00
hugo 7345e415a7 chore(release): publish packages
- wyatt_crud_bloc@0.1.0
2022-11-13 20:29:19 -05:00
hugo ff680614aa typo(crud): fix line length 2022-11-13 20:21:20 -05:00
hugo 3e110e2eb5 fix(crud): update example 2022-11-13 20:19:21 -05:00
hugo 1ccb0a540e refactor(crud)!: migrate to wyatt architecture 2022-11-13 20:19:10 -05:00
hugo f9da719b91 refactor(crud): add vscode config 2022-11-13 20:18:10 -05:00
237 changed files with 4910 additions and 2777 deletions
+7 -2
View File
@@ -1,4 +1,10 @@
{
// Dart
"dart.runPubGetOnPubspecChanges": "never",
// Gitea
"gitea.owner": "Wyatt-FOSS",
"gitea.repo": "wyatt-packages",
// Header
"psi-header.changes-tracking": {
"isActive": true
},
@@ -67,5 +73,4 @@
],
}
],
"dart.runPubGetOnPubspecChanges": false,
}
}
+56
View File
@@ -3,6 +3,62 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## 2022-11-16
### Changes
---
Packages with breaking changes:
- [`wyatt_authentication_bloc` - `v0.4.0`](#wyatt_authentication_bloc---v040)
- [`wyatt_form_bloc` - `v0.2.0`](#wyatt_form_bloc---v020)
Packages with other changes:
- There are no other changes in this release.
---
#### `wyatt_authentication_bloc` - `v0.4.0`
- **REFACTOR**: update example with new input builders.
- **FIX**: add initial null account event in stream in the mock authentication.
- **BREAKING** **FIX**: add signInWithEmailAndPassword and signInAnonymously methods in SignInCubit #26.
#### `wyatt_form_bloc` - `v0.2.0`
- **FIX**: disable status selection and rebuild SubmitBuilder on every state changes #28.
- **FIX**: fix set operations behaviors.
- **FIX**: add nullable validator on boolean value.
- **FEAT**: add metadata tag to bypass validation #29.
- **FEAT**: add shorthands to access validator status.
- **BREAKING** **REFACTOR**: input builders provides FormInput.
## 2022-11-13
### Changes
---
Packages with breaking changes:
- [`wyatt_crud_bloc` - `v0.1.0`](#wyatt_crud_bloc---v010)
Packages with other changes:
- There are no other changes in this release.
---
#### `wyatt_crud_bloc` - `v0.1.0`
- **REFACTOR**: add vscode config.
- **FIX**: update example.
- **BREAKING** **REFACTOR**: migrate to wyatt architecture.
## 2022-11-11
### Changes
+1
View File
@@ -0,0 +1 @@
../../.vscode/
@@ -1,3 +1,11 @@
## 0.4.0
> Note: This release has breaking changes.
- **REFACTOR**: update example with new input builders.
- **FIX**: add initial null account event in stream in the mock authentication.
- **BREAKING** **FIX**: add signInWithEmailAndPassword and signInAnonymously methods in SignInCubit #26.
## 0.3.0+1
- **FIX**: fix some bugs to validate publishing.
@@ -1 +1,4 @@
include: package:wyatt_analysis/analysis_options.flutter.yaml
include: package:wyatt_analysis/analysis_options.flutter.yaml
analyzer:
exclude: "!example/**"
@@ -8,6 +8,7 @@
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
@@ -45,4 +46,4 @@ app.*.map.json
/android/app/profile
/android/app/release
lib/firebase_options.dart
firebase_options.dart
@@ -1,10 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
# This file should be version controlled.
version:
revision: 5464c5bac742001448fe4fc0597be939379f88ea
revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
- platform: ios
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
@@ -1,4 +0,0 @@
## 1.0.1
- Update a dependency to the latest release.
@@ -1,4 +1,4 @@
# authentication_bloc_example
# example_router
A new Flutter project.
@@ -8,9 +8,9 @@ This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
@@ -30,6 +30,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@@ -46,7 +47,9 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.authentication_bloc_example"
applicationId "com.example.example_router"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.authentication_bloc_example">
<!-- Flutter needs it to communicate with the running application
package="com.example.example_router">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.authentication_bloc_example">
package="com.example.example_router">
<application
android:label="authentication_bloc_example"
android:label="example_router"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
@@ -1,6 +0,0 @@
package com.example.authentication_bloc_example
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
@@ -3,7 +3,7 @@
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
@@ -3,7 +3,7 @@
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.authentication_bloc_example">
<!-- Flutter needs it to communicate with the running application
package="com.example.example_router">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
@@ -6,7 +6,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath 'com.android.tools.build:gradle:7.1.2'
// START: FlutterFire Configuration
classpath 'com.google.gms:google-services:4.3.10'
// END: FlutterFire Configuration
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
@@ -1,182 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:developer';
import 'package:authentication_bloc_example/constants.dart';
import 'package:authentication_bloc_example/home/home_page.dart';
import 'package:authentication_bloc_example/login/login_page.dart';
import 'package:authentication_bloc_example/model.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
static FormData getNormalFormData() {
return const FormData([
FormInput(formFieldName, Name.pure()),
FormInput(formFieldPhone, Phone.pure()),
FormInput(formFieldPro, Boolean.pure()),
FormInput(
formFieldConfirmedPassword,
ConfirmedPassword.pure(),
metadata: FormInputMetadata(export: false),
),
]);
}
static FormData getProFormData() {
return const FormData([
FormInput(formFieldName, Name.pure()),
FormInput(formFieldPhone, Phone.pure()),
FormInput(formFieldPro, Boolean.pure()),
FormInput(formFieldSiren, Siren.pure()),
FormInput(formFieldIban, Iban.pure()),
FormInput(
formFieldConfirmedPassword,
ConfirmedPassword.pure(),
metadata: FormInputMetadata(export: false),
),
]);
}
// On Authentication Success. (Authenticated or Anonymous)
// User callback.
Future<Map<String, dynamic>> onAuthSuccess(UserInterface user) async {
if (user.isNotEmpty && !user.isAnonymous) {
// Check if user is register in Firesore.
DocumentSnapshot firestoreUser = await FirebaseFirestore.instance
.collection(firestoreCollectionUsers)
.doc(user.uid)
.get();
if (!firestoreUser.exists) {
// Register user in Firestore when sign in with social account.
final uid = user.uid;
final u = {'uid': uid, 'email': user.email};
await FirebaseFirestore.instance
.collection(firestoreCollectionUsers)
.doc(uid)
.set(u);
return {
'user': UserFirestore(
uid: uid,
email: user.email ?? '',
name: user.displayName ?? '',
phone: user.phoneNumber ?? ''),
};
} else {
return {
'user': UserFirestore.fromMap(
firestoreUser.data() as Map<String, dynamic>),
...firestoreUser.data() as Map<String, dynamic>? ?? {}
};
}
} else {
return {};
}
}
// On Sign Up Success.
Future<void> onSignUpSuccess(SignUpState state, String? uid) async {
if (uid != null) {
final data = state.data.toMap();
final user = {'uid': uid, 'email': state.email.value, ...data};
log('onSignUpSuccess: $user');
await FirebaseFirestore.instance
.collection(firestoreCollectionUsers)
.doc(uid)
.set(user);
}
}
@override
Widget build(BuildContext context) {
AuthenticationRepositoryInterface authenticationRepository =
AuthenticationRepositoryFirebase();
AuthenticationCubit authenticationCubit = AuthenticationCubit(
authenticationRepository: authenticationRepository,
onAuthSuccess: onAuthSuccess,
);
SignUpCubit signUpCubit = SignUpCubit(
authenticationRepository: authenticationRepository,
authenticationCubit: authenticationCubit,
entries: getNormalFormData(),
onSignUpSuccess: onSignUpSuccess,
);
SignInCubit signInCubit = SignInCubit(
authenticationRepository: authenticationRepository,
authenticationCubit: authenticationCubit,
);
return MultiRepositoryProvider(
providers: [
RepositoryProvider<AuthenticationRepositoryInterface>(
create: (context) => authenticationRepository,
),
],
child: MultiBlocProvider(
providers: [
BlocProvider<AuthenticationCubit>(
create: (context) => authenticationCubit..init(),
),
BlocProvider<SignUpCubit>(
create: (context) => signUpCubit,
),
BlocProvider<SignInCubit>(
create: (context) => signInCubit,
),
],
child: const AppView(),
),
);
}
}
class AppView extends StatelessWidget {
const AppView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
buttonTheme: const ButtonThemeData(
buttonColor: Colors.blue,
textTheme: ButtonTextTheme.primary,
),
),
home: AuthenticationBuilder(
unknown: (context) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
},
authenticated: (context, user, userData) => const HomePage(),
unauthenticated: (context) => const LoginPage(),
),
);
}
}
@@ -1,44 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:authentication_bloc_example/forgot_password/widgets/forgot_password_form.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class ForgotPasswordPage extends StatelessWidget {
const ForgotPasswordPage({Key? key}) : super(key: key);
static Route route() {
return MaterialPageRoute<void>(builder: (_) => const ForgotPasswordPage());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Forgot Password')),
body: Padding(
padding: const EdgeInsets.all(8),
child: BlocProvider(
create: (_) => PasswordResetCubit(
context.read<AuthenticationRepositoryInterface>(),
),
child: const ForgotPasswordForm(),
),
),
);
}
}
@@ -1,92 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
class _EmailInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<PasswordResetCubit, PasswordResetState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return TextField(
onChanged: (email) =>
context.read<PasswordResetCubit>().emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'email',
helperText: '',
errorText: state.email.invalid ? 'invalid email' : null,
),
);
},
);
}
}
class _ResetButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<PasswordResetCubit, PasswordResetState>(
buildWhen: (previous, current) => previous.status != current.status,
builder: (context, state) {
return state.status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: state.status.isValidated
? () => context
.read<PasswordResetCubit>()
.sendPasswordResetEmail()
: null,
child: const Text('SEND EMAIL'),
);
},
);
}
}
class ForgotPasswordForm extends StatelessWidget {
const ForgotPasswordForm({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocListener<PasswordResetCubit, PasswordResetState>(
listener: (context, state) {
if (state.status.isSubmissionSuccess) {
Navigator.of(context).pop();
} else if (state.status.isSubmissionFailure) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Text(state.errorMessage ?? 'Password reset Failure'),
),
);
}
},
child: Align(
alignment: const Alignment(0, -1 / 3),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [_EmailInput(), const SizedBox(height: 8), _ResetButton()],
),
),
);
}
}
@@ -1,65 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:authentication_bloc_example/home/widgets/infos.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:authentication_bloc_example/home/widgets/email_verification.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
static Route route() {
return MaterialPageRoute<void>(builder: (_) => const HomePage());
}
@override
Widget build(BuildContext context) {
final user = context.select((AuthenticationCubit cubit) => cubit.state.user);
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.exit_to_app),
onPressed: () => context
.read<AuthenticationCubit>()
.logOut(),
)
],
),
body: Padding(
padding: const EdgeInsets.all(8),
child: BlocProvider(
create: (_) => EmailVerificationCubit(
context.read<AuthenticationRepositoryInterface>(),
)..checkEmailVerification(),
child: BlocBuilder<EmailVerificationCubit, EmailVerificationState>(
builder: (context, state) {
if (state.isVerified || user!.isAnonymous) {
return const UserInfo();
} else {
return const EmailVerification();
}
},
),
),
),
);
}
}
@@ -1,53 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:flutter/material.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class EmailVerification extends StatelessWidget {
const EmailVerification({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final user = context.select((AuthenticationCubit cubit) => cubit.state.user);
final userData = context.select((AuthenticationCubit cubit) => cubit.state.userData);
return Align(
alignment: const Alignment(0, -1 / 3),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Hello ${userData!['name'] ?? 'null'}!"),
const SizedBox(height: 4),
Text("Email '${user?.email ?? 'null'}' is not verified"),
const SizedBox(height: 4),
ElevatedButton(
onPressed: () {
context.read<EmailVerificationCubit>().sendEmailVerification();
},
child: const Text('(Re)send email'),
),
ElevatedButton(
onPressed: () {
context.read<EmailVerificationCubit>().checkEmailVerification();
},
child: const Text('Refresh'),
),
],
),
);
}
}
@@ -1,58 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:authentication_bloc_example/home/widgets/avatar.dart';
import 'package:flutter/material.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:authentication_bloc_example/constants.dart';
class UserInfo extends StatelessWidget {
const UserInfo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
final user = context.select((AuthenticationCubit cubit) => cubit.state.user);
final userData = context.select((AuthenticationCubit cubit) => cubit.state.userData);
return Align(
alignment: const Alignment(0, -1 / 3),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Avatar(photo: user?.photoURL),
const SizedBox(height: 4),
Text("Email: ${user?.email ?? 'null'}", style: textTheme.headline6),
const SizedBox(height: 4),
Text("Name: ${userData![formFieldName] ?? 'null'}",
style: textTheme.headline6),
const SizedBox(height: 4),
Text("Phone: ${userData[formFieldPhone] ?? 'null'}",
style: textTheme.headline6),
const SizedBox(height: 4),
Text("IsPro: ${userData[formFieldPro] ?? 'null'}",
style: textTheme.headline6),
const SizedBox(height: 4),
Text("IsAnonymous: ${user?.isAnonymous.toString() ?? 'null'}",
style: textTheme.headline6),
const SizedBox(height: 4),
Text("IsEmailVerified: ${user?.emailVerified.toString() ?? 'null'}",
style: textTheme.headline6),
],
),
);
}
}
@@ -1,214 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:authentication_bloc_example/app/app.dart';
import 'package:authentication_bloc_example/constants.dart';
import 'package:authentication_bloc_example/forgot_password/forgot_password_page.dart';
import 'package:authentication_bloc_example/sign_up/sign_up_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
class _EmailInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInCubit, SignInState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return TextField(
onChanged: (email) => context.read<SignInCubit>().emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'email',
helperText: '',
errorText: state.email.invalid ? 'invalid email' : null,
),
);
},
);
}
}
class _PasswordInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInCubit, SignInState>(
buildWhen: (previous, current) => previous.password != current.password,
builder: (context, state) {
return TextField(
onChanged: (password) =>
context.read<SignInCubit>().passwordChanged(password),
obscureText: true,
decoration: InputDecoration(
labelText: 'password',
helperText: '',
errorText: state.password.invalid ? 'invalid password' : null,
),
);
},
);
}
}
class _LoginAnonButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInCubit, SignInState>(
buildWhen: (previous, current) => previous.status != current.status,
builder: (context, state) {
return state.status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: () =>
context.read<SignInCubit>().signInAnonymously(),
child: const Text('LOGIN ANONYMOUSLY'),
);
},
);
}
}
class _LoginWithPasswordButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInCubit, SignInState>(
buildWhen: (previous, current) => previous.status != current.status,
builder: (context, state) {
return state.status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: state.status.isValidated
? () =>
context.read<SignInCubit>().signInWithEmailAndPassword()
: null,
child: const Text('LOGIN WITH PASSWORD'),
);
},
);
}
}
class _LoginWithGoogleButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignInCubit, SignInState>(
buildWhen: (previous, current) => previous.status != current.status,
builder: (context, state) {
return state.status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: () =>
context.read<SignInCubit>().signInWithGoogle(),
child: const Text('LOGIN GOOGLE'),
);
},
);
}
}
class _SignUpButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return TextButton(
onPressed: () {
context.read<SignUpCubit>().updateFormData(App.getNormalFormData());
Navigator.of(context).push<void>(SignUpPage.route());
},
child: Text(
'CREATE ACCOUNT',
style: TextStyle(color: theme.primaryColor),
),
);
}
}
class _SignUpAsProButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return TextButton(
onPressed: () {
context.read<SignUpCubit>().updateFormData(App.getProFormData());
context.read<SignUpCubit>().dataChanged(
formFieldPro,
const Boolean.dirty(value: true),
);
Navigator.of(context).push<void>(SignUpPage.route());
},
child: Text(
'CREATE PRO ACCOUNT',
style: TextStyle(color: theme.primaryColor),
),
);
}
}
class LoginForm extends StatelessWidget {
const LoginForm({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocListener<SignInCubit, SignInState>(
listener: (context, state) {
if (state.status.isSubmissionFailure) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Text(state.errorMessage ?? 'Authentication Failure'),
),
);
}
},
child: Align(
alignment: const Alignment(0, -1 / 3),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 120),
_EmailInput(),
const SizedBox(height: 8),
_PasswordInput(),
const SizedBox(height: 8),
GestureDetector(
onTap: () {
Navigator.of(context).push(ForgotPasswordPage.route());
},
child: Text(
'Forgot password ?',
style: Theme.of(context).textTheme.bodyText2,
),
),
const SizedBox(height: 8),
_LoginWithPasswordButton(),
const SizedBox(height: 8),
_LoginAnonButton(),
const SizedBox(height: 8),
_LoginWithGoogleButton(),
const SizedBox(height: 8),
_SignUpButton(),
const SizedBox(height: 8),
_SignUpAsProButton(),
],
),
),
),
);
}
}
@@ -1,35 +1,6 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:example_router/bootstrap.dart';
import 'package:example_router/presentation/features/app/app.dart';
import 'package:authentication_bloc_example/app/app.dart';
import 'package:authentication_bloc_example/app/bloc_observer.dart';
import 'package:authentication_bloc_example/firebase_options.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
BlocOverrides.runZoned(
() => runApp(
const App(),
),
blocObserver: AppBlocObserver(),
);
void main() {
bootstrap(App.new);
}
@@ -3,7 +3,7 @@
// -----
// File: sign_in_form.dart
// Created Date: 19/08/2022 15:24:37
// Last Modified: Fri Nov 11 2022
// Last Modified: Wed Nov 16 2022
// -----
// Copyright (c) 2022
@@ -16,14 +16,14 @@ class _EmailInput extends StatelessWidget {
Widget build(BuildContext context) {
return InputBuilder<SignInCubit<int>>(
field: AuthFormField.email,
builder: ((context, cubit, state, field, inputValid) {
builder: ((context, cubit, state, field, input) {
return TextField(
onChanged: (email) => cubit.emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email',
helperText: '',
errorText: !inputValid ? 'Invalid email' : null,
errorText: input.validator.invalid ? 'Invalid email' : null,
),
);
}),
@@ -36,14 +36,14 @@ class _PasswordInput extends StatelessWidget {
Widget build(BuildContext context) {
return InputBuilder<SignInCubit<int>>(
field: AuthFormField.password,
builder: ((context, cubit, state, field, inputValid) {
builder: ((context, cubit, state, field, input) {
return TextField(
onChanged: (pwd) => cubit.passwordChanged(pwd),
obscureText: true,
decoration: InputDecoration(
labelText: 'Password',
helperText: '',
errorText: !inputValid ? 'Invalid password' : null,
errorText: input.validator.invalid ? 'Invalid password' : null,
),
);
}),
@@ -59,8 +59,24 @@ class _SignInButton extends StatelessWidget {
return status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: status.isValidated ? () => cubit.submit() : null,
child: const Text('Sign in'),
onPressed: status.isValidated ? () => cubit.signInWithEmailAndPassword() : null,
child: const Text('Sign in with credentials'),
);
}),
);
}
}
class _SignInAnonymouslyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SubmitBuilder<SignInCubit<int>>(
builder: ((context, cubit, status) {
return status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: () => cubit.signInAnonymously(),
child: const Text('Sign in anonymously'),
);
}),
);
@@ -80,12 +96,15 @@ class SignInForm extends StatelessWidget {
),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_EmailInput(),
const SizedBox(height: 8),
_PasswordInput(),
const SizedBox(height: 16),
_SignInButton(),
const SizedBox(height: 16),
_SignInAnonymouslyButton(),
],
),
),
@@ -3,7 +3,7 @@
// -----
// File: sign_up_form.dart
// Created Date: 19/08/2022 14:41:08
// Last Modified: Fri Nov 11 2022
// Last Modified: Wed Nov 16 2022
// -----
// Copyright (c) 2022
@@ -17,14 +17,14 @@ class _EmailInput extends StatelessWidget {
Widget build(BuildContext context) {
return InputBuilder<SignUpCubit<int>>(
field: AuthFormField.email,
builder: ((context, cubit, state, field, inputValid) {
builder: ((context, cubit, state, field, input) {
return TextField(
onChanged: (email) => cubit.emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email',
helperText: '',
errorText: !inputValid ? 'Invalid email' : null,
errorText: input.validator.invalid ? 'Invalid email' : null,
),
);
}),
@@ -37,7 +37,7 @@ class _PasswordInput extends StatelessWidget {
Widget build(BuildContext context) {
return InputBuilder<SignUpCubit<int>>(
field: AuthFormField.password,
builder: ((context, cubit, state, field, inputValid) {
builder: ((context, cubit, state, field, input) {
return TextField(
onChanged: (pwd) {
cubit.passwordChanged(pwd);
@@ -52,7 +52,7 @@ class _PasswordInput extends StatelessWidget {
decoration: InputDecoration(
labelText: 'Password',
helperText: '',
errorText: !inputValid ? 'Invalid password' : null,
errorText: input.validator.invalid ? 'Invalid password' : null,
),
);
}),
@@ -65,7 +65,7 @@ class _ConfirmPasswordInput extends StatelessWidget {
Widget build(BuildContext context) {
return InputBuilder<SignUpCubit<int>>(
field: AppFormField.confirmedPassword,
builder: ((context, cubit, state, field, inputValid) {
builder: ((context, cubit, state, field, input) {
return TextField(
onChanged: (pwd) {
cubit.dataChanged(
@@ -80,7 +80,8 @@ class _ConfirmPasswordInput extends StatelessWidget {
decoration: InputDecoration(
labelText: 'Confirm password',
helperText: '',
errorText: !inputValid ? 'Passwords do not match' : null,
errorText:
input.validator.invalid ? 'Passwords do not match' : null,
),
);
}),
@@ -1,325 +0,0 @@
// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:developer';
import 'package:authentication_bloc_example/app/app.dart';
import 'package:authentication_bloc_example/constants.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
class _NameInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return TextField(
onChanged: (name) => context
.read<SignUpCubit>()
.dataChanged(formFieldName, Name.dirty(name)),
keyboardType: TextInputType.name,
decoration: InputDecoration(
labelText: 'name',
helperText: '',
errorText:
state.data.isNotValid(formFieldName) ? 'invalid name' : null,
),
);
},
);
}
}
class _PhoneInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return TextField(
onChanged: (phone) => context
.read<SignUpCubit>()
.dataChanged(formFieldPhone, Phone.dirty(phone)),
keyboardType: TextInputType.phone,
decoration: InputDecoration(
labelText: 'phone',
helperText: '',
errorText: state.data.isNotValid(formFieldPhone)
? 'invalid phone'
: null,
),
);
},
);
}
}
class _SirenInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return TextField(
onChanged: (siren) => context
.read<SignUpCubit>()
.dataChanged(formFieldSiren, Siren.dirty(siren)),
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'siren',
helperText: '',
errorText: state.data.isNotValid(formFieldSiren)
? 'invalid SIREN'
: null,
),
);
},
);
}
}
class _IbanInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return TextField(
onChanged: (iban) => context
.read<SignUpCubit>()
.dataChanged(formFieldIban, Iban.dirty(iban)),
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: 'iban',
helperText: '',
errorText:
state.data.isNotValid(formFieldIban) ? 'invalid IBAN' : null,
),
);
},
);
}
}
class _EmailInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
buildWhen: (previous, current) => previous.email != current.email,
builder: (context, state) {
return TextField(
onChanged: (email) => context.read<SignUpCubit>().emailChanged(email),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'email',
helperText: '',
errorText: state.email.invalid ? 'invalid email' : null,
),
);
},
);
}
}
class _PasswordInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return TextField(
onChanged: (password) {
context.read<SignUpCubit>().passwordChanged(password);
context.read<SignUpCubit>().dataChanged(
formFieldConfirmedPassword,
ConfirmedPassword.dirty(
password: password,
value: context
.read<SignUpCubit>()
.state
.data
.valueOf<String>(formFieldConfirmedPassword),
),
);
},
obscureText: true,
decoration: InputDecoration(
labelText: 'password',
helperText: '',
errorText: state.password.invalid ? 'invalid password' : null,
),
);
},
);
}
}
class _ConfirmPasswordInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return TextField(
onChanged: (confirmPassword) => context
.read<SignUpCubit>()
.dataChanged(
formFieldConfirmedPassword,
ConfirmedPassword.dirty(
password: context.read<SignUpCubit>().state.password.value,
value: confirmPassword,
),
),
obscureText: true,
decoration: InputDecoration(
labelText: 'confirm password',
helperText: '',
errorText: state.data.isNotValid(formFieldConfirmedPassword)
? 'passwords do not match'
: null,
),
);
},
);
}
}
class _CheckIsProInput extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListTile(
title: const Text('Are you a pro?'),
trailing: BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return Checkbox(
value: state.data.valueOf<bool>(formFieldPro),
onChanged: (isPro) {
final value =
isPro!; // tristate is false, so value can't be null
context.read<SignUpCubit>().dataChanged(
formFieldPro,
Boolean.dirty(value: value),
);
if (value) {
context.read<SignUpCubit>().updateFormData(
App.getProFormData(),
operation: SetOperation.union);
} else {
context.read<SignUpCubit>().updateFormData(
App.getNormalFormData(),
operation: SetOperation.intersection);
}
});
},
),
);
}
}
class _SignUpButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
buildWhen: (previous, current) => previous.status != current.status,
builder: (context, state) {
return state.status.isSubmissionInProgress
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: state.status.isValidated
? () => context.read<SignUpCubit>().signUpFormSubmitted()
: null,
child: const Text('SIGN UP'),
);
},
);
}
}
class _DebugButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
return ElevatedButton(
onPressed: () {
// log(state.toString());
log(state.data.toMap().toString());
},
child: const Text('DEBUG'),
);
},
);
}
}
class SignUpForm extends StatelessWidget {
const SignUpForm({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocListener<SignUpCubit, SignUpState>(
listener: (context, state) {
if (state.status.isSubmissionSuccess) {
Navigator.of(context).pop();
} else if (state.status.isSubmissionFailure) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(content: Text(state.errorMessage ?? 'Sign Up Failure')),
);
}
},
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Align(
alignment: const Alignment(0, -1 / 3),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_NameInput(),
const SizedBox(height: 8),
_PhoneInput(),
const SizedBox(height: 8),
_CheckIsProInput(),
const SizedBox(height: 8),
BlocBuilder<SignUpCubit, SignUpState>(
builder: (context, state) {
if (state.data.valueOf<bool>(formFieldPro)) {
return Column(children: [
_SirenInput(),
const SizedBox(height: 8),
_IbanInput(),
const SizedBox(height: 8),
]);
}
return const SizedBox.shrink();
},
),
_EmailInput(),
const SizedBox(height: 8),
_PasswordInput(),
const SizedBox(height: 8),
_ConfirmPasswordInput(),
const SizedBox(height: 8),
_SignUpButton(),
const SizedBox(height: 8),
_DebugButton(),
],
),
),
),
);
}
}
@@ -1,4 +1,4 @@
name: authentication_bloc_example
name: example_router
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
@@ -15,10 +15,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.1
version: 1.0.0+1
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.6 <3.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@@ -29,22 +29,30 @@ environment:
dependencies:
flutter:
sdk: flutter
go_router: ^5.1.5
firebase_core: ^2.1.1
flutter_bloc: ^8.1.1
get_it: ^7.2.0
firebase_core: ^1.14.1
flutter_bloc: ^8.0.1
wyatt_authentication_bloc:
path: "../"
wyatt_form_bloc:
git:
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
ref: wyatt_form_bloc-v0.1.0+1
path: packages/wyatt_form_bloc
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
version: 0.2.0
wyatt_architecture:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
version: 0.0.2
wyatt_type_utils:
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
version: 0.0.3+1
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.4
cloud_firestore: ^3.1.12
cupertino_icons: ^1.0.5
dev_dependencies:
flutter_test:
@@ -60,7 +68,7 @@ dev_dependencies:
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
@@ -74,7 +82,7 @@ flutter:
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
@@ -1,49 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
firebase_options.dart
@@ -1,30 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
- platform: ios
create_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
base_revision: e99c9c7cd9f6c0b2f8ae6e3ebfd585239f5568f4
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
@@ -1,16 +0,0 @@
# example_router
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
@@ -1,29 +0,0 @@
# 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.
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
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
@@ -1,13 +0,0 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
@@ -1,74 +0,0 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
// START: FlutterFire Configuration
apply plugin: 'com.google.gms.google-services'
// END: FlutterFire Configuration
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.example_router"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
@@ -1,8 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example_router">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
@@ -1,34 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example_router">
<application
android:label="example_router"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

Some files were not shown because too many files have changed in this diff Show More