From 09c88b6e28d5712f7855959966c1786e0fda6f4c Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:06:27 -0500 Subject: [PATCH] 1137 room visibility changes (#1139) * only show visbility toggles for parent spaces. update copy and toggle icon. * when a space is added to another space, reset its join rules / visibility to defaults * before adding space to space, give visibility warning --- assets/l10n/intl_en.arb | 5 +- lib/pages/chat_list/chat_list.dart | 17 +++-- lib/pages/new_group/new_group_view.dart | 50 ++++++------- lib/pages/new_space/new_space.dart | 41 ++++++----- lib/pages/new_space/new_space_view.dart | 22 +++--- .../pangea_room_extension.dart | 1 + .../room_children_and_parents_extension.dart | 34 +++++---- .../chat_details/pangea_chat_details.dart | 8 ++- lib/pangea/widgets/chat/add_room_dialog.dart | 24 +------ .../widgets/chat/visibility_toggle.dart | 71 +++++++++---------- 10 files changed, 141 insertions(+), 132 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 56702fedb..f956313b5 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4519,5 +4519,8 @@ "notificationsOn": "Notifications on", "notificationsOff": "Notifications off", "spaceCanBeFoundViaSearch": "Space can be found via search", - "chatCanBeFoundViaSearch": "Chat can be found via search" + "chatCanBeFoundViaSearch": "Chat can be found via search", + "requireCodeToJoin": "Require code to join", + "canFindInSearch": "Can find in search", + "addSubspaceWarning": "Once you add this, it will not appear in public search results, and it will be visible to all members of the parent space." } \ No newline at end of file diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index b6f004fea..4534bde37 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -924,6 +924,15 @@ class ChatListController extends State .toList(), ); if (space == null) return; + // #Pangea + if (room.isSpace) { + final resp = await showOkCancelAlertDialog( + context: context, + title: L10n.of(context)!.addSubspaceWarning, + ); + if (resp == OkCancelResult.cancel) return; + } + // Pangea# await showFutureLoadingDialog( context: context, // #Pangea @@ -949,10 +958,10 @@ class ChatListController extends State } // #Pangea - // Remove a room from a space. Often, the user will have permission to set - // the SpaceChild event for the parent space, but not the SpaceParent event. - // This would cause a permissions error, but the child will still be removed - // via the SpaceChild event. If that's the case, silence the error. + /// Remove a room from a space. Often, the user will have permission to set + /// the SpaceChild event for the parent space, but not the SpaceParent event. + /// This would cause a permissions error, but the child will still be removed + /// via the SpaceChild event. If that's the case, silence the error. Future removeSpaceChild(Room space, String roomId) async { try { await space.removeSpaceChild(roomId); diff --git a/lib/pages/new_group/new_group_view.dart b/lib/pages/new_group/new_group_view.dart index a28b801a6..c6001e9ca 100644 --- a/lib/pages/new_group/new_group_view.dart +++ b/lib/pages/new_group/new_group_view.dart @@ -70,34 +70,34 @@ class NewGroupView extends StatelessWidget { ), ), const SizedBox(height: 16), - SwitchListTile.adaptive( - contentPadding: const EdgeInsets.symmetric(horizontal: 32), - secondary: const Icon(Icons.public_outlined), - title: Text(L10n.of(context)!.groupIsPublic), - value: controller.publicGroup, - onChanged: controller.loading ? null : controller.setPublicGroup, - ), - AnimatedSize( - duration: FluffyThemes.animationDuration, - child: controller.publicGroup - ? SwitchListTile.adaptive( - contentPadding: - const EdgeInsets.symmetric(horizontal: 32), - secondary: const Icon(Icons.search_outlined), - // #Pangea - // title: Text(L10n.of(context)!.groupCanBeFoundViaSearch), - title: Text(L10n.of(context)!.chatCanBeFoundViaSearch), - // Pangea# - value: controller.groupCanBeFound, - onChanged: controller.loading - ? null - : controller.setGroupCanBeFound, - ) - : const SizedBox.shrink(), - ), // #Pangea // SwitchListTile.adaptive( // contentPadding: const EdgeInsets.symmetric(horizontal: 32), + // secondary: const Icon(Icons.public_outlined), + // title: Text(L10n.of(context)!.groupIsPublic), + // value: controller.publicGroup, + // onChanged: controller.loading ? null : controller.setPublicGroup, + // ), + // AnimatedSize( + // duration: FluffyThemes.animationDuration, + // child: controller.publicGroup + // ? SwitchListTile.adaptive( + // contentPadding: + // const EdgeInsets.symmetric(horizontal: 32), + // secondary: const Icon(Icons.search_outlined), + // // #Pangea + // // title: Text(L10n.of(context)!.groupCanBeFoundViaSearch), + // title: Text(L10n.of(context)!.chatCanBeFoundViaSearch), + // // Pangea# + // value: controller.groupCanBeFound, + // onChanged: controller.loading + // ? null + // : controller.setGroupCanBeFound, + // ) + // : const SizedBox.shrink(), + // ), + // SwitchListTile.adaptive( + // contentPadding: const EdgeInsets.symmetric(horizontal: 32), // secondary: Icon( // Icons.lock_outlined, // color: theme.colorScheme.onSurface, diff --git a/lib/pages/new_space/new_space.dart b/lib/pages/new_space/new_space.dart index be598bea7..a1d5f1bfd 100644 --- a/lib/pages/new_space/new_space.dart +++ b/lib/pages/new_space/new_space.dart @@ -27,10 +27,13 @@ class NewSpace extends StatefulWidget { class NewSpaceController extends State { TextEditingController nameController = TextEditingController(); TextEditingController topicController = TextEditingController(); - bool publicGroup = false; + // #Pangea - bool spaceCanBeFound = true; + // bool publicGroup = false; + bool requiredCodeToJoin = false; + bool spaceCanBeFound = false; // Pangea# + bool loading = false; String? nameError; String? topicError; @@ -55,10 +58,13 @@ class NewSpaceController extends State { void setSpaceCanBeFound(bool b) => setState(() => spaceCanBeFound = b); // Pangea# - void setPublicGroup(bool b) => setState(() => publicGroup = b); + // #Pangea + // void setPublicGroup(bool b) => setState(() => publicGroup = b); + void setRequireCode(bool b) => setState(() => requiredCodeToJoin = b); + // Pangea# // #Pangea - List initialState(String joinCode, bool publicGroup) { + List initialState(String joinCode) { return [ StateEvent( type: EventTypes.RoomPowerLevels, @@ -77,9 +83,9 @@ class NewSpaceController extends State { StateEvent( type: sdk.EventTypes.RoomJoinRules, content: { - ModelKey.joinRule: publicGroup - ? sdk.JoinRules.public.toString().replaceAll('JoinRules.', '') - : sdk.JoinRules.invite.toString().replaceAll('JoinRules.', ''), + ModelKey.joinRule: requiredCodeToJoin + ? sdk.JoinRules.knock.toString().replaceAll('JoinRules.', '') + : sdk.JoinRules.public.toString().replaceAll('JoinRules.', ''), ModelKey.accessCode: joinCode, }, ), @@ -109,24 +115,25 @@ class NewSpaceController extends State { // Pangea# final spaceId = await client.createRoom( - preset: publicGroup - ? sdk.CreateRoomPreset.publicChat - : sdk.CreateRoomPreset.privateChat, // #Pangea - visibility: publicGroup && spaceCanBeFound - ? sdk.Visibility.public - : sdk.Visibility.private, + // preset: publicGroup + // ? sdk.CreateRoomPreset.publicChat + // : sdk.CreateRoomPreset.privateChat, + visibility: + spaceCanBeFound ? sdk.Visibility.public : sdk.Visibility.private, // Pangea# creationContent: {'type': RoomCreationTypes.mSpace}, - roomAliasName: publicGroup - ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') - : null, + // #Pangea + // roomAliasName: publicGroup + // ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') + // : null, + // Pangea# name: nameController.text.trim(), topic: topicController.text.isEmpty ? null : topicController.text, powerLevelContentOverride: {'events_default': 100}, initialState: [ // #Pangea - ...initialState(joinCode, publicGroup), + ...initialState(joinCode), // Pangea# if (avatar != null) sdk.StateEvent( diff --git a/lib/pages/new_space/new_space_view.dart b/lib/pages/new_space/new_space_view.dart index 5c9e69a1b..8d3ee12ee 100644 --- a/lib/pages/new_space/new_space_view.dart +++ b/lib/pages/new_space/new_space_view.dart @@ -58,18 +58,20 @@ class NewSpaceView extends StatelessWidget { const SizedBox(height: 16), SwitchListTile.adaptive( contentPadding: const EdgeInsets.symmetric(horizontal: 32), - title: Text(L10n.of(context)!.spaceIsPublic), - value: controller.publicGroup, - onChanged: controller.setPublicGroup, + // #Pangea + // title: Text(L10n.of(context)!.spaceIsPublic), + title: Text(L10n.of(context)!.requireCodeToJoin), + // Pangea# + value: controller.requiredCodeToJoin, + onChanged: controller.setRequireCode, ), // #Pangea - if (controller.publicGroup) - SwitchListTile.adaptive( - contentPadding: const EdgeInsets.symmetric(horizontal: 32), - title: Text(L10n.of(context)!.spaceCanBeFoundViaSearch), - value: controller.spaceCanBeFound, - onChanged: controller.setSpaceCanBeFound, - ), + SwitchListTile.adaptive( + contentPadding: const EdgeInsets.symmetric(horizontal: 32), + title: Text(L10n.of(context)!.canFindInSearch), + value: controller.spaceCanBeFound, + onChanged: controller.setSpaceCanBeFound, + ), // Pangea# ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 32), 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 b5a5976fc..f25bde424 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -27,6 +27,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; // import markdown.dart import 'package:html_unescape/html_unescape.dart'; +import 'package:matrix/matrix.dart' as matrix; import 'package:matrix/matrix.dart'; import 'package:matrix/src/utils/markdown.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; diff --git a/lib/pangea/extensions/pangea_room_extension/room_children_and_parents_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_children_and_parents_extension.dart index 9d5d9e726..9a91f1cbf 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_children_and_parents_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_children_and_parents_extension.dart @@ -109,25 +109,35 @@ extension ChildrenAndParentsRoomExtension on Room { } /// Wrapper around call to setSpaceChild with added functionality - /// to prevent adding one room to multiple spaces + /// to prevent adding one room to multiple spaces, and resets the + /// subspace's JoinRules and Visibility to defaults. 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', - ); - } + if (child == null) return; + 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', + ); } + } + + try { await setSpaceChild(roomId, suggested: suggested); + await child.setJoinRules(JoinRules.public); + await child.client.setRoomVisibilityOnDirectory( + roomId, + visibility: matrix.Visibility.private, + ); + } catch (err, stack) { + ErrorHandler.logError(e: err, s: stack); } } diff --git a/lib/pangea/pages/chat_details/pangea_chat_details.dart b/lib/pangea/pages/chat_details/pangea_chat_details.dart index 2edb04e7a..6c9cd36ec 100644 --- a/lib/pangea/pages/chat_details/pangea_chat_details.dart +++ b/lib/pangea/pages/chat_details/pangea_chat_details.dart @@ -313,14 +313,18 @@ class PangeaChatDetailsView extends StatelessWidget { ), if (isGroupChat && room.isRoomAdmin) Divider(color: theme.dividerColor, height: 1), - if (room.isRoomAdmin) + if (room.isRoomAdmin && + room.isSpace && + room.spaceParents.isEmpty) VisibilityToggle( room: room, setVisibility: controller.setVisibility, setJoinRules: controller.setJoinRules, iconColor: iconColor, ), - if (room.isRoomAdmin) + if (room.isRoomAdmin && + room.isSpace && + room.spaceParents.isEmpty) Divider(color: theme.dividerColor, height: 1), RoomCapacityButton( room: room, diff --git a/lib/pangea/widgets/chat/add_room_dialog.dart b/lib/pangea/widgets/chat/add_room_dialog.dart index 42d8b4786..3e286dbb8 100644 --- a/lib/pangea/widgets/chat/add_room_dialog.dart +++ b/lib/pangea/widgets/chat/add_room_dialog.dart @@ -1,5 +1,4 @@ import 'package:fluffychat/pages/chat_list/space_view.dart'; -import 'package:fluffychat/pangea/widgets/chat/visibility_toggle.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart' as matrix; @@ -23,17 +22,6 @@ class AddRoomDialogState extends State { final TextEditingController _roomDescriptionController = TextEditingController(); - matrix.Visibility visibility = matrix.Visibility.public; - JoinRules joinRules = JoinRules.public; - - Future _setJoinRules(JoinRules newJoinRules) async { - setState(() => joinRules = newJoinRules); - } - - Future _setVisibility(matrix.Visibility newVisibility) async { - setState(() => visibility = newVisibility); - } - @override void dispose() { _roomNameController.dispose(); @@ -98,13 +86,6 @@ class AddRoomDialogState extends State { ], ), ), - VisibilityToggle( - setJoinRules: _setJoinRules, - setVisibility: _setVisibility, - spaceMode: widget.roomType == AddRoomType.subspace, - visibility: visibility, - joinRules: joinRules, - ), Padding( padding: const EdgeInsets.all(20), child: Row( @@ -121,13 +102,12 @@ class AddRoomDialogState extends State { onPressed: () async { final isValid = _formKey.currentState!.validate(); if (!isValid) return; - Navigator.of(context).pop( RoomResponse( roomName: _roomNameController.text, roomDescription: _roomDescriptionController.text, - joinRules: joinRules, - visibility: visibility, + joinRules: JoinRules.public, + visibility: matrix.Visibility.private, ), ); }, diff --git a/lib/pangea/widgets/chat/visibility_toggle.dart b/lib/pangea/widgets/chat/visibility_toggle.dart index 41175d203..7bc9fd3c6 100644 --- a/lib/pangea/widgets/chat/visibility_toggle.dart +++ b/lib/pangea/widgets/chat/visibility_toggle.dart @@ -23,7 +23,7 @@ class VisibilityToggle extends StatelessWidget { this.iconColor, this.spaceMode = false, this.visibility = matrix.Visibility.private, - this.joinRules = JoinRules.invite, + this.joinRules = JoinRules.knock, this.showSearchToggle = true, super.key, }); @@ -40,9 +40,7 @@ class VisibilityToggle extends StatelessWidget { SwitchListTile.adaptive( activeColor: AppConfig.activeToggleColor, title: Text( - room?.isSpace ?? spaceMode - ? L10n.of(context)!.spaceIsPublic - : L10n.of(context)!.groupIsPublic, + L10n.of(context)!.requireCodeToJoin, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, @@ -51,45 +49,40 @@ class VisibilityToggle extends StatelessWidget { secondary: CircleAvatar( backgroundColor: Theme.of(context).scaffoldBackgroundColor, foregroundColor: iconColor, - child: const Icon(Icons.public_outlined), + child: const Icon(Icons.key_outlined), ), - value: _isPublic, + value: !_isPublic, onChanged: (value) => - setJoinRules(value ? JoinRules.public : JoinRules.invite), + setJoinRules(value ? JoinRules.knock : JoinRules.public), ), - if (_isPublic && showSearchToggle) - FutureBuilder( - future: room != null - ? Matrix.of(context) - .client - .getRoomVisibilityOnDirectory(room!.id) - : null, - builder: (context, snapshot) { - return SwitchListTile.adaptive( - activeColor: AppConfig.activeToggleColor, - title: Text( - room?.isSpace ?? spaceMode - ? L10n.of(context)!.spaceCanBeFoundViaSearch - : L10n.of(context)!.chatCanBeFoundViaSearch, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), + FutureBuilder( + future: room != null + ? Matrix.of(context).client.getRoomVisibilityOnDirectory(room!.id) + : null, + builder: (context, snapshot) { + return SwitchListTile.adaptive( + activeColor: AppConfig.activeToggleColor, + title: Text( + L10n.of(context)!.canFindInSearch, + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, ), - secondary: CircleAvatar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - foregroundColor: iconColor, - child: const Icon(Icons.search_outlined), - ), - value: room != null - ? snapshot.data == matrix.Visibility.public - : visibility == matrix.Visibility.public, - onChanged: (value) => setVisibility( - value ? matrix.Visibility.public : matrix.Visibility.private, - ), - ); - }, - ), + ), + secondary: CircleAvatar( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + foregroundColor: iconColor, + child: const Icon(Icons.search_outlined), + ), + value: room != null + ? snapshot.data == matrix.Visibility.public + : visibility == matrix.Visibility.public, + onChanged: (value) => setVisibility( + value ? matrix.Visibility.public : matrix.Visibility.private, + ), + ); + }, + ), ], ); }