Skip to content

Commit

Permalink
chore: allow using external auth state change listener to avoid dupli…
Browse files Browse the repository at this point in the history
…cate listeners (supabase-community#104)
  • Loading branch information
domhel committed Jul 6, 2024
1 parent 6c74f50 commit 099a0e9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 32 deletions.
12 changes: 6 additions & 6 deletions lib/src/components/supa_email_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ class SupaEmailAuth extends StatefulWidget {
final String? resetPasswordRedirectTo;

/// Callback for the user to complete a sign in.
final void Function(AuthResponse response) onSignInComplete;
final void Function(AuthResponse response)? onSignInComplete;

/// Callback for the user to complete a signUp.
///
/// If email confirmation is turned on, the user is
final void Function(AuthResponse response) onSignUpComplete;
final void Function(AuthResponse response)? onSignUpComplete;

/// Callback for sending the password reset email
final void Function()? onPasswordResetEmailSent;
Expand Down Expand Up @@ -100,8 +100,8 @@ class SupaEmailAuth extends StatefulWidget {
super.key,
this.redirectTo,
this.resetPasswordRedirectTo,
required this.onSignInComplete,
required this.onSignUpComplete,
this.onSignInComplete,
this.onSignUpComplete,
this.onPasswordResetEmailSent,
this.onError,
this.onToggleSignIn,
Expand Down Expand Up @@ -242,7 +242,7 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
widget.onSignInComplete.call(response);
widget.onSignInComplete?.call(response);
} else {
final user = supabase.auth.currentUser;
late final AuthResponse response;
Expand All @@ -265,7 +265,7 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
data: _resolveData(),
);
}
widget.onSignUpComplete.call(response);
widget.onSignUpComplete?.call(response);
}
} on AuthException catch (error) {
if (widget.onError == null && context.mounted) {
Expand Down
36 changes: 23 additions & 13 deletions lib/src/components/supa_magic_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,28 @@ class SupaMagicAuth extends StatefulWidget {
/// Typically used to pass a DeepLink
final String? redirectUrl;

/// Method to be called when the auth action is success
final void Function(Session response) onSuccess;
/// Method to be called when the auth action is successful.
/// Only called when `useExternalAuthChangeListener` is false
final void Function(Session response)? onSuccess;

/// Method to be called when the auth action threw an excepction
final void Function(Object error)? onError;

/// Setting this to true will not instantiate a new onAuthStateChanged
/// subscription. Must not be used together with `onSuccess`
final bool useExternalAuthChangeListener;

/// Localization for the form
final SupaMagicAuthLocalization localization;

const SupaMagicAuth({
super.key,
this.redirectUrl,
required this.onSuccess,
this.onSuccess,
this.onError,
this.useExternalAuthChangeListener = false,
this.localization = const SupaMagicAuthLocalization(),
});
}) : assert(useExternalAuthChangeListener == false || onSuccess == null);

@override
State<SupaMagicAuth> createState() => _SupaMagicAuthState();
Expand All @@ -37,26 +43,30 @@ class SupaMagicAuth extends StatefulWidget {
class _SupaMagicAuthState extends State<SupaMagicAuth> {
final _formKey = GlobalKey<FormState>();
final _email = TextEditingController();
late final StreamSubscription<AuthState> _gotrueSubscription;
late final StreamSubscription<AuthState>? _gotrueSubscription;

bool _isLoading = false;

@override
void initState() {
super.initState();
_gotrueSubscription =
Supabase.instance.client.auth.onAuthStateChange.listen((data) {
final session = data.session;
if (session != null && mounted) {
widget.onSuccess(session);
}
});
if (widget.useExternalAuthChangeListener) {
_gotrueSubscription = null;
} else {
_gotrueSubscription =
Supabase.instance.client.auth.onAuthStateChange.listen((data) {
final session = data.session;
if (session != null && mounted) {
widget.onSuccess?.call(session);
}
});
}
}

@override
void dispose() {
_email.dispose();
_gotrueSubscription.cancel();
_gotrueSubscription?.cancel();
super.dispose();
}

Expand Down
38 changes: 25 additions & 13 deletions lib/src/components/supa_socials_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,17 @@ class SupaSocialsAuth extends StatefulWidget {
/// Typically used to pass a DeepLink
final String? redirectUrl;

/// Method to be called when the auth action is success
final void Function(Session session) onSuccess;
/// Method to be called when the auth action is successful.
/// Only called when `useExternalAuthChangeListener` is false
final void Function(Session response)? onSuccess;

/// Method to be called when the auth action threw an excepction
final void Function(Object error)? onError;

/// Setting this to true will not instantiate a new onAuthStateChanged
/// subscription. Must not be used together with `onSuccess`
final bool useExternalAuthChangeListener;

/// Whether to show a SnackBar after a successful sign in
final bool showSuccessSnackBar;

Expand All @@ -132,21 +137,22 @@ class SupaSocialsAuth extends StatefulWidget {
required this.socialProviders,
this.colored = true,
this.redirectUrl,
required this.onSuccess,
this.onSuccess,
this.onError,
this.useExternalAuthChangeListener = false,
this.socialButtonVariant = SocialButtonVariant.iconAndText,
this.showSuccessSnackBar = true,
this.scopes,
this.queryParams,
this.localization = const SupaSocialsAuthLocalization(),
});
}) : assert(useExternalAuthChangeListener == false || onSuccess == null);

@override
State<SupaSocialsAuth> createState() => _SupaSocialsAuthState();
}

class _SupaSocialsAuthState extends State<SupaSocialsAuth> {
late final StreamSubscription<AuthState> _gotrueSubscription;
late final StreamSubscription<AuthState>? _gotrueSubscription;
late final SupaSocialsAuthLocalization localization;

/// Performs Google sign in on Android and iOS
Expand Down Expand Up @@ -210,22 +216,28 @@ class _SupaSocialsAuthState extends State<SupaSocialsAuth> {
void initState() {
super.initState();
localization = widget.localization;
_gotrueSubscription =
Supabase.instance.client.auth.onAuthStateChange.listen((data) {
final session = data.session;
if (session != null && mounted) {
widget.onSuccess.call(session);
if (widget.useExternalAuthChangeListener) {
_gotrueSubscription = null;
} else {
_gotrueSubscription =
Supabase.instance.client.auth.onAuthStateChange.listen((data) {
final session = data.session;
final onSuccess = widget.onSuccess;
if (session != null && mounted && onSuccess != null) {
onSuccess(session);
widget.onSuccess?.call(session);
if (widget.showSuccessSnackBar) {
context.showSnackBar(localization.successSignInMessage);
}
}
});
}
});
}
}

@override
void dispose() {
super.dispose();
_gotrueSubscription.cancel();
_gotrueSubscription?.cancel();
}

@override
Expand Down

0 comments on commit 099a0e9

Please sign in to comment.