From 7cab2cba7c3e5fcd5098160d1dbd733b1f3f6089 Mon Sep 17 00:00:00 2001 From: OfficialDakari Date: Sun, 2 Nov 2025 18:17:08 +0500 Subject: [PATCH] Add support for restricted join rule --- assets/l10n/intl_en.arb | 18 +++ assets/l10n/intl_ru.arb | 18 +++ .../chat_access_settings_controller.dart | 29 ++++- .../chat_access_settings_page.dart | 115 +++++++++++------- 4 files changed, 133 insertions(+), 47 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 3776fd5..cdb000e 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3154,6 +3154,24 @@ }, "restricted": "Restricted", "@restricted": {}, + }, + "spaceMemberOf": "Space member of {spaces}", + "@spaceMemberOf": { + "type": "String", + "placeholders": { + "spaces": { + "type": "String" + } + } + }, + "spaceMemberOfCanKnock": "Space member of {spaces} can knock", + "@spaceMemberOfCanKnock": { + "type": "String", + "placeholders": { + "spaces": { + "type": "String" + } + }, "knockRestricted": "Knock restricted", "@knockRestricted": {}, "goToSpace": "Go to space: {space}", diff --git a/assets/l10n/intl_ru.arb b/assets/l10n/intl_ru.arb index 01996ee..980f7b9 100644 --- a/assets/l10n/intl_ru.arb +++ b/assets/l10n/intl_ru.arb @@ -3154,6 +3154,24 @@ "space": {} }, "markAsUnread": "Отметить как непрочитанное", + + "spaceMemberOf": "Участники пространства {spaces}", + "@spaceMemberOf": { + "type": "String", + "placeholders": { + "spaces": { + "type": "String" + } + } + }, + "spaceMemberOfCanKnock": "Участники пространства {spaces} (по запросу)", + "@spaceMemberOfCanKnock": { + "type": "String", + "placeholders": { + "spaces": { + "type": "String" + } + }, "userLevel": "{level} - Пользователь", "@userLevel": { "type": "String", diff --git a/lib/pages/chat_access_settings/chat_access_settings_controller.dart b/lib/pages/chat_access_settings/chat_access_settings_controller.dart index 3840ebb..c4b075a 100644 --- a/lib/pages/chat_access_settings/chat_access_settings_controller.dart +++ b/lib/pages/chat_access_settings/chat_access_settings_controller.dart @@ -26,6 +26,16 @@ class ChatAccessSettingsController extends State { bool historyVisibilityLoading = false; bool guestAccessLoading = false; Room get room => Matrix.of(context).client.getRoomById(widget.roomId)!; + Set get knownSpaceParents => { + ...room.client.rooms.where( + (space) => + space.isSpace && + space.spaceChildren.any((child) => child.roomId == room.id), + ), + ...room.spaceParents + .map((parent) => room.client.getRoomById(parent.roomId ?? '')) + .whereType(), + }; String get roomVersion => room @@ -46,9 +56,12 @@ class ChatAccessSettingsController extends State { joinRules.remove(JoinRules.knock); } - // Not yet supported in FluffyChat: - joinRules.remove(JoinRules.restricted); - joinRules.remove(JoinRules.knockRestricted); + if (knownSpaceParents.isEmpty) { + joinRules.remove(JoinRules.restricted); + if (roomVersionInt != null && roomVersionInt <= 6) { + joinRules.remove(JoinRules.knockRestricted); + } + } // If an unsupported join rule is the current join rule, display it: final currentJoinRule = room.joinRules; @@ -64,7 +77,13 @@ class ChatAccessSettingsController extends State { }); try { - await room.setJoinRules(newJoinRules); + await room.setJoinRules( + newJoinRules, + allowConditionRoomId: {JoinRules.restricted, JoinRules.knockRestricted} + .contains(newJoinRules) + ? knownSpaceParents.first.id + : null, + ); } catch (e, s) { Logs().w('Unable to change join rules', e, s); if (mounted) { @@ -297,4 +316,4 @@ class ChatAccessSettingsController extends State { Widget build(BuildContext context) { return ChatAccessSettingsPageView(this); } -} +} \ No newline at end of file diff --git a/lib/pages/chat_access_settings/chat_access_settings_page.dart b/lib/pages/chat_access_settings/chat_access_settings_page.dart index dc11925..d6ad0de 100644 --- a/lib/pages/chat_access_settings/chat_access_settings_page.dart +++ b/lib/pages/chat_access_settings/chat_access_settings_page.dart @@ -45,19 +45,27 @@ class ChatAccessSettingsPageView extends StatelessWidget { ), ), ), - for (final historyVisibility in HistoryVisibility.values) - RadioListTile.adaptive( - title: Text( - historyVisibility - .getLocalizedString(MatrixLocals(L10n.of(context))), - ), - value: historyVisibility, - groupValue: room.historyVisibility, - onChanged: controller.historyVisibilityLoading || - !room.canChangeHistoryVisibility - ? null - : controller.setHistoryVisibility, + RadioGroup( + groupValue: room.historyVisibility, + onChanged: controller.historyVisibilityLoading || + !room.canChangeHistoryVisibility + ? (_) {} + : controller.setHistoryVisibility, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (final historyVisibility in HistoryVisibility.values) + RadioListTile.adaptive( + title: Text( + historyVisibility.getLocalizedString( + MatrixLocals(L10n.of(context)), + ), + ), + value: historyVisibility, + ), + ], ), + ), Divider(color: theme.dividerColor), ListTile( title: Text( @@ -68,19 +76,28 @@ class ChatAccessSettingsPageView extends StatelessWidget { ), ), ), - for (final joinRule in controller.availableJoinRules) - if (joinRule != JoinRules.private) - RadioListTile.adaptive( - title: Text( - joinRule.localizedString(L10n.of(context)), - ), - value: joinRule, - groupValue: room.joinRules, - onChanged: controller.joinRulesLoading || - !room.canChangeJoinRules - ? null - : controller.setJoinRule, - ), + RadioGroup( + groupValue: room.joinRules, + onChanged: controller.setJoinRule, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (final joinRule in controller.availableJoinRules) + if (joinRule != JoinRules.private) + RadioListTile.adaptive( + enabled: !controller.joinRulesLoading && + room.canChangeJoinRules, + title: Text( + joinRule.localizedString( + L10n.of(context), + controller.knownSpaceParents, + ), + ), + value: joinRule, + ), + ], + ), + ), Divider(color: theme.dividerColor), if ({JoinRules.public, JoinRules.knock} .contains(room.joinRules)) ...[ @@ -93,20 +110,26 @@ class ChatAccessSettingsPageView extends StatelessWidget { ), ), ), - for (final guestAccess in GuestAccess.values) - RadioListTile.adaptive( - title: Text( - guestAccess.getLocalizedString( - MatrixLocals(L10n.of(context)), - ), - ), - value: guestAccess, - groupValue: room.guestAccess, - onChanged: controller.guestAccessLoading || - !room.canChangeGuestAccess - ? null - : controller.setGuestAccess, + RadioGroup( + groupValue: room.guestAccess, + onChanged: controller.setGuestAccess, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (final guestAccess in GuestAccess.values) + RadioListTile.adaptive( + enabled: !controller.guestAccessLoading && + room.canChangeGuestAccess, + title: Text( + guestAccess.getLocalizedString( + MatrixLocals(L10n.of(context)), + ), + ), + value: guestAccess, + ), + ], ), + ), Divider(color: theme.dividerColor), ListTile( title: Text( @@ -260,7 +283,7 @@ class _AliasListTile extends StatelessWidget { } extension JoinRulesDisplayString on JoinRules { - String localizedString(L10n l10n) { + String localizedString(L10n l10n, Set spaceParents) { switch (this) { case JoinRules.public: return l10n.anyoneCanJoin; @@ -271,9 +294,17 @@ extension JoinRulesDisplayString on JoinRules { case JoinRules.private: return l10n.noOneCanJoin; case JoinRules.restricted: - return l10n.restricted; + return l10n.spaceMemberOf( + spaceParents + .map((space) => space.getLocalizedDisplayname(MatrixLocals(l10n))) + .join(', '), + ); case JoinRules.knockRestricted: - return l10n.knockRestricted; + return l10n.spaceMemberOfCanKnock( + spaceParents + .map((space) => space.getLocalizedDisplayname(MatrixLocals(l10n))) + .join(', '), + ); } } -} +} \ No newline at end of file