import 'package:flutter/material.dart'; import 'package:mobile/models/user.dart'; import 'package:mobile/results.dart'; import 'package:mobile/server/server.dart'; class UserController extends ChangeNotifier { final Server server; String? _sessionToken; User? _user; Future> userLoad = Future.error(Null); UserController({required this.server}); /// Make sure a user exists before calling using `.loadUser()`. User get user { final user = _user; if (user == null) { throw NoUserExcept(); } return user; } Future> loadUser() async { if (_sessionToken == null) { return const Err(null); } final userResult = await server.sessionUser(_sessionToken!); switch (userResult) { case Success(data: final user): _user = user; return const Ok(null); case Error(): return const Err(null); } } Future> loadedUser() async { throw Exception(); } Future> login(String email, String password) async { switch (await server.login(email, password)) { case Success(data: final token): _sessionToken = token; notifyListeners(); return const Ok(null); case Error(message: final message): notifyListeners(); return Err(message); } } Future _validateToken() async { final token = _sessionToken; if (token == null) { return; } final res = await server.sessionUser(token); switch (res) { case Success(): return; case Error(): _sessionToken = null; return; } } @Deprecated("Use 'user' instead.") User? get userOld { loadUserOld(); return _user; } Future _notifyIfTokenChanged() async { final prev = _sessionToken; _validateToken(); if (prev != _sessionToken) { notifyListeners(); } } @Deprecated("Use 'loadUser' instead.") Future loadUserOld() async { final token = _sessionToken; if (token == null) { _user = null; return; } final res = await server.sessionUser(token); switch (res) { case Success(data: final user): _user = user; return; case Error(): _user = null; return; } } String? get sessionToken { _notifyIfTokenChanged(); return _sessionToken; } Future logout() async { final token = _sessionToken; if (token != null) { await server.logout(token); _sessionToken = null; } notifyListeners(); } Future> addBalance() async { final token = _sessionToken; if (token == null) { return const Err("No token"); } final res = await server.addBalance(token); notifyListeners(); switch (res) { case Success(): return const Ok(null); case Error(message: final message): return Err(message); } } } class NoUserExcept implements Exception {}