docs(authentication): update example with multiple data sources

This commit is contained in:
2023-04-13 23:24:12 +02:00
parent d53e7b80da
commit 4d872edc4e
13 changed files with 261 additions and 41 deletions
@@ -18,11 +18,8 @@ import 'dart:async';
import 'package:example_router/core/dependency_injection/get_it.dart';
import 'package:example_router/core/utils/app_bloc_observer.dart';
import 'package:example_router/firebase_options.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
class MockSettings {
static MockSettings? _instance;
@@ -70,12 +67,6 @@ Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
debugPrint(details.toString());
};
if (MockSettings.isDisable()) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
}
await GetItInitializer.init();
runApp(await builder());
@@ -14,20 +14,81 @@
// 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:async';
import 'package:example_router/core/enums/dev_mode.dart';
import 'package:example_router/core/flavors/flavor.dart';
import 'package:example_router/firebase_options.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:get_it/get_it.dart';
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
final getIt = GetIt.I;
/// Service and Data Source locator
abstract class GetItInitializer {
static Future<void> init() async {
getIt.registerLazySingleton<AuthenticationRemoteDataSource<int>>(
() => AuthenticationFirebaseDataSourceImpl<int>(
firebaseAuth: FirebaseAuth.instance,
googleSignIn:
GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)),
static FutureOr<void> _initCommon() async {
// Initialize common sources/services
getIt.registerLazySingleton<AuthenticationSessionDataSource<int>>(
() => AuthenticationSessionDataSourceImpl<int>(),
);
}
static FutureOr<void> _initEmulator() async {
// Initialize emulator sources/services
final firebaseAuth = FirebaseAuth.instance;
await firebaseAuth.useAuthEmulator('localhost', 9099);
getIt
..registerLazySingleton<AuthenticationRemoteDataSource<int>>(
() => AuthenticationFirebaseDataSourceImpl<int>(
firebaseAuth: firebaseAuth,
googleSignIn:
GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)),
)
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
() => AuthenticationFirebaseCacheDataSourceImpl<int>(
firebaseAuth: firebaseAuth,
),
);
}
static FutureOr<void> _initFirebase() async {
// Initialize firebase sources/services.
getIt
..registerLazySingleton<AuthenticationRemoteDataSource<int>>(
() => AuthenticationFirebaseDataSourceImpl<int>(
firebaseAuth: FirebaseAuth.instance,
googleSignIn:
GoogleSignIn(clientId: DefaultFirebaseOptions.ios.iosClientId)),
)
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
() => AuthenticationFirebaseCacheDataSourceImpl<int>(
firebaseAuth: FirebaseAuth.instance,
),
);
}
static FutureOr<void> _initRest() async {
// Initialize rest api sources/services
}
static FutureOr<void> init() async {
await _initCommon();
final flavor = Flavor.get();
if (flavor.devMode == DevMode.rest) {
await _initRest();
} else if (flavor.devMode == DevMode.emulator) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await _initEmulator();
} else {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await _initFirebase();
}
await getIt.allReady();
}
@@ -0,0 +1,44 @@
// Copyright (C) 2023 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/>.
enum DevMode {
/// Mocked values
mock,
/// Real values from REST API
rest,
/// Emulated values with Firebase Emulator
emulator,
/// Real values from Firebase
real;
@override
String toString() => name;
/// Tries to parse String and returns mode. Fallback is returned if there
/// is an error during parsing.
static DevMode fromString(String? mode, {DevMode fallback = DevMode.mock}) {
for (final m in values) {
if (m.name == mode) {
return m;
}
}
return fallback;
}
}
@@ -0,0 +1,72 @@
// Copyright (C) 2023 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/core/enums/dev_mode.dart';
import 'package:flutter/material.dart';
abstract class Flavor {
Flavor._({
this.banner,
this.bannerColor = Colors.red,
this.devMode,
}) {
_instance = this;
}
static Flavor? _instance;
final String? banner;
final Color bannerColor;
final DevMode? devMode;
/// Returns [Flavor] instance.
static Flavor get() {
if (_instance == null) {
throw Exception('Flavor not initialized!');
}
return _instance!;
}
@override
String toString() => runtimeType.toString().replaceAll('Flavor', '');
}
class DevelopmentFlavor extends Flavor {
factory DevelopmentFlavor() {
const modeString = String.fromEnvironment('dev_mode', defaultValue: 'mock');
final mode = DevMode.fromString(modeString);
return DevelopmentFlavor._(devMode: mode);
}
DevelopmentFlavor._({
required super.devMode,
}) : super._(
banner: 'Dev',
);
}
class StagingFlavor extends Flavor {
StagingFlavor()
: super._(
banner: 'Staging',
bannerColor: Colors.green,
);
}
class ProductionFlavor extends Flavor {
ProductionFlavor() : super._();
}
@@ -65,8 +65,10 @@ class DefaultFirebaseOptions {
projectId: 'tchat-beta',
databaseURL: 'https://tchat-beta.firebaseio.com',
storageBucket: 'tchat-beta.appspot.com',
androidClientId: '136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com',
iosClientId: '136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com',
androidClientId:
'136771801992-n2pq8oqutvrqj58e05hbavvc7n1jdfjb.apps.googleusercontent.com',
iosClientId:
'136771801992-p629tpo9bk3hcm2955s5ahivdla57ln9.apps.googleusercontent.com',
iosBundleId: 'com.example.exampleRouter',
);
}
@@ -15,9 +15,13 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:example_router/bootstrap.dart';
import 'package:example_router/core/flavors/flavor.dart';
import 'package:example_router/presentation/features/app/app.dart';
void main() {
MockSettings.enable();
void main(List<String> args) {
// Define environment
ProductionFlavor();
// Initialize environment and variables
bootstrap(App.new);
}
@@ -15,9 +15,13 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'package:example_router/bootstrap.dart';
import 'package:example_router/core/flavors/flavor.dart';
import 'package:example_router/presentation/features/app/app.dart';
void main() {
MockSettings.disable();
void main(List<String> args) {
// Define environment
DevelopmentFlavor();
// Initialize environment and variables
bootstrap(App.new);
}
@@ -34,6 +34,9 @@ class App extends StatelessWidget {
AuthenticationRepositoryImpl(
authenticationRemoteDataSource:
getIt<AuthenticationRemoteDataSource<int>>(),
authenticationSessionDataSource:
getIt<AuthenticationSessionDataSource<int>>(),
authenticationCacheDataSource: getIt<AuthenticationCacheDataSource<int>>(),
customPasswordValidator: const CustomPassword.pure(),
extraSignUpInputs: [
FormInput(
@@ -45,7 +45,8 @@ class SubPage extends StatelessWidget {
children: [
const Text('Another page'),
ElevatedButton(
onPressed: () => context.read<AuthenticationCubit<int>>().delete(),
onPressed: () =>
context.read<AuthenticationCubit<int>>().delete(),
child: const Text('Delete account'),
),
],