mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-04-23 10:27:56 +02:00
feat: Add account bundles
This commit is contained in:
parent
0e914be5b6
commit
31815a2fc2
@ -19,6 +19,7 @@ import 'package:uni_links/uni_links.dart';
|
||||
import 'package:vrouter/vrouter.dart';
|
||||
import '../main.dart';
|
||||
import '../widgets/matrix.dart';
|
||||
import '../../utils/account_bundles.dart';
|
||||
import '../utils/matrix_sdk_extensions.dart/matrix_file_extension.dart';
|
||||
import '../utils/url_launcher.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
@ -416,6 +417,61 @@ class ChatListController extends State<ChatList> {
|
||||
i - (Matrix.of(context).hasComplexBundles ? 1 : 0);
|
||||
});
|
||||
|
||||
void setActiveBundle(String bundle) => setState(() {
|
||||
_activeSpaceId = null;
|
||||
selectedRoomIds.clear();
|
||||
Matrix.of(context).activeBundle = bundle;
|
||||
});
|
||||
|
||||
void editBundlesForAccount(String userId) async {
|
||||
final client = Matrix.of(context)
|
||||
.widget
|
||||
.clients[Matrix.of(context).getClientIndexByMatrixId(userId)];
|
||||
final action = await showConfirmationDialog<EditBundleAction>(
|
||||
context: context,
|
||||
title: 'Edit bundles for this account',
|
||||
actions: [
|
||||
AlertDialogAction(
|
||||
key: EditBundleAction.addToBundle,
|
||||
label: 'Add to bundle',
|
||||
),
|
||||
if (Matrix.of(context).activeBundle != null)
|
||||
AlertDialogAction(
|
||||
key: EditBundleAction.removeFromBundle,
|
||||
label: 'Remove from this bundle',
|
||||
),
|
||||
],
|
||||
);
|
||||
if (action == null) return;
|
||||
switch (action) {
|
||||
case EditBundleAction.addToBundle:
|
||||
final bundle = await showTextInputDialog(
|
||||
context: context,
|
||||
title: 'Bundle name',
|
||||
textFields: [DialogTextField(hintText: 'Bundle name')]);
|
||||
if (bundle.isEmpty && bundle.single.isEmpty) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => client.setAccountBundle(bundle.single),
|
||||
);
|
||||
break;
|
||||
case EditBundleAction.removeFromBundle:
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () =>
|
||||
client.removeFromAccountBundle(Matrix.of(context).activeBundle),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void resetActiveBundle() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
setState(() {
|
||||
Matrix.of(context).activeBundle = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Matrix.of(context).navigatorContext = context;
|
||||
@ -431,3 +487,5 @@ class ChatListController extends State<ChatList> {
|
||||
return ChatListView(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum EditBundleAction { addToBundle, removeFromBundle }
|
||||
|
@ -1,6 +1,8 @@
|
||||
import 'dart:math';
|
||||
import 'package:async/async.dart';
|
||||
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:fluffychat/pages/chat_list.dart';
|
||||
import 'package:fluffychat/widgets/connection_status_header.dart';
|
||||
@ -23,18 +25,30 @@ class ChatListView extends StatelessWidget {
|
||||
List<BottomNavigationBarItem> getBottomBarItems(BuildContext context) {
|
||||
final displayClients = Matrix.of(context).hasComplexBundles
|
||||
? Matrix.of(context).accountBundles[Matrix.of(context).activeBundle ??
|
||||
Matrix.of(context).client.accountBundles.first.name]
|
||||
Matrix.of(context).client.accountBundles.first.name] ??
|
||||
[]
|
||||
: Matrix.of(context).widget.clients;
|
||||
if (displayClients.isEmpty) {
|
||||
displayClients.addAll(Matrix.of(context).widget.clients);
|
||||
controller.resetActiveBundle();
|
||||
}
|
||||
final items = displayClients.map((client) {
|
||||
return BottomNavigationBarItem(
|
||||
label: client.userID,
|
||||
icon: FutureBuilder<Profile>(
|
||||
future: client.ownProfile,
|
||||
builder: (context, snapshot) {
|
||||
return Avatar(
|
||||
snapshot.data?.avatarUrl,
|
||||
snapshot.data?.displayName ?? client.userID.localpart,
|
||||
size: 32,
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
onTap: () => controller.setActiveClient(
|
||||
Matrix.of(context).getClientIndexByMatrixId(client.userID)),
|
||||
onLongPress: () =>
|
||||
controller.editBundlesForAccount(client.userID),
|
||||
child: Avatar(
|
||||
snapshot.data?.avatarUrl,
|
||||
snapshot.data?.displayName ?? client.userID.localpart,
|
||||
size: 32,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
@ -50,11 +64,13 @@ class ChatListView extends StatelessWidget {
|
||||
Icons.menu,
|
||||
color: Theme.of(context).textTheme.bodyText1.color,
|
||||
),
|
||||
onSelected: controller.setActiveBundle,
|
||||
itemBuilder: (context) => Matrix.of(context)
|
||||
.accountBundles
|
||||
.keys
|
||||
.map(
|
||||
(bundle) => PopupMenuItem(
|
||||
value: bundle,
|
||||
child: Text(bundle),
|
||||
),
|
||||
)
|
||||
@ -264,22 +280,31 @@ class ChatListView extends StatelessWidget {
|
||||
)
|
||||
: null,
|
||||
bottomNavigationBar: Matrix.of(context).isMultiAccount
|
||||
? SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: SizedBox(
|
||||
width: max(
|
||||
MediaQuery.of(context).size.width,
|
||||
Matrix.of(context).widget.clients.length * 84.0,
|
||||
),
|
||||
child: BottomNavigationBar(
|
||||
onTap: controller.setActiveClient,
|
||||
currentIndex: Matrix.of(context).activeClient +
|
||||
(Matrix.of(context).hasComplexBundles ? 1 : 0),
|
||||
showUnselectedLabels: false,
|
||||
showSelectedLabels: true,
|
||||
type: BottomNavigationBarType.shifting,
|
||||
selectedItemColor: Theme.of(context).primaryColor,
|
||||
items: getBottomBarItems(context),
|
||||
? StreamBuilder(
|
||||
stream: StreamGroup.merge(Matrix.of(context)
|
||||
.widget
|
||||
.clients
|
||||
.map((client) => client.onSync.stream.where((s) =>
|
||||
s.accountData != null &&
|
||||
s.accountData
|
||||
.any((e) => e.type == accountBundlesType)))),
|
||||
builder: (context, _) => SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: SizedBox(
|
||||
width: max(
|
||||
MediaQuery.of(context).size.width,
|
||||
Matrix.of(context).widget.clients.length * 84.0,
|
||||
),
|
||||
child: BottomNavigationBar(
|
||||
onTap: controller.setActiveClient,
|
||||
currentIndex: Matrix.of(context).activeClient +
|
||||
(Matrix.of(context).hasComplexBundles ? 1 : 0),
|
||||
showUnselectedLabels: false,
|
||||
showSelectedLabels: true,
|
||||
type: BottomNavigationBarType.shifting,
|
||||
selectedItemColor: Theme.of(context).primaryColor,
|
||||
items: getBottomBarItems(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -43,13 +43,13 @@ class AccountBundle {
|
||||
};
|
||||
}
|
||||
|
||||
const _accountBundlesType = 'im.fluffychat.account_bundles';
|
||||
const accountBundlesType = 'im.fluffychat.account_bundles';
|
||||
|
||||
extension AccountBundlesExtension on Client {
|
||||
List<AccountBundle> get accountBundles {
|
||||
List<AccountBundle> ret;
|
||||
if (accountData.containsKey(_accountBundlesType)) {
|
||||
ret = AccountBundles.fromJson(accountData[_accountBundlesType].content)
|
||||
if (accountData.containsKey(accountBundlesType)) {
|
||||
ret = AccountBundles.fromJson(accountData[accountBundlesType].content)
|
||||
.bundles;
|
||||
}
|
||||
ret ??= [];
|
||||
@ -63,9 +63,10 @@ extension AccountBundlesExtension on Client {
|
||||
}
|
||||
|
||||
Future<void> setAccountBundle(String name, [int priority]) async {
|
||||
final data = AccountBundles.fromJson(
|
||||
accountData[_accountBundlesType]?.content ?? {});
|
||||
final data =
|
||||
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
|
||||
var foundBundle = false;
|
||||
data.bundles ??= [];
|
||||
for (final bundle in data.bundles) {
|
||||
if (bundle.name == name) {
|
||||
bundle.priority = priority;
|
||||
@ -76,22 +77,23 @@ extension AccountBundlesExtension on Client {
|
||||
if (!foundBundle) {
|
||||
data.bundles.add(AccountBundle(name: name, priority: priority));
|
||||
}
|
||||
await setAccountData(userID, _accountBundlesType, data.toJson());
|
||||
await setAccountData(userID, accountBundlesType, data.toJson());
|
||||
}
|
||||
|
||||
Future<void> removeFromAccountBundle(String name) async {
|
||||
if (!accountData.containsKey(_accountBundlesType)) {
|
||||
if (!accountData.containsKey(accountBundlesType)) {
|
||||
return; // nothing to do
|
||||
}
|
||||
final data =
|
||||
AccountBundles.fromJson(accountData[_accountBundlesType].content);
|
||||
AccountBundles.fromJson(accountData[accountBundlesType].content);
|
||||
if (data.bundles == null) return;
|
||||
data.bundles.removeWhere((b) => b.name == name);
|
||||
await setAccountData(userID, _accountBundlesType, data.toJson());
|
||||
await setAccountData(userID, accountBundlesType, data.toJson());
|
||||
}
|
||||
|
||||
String get sendPrefix {
|
||||
final data = AccountBundles.fromJson(
|
||||
accountData[_accountBundlesType]?.content ?? {});
|
||||
final data =
|
||||
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
|
||||
return data.prefix;
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,9 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
||||
|
||||
bool get isMultiAccount => widget.clients.length > 1;
|
||||
|
||||
int getClientIndexByMatrixId(String matrixId) =>
|
||||
widget.clients.indexWhere((client) => client.userID == matrixId);
|
||||
|
||||
int get _safeActiveClient {
|
||||
if (activeClient < 0 || activeClient >= widget.clients.length) {
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user