diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 1d5ff4218..75ebb54e7 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3681,24 +3681,8 @@ "lockSpace": "Lock Space", "lockChat": "Lock Chat", "archiveSpace": "Archive Space", - "suggestTo": "Suggest to {spaceName}", - "@suggestTo": { - "placeholders": { - "spaceName": {} - } - }, - "suggestChatDesc": "Suggested chats will appear in the chat list for {spaceName}", - "@suggestToDesc": { - "placeholders": { - "spaceName": {} - } - }, - "suggestExchangeDesc": "Suggested exchanges will appear in the chat list for {spaceName}", - "@suggestToExchangeDesc": { - "placeholders": { - "spaceName": {} - } - }, + "suggestToChat": "Suggest this chat", + "suggestToChatDesc": "Suggested chats will appear in chat lists", "acceptSelection": "Accept Correction", "acceptSelectionAnyway": "Use this anyway", "makingActivity": "Making activity", diff --git a/lib/pages/new_group/new_group.dart b/lib/pages/new_group/new_group.dart index 2ada80dfa..2aec182fb 100644 --- a/lib/pages/new_group/new_group.dart +++ b/lib/pages/new_group/new_group.dart @@ -130,9 +130,7 @@ class NewGroupController extends State { powerLevelContentOverride: await ClassChatPowerLevels.powerLevelOverrideForClassChat( context, - addToSpaceKey.currentState!.parents - .map((suggestionStatus) => suggestionStatus.room) - .toList(), + addToSpaceKey.currentState!.parents, ), 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 15420a4f5..e8145080b 100644 --- a/lib/pages/new_space/new_space.dart +++ b/lib/pages/new_space/new_space.dart @@ -176,9 +176,7 @@ class NewSpaceController extends State { powerLevelContentOverride: addToSpaceKey.currentState != null ? await ClassChatPowerLevels.powerLevelOverrideForClassChat( context, - addToSpaceKey.currentState!.parents - .map((suggestionStatus) => suggestionStatus.room) - .toList(), + addToSpaceKey.currentState!.parents, ) : null, // initialState: [ diff --git a/lib/pangea/controllers/class_controller.dart b/lib/pangea/controllers/class_controller.dart index 0820f769b..4574151d7 100644 --- a/lib/pangea/controllers/class_controller.dart +++ b/lib/pangea/controllers/class_controller.dart @@ -34,8 +34,9 @@ class ClassController extends BaseController { Future fixClassPowerLevels() async { try { final List> classFixes = []; - for (final room in (await _pangeaController - .matrixState.client.classesAndExchangesImTeaching)) { + final teacherSpaces = await _pangeaController + .matrixState.client.classesAndExchangesImTeaching; + for (final room in teacherSpaces) { classFixes.add(room.setClassPowerLevels()); } await Future.wait(classFixes); diff --git a/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart b/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart index 02888710e..14ee5f4ce 100644 --- a/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart @@ -62,13 +62,19 @@ extension ClassAndExchangeSettingsRoomExtension on Room { } final Event? currentPower = getState(EventTypes.RoomPowerLevels); final Map? currentPowerContent = - currentPower?.content["events"] as Map?; - final spaceChildPower = currentPowerContent?[EventTypes.spaceChild]; + currentPower?.content as Map?; + if (currentPowerContent == null) { + return; + } + if (!(currentPowerContent.containsKey("events"))) { + currentPowerContent["events"] = {}; + } + final spaceChildPower = + currentPowerContent["events"][EventTypes.spaceChild]; final studentAnalyticsPower = - currentPowerContent?[PangeaEventTypes.studentAnalyticsSummary]; + currentPowerContent[PangeaEventTypes.studentAnalyticsSummary]; - if ((spaceChildPower == null || studentAnalyticsPower == null) && - currentPowerContent != null) { + if ((spaceChildPower == null || studentAnalyticsPower == null)) { currentPowerContent["events"][EventTypes.spaceChild] = 0; currentPowerContent["events"] [PangeaEventTypes.studentAnalyticsSummary] = 0; 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 13606fbc2..ba7696a50 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -253,11 +253,10 @@ extension PangeaRoom on Room { BotOptionsModel? get botOptions => _botOptions; - Future suggestedInSpace(Room space) async => - await _suggestedInSpace(space); + Future setSuggested(bool suggested) async => + await _setSuggested(suggested); - Future setSuggestedInSpace(bool suggest, Room space) async => - await _setSuggestedInSpace(suggest, space); + Future isSuggested() async => await _isSuggested(); // user_permissions 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 6995659d3..9746a5680 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart @@ -55,7 +55,40 @@ extension RoomSettingsRoomExtension on Room { ); } - Future _suggestedInSpace(Room space) async { + Future _isSuggested() async { + final List spaceParents = client.rooms + .where( + (room) => + room.isSpace && + room.spaceChildren.any( + (sc) => sc.roomId == id, + ), + ) + .toList(); + + for (final parent in spaceParents) { + final suggested = await _isSuggestedInSpace(parent); + if (!suggested) return false; + } + return true; + } + + Future _setSuggested(bool suggested) async { + final List spaceParents = client.rooms + .where( + (room) => + room.isSpace && + room.spaceChildren.any( + (sc) => sc.roomId == id, + ), + ) + .toList(); + for (final parent in spaceParents) { + await _setSuggestedInSpace(suggested, parent); + } + } + + Future _isSuggestedInSpace(Room space) async { try { final Map resp = await client.getRoomStateWithKey(space.id, EventTypes.spaceChild, id); diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index d3bfdbd3d..cfea4dd7b 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -33,9 +33,10 @@ class AddToSpaceToggles extends StatefulWidget { class AddToSpaceState extends State { late Room? room; - late List parents; + late List parents; late List possibleParents; late bool isOpen; + late bool isSuggested; AddToSpaceState({Key? key}); @@ -46,6 +47,9 @@ class AddToSpaceState extends State { ? Matrix.of(context).client.getRoomById(widget.roomId!) : null; + isSuggested = true; + room?.isSuggested().then((value) => isSuggested = value); + possibleParents = Matrix.of(context) .client .rooms @@ -63,8 +67,6 @@ class AddToSpaceState extends State { (r) => r.spaceChildren.any((room) => room.roomId == widget.roomId), ) - .map((r) => SuggestionStatus(false, r)) - .cast() .toList() : []; @@ -72,7 +74,7 @@ class AddToSpaceState extends State { final activeSpace = Matrix.of(context).client.getRoomById(widget.activeSpaceId!); if (activeSpace != null && activeSpace.canIAddSpaceChild(null)) { - parents.add(SuggestionStatus(true, activeSpace)); + parents.add(activeSpace); } else { ErrorHandler.logError( e: Exception('activeSpaceId ${widget.activeSpaceId} not found'), @@ -84,10 +86,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((suggestionStatus) => suggestionStatus.room.id == a.id)) { + if (parents.any((parent) => parent.id == a.id)) { return -1; - } else if (parents - .any((suggestionStatus) => suggestionStatus.room.id == b.id)) { + } else if (parents.any((parent) => parent.id == b.id)) { return 1; } else { return a.name.compareTo(b.name); @@ -95,35 +96,21 @@ class AddToSpaceState extends State { }); isOpen = widget.startOpen; - initSuggestedParents(); super.initState(); } - Future initSuggestedParents() async { - if (room != null) { - for (var i = 0; i < parents.length; i++) { - final parent = parents[i]; - final bool suggested = - await room?.suggestedInSpace(parent.room) ?? false; - parents[i].suggested = suggested; - } - setState(() {}); - } - } - Future _addSingleSpace(String roomToAddId, Room newParent) async { GoogleAnalytics.addParent(roomToAddId, newParent.classCode); await newParent.setSpaceChild( roomToAddId, - suggested: isSuggestedInSpace(newParent), + suggested: isSuggested, ); - await setSuggested(true, newParent); } Future addSpaces(String roomToAddId) async { final List> addFutures = []; - for (final SuggestionStatus newParent in parents) { - addFutures.add(_addSingleSpace(roomToAddId, newParent.room)); + for (final Room parent in parents) { + addFutures.add(_addSingleSpace(roomToAddId, parent)); } await addFutures.wait; } @@ -148,39 +135,18 @@ class AddToSpaceState extends State { setState( () => add - ? parents.add(SuggestionStatus(true, possibleParent)) + ? parents.add(possibleParent) : parents.removeWhere( - (suggestionStatus) => - suggestionStatus.room.id == possibleParent.id, + (parent) => parent.id == possibleParent.id, ), ); } - Future setSuggested(bool suggest, Room possibleParent) async { - if (room != null) { - await showFutureLoadingDialog( - context: context, - future: () => room!.setSuggestedInSpace(suggest, possibleParent), - ); - } - - for (final SuggestionStatus suggestionStatus in parents) { - if (suggestionStatus.room.id == possibleParent.id) { - suggestionStatus.suggested = suggest; - } - } - - setState(() {}); - } - - bool isSuggestedInSpace(Room parent) => - parents.firstWhereOrNull((r) => r.room.id == parent.id)?.suggested ?? - false; - Widget getAddToSpaceToggleItem(int index) { final Room possibleParent = possibleParents[index]; - final String possibleParentName = possibleParent.getLocalizedDisplayname(); - final bool canAdd = possibleParent.canIAddSpaceChild(room); + final bool canAdd = !(!possibleParent.isRoomAdmin && + widget.mode == AddToClassMode.exchange) && + possibleParent.canIAddSpaceChild(room); return Opacity( opacity: canAdd ? 1 : 0.5, @@ -189,7 +155,7 @@ class AddToSpaceState extends State { SwitchListTile.adaptive( title: possibleParent.nameAndRoomTypeIcon(), activeColor: AppConfig.activeToggleColor, - value: parents.any((r) => r.room.id == possibleParent.id), + value: parents.any((r) => r.id == possibleParent.id), onChanged: (bool add) => canAdd ? handleAdd(add, possibleParent) : ScaffoldMessenger.of(context).showSnackBar( @@ -198,53 +164,6 @@ class AddToSpaceState extends State { ), ), ), - AnimatedSize( - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - child: parents.any((r) => r.room.id == possibleParent.id) - ? SwitchListTile.adaptive( - title: Row( - children: [ - const SizedBox(width: 32), - Expanded( - child: Text( - L10n.of(context)!.suggestTo(possibleParentName), - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - subtitle: Row( - children: [ - const SizedBox(width: 32), - Expanded( - child: Text( - widget.mode == AddToClassMode.chat - ? L10n.of(context)! - .suggestChatDesc(possibleParentName) - : L10n.of(context)!.suggestExchangeDesc( - possibleParentName, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - activeColor: AppConfig.activeToggleColor, - value: isSuggestedInSpace(possibleParent), - onChanged: (bool suggest) => canAdd - ? setSuggested(suggest, possibleParent) - : ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(L10n.of(context)!.noPermission), - ), - ), - ) - : Container(), - ), Divider( height: 0.5, color: Theme.of(context).colorScheme.secondary.withAlpha(25), @@ -254,6 +173,16 @@ class AddToSpaceState extends State { ); } + Future setSuggested(bool suggested) async { + setState(() => isSuggested = suggested); + if (room != null) { + await showFutureLoadingDialog( + context: context, + future: () async => await room?.setSuggested(suggested), + ); + } + } + @override Widget build(BuildContext context) { final String title = widget.mode == AddToClassMode.exchange @@ -292,9 +221,28 @@ class AddToSpaceState extends State { const Divider(height: 1), possibleParents.isNotEmpty ? Column( - children: possibleParents - .mapIndexed((index, _) => getAddToSpaceToggleItem(index)) - .toList(), + children: [ + SwitchListTile.adaptive( + title: Text(L10n.of(context)!.suggestToChat), + secondary: Icon( + isSuggested + ? Icons.visibility_outlined + : Icons.visibility_off_outlined, + ), + subtitle: Text(L10n.of(context)!.suggestToChatDesc), + activeColor: AppConfig.activeToggleColor, + value: isSuggested, + onChanged: (bool add) => setSuggested(add), + ), + Divider( + height: 0.5, + color: + Theme.of(context).colorScheme.secondary.withAlpha(25), + ), + ...possibleParents.mapIndexed( + (index, _) => getAddToSpaceToggleItem(index), + ), + ], ) : Center( child: Padding( @@ -312,10 +260,3 @@ class AddToSpaceState extends State { ); } } - -class SuggestionStatus { - bool suggested; - final Room room; - - SuggestionStatus(this.suggested, this.room); -}