Chat details redesign (#1010)

* replace chat details dropdown with chat details button

* initial work on chat details design updates

* added back space invite buttons, openning up invite search, removed references to room locking
This commit is contained in:
ggurdin 2024-11-19 10:03:04 -05:00 committed by GitHub
parent 22f33b0a85
commit a44305a5af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 878 additions and 321 deletions

View file

@ -4024,7 +4024,7 @@
"conversationBotCustomZone_customSystemPromptPlaceholder": "Set custom system prompt",
"conversationBotCustomZone_customSystemPromptEmptyError": "Missing custom system prompt",
"conversationBotCustomZone_customTriggerReactionEnabledLabel": "Responds on ⏩ reaction",
"botConfig": "Chat settings",
"botConfig": "Bot and activity settings",
"addConversationBotDialogTitleInvite": "Confirm inviting conversation bot",
"addConversationBotButtonInvite": "Invite",
"addConversationBotDialogInviteConfirmation": "Invite",
@ -4500,5 +4500,11 @@
"other": "Other",
"botModeValidation": "Please select a chat mode",
"clickBestOption": "Choose the best options to translate your message!",
"unlockedLanguageTools": "Youve unlocked the language tools for this message. Try them out by clicking below!"
"unlockedLanguageTools": "Youve unlocked the language tools for this message. Try them out by clicking below!",
"botSettingsSubtitle": "Invite bot to moderate chat activity",
"invitePeople": "Invite users",
"invitePeopleChatSubtitle": "Invite users or admins to this chat",
"invitePeopleSpaceSubtitle": "Invite users or admins to this space",
"noCapacityLimit": "No capacity limit",
"downloadGroupText": "Download group text"
}

View file

@ -5004,9 +5004,286 @@
"enterDiscussionTopic": "Introduzca un tema de debate",
"selectBotChatMode": "Selecciona el modo de chat",
"messageNotInTargetLang": "El mensaje no está en la lengua de llegada",
"botConfig": "Configuración del chat",
"chatCapacityNotSet": "Este chat no tiene límite de capacidad.",
"spaceCapacityNotSet": "Este espacio no tiene límite de capacidad.",
"chatExceedsCapacity": "Este chat supera su capacidad.",
"spaceExceedsCapacity": "Este espacio supera su capacidad."
}
"spaceExceedsCapacity": "Este espacio supera su capacidad.",
"botConfig": "Configuración de bots y actividades",
"missingVoiceTitle": "La voz que falta",
"grammarCopyPOSsconj": "Conjunción subordinante",
"grammarCopyPOSnum": "Número",
"grammarCopyPOSverb": "Verbo",
"grammarCopyPOSaffix": "Coloque",
"grammarCopyPOSpart": "Partículas",
"grammarCopyPOSadj": "Adjetivo",
"grammarCopyPOScconj": "Conjunción de coordinación",
"grammarCopyPOSpunct": "Puntuación",
"grammarCopyPOSadv": "Adverbio",
"grammarCopyPOSaux": "Auxiliar",
"grammarCopyPOSspace": "Espacio",
"grammarCopyPOSsym": "Símbolo",
"grammarCopyPOSdet": "Determinante",
"grammarCopyPOSpron": "Pronombre",
"grammarCopyPOSadp": "Adposición",
"grammarCopyPOSpropn": "Nombre propio",
"grammarCopyPOSnoun": "Sustantivo",
"grammarCopyPOSintj": "Interjección",
"grammarCopyPOSx": "Otros",
"grammarCopyGENDERfem": "Femenino",
"grammarCopyPERSON2": "Segunda persona",
"grammarCopyMOODimp": "Imperativo",
"grammarCopyPUNCTTYPEqest": "Pregunta",
"grammarCopyASPECTperf": "Perfecto",
"grammarCopyCASEaccnom": "Acusativo, Nominativo",
"grammarCopyCASEobl": "Oblicuo",
"grammarCopyVOICEact": "Activo",
"grammarCopyPUNCTTYPEbrck": "Soporte",
"grammarCopyNOUNTYPEart": "Artículo",
"grammarCopyNUMBERsing": "Singular",
"grammarCopyGENDERmasc": "Hombre",
"grammarCopyVERBTYPEmod": "Modal",
"grammarCopyADVTYPEadverbial": "Adverbial",
"grammarCopyTENSEperi": "Perifrástico",
"grammarCopyNUMFORMdigit": "Dígitos",
"grammarCopyNOUNTYPEnot_proper": "No procede",
"grammarCopyNUMTYPEcard": "Cardenal",
"grammarCopyNOUNTYPEprop": "Adecuado",
"grammarCopyPUNCTTYPEdash": "Dash",
"grammarCopyPUNCTTYPEyes": "Sí",
"grammarCopyPUNCTTYPEsemi": "Punto y coma",
"grammarCopyPUNCTTYPEcomm": "Coma",
"grammarCopyMOODcnd": "Condicional",
"grammarCopyCASEacc": "Acusativo",
"grammarCopyPARTTYPEpart": "Partitivo",
"grammarCopyTENSEpast": "Anterior",
"grammarCopyDEGREEsup": "Superlativo",
"grammarCopyPUNCTTYPEcolo": "Colon",
"grammarCopyPERSON3": "Tercera persona",
"grammarCopyNUMBERplur": "Plural",
"grammarCopyPRONTYPEnpr": "Nombre propio",
"grammarCopyPRONTYPEinterrogative": "Preguntas",
"grammarCopyPOLITEinfm": "Informal",
"grammarCopyADVTYPEtim": "Tiempo",
"grammarCopyPOLARITYneg": "Negativo",
"grammarCopyNUMTYPEtot": "Total",
"grammarCopyADVTYPEadnomial": "Adnominal",
"grammarCopyASPECTprog": "Progresiva",
"grammarCopyMOODsub": "Subjuntivo",
"grammarCopyVERBFORMcomplementive": "Complementive",
"grammarCopyCASEnom": "Nominativo",
"grammarCopyTENSEfut": "Futuro",
"grammarCopyCASEdat": "Dativo",
"grammarCopyTENSEpres": "Presente",
"grammarCopyGENDERneut": "Esterilizar",
"grammarCopyPRONTYPErel": "Relativa",
"grammarCopyVERBFORMfinalEnding": "Final",
"grammarCopyPRONTYPEdem": "Demostrativo",
"grammarCopyPREPCASEpre": "Preposicional",
"grammarCopyVERBFORMfin": "Finito",
"grammarCopyDEGREEpos": "Positivo",
"grammarCopyPUNCTTYPEquot": "Presupuesto",
"grammarCopyVERBFORMger": "Redondo",
"grammarCopyVOICEpass": "Pasivo",
"grammarCopyCASEgen": "Genitivo",
"grammarCopyTENSEprs": "Presente",
"grammarCopyDEFINITEdef": "Definitivo",
"grammarCopyNUMTYPEord": "Ordinal",
"grammarCopyCASEins": "Instrumental",
"grammarCopyVERBFORMinf": "Infinitivo",
"grammarCopyNUMFORMlong": "Largo",
"grammarCopyCASEloc": "Locativo",
"grammarCopyMOODind": "Indicativo",
"grammarCopyDEGREEcmp": "Comparativa",
"grammarCopyCASErelativeCase": "Relativa",
"grammarCopyPUNCTTYPEexcl": "Exclamativo",
"grammarCopyPERSON1": "En primera persona",
"grammarCopyPUNCTSIDEini": "Inicial",
"grammarCopyGENDERperson": "Persona",
"grammarCopyFOREIGNyes": "Extranjero",
"grammarCopyVOICEvoice": "Voz",
"grammarCopyVERBTYPEverbType": "Verbo",
"grammarCopyPOSSpass": "Posesivo",
"grammarCopyPREPCASEprepCase": "Preposicional",
"grammarCopyNUMTYPEnumType": "Numeral",
"grammarCopyNOUNTYPEnounType": "Sustantivo",
"grammarCopyREFLEXreflex": "Reflexivo",
"grammarCopyPRONTYPEpronType": "Pronombre",
"grammarCopyPUNCTSIDEpunctSide": "Puntuación Lado",
"grammarCopyVERBFORMverbForm": "Verbo",
"grammarCopyGENDERgender": "Género",
"grammarCopyMOODmood": "Estado de ánimo",
"grammarCopyASPECTaspect": "Aspecto",
"grammarCopyPUNCTTYPEpunctType": "Puntuación",
"grammarCopyTENSEtense": "Tense",
"grammarCopyDEGREEdegree": "Titulación",
"grammarCopyPOLITEpolite": "Cortesía",
"grammarCopyADVTYPEadvType": "Adverbio",
"grammarCopyNUMFORMnumber": "Número",
"grammarCopyCONJTYPEconjType": "Conjunción",
"grammarCopyPOLARITYpolarity": "Polaridad",
"grammarCopyCASEcase": "Caso",
"grammarCopyDEFINITEdefinite": "Definitividad",
"grammarCopyNUMFORMnumForm": "Numeral",
"grammarCopyPRONTYPEadn": "Adnominal",
"grammarCopyVOCvoc": "Vocativo",
"grammarCopyCMPLcmpl": "Complementizer",
"grammarCopyADVadv": "Adverbial",
"grammarCopyMOODjus": "Jussive",
"grammarCopyGENDERcom": "Común",
"grammarCopyREFLEXrflx": "Reflexivo",
"grammarCopyPARTTYPEpar": "Partitivo",
"grammarCopySPCspc": "Específico",
"grammarCopyTENSEpqp": "Pluperfect",
"grammarCopyREFLEXref": "Reflexivo",
"grammarCopyPUNCTTYPEnshrt": "Corto",
"grammarCopyNUMBERdual": "Doble",
"grammarCopyNUMFORMlng": "Largo",
"grammarCopyVOICEmid": "Medio",
"grammarCopyINTRELintRel": "Interrogativo, relativo",
"grammarCopyINTint": "Preguntas",
"grammarCopyVOICEcaus": "Causa",
"grammarCopyEVIDENTevident": "Evidencialidad",
"grammarCopyNUMFORMnumberPsor": "Número del poseedor",
"grammarCopyASPECThab": "Habitual",
"grammarCopyCASEabl": "Ablativo",
"grammarCopyCASEall": "Allative",
"grammarCopyCASEess": "Essive",
"grammarCopyCASEtra": "Translativo",
"grammarCopyCASEequ": "Ecuativo",
"grammarCopyCASEdis": "Distributivo",
"grammarCopyCASEabs": "Absolutivo",
"grammarCopyCASEerg": "Ergativa",
"grammarCopyCASEcau": "Causal",
"grammarCopyCASEben": "Benefactive",
"grammarCopyCASEtem": "Temporal",
"grammarCopyCONJTYPEcoord": "Coordinación",
"grammarCopyDEFINITEcons": "Construir el Estado",
"grammarCopyDEGREEabs": "Grado absoluto",
"grammarCopyEVIDENTfh": "Evidencialidad de los hechos",
"grammarCopyEVIDENTnfh": "Evidencialidad no factual",
"grammarCopyMOODopt": "Optativo",
"grammarCopyMOODadm": "Admirable",
"grammarCopyMOODdes": "Desiderativo",
"grammarCopyMOODnec": "Necesidades",
"grammarCopyMOODpot": "Posible",
"grammarCopyMOODprp": "Propositivo",
"grammarCopyMOODqot": "Cita",
"grammarCopyNUMFORMword": "Forma verbal",
"grammarCopyNUMFORMroman": "Número romano",
"grammarCopyNUMFORMletter": "Formulario de carta",
"grammarCopyNUMTYPEmult": "Multiplicativo",
"grammarCopyNUMTYPEfrac": "Fraccional",
"grammarCopyNUMTYPEsets": "Establecer",
"grammarCopyNUMTYPErange": "Gama",
"grammarCopyNUMTYPEdist": "Distributivo",
"grammarCopyNUMBERtri": "Ensayo",
"grammarCopyNUMBERpauc": "Paucal",
"grammarCopyNUMBERgrpa": "Gran Paucal",
"grammarCopyNUMBERgrpl": "Mayor Plural",
"grammarCopyNUMBERinv": "Inversa",
"grammarCopyPERSON0": "Cero",
"grammarCopyPERSON4": "Cuarto",
"grammarCopyPOLITEform": "Formal",
"grammarCopyPOLITEelev": "Elevado",
"grammarCopyPOLITEhumb": "Humilde",
"grammarCopyPRONTYPEemp": "Enfático",
"grammarCopyPRONTYPEexc": "Exclamativo",
"grammarCopyPRONTYPErcp": "Reciprocal",
"grammarCopyPRONTYPEintRelPronType": "Interrogativo-Relativo",
"grammarCopyTENSEaor": "aoristo",
"grammarCopyTENSEeps": "Epistémica",
"grammarCopyTENSEprosp": "Prospectiva",
"grammarCopyVERBFORMpart": "Participio",
"grammarCopyVERBFORMconv": "Converb",
"grammarCopyVERBFORMvnoun": "Sustantivo verbal",
"grammarCopyVOICEantip": "Antipasivo",
"grammarCopyVOICEcauVoice": "Causa",
"grammarCopyVOICedir": "Directo",
"grammarCopyVOICEinvVoice": "Inversa",
"grammarCopyVOICErcpVoice": "Reciprocal",
"grammarCopyPOS": "Parte de la oración",
"grammarCopyGENDER": "Género",
"grammarCopyPERSON": "Persona",
"grammarCopyMOOD": "Estado de ánimo",
"grammarCopyPUNCTTYPE": "Tipo de puntuación",
"grammarCopyASPECT": "Aspecto",
"grammarCopyCASE": "Caso",
"grammarCopyVOICE": "Voz",
"grammarCopyNOUNTYPE": "Tipo de sustantivo",
"grammarCopyVERBTYPE": "Tipo de verbo",
"grammarCopyADVTYPE": "Tipo de adverbio",
"grammarCopyNUMFORM": "Forma numérica",
"grammarCopyNUMTYPE": "Tipo de número",
"grammarCopyNUMBER": "Número",
"grammarCopyDEFINITE": "Definitividad",
"grammarCopyDEGREE": "Titulación",
"grammarCopyEVIDENT": "Evidencialidad",
"grammarCopyFOREIGN": "Extranjero",
"grammarCopyPOLARITY": "Polaridad",
"grammarCopyPOLITE": "Cortesía",
"grammarCopyPREPCASE": "Caso preposicional",
"grammarCopyPRONTYPE": "Tipo de pronombre",
"grammarCopyPUNCTSIDE": "Puntuación Lado",
"grammarCopyREFLEX": "Reflexivo",
"grammarCopyTENSE": "Tense",
"grammarCopyVERBFORM": "Forma verbal",
"grammarCopyCONJTYPE": "Tipo de conjunción",
"grammarCopySPC": "Especificidad",
"grammarCopyPARTTYPE": "Tipo Partitivo",
"grammarCopyINTREL": "Interrogativo-Relativo",
"grammarCopyNUMFORMpsor": "Número del poseedor",
"grammarCopyUNKNOWN": "Desconocido",
"grammarCopyNUMBERPSOR": "Número del poseedor",
"grammarCopyPOSS": "Posesivo",
"grammarCopyASPECTimp": "Aspecto imperfectivo",
"grammarCopyCASEvoc": "Vocativo",
"grammarCopyCASEcom": "Comitative",
"grammarCopyCASEpar": "Partitivo",
"grammarCopyCASEadv": "Adverbial",
"grammarCopyCASEref": "Referencial",
"grammarCopyCASErel": "Relativa",
"grammarCopyCASEsub": "Subesivo",
"grammarCopyCASEsup": "Superessive",
"grammarCopyCASEaccdat": "Acusativo-dativo",
"grammarCopyCASEpre": "Preposicional",
"grammarCopyCONJTYPEsub": "Subordinación",
"grammarCopyCONJTYPEcmp": "Comparativa",
"grammarCopyDEFINITEind": "Indefinido",
"grammarCopyMOODint": "Modo interrogativo",
"grammarCopyNOUNTYPEcomm": "Sustantivo común",
"grammarCopyNUMBERPSORsing": "Singular del poseedor",
"grammarCopyNUMBERPSORplur": "Plural del poseedor",
"grammarCopyNUMBERPSORdual": "Doble del poseedor",
"grammarCopyPOLARITYpos": "Polaridad positiva",
"grammarCopyPOSSyes": "Posesivo",
"grammarCopyPREPCASEnpr": "No preposicional",
"grammarCopyPRONTYPEprs": "Personal",
"grammarCopyPRONTYPEint": "Preguntas",
"grammarCopyPRONTYPEtot": "Total",
"grammarCopyPRONTYPEneg": "Negativo",
"grammarCopyPRONTYPEart": "Artículo",
"grammarCopyPRONTYPEind": "Indefinido",
"grammarCopyPRONTYPEintrel": "Interrogativo-Relativo",
"grammarCopyPUNCTSIDEfin": "Puntuación final",
"grammarCopyPUNCTTYPEperi": "Periodo",
"grammarCopyREFLEXyes": "Reflexivo",
"grammarCopyTENSEimp": "Imperfect",
"grammarCopyVERBFORMsup": "SuApine",
"grammarCopyVERBFORMadn": "Adnominal",
"grammarCopyVERBFORMlng": "Largo",
"grammarCopyVERBTYPEcaus": "Verbo causativo",
"grammarCopyVOICEcau": "Causa",
"grammarCopyVOICEdir": "Directo",
"grammarCopyVOICEinv": "Inversa",
"grammarCopyVOICErcp": "Reciprocal",
"other": "Otros",
"botModeValidation": "Seleccione un modo de chat",
"clickBestOption": "Elija las mejores opciones para traducir su mensaje",
"unlockedLanguageTools": "Has desbloqueado las herramientas lingüísticas para este mensaje. Pruébalas haciendo clic a continuación.",
"botSettingsSubtitle": "Invitar a un bot a moderar la actividad del chat",
"invitePeople": "Invitar a usuarios",
"invitePeopleChatSubtitle": "Invitar a usuarios o administradores a este chat",
"invitePeopleSpaceSubtitle": "Invitar a usuarios o administradores a este espacio",
"noCapacityLimit": "Sin límite de capacidad",
"downloadGroupText": "Descargar texto del grupo"
}

View file

@ -6,8 +6,6 @@ import 'package:fluffychat/pages/chat/seen_by_row.dart';
import 'package:fluffychat/pages/chat/typing_indicators.dart';
import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart';
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/widgets/chat/locked_chat_message.dart';
import 'package:fluffychat/utils/account_config.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart';
@ -99,14 +97,6 @@ class ChatEventList extends StatelessWidget {
);
}
// #Pangea
if (i == 1) {
return (controller.room.isLocked) && !controller.room.isRoomAdmin
? const LockedChatMessage()
: const SizedBox.shrink();
}
// Pangea#
// Request history button or progress indicator:
if (i == events.length + 1) {
if (controller.timeline!.isRequestingHistory) {
@ -158,10 +148,7 @@ class ChatEventList extends StatelessWidget {
return const SizedBox(height: AppConfig.toolbarMaxHeight);
// Pangea#
}
// #Pangea
// i--;
i = i - 2;
// Pangea#
i--;
final event = events[i];
final animateIn = animateInEventIndex != null &&

View file

@ -16,7 +16,6 @@ import 'package:fluffychat/pangea/widgets/chat/chat_floating_action_button.dart'
import 'package:fluffychat/pangea/widgets/chat/chat_view_background.dart';
import 'package:fluffychat/pangea/widgets/chat/input_bar_wrapper.dart';
import 'package:fluffychat/utils/account_config.dart';
import 'package:fluffychat/widgets/chat_settings_popup_menu.dart';
import 'package:fluffychat/widgets/connection_status_header.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:fluffychat/widgets/mxc_image.dart';
@ -117,9 +116,16 @@ class ChatView extends StatelessWidget {
// #Pangea
} else {
return [
ChatSettingsPopupMenu(
controller.room,
(!controller.room.isDirectChat && !controller.room.isArchived),
IconButton(
icon: const Icon(Icons.info_outline),
tooltip: L10n.of(context)!.chatDetails,
onPressed: () {
if (GoRouterState.of(context).uri.path.endsWith('/details')) {
context.go('/rooms/${controller.room.id}');
} else {
context.go('/rooms/${controller.room.id}/details');
}
},
),
];
}

View file

@ -1,8 +1,8 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
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/chat_details/pangea_chat_details.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/utils/platform_infos.dart';
@ -199,7 +199,10 @@ class ChatDetailsController extends State<ChatDetails> {
static const fixedWidth = 360.0;
@override
Widget build(BuildContext context) => ChatDetailsView(this);
// #Pangea
Widget build(BuildContext context) => PangeaChatDetailsView(this);
// Widget build(BuildContext context) => ChatDetailsView(this);
// Pangea#
// #Pangea
bool showEditNameIcon = false;
@ -220,6 +223,29 @@ class ChatDetailsController extends State<ChatDetails> {
if (mounted) setState(() {});
}
Future<void> toggleMute() async {
final client = Matrix.of(context).client;
final Room? room = client.getRoomById(roomId!);
if (room == null) return;
await showFutureLoadingDialog(
context: context,
future: () async {
await (room.pushRuleState == PushRuleState.notify
? room.setPushRuleState(PushRuleState.mentionsOnly)
: room.setPushRuleState(PushRuleState.notify));
},
);
// wait for push rule update in sync
await client.onSync.stream.firstWhere(
(sync) =>
sync.accountData != null &&
sync.accountData!.isNotEmpty &&
sync.accountData!.any((e) => e.type == 'm.push_rules'),
);
if (mounted) setState(() {});
}
@override
void initState() {
super.initState();

View file

@ -1,5 +1,4 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/chat_details/chat_details.dart';
import 'package:fluffychat/pages/chat_details/participant_list_item.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
@ -8,13 +7,11 @@ 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/room_capacity_button.dart';
import 'package:fluffychat/pangea/utils/lock_room.dart';
import 'package:fluffychat/pangea/widgets/chat/visibility_toggle.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/chat_settings_popup_menu.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
@ -66,7 +63,7 @@ class ChatDetailsView extends StatelessWidget {
leading: controller.widget.embeddedCloseButton ??
const Center(child: BackButton()),
elevation: theme.appBarTheme.elevation,
actions: <Widget>[
actions: const <Widget>[
// #Pangea
// if (room.canonicalAlias.isNotEmpty)
// IconButton(
@ -77,9 +74,9 @@ class ChatDetailsView extends StatelessWidget {
// context,
// ),
// ),
// if (controller.widget.embeddedCloseButton == null)
// ChatSettingsPopupMenu(room, false),
// Pangea#
if (controller.widget.embeddedCloseButton == null)
ChatSettingsPopupMenu(room, false),
],
// #Pangea
title: ClassNameHeader(
@ -460,44 +457,6 @@ class ChatDetailsView extends StatelessWidget {
}
},
),
if (room.isRoomAdmin && !room.isDirectChat)
SwitchListTile.adaptive(
activeColor: AppConfig.activeToggleColor,
title: Text(
room.isSpace
? L10n.of(context)!.lockSpace
: L10n.of(context)!.lockChat,
style: TextStyle(
color:
Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
secondary: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor: iconColor,
child: Icon(
room.isLocked
? Icons.lock_outlined
: Icons.no_encryption_outlined,
),
),
value: room.isLocked,
onChanged: (value) => showFutureLoadingDialog(
context: context,
future: () => value
? lockRoom(
room,
Matrix.of(context).client,
)
: unlockRoom(
room,
Matrix.of(context).client,
),
),
),
const Divider(height: 1),
// Pangea#
ListTile(
title: Text(

View file

@ -1,6 +1,5 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/utils/get_chat_list_item_subtitle.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/room_status_extension.dart';
@ -350,16 +349,6 @@ class ChatListItem extends StatelessWidget {
),
),
const SizedBox(width: 8),
// #Pangea
if (room.isLocked)
const Padding(
padding: EdgeInsets.only(right: 4.0),
child: Icon(
Icons.lock_outlined,
size: 16,
),
),
// Pangea#
AnimatedContainer(
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,

View file

@ -3,8 +3,6 @@ import 'dart:async';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart';
import 'package:fluffychat/pages/invitation_selection/invitation_selection_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/utils/bot_name.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/widgets/matrix.dart';
@ -15,10 +13,6 @@ import 'package:matrix/matrix.dart';
import '../../utils/localized_exception_extension.dart';
//#Pangea
enum InvitationSelectionMode { admin, member }
//Pangea#
class InvitationSelection extends StatefulWidget {
final String roomId;
const InvitationSelection({
@ -76,80 +70,72 @@ class InvitationSelectionController extends State<InvitationSelection> {
}
//#Pangea
// add all students (already local) from spaceParents who aren't already in room to eligibleStudents
// use room.members to get all users in room
bool _initialized = false;
Future<List<User>> eligibleStudents(
BuildContext context,
String text,
) async {
if (!_initialized) {
_initialized = true;
await requestParentSpaceParticipants();
}
// // add all students (already local) from spaceParents who aren't already in room to eligibleStudents
// // use room.members to get all users in room
// bool _initialized = false;
// Future<List<User>> eligibleStudents(
// BuildContext context,
// String text,
// ) async {
// if (!_initialized) {
// _initialized = true;
// await requestParentSpaceParticipants();
// }
final eligibleStudents = <User>[];
final spaceParents = room?.pangeaSpaceParents;
if (spaceParents == null) return eligibleStudents;
// final eligibleStudents = <User>[];
// final spaceParents = room?.pangeaSpaceParents;
// if (spaceParents == null) return eligibleStudents;
final userId = Matrix.of(context).client.userID;
for (final Room space in spaceParents) {
eligibleStudents.addAll(
space.getParticipants().where(
(spaceUser) =>
spaceUser.id != BotName.byEnvironment &&
spaceUser.id != "@support:staging.pangea.chat" &&
spaceUser.id != userId &&
(text.isEmpty ||
(spaceUser.displayName
?.toLowerCase()
.contains(text.toLowerCase()) ??
false) ||
spaceUser.id.toLowerCase().contains(text.toLowerCase())),
),
);
}
return eligibleStudents;
}
// final userId = Matrix.of(context).client.userID;
// for (final Room space in spaceParents) {
// eligibleStudents.addAll(
// space.getParticipants().where(
// (spaceUser) =>
// spaceUser.id != BotName.byEnvironment &&
// spaceUser.id != "@support:staging.pangea.chat" &&
// spaceUser.id != userId &&
// (text.isEmpty ||
// (spaceUser.displayName
// ?.toLowerCase()
// .contains(text.toLowerCase()) ??
// false) ||
// spaceUser.id.toLowerCase().contains(text.toLowerCase())),
// ),
// );
// }
// return eligibleStudents;
// }
Future<SearchUserDirectoryResponse>
eligibleStudentsAsSearchUserDirectoryResponse(
BuildContext context,
String text,
) async {
return SearchUserDirectoryResponse(
results: (await eligibleStudents(context, text))
.map(
(e) => Profile(
userId: e.id,
avatarUrl: e.avatarUrl,
displayName: e.displayName,
),
)
.toList(),
limited: false,
);
}
// Future<SearchUserDirectoryResponse>
// eligibleStudentsAsSearchUserDirectoryResponse(
// BuildContext context,
// String text,
// ) async {
// return SearchUserDirectoryResponse(
// results: (await eligibleStudents(context, text))
// .map(
// (e) => Profile(
// userId: e.id,
// avatarUrl: e.avatarUrl,
// displayName: e.displayName,
// ),
// )
// .toList(),
// limited: false,
// );
// }
List<User?> studentsInRoom(BuildContext context) =>
room
?.getParticipants()
.where(
(u) => [Membership.join, Membership.invite].contains(u.membership),
)
.toList() ??
<User>[];
// List<User?> studentsInRoom(BuildContext context) =>
// room
// ?.getParticipants()
// .where(
// (u) => [Membership.join, Membership.invite].contains(u.membership),
// )
// .toList() ??
// <User>[];
//Pangea#
// #Pangea
// void inviteAction(BuildContext context, String id, String displayname) async {
void inviteAction(
BuildContext context,
String id,
String displayname, {
InvitationSelectionMode? mode,
}) async {
// Pangea#
void inviteAction(BuildContext context, String id, String displayname) async {
final room = Matrix.of(context).client.getRoomById(roomId!)!;
if (OkCancelResult.ok !=
await showOkCancelAlertDialog(
@ -168,16 +154,7 @@ class InvitationSelectionController extends State<InvitationSelection> {
}
final success = await showFutureLoadingDialog(
context: context,
//#Pangea
// future: () => room.invite(id),
future: () async {
if (mode == InvitationSelectionMode.admin) {
await inviteTeacherAction(room, id);
} else {
await room.invite(id);
}
},
// Pangea#
future: () => room.invite(id),
);
if (success.error == null) {
ScaffoldMessenger.of(context).showSnackBar(
@ -191,13 +168,6 @@ class InvitationSelectionController extends State<InvitationSelection> {
}
}
// #Pangea
Future<void> inviteTeacherAction(Room room, String id) async {
await room.invite(id);
await room.setPower(id, ClassDefaultValues.powerLevelOfAdmin);
}
// Pangea#
void searchUserWithCoolDown(String text) async {
coolDown?.cancel();
coolDown = Timer(
@ -218,15 +188,7 @@ class InvitationSelectionController extends State<InvitationSelection> {
final matrix = Matrix.of(context);
SearchUserDirectoryResponse response;
try {
//#Pangea
// response = await matrix.client.searchUserDirectory(text, limit: 10);
response = await (mode == InvitationSelectionMode.admin
? matrix.client.searchUserDirectory(text, limit: 10)
: eligibleStudentsAsSearchUserDirectoryResponse(
context,
text,
));
//Pangea#
response = await matrix.client.searchUserDirectory(text, limit: 10);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text((e).toLocalizedString(context))),
@ -264,67 +226,6 @@ class InvitationSelectionController extends State<InvitationSelection> {
});
}
//#Pangea
Room? _room;
Room? get room => _room ??= Matrix.of(context).client.getRoomById(roomId!);
// request participants for all parent spaces
Future<void> requestParentSpaceParticipants() async {
final spaceParents = room?.pangeaSpaceParents;
if (spaceParents != null) {
await Future.wait([
...spaceParents.map((r) async {
await r.requestParticipants();
}),
room!.requestParticipants(),
]);
}
}
InvitationSelectionMode mode = InvitationSelectionMode.member;
StreamSubscription<SyncUpdate>? _spaceSubscription;
@override
void initState() {
Future.delayed(
Duration.zero,
() => setState(
() => mode = room?.isSpace ?? false
? InvitationSelectionMode.admin
: InvitationSelectionMode.member,
),
);
_spaceSubscription = Matrix.of(context)
.client
.onSync
.stream
.where(
(event) =>
event.rooms?.join?.keys.any(
(ithRoomId) =>
room?.pangeaSpaceParents
.map((e) => e.id)
.contains(ithRoomId) ??
false,
) ??
false,
)
.listen(
(SyncUpdate syncUpdate) async {
await requestParentSpaceParticipants();
setState(() {});
},
);
super.initState();
}
@override
void dispose() {
_spaceSubscription?.cancel();
super.dispose();
}
//Pangea#
@override
Widget build(BuildContext context) => InvitationSelectionView(this);
}

View file

@ -64,9 +64,7 @@ class InvitationSelectionView extends StatelessWidget {
fontWeight: FontWeight.normal,
),
// #Pangea
hintText: controller.mode == InvitationSelectionMode.admin
? L10n.of(context)!.inviteUsersFromPangea
: L10n.of(context)!.inviteStudentByUserName,
hintText: L10n.of(context)!.inviteStudentByUserName,
// hintText: L10n.of(context)!.inviteContactToGroup(groupName),
// Pangea#
prefixIcon: controller.loading
@ -93,18 +91,6 @@ class InvitationSelectionView extends StatelessWidget {
builder: (context, snapshot) {
final participants =
room.getParticipants().map((user) => user.id).toSet();
if (controller.mode != InvitationSelectionMode.admin &&
room.spaceParents.isEmpty) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Center(
child: Text(
L10n.of(context)!.emptyInviteWarning,
textAlign: TextAlign.center,
),
),
);
}
return controller.foundProfiles.isNotEmpty
? ListView.builder(
physics: const NeverScrollableScrollPhysics(),
@ -126,19 +112,11 @@ class InvitationSelectionView extends StatelessWidget {
controller.foundProfiles[i].displayName ??
controller.foundProfiles[i].userId.localpart ??
L10n.of(context)!.user,
// #Pangea
mode: controller.mode,
// Pangea#
),
),
)
: FutureBuilder<List<User>>(
// #Pangea
future: controller.mode == InvitationSelectionMode.admin
? controller.getContacts(context)
: controller.eligibleStudents(context, ""),
// future: controller.getContacts(context),
// Pangea#
future: controller.getContacts(context),
builder: (BuildContext context, snapshot) {
if (!snapshot.hasData) {
return const Center(
@ -166,9 +144,6 @@ class InvitationSelectionView extends StatelessWidget {
contacts[i].displayName ??
contacts[i].id.localpart ??
L10n.of(context)!.user,
// #Pangea
mode: controller.mode,
// Pangea#
),
),
);

View file

@ -259,7 +259,7 @@ extension PangeaRoom on Room {
Future<bool> get isBotDM async => await _isBotDM;
bool get isLocked => _isLocked;
// bool get isLocked => _isLocked;
bool isAnalyticsRoomOfUser(String userId) => _isAnalyticsRoomOfUser(userId);

View file

@ -58,24 +58,24 @@ extension RoomInformationRoomExtension on Room {
Future<bool> get _isBotDM async => botOptions?.mode == BotMode.directChat;
bool get _isLocked {
if (isDirectChat) return false;
if (!isSpace) {
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 == null || room.isAnalyticsRoom || room.isArchived) continue;
if (!room._isLocked) {
return false;
}
}
return (eventsDefaultPowerLevel ?? 0) >=
ClassDefaultValues.powerLevelOfAdmin;
}
// bool get _isLocked {
// if (isDirectChat) return false;
// if (!isSpace) {
// 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 == null || room.isAnalyticsRoom || room.isArchived) continue;
// if (!room._isLocked) {
// return false;
// }
// }
// return (eventsDefaultPowerLevel ?? 0) >=
// ClassDefaultValues.powerLevelOfAdmin;
// }
bool _isAnalyticsRoomOfUser(String userId) =>
isAnalyticsRoom && isMadeByUser(userId);

View file

@ -0,0 +1,431 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:fluffychat/pages/chat_details/chat_details.dart';
import 'package:fluffychat/pages/chat_details/participant_list_item.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/pages/class_settings/class_name_header.dart';
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/room_capacity_button.dart';
import 'package:fluffychat/pangea/utils/download_chat.dart';
import 'package:fluffychat/pangea/widgets/chat/visibility_toggle.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/widgets/matrix.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';
class PangeaChatDetailsView extends StatelessWidget {
final ChatDetailsController controller;
const PangeaChatDetailsView(this.controller, {super.key});
void _downloadChat(BuildContext context) async {
if (controller.roomId == null) return;
final Room? room =
Matrix.of(context).client.getRoomById(controller.roomId!);
if (room == null) return;
final type = await showConfirmationDialog(
context: context,
title: L10n.of(context)!.downloadGroupText,
actions: [
AlertDialogAction(
key: DownloadType.csv,
label: L10n.of(context)!.downloadCSVFile,
),
AlertDialogAction(
key: DownloadType.txt,
label: L10n.of(context)!.downloadTxtFile,
),
AlertDialogAction(
key: DownloadType.xlsx,
label: L10n.of(context)!.downloadXLSXFile,
),
],
);
if (type == null) return;
downloadChat(room, type, context);
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final room = Matrix.of(context).client.getRoomById(controller.roomId!);
if (room == null || room.membership == Membership.leave) {
return Scaffold(
appBar: AppBar(
title: Text(L10n.of(context)!.oopsSomethingWentWrong),
),
body: Center(
child: Text(L10n.of(context)!.youAreNoLongerParticipatingInThisChat),
),
);
}
final bool isGroupChat = !room.isDirectChat && !room.isSpace;
return StreamBuilder(
stream: room.client.onRoomState.stream
.where((update) => update.roomId == room.id),
builder: (context, snapshot) {
var members = room.getParticipants().toList()
..sort((b, a) => a.powerLevel.compareTo(b.powerLevel));
members = members.take(10).toList();
final actualMembersCount = (room.summary.mInvitedMemberCount ?? 0) +
(room.summary.mJoinedMemberCount ?? 0);
final canRequestMoreMembers = members.length < actualMembersCount;
final iconColor = theme.textTheme.bodyLarge!.color;
final displayname = room.getLocalizedDisplayname(
MatrixLocals(L10n.of(context)!),
);
return Scaffold(
appBar: AppBar(
leading: controller.widget.embeddedCloseButton ??
const Center(child: BackButton()),
elevation: theme.appBarTheme.elevation,
title: ClassNameHeader(
controller: controller,
room: room,
),
backgroundColor: theme.appBarTheme.backgroundColor,
),
body: MaxWidthBody(
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: members.length + 1 + (canRequestMoreMembers ? 1 : 0),
itemBuilder: (BuildContext context, int i) => i == 0
? Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
children: [
Padding(
padding: const EdgeInsets.all(32.0),
child: Stack(
children: [
Hero(
tag:
controller.widget.embeddedCloseButton !=
null
? 'embedded_content_banner'
: 'content_banner',
child: Avatar(
mxContent: room.avatar,
name: displayname,
size: Avatar.defaultSize * 2.5,
),
),
if (!room.isDirectChat &&
room.canChangeStateEvent(
EventTypes.RoomAvatar,
))
Positioned(
bottom: 0,
right: 0,
child: FloatingActionButton.small(
onPressed: controller.setAvatarAction,
heroTag: null,
child: const Icon(
Icons.camera_alt_outlined,
),
),
),
],
),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextButton.icon(
onPressed: () => room.isDirectChat
? null
: room.canChangeStateEvent(
EventTypes.RoomName,
)
? controller.setDisplaynameAction()
: FluffyShare.share(
displayname,
context,
copyOnly: true,
),
icon: Icon(
room.isDirectChat
? Icons.chat_bubble_outline
: room.canChangeStateEvent(
EventTypes.RoomName,
)
? Icons.edit_outlined
: Icons.copy_outlined,
size: 16,
),
style: TextButton.styleFrom(
foregroundColor:
theme.colorScheme.onSurface,
),
label: Text(
room.isDirectChat
? L10n.of(context)!.directChat
: displayname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 18),
),
),
TextButton.icon(
onPressed: () => room.isDirectChat
? null
: context.push(
'/rooms/${controller.roomId}/details/members',
),
icon: const Icon(
Icons.group_outlined,
size: 14,
),
style: TextButton.styleFrom(
foregroundColor:
theme.colorScheme.secondary,
),
label: Text(
L10n.of(context)!.countParticipants(
actualMembersCount,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
],
),
Divider(color: theme.dividerColor, height: 1),
if (isGroupChat && room.canInvite)
ConversationBotSettings(
key: controller.addConversationBotKey,
room: room,
),
if (isGroupChat && room.canInvite)
Divider(color: theme.dividerColor, height: 1),
if (room.canInvite && !room.isDirectChat)
ListTile(
title: Text(
L10n.of(context)!.inviteStudentByUserName,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
leading: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor:
Theme.of(context).textTheme.bodyLarge!.color,
child: const Icon(
Icons.person_add_outlined,
),
),
onTap: () => context.go('/rooms/${room.id}/invite'),
),
if (room.canInvite && !room.isDirectChat)
Divider(color: theme.dividerColor, height: 1),
if (room.isSpace && room.isRoomAdmin)
SpaceDetailsToggleAddStudentsTile(
controller: controller,
),
if (room.isSpace && room.isRoomAdmin)
Divider(color: theme.dividerColor, height: 1),
if (isGroupChat && room.isRoomAdmin)
ListTile(
title: Text(
L10n.of(context)!.editChatPermissions,
style: TextStyle(
color: theme.colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
L10n.of(context)!.whoCanPerformWhichAction,
),
leading: CircleAvatar(
backgroundColor: theme.scaffoldBackgroundColor,
foregroundColor: iconColor,
child: const Icon(
Icons.manage_accounts_outlined,
),
),
onTap: () => context.push(
'/rooms/${room.id}/details/permissions',
),
),
if (isGroupChat && room.isRoomAdmin)
Divider(color: theme.dividerColor, height: 1),
if (room.isRoomAdmin)
VisibilityToggle(
room: room,
setVisibility: controller.setVisibility,
iconColor: iconColor,
),
if (room.isRoomAdmin)
Divider(color: theme.dividerColor, height: 1),
RoomCapacityButton(
room: room,
controller: controller,
),
Divider(color: theme.dividerColor, height: 1),
if (isGroupChat)
ListTile(
title: Text(
L10n.of(context)!.downloadGroupText,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
leading: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor: iconColor,
child: const Icon(
Icons.download_outlined,
),
),
onTap: () => _downloadChat(context),
),
if (isGroupChat)
Divider(color: theme.dividerColor, height: 1),
if (isGroupChat)
ListTile(
title: Text(
L10n.of(context)!.muteChat,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
leading: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor: iconColor,
child: Icon(
room.pushRuleState == PushRuleState.notify
? Icons.volume_up
: Icons.volume_off,
),
),
onTap: controller.toggleMute,
),
if (isGroupChat)
Divider(color: theme.dividerColor, height: 1),
ListTile(
title: Text(
L10n.of(context)!.leave,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
leading: CircleAvatar(
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor: iconColor,
child: const Icon(
Icons.logout_outlined,
),
),
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');
}
}
},
),
Divider(color: theme.dividerColor, height: 1),
ListTile(
title: Text(
L10n.of(context)!.countParticipants(
actualMembersCount.toString(),
),
style: TextStyle(
color: theme.colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
],
)
: i < members.length + 1
? ParticipantListItem(members[i - 1])
: ListTile(
title: Text(
L10n.of(context)!.loadCountMoreParticipants(
(actualMembersCount - members.length).toString(),
),
),
leading: CircleAvatar(
backgroundColor: theme.scaffoldBackgroundColor,
child: const Icon(
Icons.group_outlined,
color: Colors.grey,
),
),
onTap: () => context.push(
'/rooms/${controller.roomId!}/details/members',
),
trailing: const Icon(Icons.chevron_right_outlined),
),
),
),
);
},
);
}
}

View file

@ -1,5 +1,5 @@
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_invitation_buttons.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import '../../../../pages/chat_details/chat_details.dart';
@ -14,27 +14,33 @@ class SpaceDetailsToggleAddStudentsTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(
L10n.of(context)!.addStudents,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
return Column(
children: [
ListTile(
title: Text(
L10n.of(context)!.addStudents,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: Theme.of(context).textTheme.bodyLarge!.color,
child: const Icon(
Icons.add,
),
),
trailing: Icon(
controller.displayAddStudentOptions
? Icons.keyboard_arrow_down_outlined
: Icons.keyboard_arrow_right_outlined,
),
onTap: controller.toggleAddStudentOptions,
),
),
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: Theme.of(context).textTheme.bodyLarge!.color,
child: const Icon(
Icons.add,
),
),
trailing: Icon(
controller.displayAddStudentOptions
? Icons.keyboard_arrow_down_outlined
: Icons.keyboard_arrow_right_outlined,
),
onTap: controller.toggleAddStudentOptions,
if (controller.displayAddStudentOptions)
ClassInvitationButtons(roomId: controller.roomId!),
],
);
}
}

View file

@ -86,11 +86,9 @@ class RoomCapacityButtonState extends State<RoomCapacityButton> {
foregroundColor: iconColor,
child: const Icon(Icons.reduce_capacity),
),
subtitle: Text(
trailing: Text(
(capacity == null)
? spaceMode
? L10n.of(context)!.spaceCapacityNotSet
: L10n.of(context)!.chatCapacityNotSet
? L10n.of(context)!.noCapacityLimit
: (nonAdmins != null)
? '$nonAdmins/$capacity'
: '$capacity',

View file

@ -23,13 +23,12 @@ enum DownloadType { txt, csv, xlsx }
Future<void> downloadChat(
Room room,
DownloadType type,
Client client,
BuildContext context,
) async {
List<PangeaMessageEvent> allPangeaMessages;
try {
final List<Event> allEvents = await getAllEvents(room, client);
final List<Event> allEvents = await getAllEvents(room);
final TimelineChunk chunk = TimelineChunk(events: allEvents);
final Timeline timeline = Timeline(
room: room,
@ -85,14 +84,14 @@ Future<void> downloadChat(
}
}
Future<List<Event>> getAllEvents(Room room, Client client) async {
Future<List<Event>> getAllEvents(Room room) async {
final GetRoomEventsResponse initalResp =
await client.getRoomEvents(room.id, Direction.b);
await room.client.getRoomEvents(room.id, Direction.b);
if (initalResp.end == null) return [];
String? nextStartToken = initalResp.end;
List<MatrixEvent> allMatrixEvents = initalResp.chunk;
while (nextStartToken != null) {
final GetRoomEventsResponse resp = await client.getRoomEvents(
final GetRoomEventsResponse resp = await room.client.getRoomEvents(
room.id,
Direction.b,
from: nextStartToken,

View file

@ -70,6 +70,7 @@ class ConversationBotSettingsState extends State<ConversationBotSettings> {
fontWeight: FontWeight.bold,
),
),
subtitle: Text(L10n.of(context)!.botSettingsSubtitle),
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: Theme.of(context).textTheme.bodyLarge!.color,
@ -78,7 +79,6 @@ class ConversationBotSettingsState extends State<ConversationBotSettings> {
expression: BotExpression.idle,
),
),
trailing: const Icon(Icons.settings),
onTap: showBotOptionsDialog,
),
],

View file

@ -123,7 +123,6 @@ class ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
future: () => downloadChat(
widget.room,
DownloadType.txt,
Matrix.of(context).client,
context,
),
);
@ -134,7 +133,6 @@ class ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
future: () => downloadChat(
widget.room,
DownloadType.csv,
Matrix.of(context).client,
context,
),
);
@ -145,7 +143,6 @@ class ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
future: () => downloadChat(
widget.room,
DownloadType.xlsx,
Matrix.of(context).client,
context,
),
);