import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:matrix/matrix.dart'; import 'package:pyramid/core/matrix_client.dart'; enum LoginStatus { idle, loading, error } class LoginState { final LoginStatus status; final String? errorMessage; const LoginState({this.status = LoginStatus.idle, this.errorMessage}); LoginState copyWith({LoginStatus? status, String? errorMessage}) => LoginState( status: status ?? this.status, errorMessage: errorMessage, ); } class LoginNotifier extends StateNotifier { final Ref _ref; LoginNotifier(this._ref) : super(const LoginState()); Future login({ required String userId, required String password, String? deviceName, }) async { state = state.copyWith(status: LoginStatus.loading, errorMessage: null); final clientAsync = _ref.read(matrixClientProvider); final client = clientAsync.valueOrNull; if (client == null) { state = state.copyWith( status: LoginStatus.error, errorMessage: 'Client nicht initialisiert', ); return; } try { // Auto-discover homeserver from MXID if (userId.isValidMatrixId) { final domain = Uri.https(userId.domain!, ''); try { await client.checkHomeserver(domain); } catch (_) { client.homeserver = domain; } } await client.login( LoginType.mLoginPassword, identifier: AuthenticationUserIdentifier(user: userId), password: password, initialDeviceDisplayName: deviceName ?? 'Pyramid', ); state = state.copyWith(status: LoginStatus.idle); } on 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 = Provider((ref) { final client = ref.watch(matrixClientProvider).valueOrNull; return client?.isLogged() ?? false; });