Merge branch 'main' into analytics-rooms-data

pull/1183/head
ggurdin 1 year ago
commit a9105c0804

@ -3948,6 +3948,15 @@
"roomDataMissing": "Some data may be missing from rooms in which you are not a member.",
"updatePhoneOS": "You may need to update your device's OS version.",
"wordsPerMinute": "Words per minute",
"roomCapacity": "Room Capacity",
"roomFull": "This room is already at capacity.",
"topicNotSet": "The topic has not been set.",
"capacityNotSet": "This room has no capacity limit.",
"roomCapacityHasBeenChanged": "Room capacity changed",
"roomExceedsCapacity": "Room exceeds capacity. Consider removing students from the room, or raising the capacity.",
"capacitySetTooLow": "Room capacity cannot be set below the current number of non-admins.",
"roomCapacityExplanation": "Room capacity limits the number of non-admins allowed in a room.",
"enterNumber": "Please enter a whole number value.",
"autoIGCToolName": "Run Language Assistance Automatically",
"autoIGCToolDescription": "Automatically run language assistance after typing messages",
"runGrammarCorrection": "Run grammar correction",

@ -67,7 +67,10 @@ class ChatPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final room = Matrix.of(context).client.getRoomById(roomId);
if (room == null) {
// #Pangea
if (room == null || room.membership == Membership.leave) {
// if (room == null) {
// Pangea#
return Scaffold(
appBar: AppBar(title: Text(L10n.of(context)!.oopsSomethingWentWrong)),
body: Center(

@ -21,6 +21,7 @@ import 'package:fluffychat/widgets/unread_rooms_badge.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart';
import '../../utils/stream_extension.dart';
@ -152,6 +153,11 @@ class ChatView extends StatelessWidget {
context: context,
future: () => controller.room.join(),
);
// #Pangea
controller.room.leaveIfFull().then(
(full) => full ? context.go('/rooms') : null,
);
// Pangea#
}
final bottomSheetPadding = FluffyThemes.isColumnMode(context) ? 16.0 : 8.0;
final scrollUpBannerEventId = controller.scrollUpBannerEventId;

@ -3,8 +3,8 @@ import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:fluffychat/pages/chat_details/chat_details_view.dart';
import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_description_button.dart';
import 'package:fluffychat/pangea/utils/set_class_name.dart';
import 'package:fluffychat/pangea/utils/set_class_topic.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';

@ -8,6 +8,7 @@ import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_des
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_details_toggle_add_students_tile.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_invitation_buttons.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_name_button.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart';
import 'package:fluffychat/pangea/utils/lock_room.dart';
import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart';
@ -34,7 +35,10 @@ class ChatDetailsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final room = Matrix.of(context).client.getRoomById(controller.roomId!);
if (room == null) {
// #Pangea
if (room == null || room.membership == Membership.leave) {
// if (room == null) {
// Pangea#
return Scaffold(
appBar: AppBar(
title: Text(L10n.of(context)!.oopsSomethingWentWrong),
@ -236,8 +240,9 @@ class ChatDetailsView extends StatelessWidget {
height: 1,
color: Theme.of(context).dividerColor,
),
// #Pangea
if (room.canSendEvent('m.room.name'))
// if (room.canSendEvent('m.room.name'))
if (room.isRoomAdmin)
// #Pangea
ClassNameButton(
room: room,
controller: controller,
@ -247,6 +252,12 @@ class ChatDetailsView extends StatelessWidget {
room: room,
controller: controller,
),
// #Pangea
RoomCapacityButton(
room: room,
controller: controller,
),
// Pangea#
if ((room.isPangeaClass || room.isExchange) &&
room.isRoomAdmin)
ListTile(
@ -435,7 +446,9 @@ class ChatDetailsView extends StatelessWidget {
// : null,
// ),
// if (!room.isDirectChat)
if (!room.isDirectChat && !room.isSpace)
if (!room.isDirectChat &&
!room.isSpace &&
room.isRoomAdmin)
// Pangea#
ListTile(
// #Pangea
@ -510,7 +523,9 @@ class ChatDetailsView extends StatelessWidget {
room: room,
),
const Divider(height: 1),
if (!room.isPangeaClass && !room.isDirectChat)
if (!room.isPangeaClass &&
!room.isDirectChat &&
room.isRoomAdmin)
AddToSpaceToggles(
roomId: room.id,
key: controller.addToSpaceKey,

@ -179,6 +179,12 @@ class _SpaceViewState extends State<SpaceView> {
// Wait for room actually appears in sync
await client.waitForRoomInSync(spaceChild.roomId, join: true);
}
// #Pangea
final room = client.getRoomById(spaceChild.roomId);
if (room != null && (await room.leaveIfFull())) {
throw L10n.of(context)!.roomFull;
}
// Pangea#
},
);
if (result.error != null) return;
@ -197,6 +203,9 @@ class _SpaceViewState extends State<SpaceView> {
);
await room.join();
await waitForRoom;
if (await room.leaveIfFull()) {
throw L10n.of(context)!.roomFull;
}
},
);
if (joinResult.error != null) return;
@ -271,9 +280,8 @@ class _SpaceViewState extends State<SpaceView> {
icon: Icons.architecture_outlined,
isDestructiveAction: true,
),
// if (room != null)
if (room != null && room.membership != Membership.leave)
// if (room != null)
// Pangea#
SheetAction(
key: SpaceChildContextAction.leave,
@ -329,34 +337,14 @@ class _SpaceViewState extends State<SpaceView> {
case SpaceChildContextAction.archive:
widget.controller.cancelAction();
// #Pangea
if (room == null) return;
// room.isSpace
// ? await showFutureLoadingDialog(
// context: context,
// future: () async {
// await room.archiveSpace(
// Matrix.of(context).client,
// );
// widget.controller.selectedRoomIds.clear();
// },
// )
// : await widget.controller.archiveAction();
if (room.isSpace) {
await room.archiveSpace(
context,
Matrix.of(context).client,
);
} else {
widget.controller.toggleSelection(room.id);
await widget.controller.archiveAction();
}
if (room == null || room.membership == Membership.leave) return;
// Pangea#
_refresh();
break;
case SpaceChildContextAction.addToSpace:
widget.controller.cancelAction();
// #Pangea
if (room == null) return;
if (room == null || room.membership == Membership.leave) return;
// Pangea#
widget.controller.toggleSelection(room.id);
await widget.controller.addToSpace();
@ -614,7 +602,7 @@ class _SpaceViewState extends State<SpaceView> {
MatrixLocals(L10n.of(context)!),
);
return Material(
color: Theme.of(context).colorScheme.background,
color: Theme.of(context).colorScheme.surface,
child: ListTile(
leading: Avatar(
mxContent: rootSpace.avatar,
@ -949,7 +937,7 @@ class _SpaceViewState extends State<SpaceView> {
: L10n.of(context)!.enterRoom),
maxLines: 1,
style: TextStyle(
color: Theme.of(context).colorScheme.onBackground,
color: Theme.of(context).colorScheme.onSurface,
),
),
trailing: isSpace

@ -1,5 +1,6 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/pages/chat/send_file_dialog.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
@ -65,6 +66,9 @@ void onChatTap(Room room, BuildContext context) async {
room.id,
join: true,
);
if (await room.leaveIfFull()) {
throw L10n.of(context)!.roomFull;
}
await room.join();
await waitForRoom;
},

@ -3,8 +3,10 @@ import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:fluffychat/pages/new_group/new_group_view.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/models/chat_topic_model.dart';
import 'package:fluffychat/pangea/models/lemma.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/utils/class_chat_power_levels.dart';
import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
@ -51,6 +53,8 @@ class NewGroupController extends State<NewGroup> {
final GlobalKey<AddToSpaceState> addToSpaceKey = GlobalKey<AddToSpaceState>();
final GlobalKey<ConversationBotSettingsState> addConversationBotKey =
GlobalKey<ConversationBotSettingsState>();
final GlobalKey<RoomCapacityButtonState> addCapacityKey =
GlobalKey<RoomCapacityButtonState>();
ChatTopic chatTopic = ChatTopic.empty;
@ -145,10 +149,16 @@ class NewGroupController extends State<NewGroup> {
visibility: sdk.Visibility.public,
);
}
//#Pangea
// #Pangea
GoogleAnalytics.createChat(roomId);
await addToSpaceKey.currentState!.addSpaces(roomId);
//Pangea#
final capacity = addCapacityKey.currentState?.capacity;
final room = client.getRoomById(roomId);
if (capacity != null && room != null) {
room.updateRoomCapacity(capacity);
}
// Pangea#
context.go('/rooms/$roomId/invite');
} catch (e, s) {
sdk.Logs().d('Unable to create group', e, s);

@ -1,5 +1,6 @@
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/new_group/new_group.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
@ -87,6 +88,9 @@ class NewGroupView extends StatelessWidget {
// ),
// ),
// ),
RoomCapacityButton(
key: controller.addCapacityKey,
),
ConversationBotSettings(
key: controller.addConversationBotKey,
activeSpaceId: controller.activeSpaceId,

@ -4,6 +4,7 @@ import 'package:file_picker/file_picker.dart';
import 'package:fluffychat/pages/new_space/new_space_view.dart';
import 'package:fluffychat/pangea/constants/class_default_values.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/utils/class_chat_power_levels.dart';
@ -37,6 +38,8 @@ class NewSpaceController extends State<NewSpace> {
final GlobalKey<AddToSpaceState> addToSpaceKey = GlobalKey<AddToSpaceState>();
final GlobalKey<ClassSettingsState> classSettingsKey =
GlobalKey<ClassSettingsState>();
final GlobalKey<RoomCapacityButtonState> addCapacityKey =
GlobalKey<RoomCapacityButtonState>();
//Pangea#
bool loading = false;
@ -196,6 +199,11 @@ class NewSpaceController extends State<NewSpace> {
}
await Future.wait(futures);
final capacity = addCapacityKey.currentState?.capacity;
final space = client.getRoomById(spaceId);
if (capacity != null && space != null) {
space.updateRoomCapacity(capacity);
}
final newChatRoomId = await Matrix.of(context).client.createGroupChat(
enableEncryption: false,
preset: sdk.CreateRoomPreset.publicChat,

@ -1,6 +1,7 @@
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart';
import 'package:fluffychat/pangea/models/class_model.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart';
import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
@ -130,6 +131,10 @@ class NewSpaceView extends StatelessWidget {
// ),
// ),
// const SizedBox(height: 16),
RoomCapacityButton(
key: controller.addCapacityKey,
),
if (controller.newClassMode)
ClassSettings(
key: controller.classSettingsKey,

@ -20,6 +20,7 @@ class PangeaEventTypes {
static const audio = "p.audio";
static const botOptions = "pangea.bot_options";
static const capacity = "pangea.capacity";
static const userAge = "pangea.user_age";

@ -13,6 +13,7 @@ import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
import '../../widgets/matrix.dart';
@ -133,8 +134,9 @@ class ClassController extends BaseController {
ClassCodeUtil.messageSnack(context, L10n.of(context)!.alreadyInClass);
return;
}
await _pangeaController.matrixState.client.joinRoom(classChunk.roomId);
setActiveSpaceIdInChatListController(classChunk.roomId);
if (_pangeaController.matrixState.client.getRoomById(classChunk.roomId) ==
null) {
await _pangeaController.matrixState.client.waitForRoomInSync(
@ -143,6 +145,26 @@ class ClassController extends BaseController {
);
}
// If the room is full, leave
final room =
_pangeaController.matrixState.client.getRoomById(classChunk.roomId);
if (room == null) {
return;
}
final joinResult = await showFutureLoadingDialog(
context: context,
future: () async {
if (await room.leaveIfFull()) {
throw L10n.of(context)!.roomFull;
}
},
);
if (joinResult.error != null) {
return;
}
setActiveSpaceIdInChatListController(classChunk.roomId);
// add the user's analytics room to this joined space
// so their teachers can join them via the space hierarchy
final Room? joinedSpace =

@ -1,6 +1,20 @@
part of "pangea_room_extension.dart";
extension EventsRoomExtension on Room {
Future<bool> _leaveIfFull() async {
await postLoad();
if (!isRoomAdmin &&
(_capacity != null) &&
(await _numNonAdmins) > (_capacity!)) {
if (!isSpace) {
markUnread(false);
}
await leave();
return true;
}
return false;
}
Future<void> _archive() async {
final students = (await requestParticipants())
.where(

@ -137,6 +137,7 @@ extension PangeaRoom on Room {
// events
Future<bool> leaveIfFull() async => await _leaveIfFull();
Future<void> archive() async => await _archive();
Future<bool> archiveSpace(
@ -200,6 +201,8 @@ extension PangeaRoom on Room {
// room_information
Future<int> get numNonAdmins async => await _numNonAdmins;
DateTime? get creationTime => _creationTime;
String? get creatorId => _creatorId;
@ -230,6 +233,11 @@ extension PangeaRoom on Room {
// room_settings
Future<void> updateRoomCapacity(int newCapacity) =>
_updateRoomCapacity(newCapacity);
int? get capacity => _capacity;
PangeaRoomRules? get pangeaRoomRules => _pangeaRoomRules;
PangeaRoomRules? get firstRules => _firstRules;

@ -1,6 +1,17 @@
part of "pangea_room_extension.dart";
extension RoomInformationRoomExtension on Room {
Future<int> get _numNonAdmins async {
return (await requestParticipants())
.where(
(e) =>
e.powerLevel < ClassDefaultValues.powerLevelOfAdmin &&
e.id != BotName.byEnvironment,
)
.toList()
.length;
}
DateTime? get _creationTime =>
getState(EventTypes.RoomCreate)?.originServerTs;

@ -1,6 +1,19 @@
part of "pangea_room_extension.dart";
extension RoomSettingsRoomExtension on Room {
Future<void> _updateRoomCapacity(int newCapacity) =>
client.setRoomStateWithKey(
id,
PangeaEventTypes.capacity,
'',
{'capacity': newCapacity},
);
int? get _capacity {
final t = getState(PangeaEventTypes.capacity)?.content['capacity'];
return t is int ? t : null;
}
PangeaRoomRules? get _pangeaRoomRules {
try {
final Map<String, dynamic>? content = pangeaRoomRulesStateEvent?.content;

@ -1,10 +1,10 @@
import 'package:fluffychat/pages/chat_details/chat_details.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/pages/chat_details/chat_details.dart';
class ClassDescriptionButton extends StatelessWidget {
final Room room;
final ChatDetailsController controller;
@ -20,21 +20,19 @@ class ClassDescriptionButton extends StatelessWidget {
return Column(
children: [
ListTile(
onTap: room.canSendEvent(EventTypes.RoomTopic)
? controller.setTopicAction
: null,
leading: room.canSendEvent(EventTypes.RoomTopic)
? CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: iconColor,
child: const Icon(Icons.topic_outlined),
)
: null,
onTap: room.isRoomAdmin ? controller.setTopicAction : null,
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: iconColor,
child: const Icon(Icons.topic_outlined),
),
subtitle: Text(
room.topic.isEmpty
? (room.isSpace
? L10n.of(context)!.classDescriptionDesc
: L10n.of(context)!.chatTopicDesc)
? (room.isRoomAdmin
? (room.isSpace
? L10n.of(context)!.classDescriptionDesc
: L10n.of(context)!.chatTopicDesc)
: L10n.of(context)!.topicNotSet)
: room.topic,
),
title: Text(
@ -51,3 +49,53 @@ class ClassDescriptionButton extends StatelessWidget {
);
}
}
void setClassTopic(Room room, BuildContext context) {
final TextEditingController textFieldController =
TextEditingController(text: room.topic);
showDialog(
context: context,
useRootNavigator: false,
builder: (BuildContext context) => AlertDialog(
title: Text(
room.isSpace
? L10n.of(context)!.classDescription
: L10n.of(context)!.chatTopic,
),
content: TextField(
controller: textFieldController,
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 10,
maxLength: 2000,
),
actions: [
TextButton(
child: Text(L10n.of(context)!.cancel),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text(L10n.of(context)!.ok),
onPressed: () async {
if (textFieldController.text == "") return;
final success = await showFutureLoadingDialog(
context: context,
future: () => room.setDescription(textFieldController.text),
);
if (success.error == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text(L10n.of(context)!.groupDescriptionHasBeenChanged),
),
);
Navigator.of(context).pop();
}
},
),
],
),
);
}

@ -0,0 +1,158 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/pages/chat_details/chat_details.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
class RoomCapacityButton extends StatefulWidget {
final Room? room;
final ChatDetailsController? controller;
const RoomCapacityButton({
super.key,
this.room,
this.controller,
});
@override
RoomCapacityButtonState createState() => RoomCapacityButtonState();
}
class RoomCapacityButtonState extends State<RoomCapacityButton> {
int? capacity;
String? nonAdmins;
RoomCapacityButtonState({Key? key});
@override
void initState() {
super.initState();
capacity = 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 = widget.room?.capacity;
widget.room?.numNonAdmins.then(
(value) => setState(() {
nonAdmins = value.toString();
overCapacity();
}),
);
}
}
Future<void> overCapacity() async {
if ((widget.room?.isRoomAdmin ?? false) &&
capacity != null &&
nonAdmins != null &&
int.parse(nonAdmins!) > capacity!) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
L10n.of(context)!.roomExceedsCapacity,
),
),
);
}
}
@override
Widget build(BuildContext context) {
final iconColor = Theme.of(context).textTheme.bodyLarge!.color;
return Column(
children: [
ListTile(
onTap: () =>
((widget.room?.isRoomAdmin ?? true) ? (setRoomCapacity()) : null),
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: iconColor,
child: const Icon(Icons.reduce_capacity),
),
subtitle: Text(
(capacity == null)
? L10n.of(context)!.capacityNotSet
: (nonAdmins != null)
? '$nonAdmins/$capacity'
: '$capacity',
),
title: Text(
L10n.of(context)!.roomCapacity,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
],
);
}
Future<void> setCapacity(int newCapacity) async {
capacity = newCapacity;
}
Future<void> setRoomCapacity() async {
final input = await showTextInputDialog(
context: context,
title: L10n.of(context)!.roomCapacity,
message: L10n.of(context)!.roomCapacityExplanation,
okLabel: L10n.of(context)!.ok,
cancelLabel: L10n.of(context)!.cancel,
textFields: [
DialogTextField(
initialText: ((capacity != null) ? '$capacity' : ''),
keyboardType: TextInputType.number,
maxLength: 3,
validator: (value) {
if (value == null ||
value.isEmpty ||
int.tryParse(value) == null ||
int.parse(value) < 0) {
return L10n.of(context)!.enterNumber;
}
if (nonAdmins != null && int.parse(value) < int.parse(nonAdmins!)) {
return L10n.of(context)!.capacitySetTooLow;
}
return null;
},
),
],
);
if (input == null ||
input.first == "" ||
int.tryParse(input.first) == null) {
return;
}
final newCapacity = int.parse(input.first);
final success = await showFutureLoadingDialog(
context: context,
future: () => ((widget.room != null)
? (widget.room!.updateRoomCapacity(
capacity = newCapacity,
))
: setCapacity(newCapacity)),
);
if (success.error == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
L10n.of(context)!.roomCapacityHasBeenChanged,
),
),
);
setState(() {});
}
}
}

@ -33,6 +33,9 @@ void chatListHandleSpaceTap(
context: context,
future: () async {
await space.join();
if (await space.leaveIfFull()) {
throw L10n.of(context)!.roomFull;
}
await space.postLoad();
setActiveSpaceAndCloseChat();
},
@ -65,6 +68,9 @@ void chatListHandleSpaceTap(
context: context,
future: () async {
await space.join();
if (await space.leaveIfFull()) {
throw L10n.of(context)!.roomFull;
}
if (space.isSpace) {
await space.joinAnalyticsRoomsInSpace();
}

@ -1,54 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
void setClassTopic(Room room, BuildContext context) {
final TextEditingController textFieldController =
TextEditingController(text: room.topic);
showDialog(
context: context,
useRootNavigator: false,
builder: (BuildContext context) => AlertDialog(
title: Text(
room.isSpace
? L10n.of(context)!.classDescription
: L10n.of(context)!.chatTopic,
),
content: TextField(
controller: textFieldController,
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 10,
maxLength: 2000,
),
actions: [
TextButton(
child: Text(L10n.of(context)!.cancel),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text(L10n.of(context)!.ok),
onPressed: () async {
if (textFieldController.text == "") return;
final success = await showFutureLoadingDialog(
context: context,
future: () => room.setDescription(textFieldController.text),
);
if (success.error == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text(L10n.of(context)!.groupDescriptionHasBeenChanged),
),
);
Navigator.of(context).pop();
}
},
),
],
),
);
}

@ -116,6 +116,7 @@ abstract class ClientManager {
PangeaEventTypes.botOptions,
EventTypes.RoomTopic,
EventTypes.RoomAvatar,
PangeaEventTypes.capacity,
// Pangea#
},
logLevel: kReleaseMode ? Level.warning : Level.verbose,

@ -1,7 +1,12 @@
import 'package:flutter/material.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart' show IterableExtension;
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/pangea_room_extension.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart';
@ -9,11 +14,6 @@ import 'package:matrix/matrix.dart';
import 'package:punycode/punycode.dart';
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/utils/adaptive_bottom_sheet.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
import 'platform_infos.dart';
class UrlLauncher {
@ -159,7 +159,10 @@ class UrlLauncher {
room = matrix.client.getRoomById(roomId!);
}
servers.addAll(identityParts.via);
if (room != null) {
// #Pangea
if (room != null && room.membership != Membership.leave) {
// if (room != null) {
// Pangea#
if (room.isSpace) {
// TODO: Implement navigate to space
context.go('/rooms/${room.id}');
@ -202,7 +205,19 @@ class UrlLauncher {
serverName: servers.isNotEmpty ? servers.toList() : null,
),
);
if (response.error != null) return;
// #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,

@ -1,15 +1,15 @@
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:fluffychat/utils/url_launcher.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:fluffychat/utils/url_launcher.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart';
import '../utils/localized_exception_extension.dart';
class PublicRoomBottomSheet extends StatelessWidget {
@ -44,6 +44,12 @@ class PublicRoomBottomSheet extends StatelessWidget {
if (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;
},
);

@ -839,6 +839,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -2288,6 +2297,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -3199,6 +3217,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -4110,6 +4137,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -5021,6 +5057,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -5932,6 +5977,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -6790,6 +6844,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -7701,6 +7764,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -8612,6 +8684,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -8629,6 +8710,15 @@
"es": [
"suggestToChat",
"suggestToChatDesc",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -9483,6 +9573,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -10337,6 +10436,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -11248,6 +11356,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -12159,6 +12276,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -13070,6 +13196,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -13981,6 +14116,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -14835,6 +14979,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -15746,6 +15899,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -16657,6 +16819,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -17555,6 +17726,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -18466,6 +18646,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -19901,6 +20090,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -20812,6 +21010,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -21723,6 +21930,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -22619,6 +22835,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -23530,6 +23755,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -24441,6 +24675,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -25352,6 +25595,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -26263,6 +26515,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -27174,6 +27435,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -28085,6 +28355,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -28996,6 +29275,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -29907,6 +30195,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -30787,6 +31084,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -31698,6 +32004,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -32609,6 +32924,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -33463,6 +33787,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -34374,6 +34707,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -35285,6 +35627,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -36196,6 +36547,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -37072,6 +37432,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -37983,6 +38352,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -38894,6 +39272,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -39790,6 +40177,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -40644,6 +41040,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -41555,6 +41960,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -42409,6 +42823,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",
@ -43320,6 +43743,15 @@
"roomDataMissing",
"updatePhoneOS",
"wordsPerMinute",
"roomCapacity",
"roomFull",
"topicNotSet",
"capacityNotSet",
"roomCapacityHasBeenChanged",
"roomExceedsCapacity",
"capacitySetTooLow",
"roomCapacityExplanation",
"enterNumber",
"autoIGCToolName",
"autoIGCToolDescription",
"runGrammarCorrection",

Loading…
Cancel
Save