Skip to content

Commit f87b53e

Browse files
committed
merging
2 parents 9c96ad4 + 3b928c7 commit f87b53e

8 files changed

+793
-317
lines changed

CHANGELOG.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,35 @@
1-
## [0.0.43] - Document update only
1+
## [0.0.48] - Document update only
22

33
- Add documentation on location.
44

5+
## [0.0.47] - Chat functions
6+
7+
- Document update on chat functions.
8+
9+
## [0.0.46] - Big break on user data events
10+
11+
This is going to be a big break.
12+
13+
- `userDataChange` and `userPublicDataChange` had been diverged from the previous version of `userChange`.
14+
- And `userChange` is now used as an alias of `FirebaseAuth.instance.userChanges()` which will be fired on all user change events.
15+
- Resets userPublicData property when user logs in or register.
16+
17+
## [0.0.45] - Revert fetch timeout
18+
19+
- Revert code related with `fetched` adn `fetchTimeout`. So, when it can't fetch posts, it would stuck there foerver.
20+
21+
## [0.0.44] - Fetch timeout
22+
23+
- `getPublicData()` has been deprecatd. Use `getUserPublicData()`.
24+
- `fetched` becomes true if the app had fetched the first batch of posts from Firestore. Mostly the UI shows a spinner(loader) that the fetching is in progress. And if there is no document to fetch, it would ever become true that causes the UI show spinner and wait forever. So, it will turn into true after the [fetchTimeout] when there is no documents to fetch. This does not mean any documents are actually fetched.
25+
26+
## [0.0.43] - Variable name changes and minor changes.
27+
28+
- `email` and `password` of `loginOrRegister` are now optional.
29+
- `userPublicData` has been renamed to `getUserPublicData`.
30+
- `publicData` has been renamed to `userPublicData`.
31+
- When user logs out, `userPublicData` become an empty Map.
32+
533
## [0.0.42] - Storage related code update
634

735
- Storage security rules are updated and user's uid is attached to the file metadata.

README.md

+258-95
Large diffs are not rendered by default.

lib/base.dart

+83-32
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,17 @@ class Base {
44
/// Check if Firebase has initialized.
55
bool isFirebaseInitialized = false;
66

7-
/// Fires after Firebase has initialized or if already initialized.
8-
/// The true event will be fired only once when Firebase initialized.
7+
/// Firebase intialized event
8+
///
9+
/// This event is fires after Firebase has initialized(created instance) or if
10+
/// it has already initialized.
11+
///
12+
/// When this event is fired, `initUser()` is already called which means,
13+
/// `authStateChanages` and `userChanges` are ready to be consumed.
14+
///
15+
/// The arguemnt will be true only after when Firebase initialized.
16+
///
17+
// ignore: close_sinks
918
BehaviorSubject<bool> firebaseInitialized = BehaviorSubject.seeded(false);
1019

1120
/// Returns Firestore instance. Firebase database instance.
@@ -50,17 +59,28 @@ class Base {
5059

5160
bool enableNotification;
5261

53-
/// [authStateChange] is a link to `FirebaseAuth.instance.authStateChanges()`
62+
/// [authStateChange] is fired whenever user logs in or out.
5463
///
55-
/// Use this to know if the user has logged in or not.
64+
/// Use this to know if the user has logged in or not. Since this is
65+
/// `BehaviorSubject` that delivers Firebase `User` object, it can be used
66+
/// outside of `ff.firebaseInitialized.listen()`
5667
///
5768
/// You can do the following with [authStateChanges]
58-
/// ```
69+
/// ```dart
5970
/// StreamBuilder(
6071
/// stream: ff.authStateChanges,
6172
/// builder: (context, snapshot) { ... });
6273
/// ```
63-
Stream<User> authStateChanges;
74+
///
75+
/// ```dart
76+
/// ff.authStateChanges.listen((user) { ... }
77+
/// ```
78+
BehaviorSubject<User> authStateChanges = BehaviorSubject.seeded(null);
79+
80+
/// [userChanges] is a simple alias of `FirebaseAuth.instance.userChanges()`
81+
///
82+
/// It will be fired when user changes `dispolayName` or `photoURL`.
83+
Stream<User> userChanges;
6484

6585
/// Firebase User instance
6686
///
@@ -87,22 +107,32 @@ class Base {
87107
/// User document data.
88108
Map<String, dynamic> userData = {};
89109

90-
/// User public document data.
91-
Map<String, dynamic> publicData = {};
110+
@Deprecated('Use userPublicData')
92111

93-
bool get loggedIn => user != null;
94-
bool get notLoggedIn => !loggedIn;
112+
/// User public document data.
113+
Map<String, dynamic> get publicData => userPublicData;
114+
Map<String, dynamic> userPublicData = {};
115+
116+
// /// [userChange] event fires when
117+
// /// - user document(without subcollection) like when user updates his profile
118+
// /// - user log in,
119+
// /// - user log out,
120+
// /// - user verify his phone nubmer
121+
// /// - user profile photo changes
122+
// ///
123+
// /// It is important to know that [authStateChanges] event happens only when
124+
// /// user logs in or logs out.
125+
// BehaviorSubject<UserChangeData> userChange = BehaviorSubject.seeded(null);
126+
127+
/// [userDataChange] is fired when `/users/{uid}` changes.
128+
// ignore: close_sinks
129+
BehaviorSubject<Map<String, dynamic>> userDataChange =
130+
BehaviorSubject.seeded(null);
95131

96-
/// [userChange] event fires when
97-
/// - user document(without subcollection) like when user updates his profile
98-
/// - user log in,
99-
/// - user log out,
100-
/// - user verify his phone nubmer
101-
/// - user profile photo changes
102-
///
103-
/// It is important to know that [authStateChanges] event happens only when
104-
/// user logs in or logs out.
105-
BehaviorSubject<UserChangeData> userChange = BehaviorSubject.seeded(null);
132+
/// [userPublicDataChange] is fired when `/meta/user/public/{uid}` changes.
133+
// ignore: close_sinks
134+
BehaviorSubject<Map<String, dynamic>> userPublicDataChange =
135+
BehaviorSubject.seeded(null);
106136

107137
/// [notification] will be fired whenever there is a push notification.
108138
/// the return data will the following and can be use when user receive notifications.
@@ -146,13 +176,36 @@ class Base {
146176
/// For chat and other functionalities that do user search need this option.
147177
bool openProfile = false;
148178

179+
/// Helper functions
180+
///
181+
/// [loggedIn] returns true if the user has logged in.
182+
bool get loggedIn => user != null;
183+
184+
/// [notLoggedIn] returns true if the user is not logged in.
185+
bool get notLoggedIn => !loggedIn;
186+
187+
/// [uid] returns login user's uid.
188+
String get uid => user == null ? null : user.uid;
189+
190+
/// [displayName] returns displayName or null if the user has not logged in.
191+
///
192+
/// ```dart
193+
/// Text(ff.displayName ?? '')
194+
/// ```
195+
String get displayName => user == null ? null : user.displayName;
196+
197+
/// [photoURL] returns login user's phogo URL.
198+
String get photoURL => user == null ? null : user.photoURL;
199+
149200
initUser() {
150-
authStateChanges = FirebaseAuth.instance.authStateChanges();
201+
userChanges = FirebaseAuth.instance.userChanges();
151202

152203
/// Note: listen handler will called twice if Firestore is working as offline mode.
153-
authStateChanges.listen((User user) {
204+
FirebaseAuth.instance.authStateChanges().listen((User user) {
205+
authStateChanges.add(user);
206+
154207
/// [userChange] event fires when user is logs in or logs out.
155-
userChange.add(UserChangeData(UserChangeType.auth, user: user));
208+
// userChange.add(UserChangeData(UserChangeType.auth, user: user));
156209

157210
/// Cancel listening user document.
158211
///
@@ -172,8 +225,7 @@ class Base {
172225
(DocumentSnapshot snapshot) {
173226
if (snapshot.exists) {
174227
userData = snapshot.data();
175-
userChange
176-
.add(UserChangeData(UserChangeType.document, user: user));
228+
userDataChange.add(userData);
177229
}
178230
},
179231
);
@@ -182,8 +234,8 @@ class Base {
182234
userPublicDocSubscription = publicDoc.snapshots().listen(
183235
(DocumentSnapshot snapshot) {
184236
if (snapshot.exists) {
185-
publicData = snapshot.data();
186-
userChange.add(UserChangeData(UserChangeType.public, user: user));
237+
userPublicData = snapshot.data();
238+
userPublicDataChange.add(userPublicData);
187239
}
188240
},
189241
);
@@ -195,17 +247,16 @@ class Base {
195247

196248
/// Initialize Firebase
197249
///
198-
/// Firebase is initialized asynchronously. It does not block the app by async/await.
250+
/// Firebase is initialized asynchronously. Meaning, it does not block the app
251+
/// while it's intializaing.
252+
///
253+
/// Invoked by `ff.init()`.
199254
initFirebase() {
200255
// WidgetsFlutterBinding.ensureInitialized();
201256
return Firebase.initializeApp().then((firebaseApp) {
202-
isFirebaseInitialized = true;
203-
firebaseInitialized.add(isFirebaseInitialized);
204257
FirebaseFirestore.instance.settings =
205258
Settings(cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED);
206259

207-
usersCol = FirebaseFirestore.instance.collection('users');
208-
postsCol = FirebaseFirestore.instance.collection('posts');
209260
return firebaseApp;
210261
});
211262
}

lib/definitions.dart

+13-35
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ enum RenderType {
1616
fileUpload,
1717
fileDelete,
1818
fetching,
19-
finishFetching
19+
finishFetching,
2020
}
2121

2222
enum ForumStatus {
@@ -64,14 +64,14 @@ const ERROR_SIGNIN_ABORTED = 'ERROR_SIGNIN_ABORTED';
6464
/// [UserChangeType.document] is for `/users/{uid}` change.
6565
/// [UserChangeType.auth] is for login, or logout. Be reminded that login even will be fired twice. This is the nature of firebase.
6666
/// [UserChangeType.profile] is for changing `photoURL` or `displayName`.
67-
enum UserChangeType { auth, document, public, register, profile }
67+
// enum UserChangeType { auth, document, public, register, profile }
6868

6969
/// Event data on [userChange] event
70-
class UserChangeData {
71-
UserChangeData(this.type, {this.user});
72-
UserChangeType type;
73-
User user;
74-
}
70+
// class UserChangeData {
71+
// UserChangeData(this.type, {this.user});
72+
// UserChangeType type;
73+
// User user;
74+
// }
7575

7676
enum NotificationType { onMessage, onLaunch, onResume }
7777

@@ -114,10 +114,13 @@ class ForumData {
114114
/// [uid] could be the login user's uid or other user's uid.
115115
String uid;
116116

117-
/// [fetched] becomes true if the app has fetched from Firestore.
117+
/// [fetched] becomes true if the app had fetched the first batch of posts
118+
/// from Firestore. Mostly the UI shows a spinner(loader) that the fetching
119+
/// is in progress. And if there is no document to fetch, it would never
120+
/// become true that causes the UI show spinner and wait forever.
118121
///
119-
/// There might no no there even after it has fetched. So, [fetched] will be true
120-
/// while [posts] is still empty array.
122+
/// There might no posts there even after it has fetched. So, [fetched] might
123+
/// be true while [posts] is still empty array.
121124
///
122125
bool fetched = false;
123126

@@ -141,28 +144,3 @@ class ForumData {
141144
}
142145
}
143146
}
144-
145-
// class VoteChoice {
146-
// static String like = 'like';
147-
// static String dislike = 'dislike';
148-
// }
149-
150-
// /// Algolia search data to index
151-
// class SearchData {
152-
// /// [path] is the path of document
153-
// final String path;
154-
// final String title;
155-
// final String content;
156-
157-
// /// [stamp] is unix timestmap
158-
// final String stamp;
159-
// SearchData({@required this.path, this.title, this.content, this.stamp});
160-
// Map<String, dynamic> toMap() {
161-
// return {
162-
// 'path': path,
163-
// if (title != null) 'title': title,
164-
// if (content != null) 'content': content,
165-
// if (stamp != null) 'stamp': stamp,
166-
// };
167-
// }
168-
// }

0 commit comments

Comments
 (0)