feat: Multi account login working

This commit is contained in:
Christian Pauly 2021-09-18 12:50:02 +02:00
parent 5eb31c7a80
commit a2d37102a4
8 changed files with 41 additions and 38 deletions

View File

@ -47,13 +47,13 @@ class HomeserverPickerController extends State<HomeserverPicker> {
showFutureLoadingDialog( showFutureLoadingDialog(
context: context, context: context,
future: () async { future: () async {
if (Matrix.of(context).client.homeserver == null) { if (Matrix.of(context).getLoginClient().homeserver == null) {
await Matrix.of(context).client.checkHomeserver( await Matrix.of(context).getLoginClient().checkHomeserver(
await Store() await Store()
.getItem(HomeserverPickerController.ssoHomeserverKey), .getItem(HomeserverPickerController.ssoHomeserverKey),
); );
} }
await Matrix.of(context).createLoginClient().login( await Matrix.of(context).getLoginClient().login(
LoginType.mLoginToken, LoginType.mLoginToken,
token: token, token: token,
initialDeviceDisplayName: PlatformInfos.clientName, initialDeviceDisplayName: PlatformInfos.clientName,
@ -117,7 +117,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
isLoading = true; isLoading = true;
}); });
final wellKnown = final wellKnown =
await Matrix.of(context).client.checkHomeserver(homeserver); await Matrix.of(context).getLoginClient().checkHomeserver(homeserver);
var jitsi = wellKnown?.additionalProperties var jitsi = wellKnown?.additionalProperties
?.tryGet<Map<String, dynamic>>('im.vector.riot.jitsi') ?.tryGet<Map<String, dynamic>>('im.vector.riot.jitsi')
@ -177,13 +177,13 @@ class HomeserverPickerController extends State<HomeserverPicker> {
.any((flow) => flow['type'] == AuthenticationTypes.sso); .any((flow) => flow['type'] == AuthenticationTypes.sso);
Future<Map<String, dynamic>> getLoginTypes() async { Future<Map<String, dynamic>> getLoginTypes() async {
_rawLoginTypes ??= await Matrix.of(context).client.request( _rawLoginTypes ??= await Matrix.of(context).getLoginClient().request(
RequestType.GET, RequestType.GET,
'/client/r0/login', '/client/r0/login',
); );
if (registrationSupported == null) { if (registrationSupported == null) {
try { try {
await Matrix.of(context).client.register(); await Matrix.of(context).getLoginClient().register();
registrationSupported = true; registrationSupported = true;
} on MatrixException catch (e) { } on MatrixException catch (e) {
registrationSupported = e.requireAdditionalAuthentication ?? false; registrationSupported = e.requireAdditionalAuthentication ?? false;
@ -200,14 +200,14 @@ class HomeserverPickerController extends State<HomeserverPicker> {
if (kIsWeb) { if (kIsWeb) {
// We store the homserver in the local storage instead of a redirect // We store the homserver in the local storage instead of a redirect
// parameter because of possible CSRF attacks. // parameter because of possible CSRF attacks.
Store().setItem( Store().setItem(ssoHomeserverKey,
ssoHomeserverKey, Matrix.of(context).client.homeserver.toString()); Matrix.of(context).getLoginClient().homeserver.toString());
} }
final redirectUrl = kIsWeb final redirectUrl = kIsWeb
? AppConfig.webBaseUrl + '/#/' ? AppConfig.webBaseUrl + '/#/'
: AppConfig.appOpenUrlScheme.toLowerCase() + '://login'; : AppConfig.appOpenUrlScheme.toLowerCase() + '://login';
final url = final url =
'${Matrix.of(context).client.homeserver?.toString()}/_matrix/client/r0/login/sso/redirect/${Uri.encodeComponent(id)}?redirectUrl=${Uri.encodeQueryComponent(redirectUrl)}'; '${Matrix.of(context).getLoginClient().homeserver?.toString()}/_matrix/client/r0/login/sso/redirect/${Uri.encodeComponent(id)}?redirectUrl=${Uri.encodeQueryComponent(redirectUrl)}';
if (PlatformInfos.isMobile) { if (PlatformInfos.isMobile) {
browser ??= ChromeSafariBrowser(); browser ??= ChromeSafariBrowser();
browser.open(url: Uri.parse(url)); browser.open(url: Uri.parse(url));

View File

@ -64,7 +64,7 @@ class LoginController extends State<Login> {
} else { } else {
identifier = AuthenticationUserIdentifier(user: username); identifier = AuthenticationUserIdentifier(user: username);
} }
await matrix.createLoginClient().login(LoginType.mLoginPassword, await matrix.getLoginClient().login(LoginType.mLoginPassword,
identifier: identifier, identifier: identifier,
// To stay compatible with older server versions // To stay compatible with older server versions
// ignore: deprecated_member_use // ignore: deprecated_member_use
@ -98,12 +98,13 @@ class LoginController extends State<Login> {
setState(() => usernameError = null); setState(() => usernameError = null);
if (!userId.isValidMatrixId) return; if (!userId.isValidMatrixId) return;
try { try {
final oldHomeserver = Matrix.of(context).client.homeserver; final oldHomeserver = Matrix.of(context).getLoginClient().homeserver;
var newDomain = Uri.https(userId.domain, ''); var newDomain = Uri.https(userId.domain, '');
Matrix.of(context).client.homeserver = newDomain; Matrix.of(context).getLoginClient().homeserver = newDomain;
DiscoveryInformation wellKnownInformation; DiscoveryInformation wellKnownInformation;
try { try {
wellKnownInformation = await Matrix.of(context).client.getWellknown(); wellKnownInformation =
await Matrix.of(context).getLoginClient().getWellknown();
if (wellKnownInformation.mHomeserver?.baseUrl?.toString()?.isNotEmpty ?? if (wellKnownInformation.mHomeserver?.baseUrl?.toString()?.isNotEmpty ??
false) { false) {
newDomain = wellKnownInformation.mHomeserver.baseUrl; newDomain = wellKnownInformation.mHomeserver.baseUrl;
@ -120,8 +121,8 @@ class LoginController extends State<Login> {
.checkHomeserver(newDomain) .checkHomeserver(newDomain)
.catchError((e) => null), .catchError((e) => null),
); );
if (Matrix.of(context).client.homeserver == null) { if (Matrix.of(context).getLoginClient().homeserver == null) {
Matrix.of(context).client.homeserver = oldHomeserver; Matrix.of(context).getLoginClient().homeserver = oldHomeserver;
// okay, the server we checked does not appear to be a matrix server // okay, the server we checked does not appear to be a matrix server
Logs().v( Logs().v(
'$newDomain is not running a homeserver, asking to use $oldHomeserver'); '$newDomain is not running a homeserver, asking to use $oldHomeserver');
@ -177,11 +178,12 @@ class LoginController extends State<Login> {
final clientSecret = DateTime.now().millisecondsSinceEpoch.toString(); final clientSecret = DateTime.now().millisecondsSinceEpoch.toString();
final response = await showFutureLoadingDialog( final response = await showFutureLoadingDialog(
context: context, context: context,
future: () => Matrix.of(context).client.requestTokenToResetPasswordEmail( future: () =>
clientSecret, Matrix.of(context).getLoginClient().requestTokenToResetPasswordEmail(
input.single, clientSecret,
sendAttempt++, input.single,
), sendAttempt++,
),
); );
if (response.error != null) return; if (response.error != null) return;
final ok = await showOkAlertDialog( final ok = await showOkAlertDialog(
@ -210,7 +212,7 @@ class LoginController extends State<Login> {
if (password == null) return; if (password == null) return;
final success = await showFutureLoadingDialog( final success = await showFutureLoadingDialog(
context: context, context: context,
future: () => Matrix.of(context).client.changePassword( future: () => Matrix.of(context).getLoginClient().changePassword(
password.single, password.single,
auth: AuthenticationThreePidCreds( auth: AuthenticationThreePidCreds(
type: AuthenticationTypes.emailIdentity, type: AuthenticationTypes.emailIdentity,

View File

@ -37,7 +37,7 @@ class SignupPageController extends State<SignupPage> {
setState(() => loading = true); setState(() => loading = true);
try { try {
final client = Matrix.of(context).createLoginClient(); final client = Matrix.of(context).getLoginClient();
await client.uiaRequestBackground( await client.uiaRequestBackground(
(auth) => client.register( (auth) => client.register(
username: usernameController.text, username: usernameController.text,

View File

@ -100,7 +100,7 @@ class HomeserverPickerView extends StatelessWidget {
imageUrl: Uri.parse( imageUrl: Uri.parse(
identityProvider.icon) identityProvider.icon)
.getDownloadLink( .getDownloadLink(
Matrix.of(context).client) Matrix.of(context).getLoginClient())
.toString(), .toString(),
width: 24, width: 24,
height: 24, height: 24,

View File

@ -19,7 +19,7 @@ class LoginView extends StatelessWidget {
elevation: 0, elevation: 0,
title: Text( title: Text(
L10n.of(context).logInTo(Matrix.of(context) L10n.of(context).logInTo(Matrix.of(context)
.client .getLoginClient()
.homeserver .homeserver
.toString() .toString()
.replaceFirst('https://', '')), .replaceFirst('https://', '')),

View File

@ -38,7 +38,7 @@ class SignupPageView extends StatelessWidget {
labelText: L10n.of(context).username, labelText: L10n.of(context).username,
prefixText: '@', prefixText: '@',
suffixText: suffixText:
':${Matrix.of(context).client.homeserver.host}'), ':${Matrix.of(context).getLoginClient().homeserver.host}'),
), ),
), ),
Divider(), Divider(),

View File

@ -11,7 +11,7 @@ import 'matrix_sdk_extensions.dart/flutter_matrix_hive_database.dart';
abstract class ClientManager { abstract class ClientManager {
static const String clientNamespace = 'im.fluffychat.store.clients'; static const String clientNamespace = 'im.fluffychat.store.clients';
static Future<List<Client>> getClients() async { static Future<List<Client>> getClients() async {
final clientNames = <String>{PlatformInfos.clientName}; final clientNames = <String>{};
try { try {
final rawClientNames = await Store().getItem(clientNamespace); final rawClientNames = await Store().getItem(clientNamespace);
if (rawClientNames != null) { if (rawClientNames != null) {
@ -23,6 +23,7 @@ abstract class ClientManager {
Logs().w('Client names in store are corrupted', e, s); Logs().w('Client names in store are corrupted', e, s);
await Store().deleteItem(clientNamespace); await Store().deleteItem(clientNamespace);
} }
if (clientNames.isEmpty) clientNames.add(PlatformInfos.clientName);
return clientNames.map(createClient).toList(); return clientNames.map(createClient).toList();
} }

View File

@ -78,23 +78,23 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
return _activeClient; return _activeClient;
} }
Client createLoginClient() { Client _loginClientCandidate;
Client getLoginClient() {
final multiAccount = client.isLogged(); final multiAccount = client.isLogged();
final newClient = multiAccount if (!multiAccount) return client;
? ClientManager.createClient(client.generateUniqueTransactionId()) _loginClientCandidate ??= ClientManager.createClient(
: client; client.generateUniqueTransactionId())
if (multiAccount) { ..onLoginStateChanged
// Add to client list .stream
newClient.onLoginStateChanged.stream
.where((l) => l == LoginState.loggedIn) .where((l) => l == LoginState.loggedIn)
.first .first
.then((_) { .then((_) {
widget.clients.add(client); widget.clients.add(_loginClientCandidate);
ClientManager.addClientNameToStore(client.clientName); ClientManager.addClientNameToStore(_loginClientCandidate.clientName);
_registerSubs(client.clientName); _registerSubs(_loginClientCandidate.clientName);
}); });
} return _loginClientCandidate;
return newClient;
} }
Client getClientByName(String name) => widget.clients Client getClientByName(String name) => widget.clients