diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 4c8ffa5af..7449fde61 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4191,10 +4191,10 @@ "spaceCapacityNotSet": "This space has no capacity limit.", "chatCapacityHasBeenChanged": "Chat capacity changed", "spaceCapacityHasBeenChanged": "Space capacity changed", - "chatCapacitySetTooLow": "Chat capacity cannot be set below the current number of non-admins.", - "spaceCapacitySetTooLow": "Space capacity cannot be set below the current number of non-admins.", - "chatCapacityExplanation": "Chat capacity limits the number of non-admins allowed in a chat.", - "spaceCapacityExplanation": "Space capacity limits the number of non-admins allowed in a space.", + "chatCapacitySetTooLow": "Chat capacity cannot be set below the current number of members.", + "spaceCapacitySetTooLow": "Space capacity cannot be set below the current number of members.", + "chatCapacityExplanation": "Chat capacity limits the number of members allowed in a chat.", + "spaceCapacityExplanation": "Space capacity limits the number of members allowed in a space.", "chatExceedsCapacity": "This chat exceeds its capacity.", "spaceExceedsCapacity": "This space exceeds its capacity.", "tooManyRequest": "Too many request, please try again later.", diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 7116796b9..8beb411d9 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -43,6 +43,7 @@ import '../../widgets/matrix.dart'; import 'package:fluffychat/utils/tor_stub.dart' if (dart.library.html) 'package:tor_detector_web/tor_detector_web.dart'; + enum PopupMenuAction { settings, invite, @@ -441,6 +442,7 @@ class ChatListController extends State StreamSubscription? _invitedSpaceSubscription; StreamSubscription? _subscriptionStatusStream; StreamSubscription? _spaceChildSubscription; + StreamSubscription? _roomCapacitySubscription; final Set hasUpdates = {}; //Pangea# @@ -559,7 +561,45 @@ class ChatListController extends State }).listen((update) { hasUpdates.add(update.roomId); }); - //Pangea# + + // listen for room join events and leave room if over capacity + _roomCapacitySubscription ??= client.onSync.stream + .where((u) => u.rooms?.join != null) + .listen((update) async { + final roomUpdates = update.rooms!.join!.entries; + for (final entry in roomUpdates) { + final roomID = entry.key; + final roomUpdate = entry.value; + if (roomUpdate.timeline?.events == null) continue; + final events = roomUpdate.timeline!.events; + final memberEvents = events!.where( + (event) => + event.type == EventTypes.RoomMember && + event.senderId == client.userID, + ); + if (memberEvents.isEmpty) continue; + final room = client.getRoomById(roomID); + if (room == null || + room.isSpace || + room.isAnalyticsRoom || + room.capacity == null || + (room.summary.mJoinedMemberCount ?? 1) <= room.capacity!) { + continue; + } + + await showFutureLoadingDialog( + context: context, + future: () async { + await room.leave(); + if (GoRouterState.of(context).uri.toString().contains(roomID)) { + context.go("/rooms"); + } + throw L10n.of(context).roomFull; + }, + ); + } + }); + // Pangea# super.initState(); } @@ -574,6 +614,7 @@ class ChatListController extends State _invitedSpaceSubscription?.cancel(); _subscriptionStatusStream?.cancel(); _spaceChildSubscription?.cancel(); + _roomCapacitySubscription?.cancel(); //Pangea# scrollController.removeListener(_onScroll); super.dispose(); diff --git a/lib/pangea/chat_list/utils/chat_list_handle_space_tap.dart b/lib/pangea/chat_list/utils/chat_list_handle_space_tap.dart index baa1e4c26..a17479c94 100644 --- a/lib/pangea/chat_list/utils/chat_list_handle_space_tap.dart +++ b/lib/pangea/chat_list/utils/chat_list_handle_space_tap.dart @@ -35,9 +35,6 @@ void chatListHandleSpaceTap( context: context, future: () async { await space.join(); - if (await space.leaveIfFull()) { - throw L10n.of(context).roomFull; - } setActiveSpaceAndCloseChat(); }, ); @@ -65,9 +62,6 @@ void chatListHandleSpaceTap( context: context, future: () async { await space.join(); - if (await space.leaveIfFull()) { - throw L10n.of(context).roomFull; - } setActiveSpaceAndCloseChat(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( diff --git a/lib/pangea/chat_settings/pages/pangea_chat_details.dart b/lib/pangea/chat_settings/pages/pangea_chat_details.dart index e085c1271..858724555 100644 --- a/lib/pangea/chat_settings/pages/pangea_chat_details.dart +++ b/lib/pangea/chat_settings/pages/pangea_chat_details.dart @@ -336,10 +336,11 @@ class PangeaChatDetailsView extends StatelessWidget { room.isSpace && room.spaceParents.isEmpty) Divider(color: theme.dividerColor, height: 1), - RoomCapacityButton( - room: room, - controller: controller, - ), + if (!room.isSpace) + RoomCapacityButton( + room: room, + controller: controller, + ), if (room.isSpace && room.isRoomAdmin && kIsWeb) DownloadAnalyticsButton(space: room), Divider(color: theme.dividerColor, height: 1), diff --git a/lib/pangea/chat_settings/widgets/room_capacity_button.dart b/lib/pangea/chat_settings/widgets/room_capacity_button.dart index cbd348379..31e9ff3be 100644 --- a/lib/pangea/chat_settings/widgets/room_capacity_button.dart +++ b/lib/pangea/chat_settings/widgets/room_capacity_button.dart @@ -9,15 +9,13 @@ import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart' import 'package:fluffychat/widgets/future_loading_dialog.dart'; class RoomCapacityButton extends StatefulWidget { - final Room? room; + final Room room; final ChatDetailsController? controller; - final bool spaceMode; const RoomCapacityButton({ super.key, - this.room, + required this.room, this.controller, - this.spaceMode = false, }); @override @@ -25,64 +23,18 @@ class RoomCapacityButton extends StatefulWidget { } class RoomCapacityButtonState extends State { - int? capacity; - String? nonAdmins; + int? get capacity => widget.room.capacity; + int get memberCount => widget.room.summary.mJoinedMemberCount ?? 1; RoomCapacityButtonState({Key? key}); - @override - void initState() { - super.initState(); - capacity = RoomSettingsRoomExtension(widget.room)?.capacity; - widget.room?.numNonAdmins.then( - (value) => setState(() { - nonAdmins = value.toString(); - overCapacity(); - }), - ); - } - - @override - void didUpdateWidget(RoomCapacityButton oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.room != widget.room) { - capacity = RoomSettingsRoomExtension(widget.room)?.capacity; - widget.room?.numNonAdmins.then( - (value) => setState(() { - nonAdmins = value.toString(); - overCapacity(); - }), - ); - } - } - - Future overCapacity() async { - if ((widget.room?.isRoomAdmin ?? false) && - capacity != null && - nonAdmins != null && - int.parse(nonAdmins!) > capacity!) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - spaceMode - ? L10n.of(context).chatExceedsCapacity - : L10n.of(context).spaceExceedsCapacity, - ), - ), - ); - } - } - - bool get spaceMode => - (widget.room != null && widget.room!.isSpace) || widget.spaceMode; - @override Widget build(BuildContext context) { final iconColor = Theme.of(context).textTheme.bodyLarge!.color; return Column( children: [ ListTile( - onTap: (widget.room?.isRoomAdmin ?? true) ? setRoomCapacity : null, + onTap: setRoomCapacity, leading: CircleAvatar( backgroundColor: Theme.of(context).scaffoldBackgroundColor, foregroundColor: iconColor, @@ -91,14 +43,10 @@ class RoomCapacityButtonState extends State { trailing: Text( (capacity == null) ? L10n.of(context).noCapacityLimit - : (nonAdmins != null) - ? '$nonAdmins/$capacity' - : '$capacity', + : '$memberCount/$capacity', ), title: Text( - spaceMode - ? L10n.of(context).spaceCapacity - : L10n.of(context).chatCapacity, + L10n.of(context).chatCapacity, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, @@ -109,19 +57,11 @@ class RoomCapacityButtonState extends State { ); } - Future setCapacity(int newCapacity) async { - capacity = newCapacity; - } - Future setRoomCapacity() async { final input = await showTextInputDialog( context: context, - title: spaceMode - ? L10n.of(context).spaceCapacity - : L10n.of(context).chatCapacity, - message: spaceMode - ? L10n.of(context).spaceCapacityExplanation - : L10n.of(context).chatCapacityExplanation, + title: L10n.of(context).chatCapacity, + message: L10n.of(context).chatCapacityExplanation, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, initialText: ((capacity != null) ? '$capacity' : ''), @@ -133,10 +73,8 @@ class RoomCapacityButtonState extends State { int.parse(value) < 0) { return L10n.of(context).enterNumber; } - if (nonAdmins != null && int.parse(value) < int.parse(nonAdmins!)) { - return spaceMode - ? L10n.of(context).spaceCapacitySetTooLow - : L10n.of(context).chatCapacitySetTooLow; + if (int.parse(value) < memberCount) { + return L10n.of(context).chatCapacitySetTooLow; } return null; }, @@ -148,20 +86,12 @@ class RoomCapacityButtonState extends State { final newCapacity = int.parse(input); final success = await showFutureLoadingDialog( context: context, - future: () => ((widget.room != null) - ? (widget.room!.updateRoomCapacity( - capacity = newCapacity, - )) - : setCapacity(newCapacity)), + future: () => widget.room.updateRoomCapacity(newCapacity), ); if (success.error == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - spaceMode - ? L10n.of(context).spaceCapacityHasBeenChanged - : L10n.of(context).chatCapacityHasBeenChanged, - ), + content: Text(L10n.of(context).chatCapacityHasBeenChanged), ), ); setState(() {}); diff --git a/lib/pangea/extensions/room_events_extension.dart b/lib/pangea/extensions/room_events_extension.dart index b6d073983..12734790b 100644 --- a/lib/pangea/extensions/room_events_extension.dart +++ b/lib/pangea/extensions/room_events_extension.dart @@ -1,19 +1,6 @@ part of "pangea_room_extension.dart"; extension EventsRoomExtension on Room { - Future leaveIfFull() async { - if (!isRoomAdmin && - (capacity != null) && - (await numNonAdmins) > (capacity!)) { - if (!isSpace) { - markUnread(false); - } - await leave(); - return true; - } - return false; - } - Future leaveSpace() async { for (final child in spaceChildren) { if (child.roomId == null) continue; diff --git a/lib/pangea/spaces/controllers/space_controller.dart b/lib/pangea/spaces/controllers/space_controller.dart index 94075f858..3cede3ad5 100644 --- a/lib/pangea/spaces/controllers/space_controller.dart +++ b/lib/pangea/spaces/controllers/space_controller.dart @@ -12,7 +12,6 @@ import 'package:fluffychat/pangea/common/constants/local.key.dart'; import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import '../../common/controllers/base_controller.dart'; @@ -164,15 +163,6 @@ class ClassController extends BaseController { if (room == null) return; } - final isFull = await room.leaveIfFull(); - if (isFull) { - await showFutureLoadingDialog( - context: context, - future: () async => throw L10n.of(context).roomFull, - ); - return; - } - GoogleAnalytics.joinClass(classCode); if (room.client.getRoomById(room.id)?.membership != Membership.join) { diff --git a/lib/utils/url_launcher.dart b/lib/utils/url_launcher.dart index 2f98976fa..82bfedefa 100644 --- a/lib/utils/url_launcher.dart +++ b/lib/utils/url_launcher.dart @@ -9,7 +9,6 @@ import 'package:url_launcher/url_launcher_string.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; @@ -206,19 +205,6 @@ class UrlLauncher { serverName: servers.isNotEmpty ? servers.toList() : null, ), ); - // #Pangea - // if (response.error != null) return; - if (response.error != null || - (room != null && (await room.leaveIfFull()))) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - duration: const Duration(seconds: 10), - content: Text(L10n.of(context).roomFull), - ), - ); - return; - } - // Pangea# // wait for two seconds so that it probably came down /sync await showFutureLoadingDialog( context: context, diff --git a/lib/widgets/public_room_bottom_sheet.dart b/lib/widgets/public_room_bottom_sheet.dart index a4916afdd..cc9867c35 100644 --- a/lib/widgets/public_room_bottom_sheet.dart +++ b/lib/widgets/public_room_bottom_sheet.dart @@ -7,7 +7,6 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/utils/fluffy_share.dart'; import 'package:fluffychat/utils/url_launcher.dart'; import 'package:fluffychat/widgets/avatar.dart'; @@ -89,12 +88,6 @@ class PublicRoomBottomSheetState extends State { if (!knock && client.getRoomById(roomId) == null) { await client.waitForRoomInSync(roomId); } - // #Pangea - final room = client.getRoomById(roomId); - if (room != null && (await room.leaveIfFull())) { - throw L10n.of(context).roomFull; - } - // Pangea# return roomId; }, );