prevent adding a room to multiple spaces
This commit is contained in:
parent
71b804e23d
commit
9fa9078ea4
11 changed files with 76 additions and 102 deletions
|
|
@ -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<ChatList>
|
|||
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#
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -856,24 +856,22 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
),
|
||||
// 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,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ class NewGroupController extends State<NewGroup> {
|
|||
powerLevelContentOverride:
|
||||
await ClassChatPowerLevels.powerLevelOverrideForClassChat(
|
||||
context,
|
||||
addToSpaceKey.currentState!.parents,
|
||||
addToSpaceKey.currentState!.parent,
|
||||
),
|
||||
invite: [
|
||||
if (addConversationBotKey.currentState?.addBot ?? false)
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ class NewSpaceController extends State<NewSpace> {
|
|||
powerLevelContentOverride: addToSpaceKey.currentState != null
|
||||
? await ClassChatPowerLevels.powerLevelOverrideForClassChat(
|
||||
context,
|
||||
addToSpaceKey.currentState!.parents,
|
||||
addToSpaceKey.currentState!.parent,
|
||||
)
|
||||
: null,
|
||||
// initialState: [
|
||||
|
|
|
|||
|
|
@ -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<void> _pangeaSetSpaceChild(
|
||||
String roomId, {
|
||||
bool? suggested,
|
||||
}) async {
|
||||
final Room? child = client.getRoomById(roomId);
|
||||
if (child != null) {
|
||||
final List<Room> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,12 @@ extension PangeaRoom on Room {
|
|||
return _canAddAsParentOf(child, spaceMode: spaceMode);
|
||||
}
|
||||
|
||||
Future<void> pangeaSetSpaceChild(
|
||||
String roomId, {
|
||||
bool? suggested,
|
||||
}) async =>
|
||||
await _pangeaSetSpaceChild(roomId, suggested: suggested);
|
||||
|
||||
// class_and_exchange_settings
|
||||
|
||||
DateTime? get rulesUpdatedAt => _rulesUpdatedAt;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ extension RoomSettingsRoomExtension on Room {
|
|||
|
||||
Future<void> _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}",
|
||||
|
|
|
|||
|
|
@ -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<String, dynamic> powerLevelsMap =
|
||||
space.getState(EventTypes.RoomPowerLevels)?.content ?? {};
|
||||
final pl = powerLevelsMap
|
||||
.tryGetMap<String, dynamic>('events')
|
||||
?.tryGet<int>(EventTypes.SpaceChild) ??
|
||||
powerLevelsMap.tryGet<int>('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<void> pangeaAddToSpace(
|
||||
Room space,
|
||||
List<String> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import '../extensions/pangea_room_extension/pangea_room_extension.dart';
|
|||
class ClassChatPowerLevels {
|
||||
static Future<Map<String, dynamic>> powerLevelOverrideForClassChat(
|
||||
BuildContext context,
|
||||
List<Room> spaceParents,
|
||||
Room? parent,
|
||||
) async {
|
||||
final Client client = Matrix.of(context).client;
|
||||
final Map<String, dynamic> powerLevelOverride = {};
|
||||
|
|
@ -18,8 +18,9 @@ class ClassChatPowerLevels {
|
|||
powerLevelOverride['users'] = {};
|
||||
|
||||
final List<User> spaceAdmin = [];
|
||||
for (final classRoom in spaceParents) {
|
||||
final List<User> classTeachers = await classRoom.teachers;
|
||||
|
||||
if (parent != null) {
|
||||
final List<User> classTeachers = await parent.teachers;
|
||||
spaceAdmin.addAll(classTeachers);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class AddToSpaceToggles extends StatefulWidget {
|
|||
|
||||
class AddToSpaceState extends State<AddToSpaceToggles> {
|
||||
late Room? room;
|
||||
late List<Room> parents;
|
||||
late Room? parent;
|
||||
late List<Room> possibleParents;
|
||||
late bool isOpen;
|
||||
late bool isSuggested;
|
||||
|
|
@ -70,20 +70,17 @@ class AddToSpaceState extends State<AddToSpaceToggles> {
|
|||
)
|
||||
.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<AddToSpaceToggles> {
|
|||
//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<AddToSpaceToggles> {
|
|||
|
||||
Future<void> _addSingleSpace(String roomToAddId, Room newParent) async {
|
||||
GoogleAnalytics.addParent(roomToAddId, newParent.classCode);
|
||||
await newParent.setSpaceChild(
|
||||
await newParent.pangeaSetSpaceChild(
|
||||
roomToAddId,
|
||||
suggested: isSuggested,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addSpaces(String roomToAddId) async {
|
||||
final List<Future<void>> addFutures = [];
|
||||
for (final Room parent in parents) {
|
||||
addFutures.add(_addSingleSpace(roomToAddId, parent));
|
||||
}
|
||||
await addFutures.wait;
|
||||
if (parent == null) return;
|
||||
await _addSingleSpace(roomToAddId, parent!);
|
||||
}
|
||||
|
||||
Future<void> handleAdd(bool add, Room possibleParent) async {
|
||||
|
|
@ -142,11 +136,7 @@ class AddToSpaceState extends State<AddToSpaceToggles> {
|
|||
}
|
||||
|
||||
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<AddToSpaceToggles> {
|
|||
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(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue