diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 89f31fd68..803b773e1 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -9,7 +9,6 @@ import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/utils/add_to_space.dart'; import 'package:fluffychat/pangea/utils/chat_list_handle_space_tap.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; @@ -843,18 +842,12 @@ class ChatListController extends State if (firstSelectedRoom.isSpace && !space.isRoomAdmin) { throw L10n.of(context)!.cantAddSpaceChild; } - await pangeaAddToSpace( - space, - selectedRoomIds.toList(), - context, - pangeaController, - ); - // if (space.canSendDefaultStates) { - // for (final roomId in selectedRoomIds) { - // await space.setSpaceChild(roomId); - // } - // } + if (space.canSendDefaultStates) { + for (final roomId in selectedRoomIds) { + await space.pangeaSetSpaceChild(roomId); + } + } // Pangea# }, ); diff --git a/lib/pages/chat_list/chat_list_header.dart b/lib/pages/chat_list/chat_list_header.dart index 20f41ea08..b60a8b5be 100644 --- a/lib/pages/chat_list/chat_list_header.dart +++ b/lib/pages/chat_list/chat_list_header.dart @@ -137,7 +137,11 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { ] : selectMode == SelectMode.select ? [ - if (controller.spaces.isNotEmpty) + // #Pangea + // if (controller.spaces.isNotEmpty) + if (controller.spaces.isNotEmpty && + controller.selectedRoomIds.length == 1) + // Pangea# IconButton( tooltip: L10n.of(context)!.addToSpace, icon: const Icon(Icons.workspaces_outlined), diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index e6c85a617..f3f9749a1 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -856,24 +856,22 @@ class _SpaceViewState extends State { ), // Pangea# ), - // #Pangea - // if (activeSpace?.canChangeStateEvent( - // EventTypes.SpaceChild, - // ) == - // true) - // Material( - // child: ListTile( - // leading: const CircleAvatar( - // child: Icon(Icons.group_add_outlined), - // ), - // title: - // Text(L10n.of(context)!.addChatOrSubSpace), - // trailing: - // const Icon(Icons.chevron_right_outlined), - // onTap: _addChatOrSubSpace, - // ), - // ), - // Pangea# + if (activeSpace?.canChangeStateEvent( + EventTypes.SpaceChild, + ) == + true) + Material( + child: ListTile( + leading: const CircleAvatar( + child: Icon(Icons.group_add_outlined), + ), + title: + Text(L10n.of(context)!.addChatOrSubSpace), + trailing: + const Icon(Icons.chevron_right_outlined), + onTap: _addChatOrSubSpace, + ), + ), ], ); } diff --git a/lib/pages/new_group/new_group.dart b/lib/pages/new_group/new_group.dart index 7e77efe56..9c6e22f85 100644 --- a/lib/pages/new_group/new_group.dart +++ b/lib/pages/new_group/new_group.dart @@ -134,7 +134,7 @@ class NewGroupController extends State { powerLevelContentOverride: await ClassChatPowerLevels.powerLevelOverrideForClassChat( context, - addToSpaceKey.currentState!.parents, + addToSpaceKey.currentState!.parent, ), invite: [ if (addConversationBotKey.currentState?.addBot ?? false) diff --git a/lib/pages/new_space/new_space.dart b/lib/pages/new_space/new_space.dart index 7a7759349..1903a6200 100644 --- a/lib/pages/new_space/new_space.dart +++ b/lib/pages/new_space/new_space.dart @@ -171,7 +171,7 @@ class NewSpaceController extends State { powerLevelContentOverride: addToSpaceKey.currentState != null ? await ClassChatPowerLevels.powerLevelOverrideForClassChat( context, - addToSpaceKey.currentState!.parents, + addToSpaceKey.currentState!.parent, ) : null, // initialState: [ diff --git a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart index 2dc3f6f59..e89740788 100644 --- a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart @@ -138,4 +138,27 @@ extension ChildrenAndParentsRoomExtension on Room { child != null ? child._allSpaceChildRoomIds.contains(id) : false; return canAddChild && !isCycle; } + + /// Wrapper around call to setSpaceChild with added functionality + /// to prevent adding one room to multiple spaces + Future _pangeaSetSpaceChild( + String roomId, { + bool? suggested, + }) async { + final Room? child = client.getRoomById(roomId); + if (child != null) { + final List spaceParents = child.pangeaSpaceParents; + for (final Room parent in spaceParents) { + try { + await parent.removeSpaceChild(roomId); + } catch (e) { + ErrorHandler.logError( + e: e, + m: 'Failed to remove child from parent', + ); + } + } + await setSpaceChild(roomId, suggested: suggested); + } + } } diff --git a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart index 21f5abac5..8632f5e1e 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -116,6 +116,12 @@ extension PangeaRoom on Room { return _canAddAsParentOf(child, spaceMode: spaceMode); } + Future pangeaSetSpaceChild( + String roomId, { + bool? suggested, + }) async => + await _pangeaSetSpaceChild(roomId, suggested: suggested); + // class_and_exchange_settings DateTime? get rulesUpdatedAt => _rulesUpdatedAt; diff --git a/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart index 399382f1c..4199e6f64 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart @@ -116,7 +116,7 @@ extension RoomSettingsRoomExtension on Room { Future _setSuggestedInSpace(bool suggest, Room space) async { try { - await space.setSpaceChild(id, suggested: suggest); + await space.pangeaSetSpaceChild(id, suggested: suggest); } catch (err) { ErrorHandler.logError( e: "Failed to set suggestion status of room $id in space ${space.id}", diff --git a/lib/pangea/utils/add_to_space.dart b/lib/pangea/utils/add_to_space.dart deleted file mode 100644 index f2ed26be1..000000000 --- a/lib/pangea/utils/add_to_space.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; - -bool canAddToSpace(Room space, PangeaController pangeaController) { - final bool pangeaPermission = - pangeaController.permissionsController.canUserGroupChat(roomID: space.id); - final Map powerLevelsMap = - space.getState(EventTypes.RoomPowerLevels)?.content ?? {}; - final pl = powerLevelsMap - .tryGetMap('events') - ?.tryGet(EventTypes.SpaceChild) ?? - powerLevelsMap.tryGet('events_default') ?? - 50; - return space.ownPowerLevel >= pl && pangeaPermission; -} - -bool chatIsInSpace(Room chat, Room space) { - return chat.spaceParents.map((e) => e.roomId).toList().contains(space.id); -} - -Future pangeaAddToSpace( - Room space, - List selectedRoomIds, - BuildContext context, - PangeaController pangeaController, { - bool suggested = true, -}) async { - if (!canAddToSpace(space, pangeaController)) { - throw L10n.of(context)!.noAddToSpacePermissions; - } - for (final roomId in selectedRoomIds) { - final Room? room = Matrix.of(context).client.getRoomById(roomId); - if (room != null && chatIsInSpace(room, space)) { - throw L10n.of(context)!.alreadyInSpace; - } - await space.setSpaceChild(roomId, suggested: suggested); - } -} diff --git a/lib/pangea/utils/class_chat_power_levels.dart b/lib/pangea/utils/class_chat_power_levels.dart index 1fbaff1bf..9c1c25b31 100644 --- a/lib/pangea/utils/class_chat_power_levels.dart +++ b/lib/pangea/utils/class_chat_power_levels.dart @@ -8,7 +8,7 @@ import '../extensions/pangea_room_extension/pangea_room_extension.dart'; class ClassChatPowerLevels { static Future> powerLevelOverrideForClassChat( BuildContext context, - List spaceParents, + Room? parent, ) async { final Client client = Matrix.of(context).client; final Map powerLevelOverride = {}; @@ -18,8 +18,9 @@ class ClassChatPowerLevels { powerLevelOverride['users'] = {}; final List spaceAdmin = []; - for (final classRoom in spaceParents) { - final List classTeachers = await classRoom.teachers; + + if (parent != null) { + final List classTeachers = await parent.teachers; spaceAdmin.addAll(classTeachers); } diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index abbef7746..c7d4fba71 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -32,7 +32,7 @@ class AddToSpaceToggles extends StatefulWidget { class AddToSpaceState extends State { late Room? room; - late List parents; + late Room? parent; late List possibleParents; late bool isOpen; late bool isSuggested; @@ -70,20 +70,17 @@ class AddToSpaceState extends State { ) .toList(); - parents = widget.roomId != null - ? possibleParents - .where( - (r) => - r.spaceChildren.any((room) => room.roomId == widget.roomId), - ) - .toList() - : []; + parent = widget.roomId != null + ? possibleParents.firstWhereOrNull( + (r) => r.spaceChildren.any((room) => room.roomId == widget.roomId), + ) + : null; if (widget.activeSpaceId != null) { final activeSpace = Matrix.of(context).client.getRoomById(widget.activeSpaceId!); if (activeSpace != null && activeSpace.canIAddSpaceChild(null)) { - parents.add(activeSpace); + parent = activeSpace; } else { ErrorHandler.logError( e: Exception('activeSpaceId ${widget.activeSpaceId} not found'), @@ -95,9 +92,9 @@ class AddToSpaceState extends State { //if possibleParent in parents, put first //use sort but use any instead of contains because contains uses == and we want to compare by id possibleParents.sort((a, b) { - if (parents.any((parent) => parent.id == a.id)) { + if (parent?.id == a.id) { return -1; - } else if (parents.any((parent) => parent.id == b.id)) { + } else if (parent?.id == b.id) { return 1; } else { return a.name.compareTo(b.name); @@ -109,18 +106,15 @@ class AddToSpaceState extends State { Future _addSingleSpace(String roomToAddId, Room newParent) async { GoogleAnalytics.addParent(roomToAddId, newParent.classCode); - await newParent.setSpaceChild( + await newParent.pangeaSetSpaceChild( roomToAddId, suggested: isSuggested, ); } Future addSpaces(String roomToAddId) async { - final List> addFutures = []; - for (final Room parent in parents) { - addFutures.add(_addSingleSpace(roomToAddId, parent)); - } - await addFutures.wait; + if (parent == null) return; + await _addSingleSpace(roomToAddId, parent!); } Future handleAdd(bool add, Room possibleParent) async { @@ -142,11 +136,7 @@ class AddToSpaceState extends State { } setState( - () => add - ? parents.add(possibleParent) - : parents.removeWhere( - (parent) => parent.id == possibleParent.id, - ), + () => add ? parent = possibleParent : parent = null, ); } @@ -164,7 +154,7 @@ class AddToSpaceState extends State { SwitchListTile.adaptive( title: possibleParent.nameAndRoomTypeIcon(), activeColor: AppConfig.activeToggleColor, - value: parents.any((r) => r.id == possibleParent.id), + value: parent?.id == possibleParent.id, onChanged: (bool add) => canAdd ? handleAdd(add, possibleParent) : ScaffoldMessenger.of(context).showSnackBar(