feat: Implement adding new clients

This commit is contained in:
Christian Pauly 2021-09-18 12:12:34 +02:00
parent 12217d7cd0
commit 9705bf0c01
10 changed files with 93 additions and 30 deletions

View File

@ -1561,6 +1561,8 @@
"type": "text",
"placeholders": {}
},
"addAccount": "Add account",
"enableMultiAccounts": "Enable multi accounts on this device",
"openInMaps": "Open in maps",
"@openInMaps": {
"type": "text",

View File

@ -217,12 +217,12 @@ class AppRoutes {
buildTransition: _fadeTransition,
stackedRoutes: [
VWidget(
path: '/login',
path: 'login',
widget: Login(),
buildTransition: _fadeTransition,
),
VWidget(
path: '/signup',
path: 'signup',
widget: SignupPage(),
buildTransition: _fadeTransition,
),
@ -296,6 +296,23 @@ class AppRoutes {
widget: DevicesSettings(),
buildTransition: _dynamicTransition,
),
VWidget(
path: 'add',
widget: HomeserverPicker(),
buildTransition: _fadeTransition,
stackedRoutes: [
VWidget(
path: 'login',
widget: Login(),
buildTransition: _fadeTransition,
),
VWidget(
path: 'signup',
widget: SignupPage(),
buildTransition: _fadeTransition,
),
],
),
],
),
VWidget(

View File

@ -53,7 +53,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
.getItem(HomeserverPickerController.ssoHomeserverKey),
);
}
await Matrix.of(context).client.login(
await Matrix.of(context).createLoginClient().login(
LoginType.mLoginToken,
token: token,
initialDeviceDisplayName: PlatformInfos.clientName,
@ -216,7 +216,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
}
}
void signUpAction() => VRouter.of(context).to('/signup');
void signUpAction() => VRouter.of(context).to('signup');
bool _initialized = false;

View File

@ -64,7 +64,7 @@ class LoginController extends State<Login> {
} else {
identifier = AuthenticationUserIdentifier(user: username);
}
await matrix.client.login(LoginType.mLoginPassword,
await matrix.createLoginClient().login(LoginType.mLoginPassword,
identifier: identifier,
// To stay compatible with older server versions
// ignore: deprecated_member_use

View File

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
import 'package:vrouter/vrouter.dart';
class SettingsAccount extends StatefulWidget {
const SettingsAccount({Key key}) : super(key: key);
@ -144,6 +145,8 @@ class SettingsAccountController extends State<SettingsAccount> {
);
}
void addAccountAction() => VRouter.of(context).to('add');
@override
Widget build(BuildContext context) {
final client = Matrix.of(context).client;

View File

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

View File

@ -128,7 +128,7 @@ class HomeserverPickerView extends StatelessWidget {
Expanded(
child: _LoginButton(
onPressed: () =>
VRouter.of(context).to('/login'),
VRouter.of(context).to('login'),
icon: Icon(Icons.login_outlined),
labelText: L10n.of(context).login,
),

View File

@ -20,6 +20,14 @@ class SettingsAccountView extends StatelessWidget {
withScrolling: true,
child: Column(
children: [
if (!Matrix.of(context).isMultiAccount)
ListTile(
trailing: Icon(Icons.add_box_outlined),
title: Text(L10n.of(context).addAccount),
subtitle: Text(L10n.of(context).enableMultiAccounts),
onTap: controller.addAccountAction,
),
Divider(height: 1),
ListTile(
trailing: Icon(Icons.edit_outlined),
title: Text(L10n.of(context).editDisplayname),
@ -38,6 +46,7 @@ class SettingsAccountView extends StatelessWidget {
title: Text(L10n.of(context).devices),
onTap: () => VRouter.of(context).to('devices'),
),
Divider(height: 1),
ListTile(
trailing: Icon(Icons.exit_to_app_outlined),
title: Text(L10n.of(context).logout),

View File

@ -11,10 +11,9 @@ import 'matrix_sdk_extensions.dart/flutter_matrix_hive_database.dart';
abstract class ClientManager {
static const String clientNamespace = 'im.fluffychat.store.clients';
static Future<List<Client>> getClients() async {
final store = Store();
final clientNames = <String>{PlatformInfos.clientName};
try {
final rawClientNames = await store.getItem(clientNamespace);
final rawClientNames = await Store().getItem(clientNamespace);
if (rawClientNames != null) {
final clientNamesList =
(jsonDecode(rawClientNames) as List).cast<String>();
@ -22,9 +21,23 @@ abstract class ClientManager {
}
} catch (e, s) {
Logs().w('Client names in store are corrupted', e, s);
await Store().deleteItem(clientNamespace);
}
return clientNames
.map((clientName) => Client(
return clientNames.map(createClient).toList();
}
static Future<void> addClientNameToStore(String clientName) async {
final clientNamesList = <String>[];
final rawClientNames = await Store().getItem(clientNamespace);
if (rawClientNames != null) {
final stored = (jsonDecode(rawClientNames) as List).cast<String>();
clientNamesList.addAll(stored);
}
clientNamesList.add(clientName);
await Store().setItem(clientNamespace, jsonEncode(clientNamesList));
}
static Client createClient(String clientName) => Client(
clientName,
enableE2eeRecovery: true,
verificationMethods: {
@ -42,7 +55,5 @@ abstract class ClientManager {
AuthenticationTypes.sso
},
compute: compute,
))
.toList();
}
);
}

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'dart:convert';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/utils/client_manager.dart';
import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart';
@ -77,6 +78,26 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
return _activeClient;
}
Client createLoginClient() {
final multiAccount = Matrix.of(context).client.isLogged();
final client = multiAccount
? ClientManager.createClient(
Matrix.of(context).client.generateUniqueTransactionId())
: Matrix.of(context).client;
if (multiAccount) {
// Add to client list
client.onLoginStateChanged.stream
.where((l) => l == LoginState.loggedIn)
.first
.then((_) {
widget.clients.add(client);
ClientManager.addClientNameToStore(client.clientName);
// TODO: Connect streamsubscriptions
});
}
return client;
}
Map<String, dynamic> get shareContent => _shareContent;
set shareContent(Map<String, dynamic> content) {
_shareContent = content;