From 875d6bb7eb69c194bc7951c2a8f6d9856cb923c0 Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Fri, 31 Jan 2025 15:17:45 -0500 Subject: [PATCH] fix: revert some changes to leaving space logic, updated copy (#1677) --- assets/l10n/intl_en.arb | 9 +- assets/l10n/intl_es.arb | 6 - lib/pages/chat/chat.dart | 11 -- lib/pages/chat_list/chat_list.dart | 132 ++----------- lib/pages/chat_list/chat_list_item.dart | 13 +- lib/pages/chat_list/space_view.dart | 10 +- .../pages/pangea_chat_details.dart | 63 ++----- .../extensions/pangea_room_extension.dart | 18 +- .../extensions/room_events_extension.dart | 176 +++--------------- lib/widgets/chat_settings_popup_menu.dart | 106 +---------- 10 files changed, 86 insertions(+), 458 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 826963cac..6f90fdb02 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3764,7 +3764,7 @@ }, "noTeachersFound": "No teachers found to report to", "pleaseEnterANumber": "Please enter a number greater than 0", - "archiveRoomDescription": "The chat will be moved to the archive for yourself and other non-admin users.", + "archiveRoomDescription": "The chat will be moved to the archive. Other users will be able to see that you have left the chat.", "roomUpgradeDescription": "The chat will then be recreated with the new room version. All participants will be notified that they need to switch to the new chat. You can find out more about room versions at https://spec.matrix.org/latest/rooms/", "removeDevicesDescription": "You will be logged out of this device and will no longer be able to receive messages.", "banUserDescription": "The user will be banned from the chat and will not be able to enter the chat again until they are unbanned.", @@ -4064,10 +4064,6 @@ "runGrammarCorrection": "Check message", "grammarCorrectionFailed": "Issues to address", "grammarCorrectionComplete": "Looks good!", - "leaveRoomDescription": "The chat will be moved to the archive. Other users will be able to see that you have left the chat.", - "archiveSpaceDescription": "All chats within this space will be moved to the archive for yourself and other non-admin users.", - "leaveSpaceDescription": "All chats within this space will be moved to the archive. Other users will be able to see that you have left the space.", - "onlyAdminDescription": "Since there are no other admins, all other participants will also be removed.", "tooltipInstructionsTitle": "Not sure what that does?", "tooltipInstructionsMobileBody": "Press and hold items to view tooltips.", "tooltipInstructionsBrowserBody": "Hover over items to view tooltips.", @@ -4780,5 +4776,6 @@ "noBookmarkedActivities": "No bookmarked activities", "noLemmasFound": "No lemmas found", "constructUsePvmDesc": "Produced in voice message", - "lockedMorphFeature": "Waiting to be unlocked" + "lockedMorphFeature": "Waiting to be unlocked", + "leaveSpaceDescription": "The space will be moved to the archive. Other users will be able to see that you have left the chat." } \ No newline at end of file diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index 2c8241b50..982c1e552 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -3567,8 +3567,6 @@ "noTodosYet": "", "@noTodosYet": {}, "@readUpToHere": {}, - "archiveRoomDescription": "El chat se moverá al archivo para ti y para otros usuarios que no sean administradores", - "@archiveRoomDescription": {}, "videoCallsBetaWarning": "Tenga en cuenta que las videollamadas están actualmente en fase beta. Es posible que no funcionen como se espera o que no funcionen de ninguna manera en algunas plataformas.", "@videoCallsBetaWarning": {}, "callingPermissions": "Permisos de llamadas", @@ -4584,10 +4582,6 @@ "runGrammarCorrection": "Comprobar mensaje", "grammarCorrectionFailed": "Cuestiones a tratar", "grammarCorrectionComplete": "¡Se ve bien!", - "leaveRoomDescription": "El chat se moverá al archivo. Los demás usuarios podrán ver que has abandonado el chat.", - "archiveSpaceDescription": "Todos los chats de este espacio se moverán al archivo para ti y otros usuarios que no sean administradores.", - "leaveSpaceDescription": "Todos los chats dentro de este espacio se moverán al archivo. Los demás usuarios podrán ver que has abandonado el espacio.", - "onlyAdminDescription": "Como no hay más administradores, todos los demás participantes también serán eliminados.", "tooltipInstructionsTitle": "¿No sabes para qué sirve?", "tooltipInstructionsMobileBody": "Mantenga pulsados los elementos para ver la información sobre herramientas.", "tooltipInstructionsBrowserBody": "Pase el ratón sobre los elementos para ver información sobre herramientas.", diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 0bf8ede4d..319396d7e 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -226,17 +226,6 @@ class ChatController extends State context.go('/rooms'); } - // #Pangea - void archiveChat() async { - final success = await showFutureLoadingDialog( - context: context, - future: room.archive, - ); - if (success.error != null) return; - context.go('/rooms'); - } - // Pangea# - EmojiPickerType emojiPickerType = EmojiPickerType.keyboard; // #Pangea diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index c16336e33..f5775721a 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -42,6 +42,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 SelectMode { normal, share, @@ -934,13 +935,24 @@ class ChatListController extends State title: L10n.of(context).areYouSure, okLabel: L10n.of(context).leave, cancelLabel: L10n.of(context).no, - message: L10n.of(context).archiveRoomDescription, + // #Pangea + // message: L10n.of(context).archiveRoomDescription, + message: room.isSpace + ? L10n.of(context).leaveSpaceDescription + : L10n.of(context).archiveRoomDescription, + // Pangea# isDestructiveAction: true, ); if (confirmed == OkCancelResult.cancel) return; if (!mounted) return; - await showFutureLoadingDialog(context: context, future: room.leave); + // #Pangea + // await showFutureLoadingDialog(context: context, future: room.leave); + await showFutureLoadingDialog( + context: context, + future: room.isSpace ? room.leaveSpace : room.leave, + ); + // Pangea# return; case ChatContextAction.addToSpace: @@ -1275,119 +1287,3 @@ enum ChatContextAction { removeFromSpace, // Pangea# } - -// TODO re-integrate this logic -// // #Pangea -// Future leaveAction() async { -// final onlyAdmin = await Matrix.of(context) -// .client -// .getRoomById(selectedRoomIds.first) -// ?.isOnlyAdmin() ?? -// false; -// final confirmed = await showOkCancelAlertDialog( -// useRootNavigator: false, -// context: context, -// title: L10n.of(context).areYouSure, -// okLabel: L10n.of(context).yes, -// cancelLabel: L10n.of(context).cancel, -// message: onlyAdmin && selectedRoomIds.length == 1 -// ? L10n.of(context).onlyAdminDescription -// : L10n.of(context).leaveRoomDescription, -// ) == -// OkCancelResult.ok; -// if (!confirmed) return; -// final leftActiveRoom = -// selectedRoomIds.contains(Matrix.of(context).activeRoomId); -// await showFutureLoadingDialog( -// context: context, -// future: () => _leaveSelectedRooms(onlyAdmin), -// ); -// if (leftActiveRoom) { -// context.go('/rooms'); -// } -// } -// // Pangea# - -// Future addToSpace() async { -// // #Pangea -// final firstSelectedRoom = -// Matrix.of(context).client.getRoomById(selectedRoomIds.toList().first); -// // Pangea# -// final selectedSpace = await showConfirmationDialog( -// context: context, -// title: L10n.of(context).addToSpace, -// // #Pangea -// // message: L10n.of(context).addToSpaceDescription, -// message: L10n.of(context).addSpaceToSpaceDescription, -// // Pangea# -// fullyCapitalizedForMaterial: false, -// actions: Matrix.of(context) -// .client -// .rooms -// .where( -// (r) => -// r.isSpace -// // #Pangea -// && -// selectedRoomIds -// .map((id) => Matrix.of(context).client.getRoomById(id)) -// // Only show non-recursion-causing spaces -// // Performs a few other checks as well -// .every((e) => r.canAddAsParentOf(e)), -// //Pangea# -// ) -// .map( -// (space) => AlertDialogAction( -// key: space.id, -// // #Pangea -// // label: space -// // .getLocalizedDisplayname(MatrixLocals(L10n.of(context))), -// label: space.nameIncludingParents(context), -// // If user is not admin of space, button is grayed out -// textStyle: TextStyle( -// color: (firstSelectedRoom == null) -// ? Theme.of(context).colorScheme.outline -// : Theme.of(context).colorScheme.surfaceTint, -// ), -// // Pangea# -// ), -// ) -// .toList(), -// ); -// if (selectedSpace == null) return; -// final result = await showFutureLoadingDialog( -// context: context, -// future: () async { -// final space = Matrix.of(context).client.getRoomById(selectedSpace)!; -// // #Pangea -// if (firstSelectedRoom == null) { -// throw L10n.of(context).nonexistentSelection; -// } - -// if (space.canSendDefaultStates) { -// for (final roomId in selectedRoomIds) { -// await space.pangeaSetSpaceChild(roomId, suggested: true); -// } -// } -// // Pangea# -// }, -// ); -// if (result.error == null) { -// if (!mounted) return; -// ScaffoldMessenger.of(context).showSnackBar( -// SnackBar( -// // #Pangea -// // content: Text(L10n.of(context).chatHasBeenAddedToThisSpace), -// content: Text(L10n.of(context).roomAddedToSpace), -// // Pangea# -// ), -// ); -// } - -// // #Pangea -// // setState(() => selectedRoomIds.clear()); -// if (firstSelectedRoom != null) { -// toggleSelection(firstSelectedRoom.id); -// } -// // Pangea# -// } diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index b18b4ce48..4b676a13c 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -6,6 +6,7 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/chat_list/utils/get_chat_list_item_subtitle.dart'; +import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/room_status_extension.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; @@ -51,13 +52,21 @@ class ChatListItem extends StatelessWidget { title: L10n.of(context).areYouSure, okLabel: L10n.of(context).leave, cancelLabel: L10n.of(context).cancel, - message: L10n.of(context).archiveRoomDescription, + // #Pangea + // message: L10n.of(context).archiveRoomDescription, + message: room.isSpace + ? L10n.of(context).leaveSpaceDescription + : L10n.of(context).archiveRoomDescription, + // Pangea# isDestructiveAction: true, ); if (confirmed != OkCancelResult.ok) return false; final leaveResult = await showFutureLoadingDialog( context: context, - future: () => room.leave(), + // #Pangea + // future: () => room.leave(), + future: () => room.isSpace ? room.leaveSpace() : room.leave(), + // Pangea# ); return leaveResult.isValue; } diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index b5c579645..29c337f31 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -301,14 +301,20 @@ class _SpaceViewState extends State { title: L10n.of(context).areYouSure, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - message: L10n.of(context).archiveRoomDescription, + // #Pangea + // message: L10n.of(context).archiveRoomDescription, + message: L10n.of(context).leaveSpaceDescription, + // Pangea# ); if (!mounted) return; if (confirmed != OkCancelResult.ok) return; final success = await showFutureLoadingDialog( context: context, - future: () async => await space?.leave(), + // #Pangea + // future: () async => await space?.leave(), + future: () async => await space?.leaveSpace(), + // Pangea# ); if (!mounted) return; if (success.error != null) return; diff --git a/lib/pangea/chat_settings/pages/pangea_chat_details.dart b/lib/pangea/chat_settings/pages/pangea_chat_details.dart index 32ced6fcf..7f929d214 100644 --- a/lib/pangea/chat_settings/pages/pangea_chat_details.dart +++ b/lib/pangea/chat_settings/pages/pangea_chat_details.dart @@ -404,49 +404,26 @@ class PangeaChatDetailsView extends StatelessWidget { ), ), onTap: () async { - var confirmed = OkCancelResult.ok; - var shouldGo = false; - // If user is only admin, room will be archived - final onlyAdmin = await room.isOnlyAdmin(); - // archiveSpace has its own popup; only show if not space - if (!room.isSpace) { - confirmed = await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).ok, - cancelLabel: L10n.of(context).cancel, - message: onlyAdmin - ? L10n.of(context).onlyAdminDescription - : L10n.of(context).leaveRoomDescription, - ); - } - if (confirmed == OkCancelResult.ok) { - if (room.isSpace) { - shouldGo = onlyAdmin - ? await room.archiveSpace( - context, - Matrix.of(context).client, - onlyAdmin: true, - ) - : await room.leaveSpace( - context, - Matrix.of(context).client, - ); - } else { - final success = await showFutureLoadingDialog( - context: context, - future: () async { - onlyAdmin - ? await room.archive() - : await room.leave(); - }, - ); - shouldGo = (success.error == null); - } - if (shouldGo) { - context.go('/rooms'); - } + final confirmed = await showOkCancelAlertDialog( + useRootNavigator: false, + context: context, + title: L10n.of(context).areYouSure, + okLabel: L10n.of(context).leave, + cancelLabel: L10n.of(context).no, + message: room.isSpace + ? L10n.of(context).leaveSpaceDescription + : L10n.of(context).archiveRoomDescription, + isDestructiveAction: true, + ); + if (confirmed == OkCancelResult.cancel) return; + final resp = await showFutureLoadingDialog( + context: context, + future: + room.isSpace ? room.leaveSpace : room.leave, + ); + if (!resp.isError) { + MatrixState.pangeaController.classController + .setActiveSpaceIdInChatListController(null); } }, ), diff --git a/lib/pangea/extensions/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension.dart index dad9f71eb..9077c50f6 100644 --- a/lib/pangea/extensions/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension.dart @@ -7,7 +7,6 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:collection/collection.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:html_unescape/html_unescape.dart'; @@ -27,8 +26,6 @@ import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/spaces/constants/space_constants.dart'; import 'package:fluffychat/pangea/spaces/models/space_model.dart'; -import 'package:fluffychat/widgets/future_loading_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; import '../choreographer/models/choreo_record.dart'; import '../events/constants/pangea_event_types.dart'; import '../events/models/representation_content_model.dart'; @@ -108,21 +105,8 @@ extension PangeaRoom on Room { // events Future leaveIfFull() async => await _leaveIfFull(); - Future archive() async => await _archive(); - Future archiveSpace( - BuildContext context, - Client client, { - bool onlyAdmin = false, - }) async => - await _archiveSpace(context, client, onlyAdmin: onlyAdmin); - - Future archiveSubspace() async => await _archiveSubspace(); - - Future leaveSpace(BuildContext context, Client client) async => - await _leaveSpace(context, client); - - Future leaveSubspace() async => await _leaveSubspace(); + Future leaveSpace() async => await _leaveSpace(); Future sendPangeaEvent({ required Map content, diff --git a/lib/pangea/extensions/room_events_extension.dart b/lib/pangea/extensions/room_events_extension.dart index fdb20da99..96e7b9f37 100644 --- a/lib/pangea/extensions/room_events_extension.dart +++ b/lib/pangea/extensions/room_events_extension.dart @@ -14,161 +14,37 @@ extension EventsRoomExtension on Room { return false; } - Future _archive() async { - final students = (await requestParticipants()) - .where( - (e) => - e.id != client.userID && - e.powerLevel < SpaceConstants.powerLevelOfAdmin && - e.id != BotName.byEnvironment, - ) - .toList(); + Future _leaveSpace() async { + for (final child in spaceChildren) { + if (child.roomId == null) continue; + final Room? room = client.getRoomById(child.roomId!); + if (room == null) continue; + try { + await room.leave(); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: { + 'roomID': room.id, + }, + ); + } + } + try { - for (final student in students) { - await kick(student.id); - } - if (!isSpace && membership == Membership.join && isUnread) { - await markUnread(false); - } await leave(); - } catch (err, s) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: s, data: toJson()); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: { + 'roomID': id, + }, + ); } } - Future _archiveSpace( - BuildContext context, - Client client, { - bool onlyAdmin = false, - }) async { - final confirmed = await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).yes, - cancelLabel: L10n.of(context).cancel, - message: onlyAdmin - ? L10n.of(context).onlyAdminDescription - : L10n.of(context).archiveSpaceDescription, - ) == - OkCancelResult.ok; - if (!confirmed) return false; - final success = await showFutureLoadingDialog( - context: context, - future: () async { - final List children = await getChildRooms(); - for (final Room child in children) { - if (!child.isAnalyticsRoom && !child.isArchived) { - if (child.membership != Membership.join) { - child.join; - } - if (child.isSpace) { - await child.archiveSubspace(); - } else { - await child.archive(); - } - } - } - await _archive(); - }, - ); - MatrixState.pangeaController.classController - .setActiveSpaceIdInChatListController( - null, - ); - return success.error == null; - } - - Future _archiveSubspace() async { - final List children = await getChildRooms(); - for (final Room child in children) { - if (!child.isAnalyticsRoom && !child.isArchived) { - if (child.membership != Membership.join) { - child.join; - } - if (child.isSpace) { - await child.archiveSubspace(); - } else { - await child.archive(); - } - } - } - await _archive(); - } - - Future _leaveSpace(BuildContext context, Client client) async { - final confirmed = await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).yes, - cancelLabel: L10n.of(context).cancel, - message: L10n.of(context).leaveSpaceDescription, - ) == - OkCancelResult.ok; - if (!confirmed) return false; - final success = await showFutureLoadingDialog( - context: context, - future: () async { - try { - final List children = await getChildRooms(); - for (final Room child in children) { - if (!child.isAnalyticsRoom && !child.isArchived) { - if (!child.isSpace && - child.membership == Membership.join && - child.isUnread) { - await child.markUnread(false); - } - if (child.isSpace) { - await child.leaveSubspace(); - } else { - await child.leave(); - } - } - } - await leave(); - } catch (err, stack) { - debugger(when: kDebugMode); - ErrorHandler.logError( - e: err, - s: stack, - data: { - "powerLevel": client.userID != null - ? getPowerLevelByUserId(client.userID!) - : null, - }, - ); - rethrow; - } - }, - ); - MatrixState.pangeaController.classController - .setActiveSpaceIdInChatListController( - null, - ); - return success.error == null; - } - - Future _leaveSubspace() async { - final List children = await getChildRooms(); - for (final Room child in children) { - if (!child.isAnalyticsRoom && !child.isArchived) { - if (!child.isSpace && - child.membership == Membership.join && - child.isUnread) { - await child.markUnread(false); - } - if (child.isSpace) { - await child.leaveSubspace(); - } else { - await child.leave(); - } - } - } - await leave(); - } - Future _sendPangeaEvent({ required Map content, required String parentEventId, diff --git a/lib/widgets/chat_settings_popup_menu.dart b/lib/widgets/chat_settings_popup_menu.dart index 590db81b3..398d606dd 100644 --- a/lib/widgets/chat_settings_popup_menu.dart +++ b/lib/widgets/chat_settings_popup_menu.dart @@ -7,25 +7,10 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/chat_settings/utils/download_chat.dart'; -import 'package:fluffychat/pangea/chat_settings/utils/download_file.dart'; -import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'matrix.dart'; -enum ChatPopupMenuActions { - details, - mute, - unmute, - leave, - search, - // #Pangea - downloadTxt, - downloadCsv, - downloadXlsx, - learningSettings, - // Pangea# -} +enum ChatPopupMenuActions { details, mute, unmute, leave, search } class ChatSettingsPopupMenu extends StatefulWidget { final Room room; @@ -108,44 +93,6 @@ class ChatSettingsPopupMenuState extends State { case ChatPopupMenuActions.search: context.go('/rooms/${widget.room.id}/search'); break; - // #Pangea - case ChatPopupMenuActions.downloadTxt: - showFutureLoadingDialog( - context: context, - future: () => downloadChat( - widget.room, - DownloadType.txt, - context, - ), - ); - break; - case ChatPopupMenuActions.downloadCsv: - showFutureLoadingDialog( - context: context, - future: () => downloadChat( - widget.room, - DownloadType.csv, - context, - ), - ); - break; - case ChatPopupMenuActions.downloadXlsx: - showFutureLoadingDialog( - context: context, - future: () => downloadChat( - widget.room, - DownloadType.xlsx, - context, - ), - ); - break; - case ChatPopupMenuActions.learningSettings: - showDialog( - context: context, - builder: (c) => const SettingsLearning(), - ); - break; - // Pangea# } }, itemBuilder: (BuildContext context) => [ @@ -154,24 +101,12 @@ class ChatSettingsPopupMenuState extends State { value: ChatPopupMenuActions.details, child: Row( children: [ - const Icon(Icons.settings_outlined), + const Icon(Icons.info_outline_rounded), const SizedBox(width: 12), Text(L10n.of(context).chatDetails), ], ), ), - // #Pangea - PopupMenuItem( - value: ChatPopupMenuActions.learningSettings, - child: Row( - children: [ - const Icon(Icons.psychology_outlined), - const SizedBox(width: 12), - Text(L10n.of(context).learningSettings), - ], - ), - ), - // Pangea# if (widget.room.pushRuleState == PushRuleState.notify) PopupMenuItem( value: ChatPopupMenuActions.mute, @@ -208,47 +143,12 @@ class ChatSettingsPopupMenuState extends State { value: ChatPopupMenuActions.leave, child: Row( children: [ - // #Pangea - // const Icon(Icons.delete_outlined), - const Icon(Icons.arrow_forward), - // Pangea# + const Icon(Icons.delete_outlined), const SizedBox(width: 12), Text(L10n.of(context).leave), ], ), ), - // #Pangea - PopupMenuItem( - value: ChatPopupMenuActions.downloadTxt, - child: Row( - children: [ - const Icon(Icons.download_outlined), - const SizedBox(width: 12), - Text(L10n.of(context).downloadTxtFile), - ], - ), - ), - PopupMenuItem( - value: ChatPopupMenuActions.downloadCsv, - child: Row( - children: [ - const Icon(Icons.download_outlined), - const SizedBox(width: 12), - Text(L10n.of(context).downloadCSVFile), - ], - ), - ), - PopupMenuItem( - value: ChatPopupMenuActions.downloadXlsx, - child: Row( - children: [ - const Icon(Icons.download_outlined), - const SizedBox(width: 12), - Text(L10n.of(context).downloadXLSXFile), - ], - ), - ), - // Pangea# ], ), ],