Files
pyramid/lib/features/auth/login_notifier.dart
T

104 lines
2.9 KiB
Dart

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<String?>((ref) => null);
Future<void> initHomeserver(WidgetRef ref) async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString(_prefHomeserver);
ref.read(homeserverProvider.notifier).state = saved;
}
Future<void> 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<LoginFormState> {
final Ref _ref;
LoginNotifier(this._ref) : super(const LoginFormState());
Future<void> 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<LoginNotifier, LoginFormState>((ref) {
return LoginNotifier(ref);
});
final isLoggedInProvider = StreamProvider<bool>((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;
}
});