From 8f568fdb7204b83ed66b6fd214c1f0f260ebb7ea Mon Sep 17 00:00:00 2001 From: Gabby Gurdin Date: Tue, 5 Mar 2024 11:13:23 -0500 Subject: [PATCH 1/5] use mode to control invited user's power level --- lib/pages/chat_list/chat_list_item.dart | 10 +- .../invitation_selection.dart | 107 +++++++++++------- .../invitation_selection_view.dart | 6 + 3 files changed, 80 insertions(+), 43 deletions(-) diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 949b18112..dea77a6eb 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -111,7 +111,15 @@ class ChatListItem extends StatelessWidget { if (room.membership == Membership.join) { // Share content into this room - final shareContent = Matrix.of(context).shareContent; + // #Pangea + // final shareContent = Matrix.of(context).shareContent; + Map? shareContent; + try { + shareContent = Matrix.of(context).shareContent; + } catch (e) { + shareContent = null; + } + // Pangea# if (shareContent != null) { final shareFile = shareContent.tryGet('file'); if (shareContent.tryGet('msgtype') == diff --git a/lib/pages/invitation_selection/invitation_selection.dart b/lib/pages/invitation_selection/invitation_selection.dart index 4811934eb..a762d398c 100644 --- a/lib/pages/invitation_selection/invitation_selection.dart +++ b/lib/pages/invitation_selection/invitation_selection.dart @@ -75,7 +75,9 @@ class InvitationSelectionController extends State { } final eligibleStudents = []; - final spaceParents = room.pangeaSpaceParents; + final spaceParents = room?.pangeaSpaceParents; + if (spaceParents == null) return eligibleStudents; + final userId = Matrix.of(context).client.userID; for (final Room space in spaceParents) { eligibleStudents.addAll( @@ -115,15 +117,25 @@ class InvitationSelectionController extends State { ); } - List studentsInRoom(BuildContext context) => room - .getParticipants() - .where( - (u) => [Membership.join, Membership.invite].contains(u.membership), - ) - .toList(); + List studentsInRoom(BuildContext context) => + room + ?.getParticipants() + .where( + (u) => [Membership.join, Membership.invite].contains(u.membership), + ) + .toList() ?? + []; //Pangea# - void inviteAction(BuildContext context, String id, String displayname) async { + // #Pangea + // void inviteAction(BuildContext context, String id, String displayname) async { + void inviteAction( + BuildContext context, + String id, + String displayname, { + InvitationSelectionMode? mode, + }) async { + // Pangea# final room = Matrix.of(context).client.getRoomById(roomId!)!; if (OkCancelResult.ok != await showOkCancelAlertDialog( @@ -144,25 +156,12 @@ class InvitationSelectionController extends State { context: context, //#Pangea // future: () => room.invite(id), - future: () => Future.wait([ - room.invite(id), - room.setPower(id, ClassDefaultValues.powerLevelOfAdmin), - if (room.isSpace) - ...room.spaceChildren - .map( - (e) => roomId != null - ? Matrix.of(context).client.getRoomById(e.roomId!) - : null, - ) - .where((element) => element != null) - .cast() - .map( - (e) => Future.wait([ - e.invite(id), - e.setPower(id, ClassDefaultValues.powerLevelOfAdmin), - ]), - ), - ]), + future: () async { + await room.invite(id); + if (mode == InvitationSelectionMode.admin) { + await inviteTeacherAction(room, id); + } + }, // Pangea# ); if (success.error == null) { @@ -174,6 +173,26 @@ class InvitationSelectionController extends State { } } + // #Pangea + Future inviteTeacherAction(Room room, String id) async { + room.setPower(id, ClassDefaultValues.powerLevelOfAdmin); + if (room.isSpace) { + for (final spaceChild in room.spaceChildren) { + if (spaceChild.roomId == null) continue; + final spaceChildRoom = + Matrix.of(context).client.getRoomById(spaceChild.roomId!); + if (spaceChildRoom != null) { + await spaceChildRoom.invite(id); + await spaceChildRoom.setPower( + id, + ClassDefaultValues.powerLevelOfAdmin, + ); + } + } + } + } + // Pangea# + void searchUserWithCoolDown(String text) async { coolDown?.cancel(); coolDown = Timer( @@ -224,8 +243,8 @@ class InvitationSelectionController extends State { //#Pangea final participants = Matrix.of(context) .client - .getRoomById(roomId!)! - .getParticipants() + .getRoomById(roomId!) + ?.getParticipants() .where( (user) => [Membership.join, Membership.invite].contains(user.membership), @@ -233,7 +252,7 @@ class InvitationSelectionController extends State { .toList(); foundProfiles.removeWhere( (profile) => - participants.indexWhere((u) => u.id == profile.userId) != -1 && + participants?.indexWhere((u) => u.id == profile.userId) != -1 && BotName.byEnvironment != profile.userId, ); //Pangea# @@ -242,17 +261,19 @@ class InvitationSelectionController extends State { //#Pangea Room? _room; - Room get room => _room ??= Matrix.of(context).client.getRoomById(roomId!)!; + Room? get room => _room ??= Matrix.of(context).client.getRoomById(roomId!); // request participants for all parent spaces Future requestParentSpaceParticipants() async { - final spaceParents = room.pangeaSpaceParents; - await Future.wait([ - ...spaceParents.map((r) async { - await r.requestParticipants(); - }), - room.requestParticipants(), - ]); + final spaceParents = room?.pangeaSpaceParents; + if (spaceParents != null) { + await Future.wait([ + ...spaceParents.map((r) async { + await r.requestParticipants(); + }), + room!.requestParticipants(), + ]); + } } InvitationSelectionMode mode = InvitationSelectionMode.member; @@ -263,7 +284,7 @@ class InvitationSelectionController extends State { Future.delayed( Duration.zero, () => setState( - () => mode = room.isSpace + () => mode = room?.isSpace ?? false ? InvitationSelectionMode.admin : InvitationSelectionMode.member, ), @@ -275,9 +296,11 @@ class InvitationSelectionController extends State { .where( (event) => event.rooms?.join?.keys.any( - (ithRoomId) => room.pangeaSpaceParents - .map((e) => e.id) - .contains(ithRoomId), + (ithRoomId) => + room?.pangeaSpaceParents + .map((e) => e.id) + .contains(ithRoomId) ?? + false, ) ?? false, ) diff --git a/lib/pages/invitation_selection/invitation_selection_view.dart b/lib/pages/invitation_selection/invitation_selection_view.dart index 5a2621046..cafa5fec7 100644 --- a/lib/pages/invitation_selection/invitation_selection_view.dart +++ b/lib/pages/invitation_selection/invitation_selection_view.dart @@ -106,6 +106,9 @@ class InvitationSelectionView extends StatelessWidget { controller.foundProfiles[i].displayName ?? controller.foundProfiles[i].userId.localpart ?? L10n.of(context)!.user, + // #Pangea + mode: controller.mode, + // Pangea# ), ), ) @@ -143,6 +146,9 @@ class InvitationSelectionView extends StatelessWidget { contacts[i].displayName ?? contacts[i].id.localpart ?? L10n.of(context)!.user, + // #Pangea + mode: controller.mode, + // Pangea# ), ), ); From 67557dfb26ac472b9417d9290aba66c4d660718a Mon Sep 17 00:00:00 2001 From: Gabby Gurdin Date: Tue, 5 Mar 2024 11:58:59 -0500 Subject: [PATCH 2/5] widened criteria for bot DM rooms and prevent new one from being created if one is already present --- lib/pangea/controllers/pangea_controller.dart | 7 ++++- lib/pangea/extensions/client_extension.dart | 11 ++++++++ .../extensions/pangea_room_extension.dart | 3 ++ lib/pangea/pages/p_user_age/p_user_age.dart | 28 ++++++++++--------- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/pangea/controllers/pangea_controller.dart b/lib/pangea/controllers/pangea_controller.dart index 79006aa9d..86946f314 100644 --- a/lib/pangea/controllers/pangea_controller.dart +++ b/lib/pangea/controllers/pangea_controller.dart @@ -14,6 +14,7 @@ import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart'; import 'package:fluffychat/pangea/controllers/user_controller.dart'; import 'package:fluffychat/pangea/controllers/word_net_controller.dart'; +import 'package:fluffychat/pangea/extensions/client_extension.dart'; import 'package:fluffychat/pangea/guard/p_vguard.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -164,7 +165,11 @@ class PangeaController { void startChatWithBotIfNotPresent() { Future.delayed(const Duration(milliseconds: 10000), () async { // check if user is logged in - if (!matrixState.client.isLogged()) return; + if (!matrixState.client.isLogged() || + (await matrixState.client.hasBotDM)) { + return; + } + try { await matrixState.client.startDirectChat( BotName.byEnvironment, diff --git a/lib/pangea/extensions/client_extension.dart b/lib/pangea/extensions/client_extension.dart index 98353d29b..ea0c709d7 100644 --- a/lib/pangea/extensions/client_extension.dart +++ b/lib/pangea/extensions/client_extension.dart @@ -168,4 +168,15 @@ extension PangeaClient on Client { ) .firstOrNull ?.classSettings; + + Future get hasBotDM async { + final List chats = rooms + .where((room) => !room.isSpace && room.membership == Membership.join) + .toList(); + + for (final Room chat in chats) { + if (await chat.isBotDM) return true; + } + return false; + } } diff --git a/lib/pangea/extensions/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension.dart index 1b6370ce1..96b5711a3 100644 --- a/lib/pangea/extensions/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension.dart @@ -995,6 +995,9 @@ extension PangeaRoom on Room { ); } + Future get isBotDM async => + (await isBotRoom) && getParticipants().length == 2; + BotOptionsModel? get botOptions { if (isSpace) return null; return BotOptionsModel.fromJson( diff --git a/lib/pangea/pages/p_user_age/p_user_age.dart b/lib/pangea/pages/p_user_age/p_user_age.dart index 9d59e84b5..3cb1fccc5 100644 --- a/lib/pangea/pages/p_user_age/p_user_age.dart +++ b/lib/pangea/pages/p_user_age/p_user_age.dart @@ -2,6 +2,7 @@ import 'dart:developer'; import 'package:fluffychat/pangea/constants/age_limits.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +import 'package:fluffychat/pangea/extensions/client_extension.dart'; import 'package:fluffychat/pangea/pages/p_user_age/p_user_age_view.dart'; import 'package:fluffychat/pangea/utils/p_extension.dart'; import 'package:fluffychat/widgets/fluffy_chat_app.dart'; @@ -34,19 +35,20 @@ class PUserAgeController extends State { @override void initState() { super.initState(); - Future.delayed( - Duration.zero, - () => Matrix.of(context) - .client - .startDirectChat( - BotName.byEnvironment, - enableEncryption: false, - ) - .onError( - (error, stackTrace) => - ErrorHandler.logError(e: error, s: stackTrace), - ), - ); + Future.delayed(Duration.zero, () async { + if (!(await Matrix.of(context).client.hasBotDM)) { + Matrix.of(context) + .client + .startDirectChat( + BotName.byEnvironment, + enableEncryption: false, + ) + .onError( + (error, stackTrace) => + ErrorHandler.logError(e: error, s: stackTrace), + ); + } + }); } String? dobValidator() { From 591b0d0fa2829d079118485466d64633f6ac25b3 Mon Sep 17 00:00:00 2001 From: Gabby Gurdin Date: Tue, 5 Mar 2024 12:18:27 -0500 Subject: [PATCH 3/5] remove irrelevant settings from DM chat details --- lib/pages/chat_details/chat_details_view.dart | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index a095d49fd..a420a4ff0 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -461,6 +461,7 @@ class ChatDetailsView extends StatelessWidget { ), // #Pangea if (room.canInvite && + !room.isDirectChat && (!room.isSpace || room.isRoomAdmin)) ListTile( title: Text( @@ -491,13 +492,15 @@ class ChatDetailsView extends StatelessWidget { room.showClassEditOptions) ClassInvitationButtons(roomId: controller.roomId!), const Divider(height: 1), - if (!room.isSpace && room.canInvite) + if (!room.isSpace && + !room.isDirectChat && + room.canInvite) ConversationBotSettings( key: controller.addConversationBotKey, room: room, ), const Divider(height: 1), - if (!room.isPangeaClass) + if (!room.isPangeaClass && !room.isDirectChat) AddToSpaceToggles( roomId: room.id, key: controller.addToSpaceKey, @@ -507,7 +510,9 @@ class ChatDetailsView extends StatelessWidget { : AddToClassMode.chat, ), const Divider(height: 1), - if (!room.isSpace || (room.isSpace && room.isRoomAdmin)) + if (!room.isDirectChat && + (!room.isSpace || + (room.isSpace && room.isRoomAdmin))) ListTile( title: Text( room.isSpace @@ -539,7 +544,7 @@ class ChatDetailsView extends StatelessWidget { }, ), ), - if (room.isRoomAdmin) + if (room.isRoomAdmin && !room.isDirectChat) SwitchListTile.adaptive( activeColor: AppConfig.activeToggleColor, title: Text( From 6461496c7e98aa362e6afa4ed4e7331b477b7c9f Mon Sep 17 00:00:00 2001 From: Gabby Gurdin Date: Tue, 5 Mar 2024 12:58:18 -0500 Subject: [PATCH 4/5] disable encryption for direct chats from user bottom sheet --- .../user_bottom_sheet/user_bottom_sheet.dart | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/pages/user_bottom_sheet/user_bottom_sheet.dart b/lib/pages/user_bottom_sheet/user_bottom_sheet.dart index e2ae9c9ff..7c2d84273 100644 --- a/lib/pages/user_bottom_sheet/user_bottom_sheet.dart +++ b/lib/pages/user_bottom_sheet/user_bottom_sheet.dart @@ -1,13 +1,12 @@ -import 'package:flutter/material.dart'; - import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/widgets/permission_slider_dialog.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 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/widgets/permission_slider_dialog.dart'; import '../../widgets/matrix.dart'; import 'user_bottom_sheet_view.dart'; @@ -232,9 +231,12 @@ class UserBottomSheetController extends State { final roomIdResult = await showFutureLoadingDialog( context: widget.outerContext, - future: () => Matrix.of(widget.outerContext) - .client - .startDirectChat(user?.id ?? widget.profile!.userId), + future: () => Matrix.of(widget.outerContext).client.startDirectChat( + user?.id ?? widget.profile!.userId, + // #Pangea + enableEncryption: false, + // Pangea# + ), ); final roomId = roomIdResult.result; if (roomId == null) return; From 8bef7b2e2bd8231c27fa19ac6a5f0548ca87ab23 Mon Sep 17 00:00:00 2001 From: Gabby Gurdin Date: Tue, 5 Mar 2024 13:19:41 -0500 Subject: [PATCH 5/5] fix for bugs with locked room icons --- lib/pages/chat/chat_event_list.dart | 3 +-- lib/pages/chat_details/chat_details_view.dart | 4 ++-- lib/pages/chat_list/chat_list_item.dart | 2 +- lib/pangea/extensions/pangea_room_extension.dart | 6 +++--- lib/pangea/utils/lock_room.dart | 4 ++++ 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 30f733d1d..c32e23934 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -78,8 +78,7 @@ class ChatEventList extends StatelessWidget { // #Pangea if (i == 1) { - return (controller.room.locked ?? false) && - !controller.room.isRoomAdmin + return (controller.room.locked) && !controller.room.isRoomAdmin ? const LockedChatMessage() : const SizedBox.shrink(); } diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index a095d49fd..71924d0a5 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -556,12 +556,12 @@ class ChatDetailsView extends StatelessWidget { Theme.of(context).scaffoldBackgroundColor, foregroundColor: iconColor, child: Icon( - room.locked ?? false + room.locked ? Icons.lock_outlined : Icons.no_encryption_outlined, ), ), - value: room.locked ?? false, + value: room.locked, onChanged: (value) => showFutureLoadingDialog( context: context, future: () => value diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 949b18112..40842783a 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -365,7 +365,7 @@ class ChatListItem extends StatelessWidget { ), const SizedBox(width: 8), // #Pangea - if (room.locked ?? false) + if (room.locked) const Padding( padding: EdgeInsets.only(right: 4.0), child: Icon( diff --git a/lib/pangea/extensions/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension.dart index 1b6370ce1..b0c19095f 100644 --- a/lib/pangea/extensions/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension.dart @@ -923,17 +923,17 @@ extension PangeaRoom on Room { ?.content .tryGet('events_default'); - bool? get locked { + bool get locked { if (isDirectChat) return false; if (!isSpace) { - if (eventsDefaultPowerLevel == null) return null; + if (eventsDefaultPowerLevel == null) return false; return (eventsDefaultPowerLevel ?? 0) >= ClassDefaultValues.powerLevelOfAdmin; } for (final child in spaceChildren) { if (child.roomId == null) continue; final Room? room = client.getRoomById(child.roomId!); - if (room?.locked == false && (room?.canChangePowerLevel ?? false)) { + if (room?.locked == false) { return false; } } diff --git a/lib/pangea/utils/lock_room.dart b/lib/pangea/utils/lock_room.dart index e21ec8aba..ba11872f5 100644 --- a/lib/pangea/utils/lock_room.dart +++ b/lib/pangea/utils/lock_room.dart @@ -17,7 +17,11 @@ Future lockChat(Room room, Client client) async { final Map powerLevelsContent = Map.from( room.getState(EventTypes.RoomPowerLevels)!.content, ); + powerLevelsContent['events_default'] = 100; + if (!powerLevelsContent.containsKey('events')) { + powerLevelsContent['events'] = Map.from({}); + } powerLevelsContent['events'][EventTypes.spaceChild] = 100; await room.client.setRoomStateWithKey(