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

feat(recipient_app): Updated login registration flow #491

Merged
merged 8 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file added recipients_app/assets/earth_animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion recipients_app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ SPEC CHECKSUMS:
FirebaseCoreExtension: f17247ba8c61e4d3c8d136b5e2de3cb4ac6a85b6
FirebaseCoreInternal: 8845798510aae74703467480f71ac613788d0696
FirebaseCrashlytics: 35fdd1a433b31e28adcf5c8933f4c526691a1e0b
FirebaseFirestore: 712ff268d746fc65efb361e9ce2cfeb458f10643
FirebaseFirestore: 7b7d95b74637ed61b76996077a2b292167dae7e5
FirebaseInstallations: 59c0e4c7a816a0f76710d83f77e5369b3e45eb96
FirebaseSessions: 34e5c084da010ef3802cbc062b822e513c9e6318
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
Expand Down
4 changes: 3 additions & 1 deletion recipients_app/lib/core/cubits/signup/signup_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ class SignupCubit extends Cubit<SignupState> {
try {
await userRepository.verifyPhoneNumber(
phoneNumber: phoneNumber,
onCodeSend: (verificationId) {
forceResendingToken: state.forceResendingToken,
onCodeSend: (verificationId, forceResendingToken) {
emit(
state.copyWith(
status: SignupStatus.enterVerificationCode,
phoneNumber: phoneNumber,
forceResendingToken: forceResendingToken,
verificationId: verificationId,
),
);
Expand Down
6 changes: 5 additions & 1 deletion recipients_app/lib/core/cubits/signup/signup_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,32 @@ class SignupState extends Equatable {
final SignupStatus status;
final String? phoneNumber;
final String? verificationId;
final int? forceResendingToken;
final Exception? exception;

const SignupState({
this.status = SignupStatus.enterPhoneNumber,
this.phoneNumber,
this.verificationId,
this.forceResendingToken,
this.exception,
});

@override
List<Object?> get props => [status, phoneNumber, verificationId, exception];
List<Object?> get props => [status, phoneNumber, verificationId, forceResendingToken, exception];

SignupState copyWith({
SignupStatus? status,
String? phoneNumber,
String? verificationId,
int? forceResendingToken,
Exception? exception,
}) {
return SignupState(
status: status ?? this.status,
phoneNumber: phoneNumber ?? this.phoneNumber,
verificationId: verificationId ?? this.verificationId,
forceResendingToken: forceResendingToken ?? this.forceResendingToken,
exception: exception ?? this.exception,
);
}
Expand Down
8 changes: 5 additions & 3 deletions recipients_app/lib/data/repositories/user_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,20 @@ class UserRepository {

Future<void> verifyPhoneNumber({
required String phoneNumber,
required Function(String) onCodeSend,
required Function(String, int?) onCodeSend,
required Function(FirebaseAuthException) onVerificationFailed,
required Function(PhoneAuthCredential) onVerificationCompleted,
required int? forceResendingToken,
}) async {
await firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumber,
forceResendingToken: forceResendingToken,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to make sure that the same phone can be provided twice even if auto retrieval timeout hasn't passed yet.

timeout: const Duration(seconds: 60),
verificationCompleted: (credential) =>
onVerificationCompleted(credential),
verificationFailed: (ex) => onVerificationFailed(ex),
codeSent: (verificationId, [forceResendingToken]) =>
onCodeSend(verificationId),
codeSent: (verificationId, forceResendingToken) =>
onCodeSend(verificationId, forceResendingToken),
codeAutoRetrievalTimeout: (e) {
log("auto-retrieval timeout");
},
Expand Down
7 changes: 6 additions & 1 deletion recipients_app/lib/my_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "package:app/core/cubits/auth/auth_cubit.dart";
import "package:app/data/repositories/repositories.dart";
import "package:app/ui/configs/configs.dart";
import "package:app/view/pages/main_app_page.dart";
import "package:app/view/pages/terms_and_conditions_page.dart";
import "package:app/view/pages/welcome_page.dart";
import "package:cloud_firestore/cloud_firestore.dart";
import "package:firebase_auth/firebase_auth.dart";
Expand Down Expand Up @@ -73,7 +74,11 @@ class MyApp extends StatelessWidget {
case AuthStatus.updateRecipientFailure:
case AuthStatus.updateRecipientSuccess:
case AuthStatus.updatingRecipient:
return const MainAppPage();
if (state.recipient?.termsAccepted == true) {
return const MainAppPage();
} else {
return const TermsAndConditionsPage();
}
}
},
),
Expand Down
7 changes: 7 additions & 0 deletions recipients_app/lib/ui/inputs/input_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class InputText extends StatelessWidget {
final bool isReadOnly;
final Widget? suffixIcon;
final TextInputType? keyboardType;
final int? maxLength;

const InputText({
super.key,
Expand All @@ -25,6 +26,7 @@ class InputText extends StatelessWidget {
this.isReadOnly = false,
this.suffixIcon,
this.keyboardType = TextInputType.text,
this.maxLength,
});

@override
Expand All @@ -37,6 +39,10 @@ class InputText extends StatelessWidget {
// labelText: hintText,
suffixIcon: suffixIcon,
floatingLabelBehavior: FloatingLabelBehavior.never,
// when maxLength is added TextFormField shows counter e.g. 0/1,
// we don't need it and one of the solutions is to provide SizedBox.shrink()
// see https://stackoverflow.com/a/58819500
counter: const SizedBox.shrink()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this good for and why is it empty?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the characters limit is added Flutter is adding the counter on the bottom of the text input automatically. Which is not what we want AFAIK. One of the solutions (which also make it not adding extra space to the bottom of input fields is like above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add this as a comment, otherwise we will stumble over this again :D?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure 👍

),
style: AppStyles.inputText,
readOnly: isReadOnly,
Expand All @@ -47,6 +53,7 @@ class InputText extends StatelessWidget {
focusNode: focusNode,
validator: validator,
keyboardType: keyboardType,
maxLength: maxLength,
),
if (hintText != null)
Positioned(
Expand Down
2 changes: 2 additions & 0 deletions recipients_app/lib/view/pages/account_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class AccountPageState extends State<AccountPage> {
"Failed to update profile. Please try again or contact our support"),
),
);
} else if (state.status == AuthStatus.unauthenticated) {
Navigator.of(context).pop();
}
},
builder: (context, state) {
Expand Down
113 changes: 0 additions & 113 deletions recipients_app/lib/view/pages/terms_and_conditions.dart

This file was deleted.

108 changes: 108 additions & 0 deletions recipients_app/lib/view/pages/terms_and_conditions_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import "package:app/core/cubits/auth/auth_cubit.dart";
import "package:app/ui/buttons/buttons.dart";
import "package:app/ui/configs/configs.dart";
import "package:flutter/gestures.dart";
import "package:flutter/material.dart";
import "package:flutter/services.dart";
import "package:flutter_bloc/flutter_bloc.dart";
import "package:url_launcher/url_launcher_string.dart";

class TermsAndConditionsPage extends StatelessWidget {
const TermsAndConditionsPage({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
title: const Text("Account"),
centerTitle: true,
),
body: Padding(
padding: AppSpacings.a16,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RichText(
textAlign: TextAlign.center,
text: TextSpan(
children: [
TextSpan(
text: "By creating an account, you agree with our ",
style: Theme.of(context)
.textTheme
.headlineLarge!
.copyWith(
color: AppColors.primaryColor,
fontWeight: FontWeight.bold,
)),
TextSpan(
text: "privacy policy.",
style: Theme.of(context)
.textTheme
.headlineLarge!
.copyWith(
color: AppColors.primaryColor,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () async {
const url = "https://socialincome.org/privacy";
if (await canLaunchUrlString(url)) {
await launchUrlString(url);
} else {
Clipboard.setData(
const ClipboardData(
text: "https://socialincome.org/privacy",
),
).then((_) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
"Can't open privacy policy right now. Copied website address to the clipboard."),
),
);
});
}
},
),
],
),
),
const SizedBox(
height: 200,
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ButtonBig(
onPressed: () {
final updated =
context.read<AuthCubit>().state.recipient?.copyWith(
termsAccepted: true,
);

if (updated != null) {
context.read<AuthCubit>().updateRecipient(updated);
}
},
label: "Create account",
),
],
),
const SizedBox(height: 32),
],
),
),
);
}
}
Loading
Loading