Reputation: 23
A custom defined User class that is available throughout my Flutter app and updates according to new data in Firebase.
Obtain uid: Using FirebaseAuth I can successfully authenticate a user and obtain a uid (user id). I then check to see if that uid is in my Firebase database.
Fetch or write to Firebase:
Instantiate my custom User class
Use Provider to provide my Custom User class throughout my app
side note: I don't think this is super relevant but I am using jsonserializable for my classes in my models.dart file
import 'package:dev_odyssey/routes.dart';
import 'package:dev_odyssey/shared/shared.dart';
import 'package:dev_odyssey/theme.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import "package:flutter/material.dart";
import 'package:dev_odyssey/services/services.dart';
import 'package:provider/provider.dart';
void main() async {
runApp(const App());
}
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
final Future<FirebaseApp> _initialization = Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FutureBuilder(
future: _initialization,
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(child: Text("Good heavens an error occured!"));
} else if (snapshot.connectionState == ConnectionState.done) {
//Multiproviders are not being called?...why?
return MultiProvider(
providers: [
ChangeNotifierProvider<DevOdysseyUserProvider>(
create: (_) => DevOdysseyUserProvider()),
FutureProvider(
create: (context) async {
await Provider.of<DevOdysseyUserProvider>(context,
listen: false)
.fetchDoUserFromFirestore(AuthService().user!.uid);
},
initialData: null)
],
child: MaterialApp(
routes: appRoutes,
theme: appTheme,
),
);
} else {
return const LoadingScreen();
}
},
),
);
}
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:dev_odyssey/services/services.dart';
import 'package:flutter/material.dart';
class DevOdysseyUserProvider extends ChangeNotifier {
DevOdysseyUser? _doUser; // Your DevOdysseyUser instance
DevOdysseyUser? get doUser => _doUser;
void setUser(DevOdysseyUser doUser) {
_doUser = doUser;
notifyListeners();
}
Future<void> fetchDoUserFromFirestore(String userId) async {
final CollectionReference devOdysseyUsersCollection =
FirebaseFirestore.instance.collection('devOdysseyUser');
// Check if the user exists in the Firestore database
final DocumentSnapshot userSnapshot =
await devOdysseyUsersCollection.doc(userId).get();
if (userSnapshot.exists) {
print("Found user in firestore");
// User already exists, retrieve the user data
final doUserData = userSnapshot.data() as Map<String, dynamic>;
final doUser = DevOdysseyUser.fromJson(doUserData);
//how do we set this new user to provider
setUser(doUser); //setting current user to doUser
final uid = doUser.uid;
final email = doUser.email;
print('doUser: $uid');
print('doUser: $email');
} else {
print("Did not find user in firestore");
// User does not exist, create a new user document in Firestore
final DevOdysseyUser newDoUser = DevOdysseyUser(
uid: AuthService().user!.uid,
email: AuthService().user!.email,
displayName: AuthService().user?.displayName ?? '',
photoURL: AuthService().user?.photoURL ?? '',
);
await DevOdysseyUserService().addUser(newDoUser);
setUser(newDoUser);
final uid = newDoUser.uid;
final email = newDoUser.email;
print('newDoUser: $uid');
print('newDoUser: $email');
}
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class AuthService {
final userStream = FirebaseAuth.instance.authStateChanges();
final user = FirebaseAuth.instance.currentUser;
Future<void> anonLogin() async {
try {
await FirebaseAuth.instance.signInAnonymously();
} on FirebaseAuthException catch (e) {
String errorMessage = 'Failed to sign in anonymously.';
if (e.code == 'ERROR_NETWORK_REQUEST_FAILED') {
errorMessage = 'No internet connection. Please check your connection.';
}
// Log error message
// ignore: avoid_print
print('Error signing in anonymously: $errorMessage');
}
}
Future<void> signOut() async {
await FirebaseAuth.instance.signOut();
}
Future<void> googleLogin() async {
try {
final googleUser = await GoogleSignIn().signIn();
if (googleUser == null) return;
final googleAuth = await googleUser.authentication;
final authCrendential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(authCrendential);
} on FirebaseAuthException catch (e) {
// ignore: avoid_print
print(e.message);
}
}
}
import 'package:json_annotation/json_annotation.dart';
part 'models.g.dart';
@JsonSerializable()
class DevOdysseyUser {
//from firebase auth user
final String uid;
final String? email;
final String? displayName;
final String? photoURL;
//custom properties
List<DevOdysseyUser> friends;
String bio;
int age;
List<Odyssey> odysseys;
DevOdysseyUser({
required this.uid,
this.email,
this.displayName = '',
this.photoURL = '',
this.friends = const [],
this.bio = '',
this.age = 0,
this.odysseys = const [],
});
factory DevOdysseyUser.fromJson(Map<String, dynamic> json) =>
_$DevOdysseyUserFromJson(json);
Map<String, dynamic> toJson() => _$DevOdysseyUserToJson(this);
}
Upvotes: 0
Views: 92