mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-02-22 17:20:43 +01:00
feat: Implement adding new clients
This commit is contained in:
parent
12217d7cd0
commit
9705bf0c01
@ -1561,6 +1561,8 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"addAccount": "Add account",
|
||||||
|
"enableMultiAccounts": "Enable multi accounts on this device",
|
||||||
"openInMaps": "Open in maps",
|
"openInMaps": "Open in maps",
|
||||||
"@openInMaps": {
|
"@openInMaps": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -217,12 +217,12 @@ class AppRoutes {
|
|||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
stackedRoutes: [
|
stackedRoutes: [
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '/login',
|
path: 'login',
|
||||||
widget: Login(),
|
widget: Login(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '/signup',
|
path: 'signup',
|
||||||
widget: SignupPage(),
|
widget: SignupPage(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
),
|
),
|
||||||
@ -296,6 +296,23 @@ class AppRoutes {
|
|||||||
widget: DevicesSettings(),
|
widget: DevicesSettings(),
|
||||||
buildTransition: _dynamicTransition,
|
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(
|
VWidget(
|
||||||
|
@ -53,7 +53,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||||||
.getItem(HomeserverPickerController.ssoHomeserverKey),
|
.getItem(HomeserverPickerController.ssoHomeserverKey),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await Matrix.of(context).client.login(
|
await Matrix.of(context).createLoginClient().login(
|
||||||
LoginType.mLoginToken,
|
LoginType.mLoginToken,
|
||||||
token: token,
|
token: token,
|
||||||
initialDeviceDisplayName: PlatformInfos.clientName,
|
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;
|
bool _initialized = false;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class LoginController extends State<Login> {
|
|||||||
} else {
|
} else {
|
||||||
identifier = AuthenticationUserIdentifier(user: username);
|
identifier = AuthenticationUserIdentifier(user: username);
|
||||||
}
|
}
|
||||||
await matrix.client.login(LoginType.mLoginPassword,
|
await matrix.createLoginClient().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
|
||||||
|
@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
import 'package:vrouter/vrouter.dart';
|
||||||
|
|
||||||
class SettingsAccount extends StatefulWidget {
|
class SettingsAccount extends StatefulWidget {
|
||||||
const SettingsAccount({Key key}) : super(key: key);
|
const SettingsAccount({Key key}) : super(key: key);
|
||||||
@ -144,6 +145,8 @@ class SettingsAccountController extends State<SettingsAccount> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addAccountAction() => VRouter.of(context).to('add');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final client = Matrix.of(context).client;
|
final client = Matrix.of(context).client;
|
||||||
|
@ -37,7 +37,7 @@ class SignupPageController extends State<SignupPage> {
|
|||||||
setState(() => loading = true);
|
setState(() => loading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final client = Matrix.of(context).client;
|
final client = Matrix.of(context).createLoginClient();
|
||||||
await client.uiaRequestBackground(
|
await client.uiaRequestBackground(
|
||||||
(auth) => client.register(
|
(auth) => client.register(
|
||||||
username: usernameController.text,
|
username: usernameController.text,
|
||||||
|
@ -128,7 +128,7 @@ class HomeserverPickerView extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: _LoginButton(
|
child: _LoginButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
VRouter.of(context).to('/login'),
|
VRouter.of(context).to('login'),
|
||||||
icon: Icon(Icons.login_outlined),
|
icon: Icon(Icons.login_outlined),
|
||||||
labelText: L10n.of(context).login,
|
labelText: L10n.of(context).login,
|
||||||
),
|
),
|
||||||
|
@ -20,6 +20,14 @@ class SettingsAccountView extends StatelessWidget {
|
|||||||
withScrolling: true,
|
withScrolling: true,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
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(
|
ListTile(
|
||||||
trailing: Icon(Icons.edit_outlined),
|
trailing: Icon(Icons.edit_outlined),
|
||||||
title: Text(L10n.of(context).editDisplayname),
|
title: Text(L10n.of(context).editDisplayname),
|
||||||
@ -38,6 +46,7 @@ class SettingsAccountView extends StatelessWidget {
|
|||||||
title: Text(L10n.of(context).devices),
|
title: Text(L10n.of(context).devices),
|
||||||
onTap: () => VRouter.of(context).to('devices'),
|
onTap: () => VRouter.of(context).to('devices'),
|
||||||
),
|
),
|
||||||
|
Divider(height: 1),
|
||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.exit_to_app_outlined),
|
trailing: Icon(Icons.exit_to_app_outlined),
|
||||||
title: Text(L10n.of(context).logout),
|
title: Text(L10n.of(context).logout),
|
||||||
|
@ -11,10 +11,9 @@ 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 store = Store();
|
|
||||||
final clientNames = <String>{PlatformInfos.clientName};
|
final clientNames = <String>{PlatformInfos.clientName};
|
||||||
try {
|
try {
|
||||||
final rawClientNames = await store.getItem(clientNamespace);
|
final rawClientNames = await Store().getItem(clientNamespace);
|
||||||
if (rawClientNames != null) {
|
if (rawClientNames != null) {
|
||||||
final clientNamesList =
|
final clientNamesList =
|
||||||
(jsonDecode(rawClientNames) as List).cast<String>();
|
(jsonDecode(rawClientNames) as List).cast<String>();
|
||||||
@ -22,27 +21,39 @@ abstract class ClientManager {
|
|||||||
}
|
}
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logs().w('Client names in store are corrupted', e, s);
|
Logs().w('Client names in store are corrupted', e, s);
|
||||||
|
await Store().deleteItem(clientNamespace);
|
||||||
}
|
}
|
||||||
return clientNames
|
return clientNames.map(createClient).toList();
|
||||||
.map((clientName) => Client(
|
|
||||||
clientName,
|
|
||||||
enableE2eeRecovery: true,
|
|
||||||
verificationMethods: {
|
|
||||||
KeyVerificationMethod.numbers,
|
|
||||||
if (PlatformInfos.isMobile || PlatformInfos.isLinux)
|
|
||||||
KeyVerificationMethod.emoji,
|
|
||||||
},
|
|
||||||
importantStateEvents: <String>{
|
|
||||||
'im.ponies.room_emotes', // we want emotes to work properly
|
|
||||||
},
|
|
||||||
databaseBuilder: FlutterMatrixHiveStore.hiveDatabaseBuilder,
|
|
||||||
supportedLoginTypes: {
|
|
||||||
AuthenticationTypes.password,
|
|
||||||
if (PlatformInfos.isMobile || PlatformInfos.isWeb)
|
|
||||||
AuthenticationTypes.sso
|
|
||||||
},
|
|
||||||
compute: compute,
|
|
||||||
))
|
|
||||||
.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: {
|
||||||
|
KeyVerificationMethod.numbers,
|
||||||
|
if (PlatformInfos.isMobile || PlatformInfos.isLinux)
|
||||||
|
KeyVerificationMethod.emoji,
|
||||||
|
},
|
||||||
|
importantStateEvents: <String>{
|
||||||
|
'im.ponies.room_emotes', // we want emotes to work properly
|
||||||
|
},
|
||||||
|
databaseBuilder: FlutterMatrixHiveStore.hiveDatabaseBuilder,
|
||||||
|
supportedLoginTypes: {
|
||||||
|
AuthenticationTypes.password,
|
||||||
|
if (PlatformInfos.isMobile || PlatformInfos.isWeb)
|
||||||
|
AuthenticationTypes.sso
|
||||||
|
},
|
||||||
|
compute: compute,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:fluffychat/utils/client_manager.dart';
|
||||||
import 'package:matrix/encryption.dart';
|
import 'package:matrix/encryption.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.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;
|
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;
|
Map<String, dynamic> get shareContent => _shareContent;
|
||||||
set shareContent(Map<String, dynamic> content) {
|
set shareContent(Map<String, dynamic> content) {
|
||||||
_shareContent = content;
|
_shareContent = content;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user