Skip to content

Commit

Permalink
Ghost sign in (#122)
Browse files Browse the repository at this point in the history
* Update firebase_remote_config

* Initialize firebase configuration

* Perform a ghost sign in if the app is in review

* Update base URL

* Fix formatting
  • Loading branch information
MillerAdulu authored Aug 30, 2024
1 parent 9bafe3d commit 23a217d
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ app.*.map.json
.fvmrc
.vscode/settings.json
devtools_options.yaml
lib/versioning/build_version.dart
6 changes: 6 additions & 0 deletions build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
targets:
$default:
builders:
build_version:
options:
output: lib/versioning/build_version.dart
18 changes: 17 additions & 1 deletion lib/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluttercon/common/repository/db_repository.dart';
import 'package:fluttercon/common/repository/firebase_repository.dart';
import 'package:fluttercon/common/repository/hive_repository.dart';
import 'package:fluttercon/common/utils/notification_service.dart';
import 'package:fluttercon/core/di/injectable.dart';
import 'package:fluttercon/features/about/cubit/fetch_individual_organisers_cubit.dart';
import 'package:fluttercon/features/auth/cubit/ghost_sign_in_cubit.dart';
import 'package:fluttercon/features/auth/cubit/google_sign_in_cubit.dart';
import 'package:fluttercon/features/auth/cubit/log_out_cubit.dart';
import 'package:fluttercon/features/auth/cubit/social_auth_sign_in_cubit.dart';
Expand Down Expand Up @@ -48,10 +50,16 @@ Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
);

await configureDependencies();

await getIt<HiveRepository>().initBoxes();

localDB = await getIt<DBRepository>().init();

await getIt<NotificationService>().requestPermission();
await getIt<NotificationService>().initNotifications();

await getIt<FirebaseRepository>().init();

runApp(
MultiBlocProvider(
// Register all the BLoCs here
Expand Down Expand Up @@ -128,7 +136,15 @@ Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
),
),
BlocProvider<SendFeedbackCubit>(
create: (context) => SendFeedbackCubit(apiRepository: getIt()),
create: (context) => SendFeedbackCubit(
apiRepository: getIt(),
),
),
BlocProvider<GhostSignInCubit>(
create: (context) => GhostSignInCubit(
authRepository: getIt(),
hiveRepository: getIt(),
),
),
],
child: await builder(),
Expand Down
15 changes: 15 additions & 0 deletions lib/common/data/models/remote_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'remote_config.freezed.dart';
part 'remote_config.g.dart';

@freezed
class RemoteConfig with _$RemoteConfig {
factory RemoteConfig({
@JsonKey(name: 'app_version') required String appVersion,
@JsonKey(name: 'is_in_review') required bool isInReview,
}) = _RemoteConfig;

factory RemoteConfig.fromJson(Map<String, dynamic> json) =>
_$RemoteConfigFromJson(json);
}
17 changes: 17 additions & 0 deletions lib/common/repository/auth_repository.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:firebase_auth/firebase_auth.dart';
import 'package:fluttercon/common/data/models/models.dart';
import 'package:fluttercon/common/utils/env/flavor_config.dart';
import 'package:fluttercon/common/utils/network.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:injectable/injectable.dart';
Expand All @@ -18,6 +19,22 @@ class AuthRepository {
],
);

Future<AuthResult> ghostSignIn() async {
try {
final response = await _networkUtil.postReq(
'${FlutterConConfig.instance!.values.baseUrl}/api/v1/login',
body: {
'email': '[email protected]',
'password': 'password',
},
);

return AuthResult.fromJson(response);
} catch (e) {
rethrow;
}
}

Future<String> signInWithGoogle() async {
try {
final googleSignInAccount = await _googleSignIn.signIn();
Expand Down
24 changes: 24 additions & 0 deletions lib/common/repository/firebase_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'dart:convert';

import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:fluttercon/common/data/models/remote_config.dart';
import 'package:injectable/injectable.dart';

@singleton
class FirebaseRepository {
final remoteConfig = FirebaseRemoteConfig.instance;

Future<void> init() async {
await remoteConfig.fetchAndActivate();
}

RemoteConfig getConfig() {
final config = remoteConfig.getValue('dev_flutterconke_fluttercon');

return RemoteConfig.fromJson(
json.decode(
config.asString(),
) as Map<String, dynamic>,
);
}
}
5 changes: 5 additions & 0 deletions lib/common/utils/misc.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:math';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttercon/versioning/build_version.dart' as package_version;
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';
Expand Down Expand Up @@ -46,4 +47,8 @@ class Misc {

return (isLightMode, colorScheme);
}

static String getAppVersion() {
return package_version.packageVersion;
}
}
34 changes: 34 additions & 0 deletions lib/features/auth/cubit/ghost_sign_in_cubit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:bloc/bloc.dart';
import 'package:fluttercon/common/repository/auth_repository.dart';
import 'package:fluttercon/common/repository/hive_repository.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'ghost_sign_in_state.dart';
part 'ghost_sign_in_cubit.freezed.dart';

class GhostSignInCubit extends Cubit<GhostSignInState> {
GhostSignInCubit({
required AuthRepository authRepository,
required HiveRepository hiveRepository,
}) : super(const GhostSignInState.initial()) {
_authRepository = authRepository;
_hiveRepository = hiveRepository;
}

late AuthRepository _authRepository;
late HiveRepository _hiveRepository;

Future<void> signIn() async {
emit(const GhostSignInState.loading());
try {
final authResult = await _authRepository.ghostSignIn();
_hiveRepository
..persistToken(authResult.token)
..persistUser(authResult.user);

emit(const GhostSignInState.loaded());
} catch (e) {
emit(GhostSignInState.error(e.toString()));
}
}
}
9 changes: 9 additions & 0 deletions lib/features/auth/cubit/ghost_sign_in_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
part of 'ghost_sign_in_cubit.dart';

@freezed
class GhostSignInState with _$GhostSignInState {
const factory GhostSignInState.initial() = _Initial;
const factory GhostSignInState.loading() = _Loading;
const factory GhostSignInState.loaded() = _Loaded;
const factory GhostSignInState.error(String message) = _Error;
}
37 changes: 36 additions & 1 deletion lib/features/auth/ui/sign_in.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import 'package:auth_buttons/auth_buttons.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluttercon/common/repository/firebase_repository.dart';
import 'package:fluttercon/common/utils/constants/app_assets.dart';
import 'package:fluttercon/common/utils/misc.dart';
import 'package:fluttercon/common/utils/router.dart';
import 'package:fluttercon/core/di/injectable.dart';
import 'package:fluttercon/features/auth/cubit/ghost_sign_in_cubit.dart';
import 'package:fluttercon/features/auth/cubit/google_sign_in_cubit.dart';
import 'package:fluttercon/features/auth/cubit/social_auth_sign_in_cubit.dart';
import 'package:go_router/go_router.dart';
Expand Down Expand Up @@ -53,7 +56,39 @@ class SignInScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Spacer(),
const Image(image: AssetImage(AppAssets.flutterConKeLogo)),
GestureDetector(
onLongPress: () {
final config = getIt<FirebaseRepository>().getConfig();
if (config.isInReview &&
config.appVersion == Misc.getAppVersion()) {
context.read<GhostSignInCubit>().signIn();
}
},
child: BlocConsumer<GhostSignInCubit, GhostSignInState>(
listener: (context, state) {
state.maybeWhen(
orElse: () {},
loaded: () => GoRouter.of(context)
.goNamed(FlutterConRouter.decisionRoute),
error: (message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: AutoSizeText(message)),
);
},
);
},
builder: (context, state) {
return state.maybeWhen(
loading: () => const Center(
child: CircularProgressIndicator(),
),
orElse: () => const Image(
image: AssetImage(AppAssets.flutterConKeLogo),
),
);
},
),
),
const SizedBox(height: 64),
BlocBuilder<GoogleSignInCubit, GoogleSignInState>(
builder: (context, state) {
Expand Down
32 changes: 32 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.3.2"
build_version:
dependency: "direct main"
description:
name: build_version
sha256: "4e8eafbf722eac3bd60c8d38f108c04bd69b80100f8792b32be3407725c7fa6a"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
built_collection:
dependency: transitive
description:
Expand Down Expand Up @@ -425,6 +433,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.6.41"
firebase_remote_config:
dependency: "direct main"
description:
name: firebase_remote_config
sha256: b5c23fb7f5b8fd2338f512587a8d2714b5b81dc02508a1c16163c51c1aa41991
url: "https://pub.dev"
source: hosted
version: "5.1.0"
firebase_remote_config_platform_interface:
dependency: transitive
description:
name: firebase_remote_config_platform_interface
sha256: "127ebc8b7c905d211396cab3b0984e4436c6350400805d196607043b8984d09c"
url: "https://pub.dev"
source: hosted
version: "1.4.41"
firebase_remote_config_web:
dependency: transitive
description:
name: firebase_remote_config_web
sha256: "29dbff195c6225f957af541d325426f1697710ac36d169431c95bc92d985f4d2"
url: "https://pub.dev"
source: hosted
version: "1.6.13"
fixnum:
dependency: transitive
description:
Expand Down
4 changes: 3 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: fluttercon
description: "A new Flutter project."
publish_to: 'none'
version: 1.15.02+11502
version: 1.16.00+11600

environment:
sdk: ">=3.5.0 <4.0.0"
Expand All @@ -12,6 +12,7 @@ dependencies:
auto_size_text: ^3.0.0
awesome_notifications: ^0.9.3+1
bloc: ^8.1.4
build_version: ^2.1.1
cached_network_image: ^3.4.0
collection: ^1.18.0
cupertino_icons: ^1.0.8
Expand All @@ -20,6 +21,7 @@ dependencies:
firebase_auth: ^5.2.0
firebase_core: ^3.4.0
firebase_crashlytics: ^4.1.0
firebase_remote_config: ^5.1.0
flutter:
sdk: flutter
flutter_bloc: ^8.1.5
Expand Down

0 comments on commit 23a217d

Please sign in to comment.