import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:matrix/matrix.dart' as mx; import 'package:pyramid/core/matrix_client.dart'; import 'package:shared_preferences/shared_preferences.dart'; const _prefHomeserver = 'homeserver_url'; final homeserverProvider = StateProvider((ref) => null); Future initHomeserver(WidgetRef ref) async { final prefs = await SharedPreferences.getInstance(); final saved = prefs.getString(_prefHomeserver); ref.read(homeserverProvider.notifier).state = saved; } Future saveHomeserver(WidgetRef ref, String url) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(_prefHomeserver, url); ref.read(homeserverProvider.notifier).state = url; } enum LoginStatus { idle, loading, error } class LoginFormState { final LoginStatus status; final String? errorMessage; const LoginFormState({this.status = LoginStatus.idle, this.errorMessage}); LoginFormState copyWith({LoginStatus? status, String? errorMessage}) => LoginFormState( status: status ?? this.status, errorMessage: errorMessage, ); } class LoginNotifier extends StateNotifier { final Ref _ref; LoginNotifier(this._ref) : super(const LoginFormState()); Future login({ required String username, required String password, required String homeserver, String? deviceName, }) async { state = state.copyWith(status: LoginStatus.loading, errorMessage: null); final client = _ref.read(matrixClientProvider).valueOrNull; if (client == null) { state = state.copyWith( status: LoginStatus.error, errorMessage: 'Client nicht initialisiert', ); return; } if (client.isLogged()) { state = state.copyWith(status: LoginStatus.idle); return; } try { final serverUri = Uri.https( homeserver.replaceAll(RegExp(r'^https?://'), ''), '', ); await client.checkHomeserver(serverUri); await client.login( mx.LoginType.mLoginPassword, identifier: mx.AuthenticationUserIdentifier(user: username), password: password, initialDeviceDisplayName: deviceName ?? 'Pyramid', ); state = state.copyWith(status: LoginStatus.idle); } on mx.MatrixException catch (e) { state = state.copyWith( status: LoginStatus.error, errorMessage: e.errorMessage, ); } catch (e) { state = state.copyWith( status: LoginStatus.error, errorMessage: e.toString(), ); } } } final loginNotifierProvider = StateNotifierProvider((ref) { return LoginNotifier(ref); }); final isLoggedInProvider = StreamProvider((ref) async* { final client = await ref.watch(matrixClientProvider.future); yield client.isLogged(); await for (final loginState in client.onLoginStateChanged.stream) { yield loginState == mx.LoginState.loggedIn; } });