Repository navigation
Expand file tree
/
Copy pathauth_session.dart
More file actions
98 lines (77 loc) · 2.7 KB
/
Copy pathauth_session.dart
File metadata and controls
98 lines (77 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import 'dart:async';
import 'package:pureflow/pureflow.dart';
Future<void> main() async {
final session = AuthSession();
void printUser() =>
print('user: ${session.user.value?.email ?? 'signed out'}');
void printLoading() => print('loading: ${session.isLoading.value}');
void printAuthenticated() =>
print('authenticated: ${session.isAuthenticated.value}');
session.user.addListener(printUser);
session.isLoading.addListener(printLoading);
session.isAuthenticated.addListener(printAuthenticated);
print('initial authenticated: ${session.isAuthenticated.value}');
final firstLogin = session.login('alex@example.com');
final duplicateLogin = session.login('alex@example.com');
await Future.wait(<Future<void>>[firstLogin, duplicateLogin]);
print('active user: ${session.user.value?.email ?? 'none'}');
await session.logout();
print('active user after logout: ${session.user.value?.email ?? 'none'}');
session.user.removeListener(printUser);
session.isLoading.removeListener(printLoading);
session.isAuthenticated.removeListener(printAuthenticated);
await session.dispose();
}
class AuthSession {
final Store<User?> _user = Store<User?>(null);
final Store<bool> _isLoading = Store<bool>(false);
final Pipeline _pipeline = Pipeline(transformer: restartable());
late final Computed<bool> _isAuthenticated = Computed<bool>(
() => _user.value != null,
);
ValueObservable<User?> get user => _user;
ValueObservable<bool> get isLoading => _isLoading;
ValueObservable<bool> get isAuthenticated => _isAuthenticated;
Future<void> login(String email) {
return _pipeline.run<void>((context) async {
_isLoading.value = true;
print('logging in $email');
await Future<void>.delayed(const Duration(milliseconds: 80));
if (!context.isActive) {
print('stale login ignored for $email');
_isLoading.value = false;
return;
}
batch(() {
_user.value = User(email: email);
_isLoading.value = false;
});
}, debugLabel: 'login:$email');
}
Future<void> logout() {
return _pipeline.run<void>((context) async {
_isLoading.value = true;
print('logging out');
await Future<void>.delayed(const Duration(milliseconds: 40));
if (!context.isActive) {
print('stale logout ignored');
_isLoading.value = false;
return;
}
batch(() {
_user.value = null;
_isLoading.value = false;
});
}, debugLabel: 'logout');
}
Future<void> dispose() async {
await _pipeline.dispose();
_isAuthenticated.dispose();
_isLoading.dispose();
_user.dispose();
}
}
class User {
final String email;
const User({required this.email});
}