Back

Does account.get throw an exception in flutter?

  • 0
  • Flutter
  • Accounts
ZachHandley
25 Jul, 2023, 22:07

and right now it's throwing, and I have no way of knowing when it's set other than after login but the authRepository handles all of the methods around the user and that ref.watch is supposed to update the data (it's a reactive caching framework so the extra network calls don't matter)

TL;DR
The user is experiencing issues with the `account.get()` method in their Flutter app using Appwrite. They are trying to use the `checkCurrentUser()` method to get the user's account, but it is not triggering any state updates. The user has made some changes to their code, but it is still not working. They are looking for a solution to properly handle authentication and state updates. No solution is provided in the support thread.
Drake
25 Jul, 2023, 22:07

thats why i recommend doing something like this where you have methods for login and/or init that can be called to make an api call and then set the state

Drake
25 Jul, 2023, 22:07

what's the new code? and where are you calling currentUser?

ZachHandley
25 Jul, 2023, 22:09

I'm currently doing this

TypeScript
@Riverpod(keepAlive: true)
Future<User?> authState(AuthStateRef ref) async {
  final User? user =ref.watch(authRepositoryProvider).currentUser;
  return user;
}

@Riverpod(keepAlive: true)
AuthRepository authRepository(AuthRepositoryRef ref) {
  final account = ref.watch(appwriteAccountProvider);
  return AuthRepository(account: account);
}

class AuthRepository {
  AuthRepository({required this.account});
  final Account account;
  User? user;

  User? get currentUser {
    if (user != null) {
      return user;
    } else {
      return null;
    }
  }

  Future<User?> _checkCurrentUser() async {
    try {
      final maybeUser = await account.get();
      user = maybeUser;
    } catch (e) {
      return Future.value(null);
    }
  }

which is obviously disconnected

ZachHandley
25 Jul, 2023, 22:10

I could do on login ref.read(authRepositoryProvider).checkCurrentUser() after login

ZachHandley
25 Jul, 2023, 22:10

but I really don't think it makes sense the way it gets translated to flutter

ZachHandley
25 Jul, 2023, 22:10

because if it was just Future<User?> instead of a User than it would be null until it's not and the provider would work correctly

ZachHandley
25 Jul, 2023, 22:13

It just seems like an implementation where error handling is on the developer even though the thing I'm asking is "is the user logged in?"

Drake
25 Jul, 2023, 22:14

calling checkCurrentUser() won't trigger any state updates

Drake
25 Jul, 2023, 22:15

so what exception is being thrown now?

ZachHandley
25 Jul, 2023, 22:19

It isn't working ATM. Working on it.

ZachHandley
25 Jul, 2023, 22:23

okay so if checkCurrentUser won't trigger any state updates what am I supposed to do?

ZachHandley
25 Jul, 2023, 22:23

that's my issue I'm having here

ZachHandley
25 Jul, 2023, 22:24

if I could call account.get() and it would return User? then I could just watch that value, because I can't do that I have to develop a roundabout way of creating a simple authentication system

Drake
25 Jul, 2023, 22:25

i already told you

Drake
25 Jul, 2023, 22:27

you can try this

ZachHandley
25 Jul, 2023, 22:28

okay. It technically shouldn't be a repository but I'll do that

ZachHandley
25 Jul, 2023, 23:15

I ended up doing this in case it happens again

TypeScript
import 'package:appwrite/models.dart';
import 'package:bealbot_ai/core/core.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'appwrite_auth_state.g.dart';

@Riverpod(keepAlive: true)
class AppwriteAuthState extends _$AppwriteAuthState {
  User? user;

  @override
  Future<User?> build() async {
    return await checkCurrentUser();
  }

  Future<User?> checkCurrentUser() async {
    if (user != null) {
      return user;
    } else {
      try {
        final account = ref.watch(appwriteAccountProvider);
        final maybeUser = await account.get();
        user = maybeUser;
        return user;
      } catch (e) {
        return Future.value(null);
      }
    }
  }
}

still testing to make sure it works

Whirlpool
29 Sep, 2023, 20:00

Please, can you publish the code of the "appwriteAccountProvider" to take the account, thanks

ZachHandley
29 Sep, 2023, 20:14
TypeScript
import 'package:appwrite/models.dart';
import 'package:bealbot_ai/core/core.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'appwrite_auth_state.g.dart';

@Riverpod(keepAlive: true)
class AppwriteAuthState extends _$AppwriteAuthState {
  User? user;

  @override
  Future<User?> build() async {
    return await checkCurrentUser();
  }

  Future<User?> checkCurrentUser() async {
    if (user != null) {
      return user;
    } else {
      try {
        final account = ref.watch(appwriteAccountProvider);
        final maybeUser = await account.get();
        user = maybeUser;
        return user;
      } catch (e) {
        return Future.value(null);
      }
    }
  }
}
TypeScript
import 'package:appwrite/appwrite.dart';
import 'package:appwrite/models.dart';
import 'package:bealbot_ai/core/core.dart';
import 'package:bealbot_ai/features/auth/data/appwrite_auth_state.dart';
import 'package:bealbot_ai/features/auth/domain/app_user.dart';
import 'package:flutter/foundation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

// Want to sign up or get user account -> Account (from appwrite)
// Want to access user related data -> model.User (from models.dart)

part 'auth_repository.g.dart';

@Riverpod(keepAlive: true)
Future<User?> authState(AuthStateRef ref) async {
  return ref.watch(appwriteAuthStateProvider).value;
}

@Riverpod(keepAlive: true)
AuthRepository authRepository(AuthRepositoryRef ref) {
  final account = ref.watch(appwriteAccountProvider);
  return AuthRepository(account: account);
}

class AuthRepository {
  AuthRepository({required this.account});
  final Account account;
  User? user;

  User? get currentUser {
    if (user != null) {
      return user;
    } else {
      return null;
    }
  }

  Future<User?> checkCurrentUser() async {
    try {
      final maybeUser = await account.get();
      user = maybeUser;
    } catch (e) {
      return Future.value(null);
    }
    return null;
  }

  Future<AppUser> signUp({
    required String email,
    required String password,
  }) async {
    try {
      final userId = ID.unique();
      await account.create(
        userId: userId,
        email: email,
        password: password,
      );
      final AppUser appUser = AppUser(
        $id: userId,
        email: email,
        name: getNameFromEmail(email),
        profilePic: '',
      );
      return appUser;
    } on AppwriteException catch (e, st) {
      //TODO: Implement Error Handling
      debugPrint("Appwrite Exception: ${e.message}\n${st.toString()}");
    } catch (e, st) {
      //TODO: Implement Error Handling
      debugPrint("Appwrite Exception: ${e.toString()}\n${st.toString()}");
    }
    throw Exception("Failed to sign up user, we should never reach here");
  }

  Future<void> login({
    required String email,
    required String password,
  }) async {
    try {
      final result = await account.createEmailSession(
        email: email,
        password: password,
      );
      debugPrint(result.toString());
    } on AppwriteException catch (e, st) {
      //TODO: Implement Error Handling
      debugPrint("Appwrite Exception: ${e.message}\n${st.toString()}");
    } catch (e, st) {
      //TODO: Implement Error Handling
      debugPrint("Appwrite Exception: ${e.toString()}\n${st.toString()}");
    }
  }
}

I did this in the end

Whirlpool
29 Sep, 2023, 21:29

One question, when it make "final account = ref.watch(appwriteAccountProvider);" that provieder where is it?

ZachHandley
29 Sep, 2023, 21:35

wherever you need it

ZachHandley
29 Sep, 2023, 21:35

oh

ZachHandley
29 Sep, 2023, 21:35

the appwrite account

ZachHandley
29 Sep, 2023, 21:35

that's in its own providers file but that's just literally doing the basic Appwrite Flutter setup as a provider

Reply

Reply to this thread by joining our Discord

Reply on Discord

Need support?

Join our Discord

Get community support by joining our Discord server.

Join Discord

Get premium support

Join Appwrite Pro and get email support from our team.

Learn more