diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb
index 793c97447..780db7e9d 100644
--- a/assets/l10n/intl_en.arb
+++ b/assets/l10n/intl_en.arb
@@ -3957,5 +3957,6 @@
"activateTrial": "Activate Trial",
"inNoSpaces": "You are not a member of any classes or exchanges",
"successfullySubscribed": "You have successfully subscribed!",
- "clickToManageSubscription": "Click here to manage your subscription."
+ "clickToManageSubscription": "Click here to manage your subscription.",
+ "emptyInviteWarning": "Add this chat to a class or exchange to invite other users."
}
diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb
index 630db9401..334cb1223 100644
--- a/assets/l10n/intl_es.arb
+++ b/assets/l10n/intl_es.arb
@@ -1527,29 +1527,29 @@
"type": "text",
"placeholders": {}
},
- "sender": "Remitente",
+ "sender": "",
"@sender": {},
- "pinMessage": "Anclar al chat",
+ "pinMessage": "",
"@pinMessage": {},
- "confirmEventUnpin": "¿Está seguro de desanclar definitivamente el mensaje?",
+ "confirmEventUnpin": "",
"@confirmEventUnpin": {},
- "emojis": "Emojis",
+ "emojis": "",
"@emojis": {},
- "placeCall": "Hacer llamada",
+ "placeCall": "",
"@placeCall": {},
"voiceCall": "Llamada de voz",
"@voiceCall": {},
- "unsupportedAndroidVersion": "Versión de Android no compatible",
+ "unsupportedAndroidVersion": "",
"@unsupportedAndroidVersion": {},
- "unsupportedAndroidVersionLong": "Esta función requiere una versión más reciente de Android. Verifique si hay actualizaciones o soporte de Lineage OS.",
+ "unsupportedAndroidVersionLong": "",
"@unsupportedAndroidVersionLong": {},
- "videoCallsBetaWarning": "Tenga en cuenta que las videollamadas se encuentran actualmente en versión beta. Es posible que no funcionen como se esperaba o que no funcionen en todas las plataformas.",
+ "videoCallsBetaWarning": "",
"@videoCallsBetaWarning": {},
- "experimentalVideoCalls": "Videollamadas experimentales",
+ "experimentalVideoCalls": "",
"@experimentalVideoCalls": {},
- "indexedDbErrorTitle": "Problemas del modo privado",
+ "indexedDbErrorTitle": "",
"@indexedDbErrorTitle": {},
- "indexedDbErrorLong": "Desafortunadamente, el almacenamiento de mensajes no está habilitado en modo privado de forma predeterminada.\nVisite\n - about:config\n - establezca dom.indexedDB.privateBrowsing.enabled en verdadero\nDe lo contrario, no es posible ejecutar FluffyChat.",
+ "indexedDbErrorLong": "",
"@indexedDbErrorLong": {},
"reactedWith": "{sender} reaccionó con {reaction}",
"@reactedWith": {
@@ -1559,7 +1559,7 @@
"reaction": {}
}
},
- "switchToAccount": "Cambiar a la cuenta {number}",
+ "switchToAccount": "",
"@switchToAccount": {
"type": "number",
"placeholders": {
@@ -2207,7 +2207,7 @@
"type": "text",
"placeholders": {}
},
- "enterASpacepName": "Ingrese nombre de espacio",
+ "enterASpacepName": "Introduzca un nombre",
"@enterASpacepName": {},
"ignore": "Bloquear",
"@ignore": {
@@ -3262,7 +3262,7 @@
"timeOfLastMessage": "Hora del último mensaje enviado",
"totalMessages": "Mensajes totales enviados",
"changeDateRange": "Cambiar rango de fechas",
- "doNotShowAgain": "No mostrar de nuevo.",
+ "doNotShowAgain": "",
"l1SpanAndGrammarTitle": "Fuera del idioma de destino",
"l1SpanAndGrammarDesc": "Esto podría estar en su idioma base o podría ser un error gramatical.",
"allCorrect": "¡Así es como lo diría yo! ¡Muy bien!",
@@ -3323,7 +3323,7 @@
"waTooltip": "Uso de L2 sin asistencia",
"unTooltip": "Otra",
"interactiveGrammarSliderHeader": "Asistencia gramatical",
- "allRooms": "Todos los chats grupales",
+ "allRooms": "",
"@allRooms": {
"type": "text",
"placeholders": {}
@@ -3338,26 +3338,26 @@
"igcIsDisabled": "La asistencia gramatical está deshabilitada.",
"goToLearningSettings": "Vaya a Ajustes de aprendizaje.",
"learningSettings": "Ajustes de aprendizaje",
- "report": "Reportar",
- "reportErrorDescription": "Oh, no. Algo salió mal. Por favor, inténtelo de nuevo más tarde. Si lo desea, puede reportar el error a los desarrolladores.",
+ "report": "",
+ "reportErrorDescription": "",
"clearAll": "¿Borrar todas las palabras?",
- "jump": "Saltar",
- "openLinkInBrowser": "Abrir enlace en el navegador.",
- "jumpToLastReadMessage": "Saltar al último mensaje leído.",
- "readUpToHere": "Leído hasta aquí.",
- "newSpaceDescription": "Espacios le permite consolidar sus chats y crear comunidades privadas o públicas.",
- "encryptThisChat": "Encriptar este chat",
- "endToEndEncryption": "Encriptado de fin a fin",
- "disableEncryptionWarning": "Por razones de seguridad, no puede deshabilitar el cifrado en un chat, donde se ha habilitado antes.",
- "sorryThatsNotPossible": "Discupla... eso no es posible",
- "deviceKeys": "Claves del dispositivo:",
- "letsStart": "¡Empecemos!",
- "enterInviteLinkOrMatrixId": "Ingrese el enlace de invitación o ID de Matrix...",
- "reopenChat": "Reabrir chat",
- "noBackupWarning": "¡No olvida su contraseña!",
- "noOtherDevicesFound": "No se encontraron otros dispositivos",
- "fileIsTooBigForServer": "El servidor informa que el archivo es demasiado grande para enviarlo.",
- "fileHasBeenSavedAt": "Se ha guardado el archivo en {path}",
+ "jump": "",
+ "openLinkInBrowser": "",
+ "jumpToLastReadMessage": "",
+ "readUpToHere": "",
+ "newSpaceDescription": "",
+ "encryptThisChat": "",
+ "endToEndEncryption": "",
+ "disableEncryptionWarning": "",
+ "sorryThatsNotPossible": "",
+ "deviceKeys": "",
+ "letsStart": "",
+ "enterInviteLinkOrMatrixId": "",
+ "reopenChat": "",
+ "noBackupWarning": "",
+ "noOtherDevicesFound": "",
+ "fileIsTooBigForServer": "",
+ "fileHasBeenSavedAt": "",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
@@ -3413,37 +3413,37 @@
"type": "text",
"placeholders": {}
},
- "user": "Usuario",
+ "user": "",
"@user": {},
- "custom": "personalizado",
+ "custom": "",
"@custom": {},
- "foregroundServiceRunning": "Esta notificación aparece cuando se está ejecutando el servicio en primer plano.",
+ "foregroundServiceRunning": "",
"@foregroundServiceRunning": {},
- "screenSharingTitle": "compartiendo pantalla",
+ "screenSharingTitle": "",
"@screenSharingTitle": {},
- "screenSharingDetail": "Está compartiendo su pantalla en FluffyChat.",
+ "screenSharingDetail": "",
"@screenSharingDetail": {},
- "callingPermissions": "Permisos de llamada",
+ "callingPermissions": "",
"@callingPermissions": {},
- "callingAccount": "Llamando cuenta",
+ "callingAccount": "",
"@callingAccount": {},
- "callingAccountDetails": "Permite que FluffyChat use la aplicación de marcación nativa de Android.",
+ "callingAccountDetails": "",
"@callingAccountDetails": {},
- "appearOnTop": "Aparecer arriba",
+ "appearOnTop": "",
"@appearOnTop": {},
- "appearOnTopDetails": "Permite que la aplicación aparezca en la parte superior (no es necesario si ya tiene configurado Fluffychat como cuenta de llamadas).",
+ "appearOnTopDetails": "",
"@appearOnTopDetails": {},
"otherCallingPermissions": "Micrófono, cámara y otros permisos de FluffyChat",
"@otherCallingPermissions": {},
- "whyIsThisMessageEncrypted": "¿Por qué este mensaje no se puede leer?",
+ "whyIsThisMessageEncrypted": "",
"@whyIsThisMessageEncrypted": {},
- "noKeyForThisMessage": "Esto puede suceder si el mensaje se envió antes de que haya iniciado sesión en su cuenta en este dispositivo.\n\nTambién es posible que el remitente haya bloqueado su dispositivo o que algo haya fallado con la conexión a Internet.\n\n¿Puede leer el mensaje en otra sesión? ¡Entonces puede transferir el mensaje desde allí! Vaya a Configuración > Dispositivos y asegúrese de que sus dispositivos se hayan verificado entre sí. La próxima vez que abra la sala y ambas sesiones estén en primer plano, las claves se transmitirán automáticamente.\n\n¿No desea perder las claves al cerrar sesión o al cambiar de dispositivo? Asegúrese de haber habilitado la copia de seguridad del chat en la configuración.",
+ "noKeyForThisMessage": "",
"@noKeyForThisMessage": {},
"newGroup": "Nuevo chat",
"@newGroup": {},
- "enterRoom": "Unirse al chat",
+ "enterRoom": "",
"@enterRoom": {},
- "numChats": "{number} chats",
+ "numChats": "",
"@numChats": {
"type": "number",
"placeholders": {
@@ -3457,52 +3457,52 @@
"number": {}
}
},
- "hideUnimportantStateEvents": "Ocultar eventos de estado sin importancia",
- "wasDirectChatDisplayName": "Chat vacío (era {oldDisplayName})",
+ "hideUnimportantStateEvents": "",
+ "wasDirectChatDisplayName": "",
"@wasDirectChatDisplayName": {
"type": "text",
"placeholders": {
"oldDisplayName": {}
}
},
- "startFirstChat": "Empezar su primer chat",
+ "startFirstChat": "",
"nextAccount": "Próxima cuenta",
"@nextAccount": {},
"previousAccount": "Cuenta anterior",
"@previousAccount": {},
- "editWidgets": "Editar artilugios",
+ "editWidgets": "",
"@editWidgets": {},
- "addWidget": "Agregar artilugio",
+ "addWidget": "",
"@addWidget": {},
- "widgetVideo": "Video",
+ "widgetVideo": "",
"@widgetVideo": {},
"widgetEtherpad": "Nota de texto",
"@widgetEtherpad": {},
"widgetJitsi": "Jitsi Meet",
"@widgetJitsi": {},
- "widgetCustom": "Personalizado",
+ "widgetCustom": "",
"@widgetCustom": {},
"widgetName": "Nombre",
"@widgetName": {},
"widgetUrlError": "Esto no es un enlace válido.",
"@widgetUrlError": {},
- "widgetNameError": "Proporcione un nombre para mostrar.",
+ "widgetNameError": "",
"@widgetNameError": {},
- "errorAddingWidget": "Error an agregar el artilugio.",
+ "errorAddingWidget": "",
"@errorAddingWidget": {},
"youRejectedTheInvitation": "Rechazó la invitación.",
"@youRejectedTheInvitation": {},
- "youJoinedTheChat": "Se unió al chat.",
+ "youJoinedTheChat": "",
"@youJoinedTheChat": {},
- "youAcceptedTheInvitation": "👍 Aceptó la invitación.",
+ "youAcceptedTheInvitation": "👍 Aceptaste la invitación",
"@youAcceptedTheInvitation": {},
- "youBannedUser": "Bloqueó {user}",
+ "youBannedUser": "",
"@youBannedUser": {
"placeholders": {
"user": {}
}
},
- "youHaveWithdrawnTheInvitationFor": "You have withdrawn the invitation for {user}",
+ "youHaveWithdrawnTheInvitationFor": "",
"@youHaveWithdrawnTheInvitationFor": {
"placeholders": {
"user": {}
@@ -3514,54 +3514,50 @@
"user": {}
}
},
- "youAcceptedTheInvitation": "👍 Aceptaste la invitación",
- "@youAcceptedTheInvitation": {},
- "widgetEtherpad": "Nota de texto",
- "@widgetEtherpad": {},
- "commandHint_cuddle": "Mandar una carantoña",
+ "commandHint_cuddle": "Enviar un arrunche.",
"@commandHint_cuddle": {},
- "supposedMxid": "Esto debería ser {mxid}",
- "youInvitedUser": "📩 Invitó {user}",
+ "supposedMxid": "Esto debe ser {mxid}",
+ "youInvitedUser": "",
"@youInvitedUser": {
"placeholders": {
"user": {}
}
},
- "youKicked": "👞 Eliminó {user}",
+ "youKicked": "",
"@youKicked": {
"placeholders": {
"user": {}
}
},
- "youKickedAndBanned": "🙅 Eliminó y bloqueó {user}",
+ "youKickedAndBanned": "",
"@youKickedAndBanned": {
"placeholders": {
"user": {}
}
},
- "youUnbannedUser": "Desbloqueó {user}",
+ "youUnbannedUser": "",
"@youUnbannedUser": {
"placeholders": {
"user": {}
}
},
- "noEmailWarning": "Por favor, introduzca una dirección de correo electrónico válida. De lo contrario, no podrá restablecer su contraseña. Si no quiere, toque de nuevo el botón para continuar.",
+ "noEmailWarning": "",
"@noEmailWarning": {},
"stories": "Historias",
"@stories": {},
"users": "Usuarios",
"@users": {},
- "unlockOldMessages": "Desbloquear mensajes viejos.",
+ "unlockOldMessages": "",
"@unlockOldMessages": {},
- "storeInSecureStorageDescription": "Guarde la clave de recuperación en el almacenamiento seguro de este dispositivo.",
+ "storeInSecureStorageDescription": "",
"@storeInSecureStorageDescription": {},
- "saveKeyManuallyDescription": "Guarde esta clave manualmente activando el cuadro de diálogo compartido del sistema o el portapapeles.",
+ "saveKeyManuallyDescription": "",
"@saveKeyManuallyDescription": {},
- "storeInAndroidKeystore": "Guardar en Android KeyStore",
+ "storeInAndroidKeystore": "",
"@storeInAndroidKeystore": {},
- "storeInAppleKeyChain": "Guardar en Apple Acceso de Llaveros",
+ "storeInAppleKeyChain": "",
"@storeInAppleKeyChain": {},
- "storeSecurlyOnThisDevice": "Almacenar de forma segura en este dispositivo",
+ "storeSecurlyOnThisDevice": "",
"@storeSecurlyOnThisDevice": {},
"countFiles": "{count} archivos",
"@countFiles": {
@@ -3571,24 +3567,22 @@
},
"confirmMatrixId": "Confirme su ID de Matrix para eliminar su cuenta.",
"@confirmMatrixId": {},
- "supposedMxid": "Esto debe ser {mxid}",
"@supposedMxid": {
"type": "text",
"placeholders": {
"mxid": {}
}
},
- "commandHint_googly": "Enviar unos ojos saltones.",
- "commandHint_cuddle": "Enviar un arrunche.",
+ "commandHint_googly": "",
"commandHint_hug": "Enviar un abrazo.",
- "googlyEyesContent": "{senderName} le manda ojos saltones.",
+ "googlyEyesContent": "",
"@googlyEyesContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
- "cuddleContent": "{senderName} se arruncha con usted.",
+ "cuddleContent": "",
"@cuddleContent": {
"type": "text",
"placeholders": {
@@ -3602,156 +3596,88 @@
"senderName": {}
}
},
- "pleaseEnterRecoveryKey": "Por favor ingrese su clave de recuperación:",
+ "pleaseEnterRecoveryKey": "",
"@pleaseEnterRecoveryKey": {},
- "commandHint_markasdm": "Marcar como chat de mensajes directos",
+ "commandHint_markasdm": "",
"@commandHint_markasdm": {},
"commandHint_markasgroup": "Marcar como grupal",
"@commandHint_markasgroup": {},
- "recoveryKey": "Clave de recuperación",
+ "recoveryKey": "",
"@recoveryKey": {},
- "recoveryKeyLost": "¿Clave de recuperación perdida?",
+ "recoveryKeyLost": "",
"@recoveryKeyLost": {},
- "separateChatTypes": "Separar chats privados y grupales",
- "@separateChatTypes": {
- "type": "text",
- "placeholders": {}
- },
- "commandHint_create": "Crear un chat grupal vacío\nUse --no-encryption para deshabilitar el cifrado",
- "replace": "Reemplazar",
- "@replace": {},
- "unsupportedAndroidVersionLong": "",
- "@unsupportedAndroidVersionLong": {},
- "storeSecurlyOnThisDevice": "",
- "@storeSecurlyOnThisDevice": {},
- "iUnderstand": "",
- "@iUnderstand": {},
- "encryptThisChat": "",
- "@encryptThisChat": {},
- "letsStart": "",
- "@letsStart": {},
- "endToEndEncryption": "",
- "@endToEndEncryption": {},
- "openChat": "",
- "@openChat": {},
- "screenSharingDetail": "",
- "@screenSharingDetail": {},
- "jumpToLastReadMessage": "",
- "@jumpToLastReadMessage": {},
- "allRooms": "",
- "@allRooms": {
- "type": "text",
- "placeholders": {}
- },
- "widgetVideo": "",
- "@widgetVideo": {},
- "dismiss": "",
- "@dismiss": {},
- "reportErrorDescription": "",
- "@reportErrorDescription": {},
- "unsupportedAndroidVersion": "",
- "@unsupportedAndroidVersion": {},
- "noEmailWarning": "",
- "@noEmailWarning": {},
- "indexedDbErrorLong": "",
- "@indexedDbErrorLong": {},
- "startFirstChat": "",
- "@startFirstChat": {},
- "callingAccount": "",
- "@callingAccount": {},
- "setColorTheme": "",
- "@setColorTheme": {},
- "commandHint_create": "",
- "@commandHint_create": {
- "type": "text",
- "description": "Usage hint for the command /create"
- },
- "commandHint_dm": "Empezar un chat privado\nUse --no-encryption para deshabilitar el cifrado",
- "user": "",
- "@user": {},
- "banUserDescription": "",
- "@banUserDescription": {},
- "requests": "",
- "@requests": {},
- "addToStory": "",
- "@addToStory": {},
- "removeDevicesDescription": "",
- "@removeDevicesDescription": {},
"separateChatTypes": "",
"@separateChatTypes": {
"type": "text",
"placeholders": {}
},
+ "commandHint_create": "",
+ "replace": "Corregir",
+ "@replace": {},
+ "iUnderstand": "Entiendo",
+ "@iUnderstand": {},
+ "@encryptThisChat": {},
+ "@letsStart": {},
+ "@endToEndEncryption": {},
+ "openChat": "Abrir Chat",
+ "@openChat": {},
+ "@jumpToLastReadMessage": {},
+ "dismiss": "Descartar",
+ "@dismiss": {},
+ "@reportErrorDescription": {},
+ "@startFirstChat": {},
+ "setColorTheme": "",
+ "@setColorTheme": {},
+ "@commandHint_create": {
+ "type": "text",
+ "description": "Usage hint for the command /create"
+ },
+ "commandHint_dm": "",
+ "banUserDescription": "",
+ "@banUserDescription": {},
+ "requests": "",
+ "@requests": {},
+ "addToStory": "Agregar a historia",
+ "@addToStory": {},
+ "removeDevicesDescription": "",
+ "@removeDevicesDescription": {},
"tryAgain": "",
"@tryAgain": {},
- "youKickedAndBanned": "",
- "@youKickedAndBanned": {
- "placeholders": {
- "user": {}
- }
- },
- "showDirectChatsInSpaces": "",
- "@showDirectChatsInSpaces": {
- "type": "text",
- "placeholders": {}
- },
+ "showDirectChatsInSpaces": "Mostrar chats directos relacionados en Spaces",
"unbanUserDescription": "",
"@unbanUserDescription": {},
"todoLists": "",
"@todoLists": {},
"messagesStyle": "",
"@messagesStyle": {},
- "newSpaceDescription": "",
"@newSpaceDescription": {},
"chatDescription": "",
"@chatDescription": {},
- "callingAccountDetails": "",
- "@callingAccountDetails": {},
- "enterSpace": "",
+ "enterSpace": "Introducir espacio",
"@enterSpace": {},
- "reopenChat": "",
"@reopenChat": {},
- "pleaseEnterRecoveryKey": "",
- "@pleaseEnterRecoveryKey": {},
- "widgetNameError": "",
- "@widgetNameError": {},
- "addWidget": "",
- "@addWidget": {},
- "noKeyForThisMessage": "",
- "@noKeyForThisMessage": {},
"editTodo": "",
"@editTodo": {},
- "hydrateTor": "",
+ "hydrateTor": "TOR Usuarios: Importar exportación de sesión",
"@hydrateTor": {},
"pushNotificationsNotAvailable": "",
"@pushNotificationsNotAvailable": {},
- "storeInAppleKeyChain": "",
- "@storeInAppleKeyChain": {},
- "hydrate": "",
+ "hydrate": "Restaurar desde archivo de copia de seguridad",
"@hydrate": {},
"invalidServerName": "",
"@invalidServerName": {},
"chatPermissions": "",
"@chatPermissions": {},
- "sender": "",
- "@sender": {},
- "storeInAndroidKeystore": "",
- "@storeInAndroidKeystore": {},
"signInWithPassword": "",
"@signInWithPassword": {},
"pleaseAddATitle": "",
"@pleaseAddATitle": {},
"makeAdminDescription": "",
"@makeAdminDescription": {},
- "saveKeyManuallyDescription": "",
- "@saveKeyManuallyDescription": {},
- "whyIsThisMessageEncrypted": "",
- "@whyIsThisMessageEncrypted": {},
"setChatDescription": "",
"@setChatDescription": {},
- "dehydrateWarning": "",
+ "dehydrateWarning": "Esta acción no se puede deshacer. Asegúrese de almacenar de forma segura el archivo de copia de seguridad.",
"@dehydrateWarning": {},
- "noOtherDevicesFound": "",
"@noOtherDevicesFound": {},
"redactedBy": "",
"@redactedBy": {
@@ -3760,11 +3686,9 @@
"username": {}
}
},
- "videoCallsBetaWarning": "",
- "@videoCallsBetaWarning": {},
- "storyPrivacyWarning": "",
+ "storyPrivacyWarning": "Tenga en cuenta que las personas pueden verse y comunicarse entre sí en su historia. Sus historias estarán visibles durante 24 horas, pero no hay garantía de que se eliminen de todos los dispositivos y servidores.",
"@storyPrivacyWarning": {},
- "matrixWidgets": "",
+ "matrixWidgets": "Artilugio de Matrix",
"@matrixWidgets": {},
"signInWith": "",
"@signInWith": {
@@ -3773,39 +3697,17 @@
"provider": {}
}
},
- "fileIsTooBigForServer": "",
"@fileIsTooBigForServer": {},
"noTodosYet": "",
"@noTodosYet": {},
- "callingPermissions": "",
- "@callingPermissions": {},
- "readUpToHere": "",
"@readUpToHere": {},
- "unlockOldMessages": "",
- "@unlockOldMessages": {},
- "numChats": "",
- "@numChats": {
- "type": "number",
- "placeholders": {
- "number": {}
- }
- },
"optionalRedactReason": "",
"@optionalRedactReason": {},
- "dehydrate": "",
+ "dehydrate": "Exportar sesión y borrar dispositivo",
"@dehydrate": {},
"archiveRoomDescription": "",
"@archiveRoomDescription": {},
- "switchToAccount": "",
- "@switchToAccount": {
- "type": "number",
- "placeholders": {
- "number": {}
- }
- },
- "experimentalVideoCalls": "",
- "@experimentalVideoCalls": {},
- "pleaseEnterRecoveryKeyDescription": "",
+ "pleaseEnterRecoveryKeyDescription": "Para desbloquear sus mensajes antiguos, ingrese su clave de recuperación que se generó en una sesión anterior. Su clave de recuperación NO es su contraseña.",
"@pleaseEnterRecoveryKeyDescription": {},
"inviteContactToGroupQuestion": "",
"@inviteContactToGroupQuestion": {},
@@ -3817,62 +3719,22 @@
"reason": {}
}
},
- "youHaveWithdrawnTheInvitationFor": "",
- "@youHaveWithdrawnTheInvitationFor": {
- "placeholders": {
- "user": {}
- }
- },
- "appearOnTopDetails": "",
- "@appearOnTopDetails": {},
- "enterRoom": "",
- "@enterRoom": {},
- "confirmEventUnpin": "",
- "@confirmEventUnpin": {},
- "youInvitedUser": "",
- "@youInvitedUser": {
- "placeholders": {
- "user": {}
- }
- },
- "fileHasBeenSavedAt": "",
- "@fileHasBeenSavedAt": {
- "type": "text",
- "placeholders": {
- "path": {}
- }
- },
"anyoneCanKnock": "",
"@anyoneCanKnock": {},
"redactMessageDescription": "",
"@redactMessageDescription": {},
- "recoveryKey": "",
- "@recoveryKey": {},
"invalidInput": "",
"@invalidInput": {},
"todosUnencrypted": "",
"@todosUnencrypted": {},
- "dehydrateTorLong": "",
+ "dehydrateTorLong": "Para TOR usuarios, se recomienda exportar la sesión antes de cerrar la ventana.",
"@dehydrateTorLong": {},
- "doNotShowAgain": "",
"@doNotShowAgain": {},
- "report": "",
"@report": {},
- "hideUnimportantStateEvents": "",
"@hideUnimportantStateEvents": {},
- "screenSharingTitle": "",
- "@screenSharingTitle": {},
- "widgetCustom": "",
- "@widgetCustom": {},
- "whoCanSeeMyStoriesDesc": "",
+ "whoCanSeeMyStoriesDesc": "Ten en cuenta que las personas pueden verse y ponerse en contacto en tu historia.",
"@whoCanSeeMyStoriesDesc": {},
- "youBannedUser": "",
- "@youBannedUser": {
- "placeholders": {
- "user": {}
- }
- },
- "unsubscribeStories": "",
+ "unsubscribeStories": "Darse de baja de historias",
"@unsubscribeStories": {},
"hasKnocked": "",
"@hasKnocked": {
@@ -3880,9 +3742,7 @@
"user": {}
}
},
- "openLinkInBrowser": "",
"@openLinkInBrowser": {},
- "disableEncryptionWarning": "",
"@disableEncryptionWarning": {},
"directChat": "",
"@directChat": {},
@@ -3897,19 +3757,8 @@
},
"inviteGroupChat": "",
"@inviteGroupChat": {},
- "appearOnTop": "",
- "@appearOnTop": {},
"invitePrivateChat": "",
"@invitePrivateChat": {},
- "foregroundServiceRunning": "",
- "@foregroundServiceRunning": {},
- "wasDirectChatDisplayName": "",
- "@wasDirectChatDisplayName": {
- "type": "text",
- "placeholders": {
- "oldDisplayName": {}
- }
- },
"noChatDescriptionYet": "",
"@noChatDescriptionYet": {},
"newTodo": "",
@@ -3918,29 +3767,20 @@
"@learnMore": {},
"chatDescriptionHasBeenChanged": "",
"@chatDescriptionHasBeenChanged": {},
- "dehydrateTor": "",
+ "dehydrateTor": "TOR Usuarios: Exportar sesión",
"@dehydrateTor": {},
"todoListChangedError": "",
"@todoListChangedError": {},
- "enterInviteLinkOrMatrixId": "",
"@enterInviteLinkOrMatrixId": {},
"roomUpgradeDescription": "",
"@roomUpgradeDescription": {},
"pleaseEnterANumber": "",
"@pleaseEnterANumber": {},
- "youKicked": "",
- "@youKicked": {
- "placeholders": {
- "user": {}
- }
- },
"profileNotFound": "",
"@profileNotFound": {},
- "jump": "",
"@jump": {},
- "sorryThatsNotPossible": "",
"@sorryThatsNotPossible": {},
- "storyFrom": "",
+ "storyFrom": "Historia de {date}: \n{body}",
"@storyFrom": {
"type": "text",
"placeholders": {
@@ -3950,11 +3790,6 @@
},
"shareInviteLink": "",
"@shareInviteLink": {},
- "commandHint_markasdm": "",
- "@commandHint_markasdm": {},
- "recoveryKeyLost": "",
- "@recoveryKeyLost": {},
- "deviceKeys": "",
"@deviceKeys": {},
"emoteKeyboardNoRecents": "",
"@emoteKeyboardNoRecents": {
@@ -3963,49 +3798,18 @@
},
"setTheme": "",
"@setTheme": {},
- "youJoinedTheChat": "",
- "@youJoinedTheChat": {},
- "thisUserHasNotPostedAnythingYet": "",
+ "thisUserHasNotPostedAnythingYet": "Este usuario aún no ha publicado nada en su historia.",
"@thisUserHasNotPostedAnythingYet": {},
- "errorAddingWidget": "",
- "@errorAddingWidget": {},
- "commandHint_dm": "",
"@commandHint_dm": {
"type": "text",
"description": "Usage hint for the command /dm"
},
- "dehydrate": "Exportar sesión y borrar dispositivo",
- "@dehydrate": {},
- "dehydrateWarning": "Esta acción no se puede deshacer. Asegúrese de almacenar de forma segura el archivo de copia de seguridad.",
- "@dehydrateWarning": {},
- "dehydrateTor": "TOR Usuarios: Exportar sesión",
- "@dehydrateTor": {},
- "dehydrateTorLong": "Para TOR usuarios, se recomienda exportar la sesión antes de cerrar la ventana.",
- "@dehydrateTorLong": {},
- "hydrateTor": "TOR Usuarios: Importar exportación de sesión",
- "@hydrateTor": {},
- "hydrateTorLong": "¿Exportó su sesión la última vez en TOR? Impórtelo rápidamente y siga chateando.",
+ "hydrateTorLong": "",
"@hydrateTorLong": {},
- "hydrate": "Restaurar desde archivo de copia de seguridad",
- "@hydrate": {},
"reportUser": "Reportar usuario",
"@reportUser": {},
- "dismiss": "Descartar",
- "@dismiss": {},
- "matrixWidgets": "Artilugio de Matrix",
- "@matrixWidgets": {},
- "storyPrivacyWarning": "Tenga en cuenta que las personas pueden verse y comunicarse entre sí en su historia. Sus historias estarán visibles durante 24 horas, pero no hay garantía de que se eliminen de todos los dispositivos y servidores.",
- "@storyPrivacyWarning": {},
- "iUnderstand": "Entiendo",
- "openChat": "Abrir Chat",
"markAsRead": "Marcar como leído",
- "pleaseEnterRecoveryKeyDescription": "Para desbloquear sus mensajes antiguos, ingrese su clave de recuperación que se generó en una sesión anterior. Su clave de recuperación NO es su contraseña.",
- "@pleaseEnterRecoveryKeyDescription": {},
- "addToStory": "Agregar a historia",
- "@addToStory": {},
"whoCanSeeMyStories": "¿Quién puede ver mis historias?",
- "unsubscribeStories": "Darse de baja de historias",
- "thisUserHasNotPostedAnythingYet": "Este usuario aún no ha publicado nada en su historia.",
"yourStory": "Su historia",
"itToggleDescription": "Esta herramienta de aprendizaje identificará palabras en su idioma base y lo ayudará a traducirlas a su idioma a aprender. Aunque es raro, la AI puede cometer errores de traducción de vez en cuando.",
"igcToggleDescription": "Esta herramienta de aprendizaje identificará errores comunes de ortografía, gramática y puntuación en su mensaje y sugerirá correcciones. Aunque es raro, la AI puede cometer errores de corrección de vez en cuando.",
@@ -4023,11 +3827,8 @@
"kickAllStudentsConfirmation": "¿Estás seguro de que quieres echar a todos los estudiantes?",
"inviteAllStudents": "Invitar a todos los estudiantes",
"inviteAllStudentsConfirmation": "¿Estás seguro de que quieres invitar a todos los estudiantes?",
- "whoCanSeeMyStoriesDesc": "Ten en cuenta que las personas pueden verse y ponerse en contacto en tu historia.",
"taAndGaTooltip": "Uso de la L2 con ayuda de traducción y asistencia gramatical.",
- "storyFrom": "Historia de {date}: \n{body}",
"createNewSpace": "Crear una sala de intercambio",
- "enterASpacepName": "Introduzca un nombre",
"oneToOneChatsWithinClass": "Chats privados dentro de la sala",
"oneToOneChatsWithinClassDesc": "Si permite chats privados, los alumnos pueden iniciar y utilizar chats privados con otros participantes de la sala. De lo contrario, sólo podrán participar en chats de grupo.",
"subscriptionManagementUnavailable": "Gestión de suscripciones no disponible",
@@ -4483,12 +4284,10 @@
"allPrivateChats": "Todos los chats privados (incluso con bots) en clase",
"chatHasBeenAddedToThisSpace": "Se ha añadido el chat a este espacio",
"classes": "Clases",
- "showDirectChatsInSpaces": "Mostrar chats directos relacionados en Spaces",
"spaceIsPublic": "El espacio es público",
"removeFromSpace": "Retirar del espacio",
"addToSpaceDescription": "Seleccione un espacio para añadirle este chat.",
"newSpace": "Nueva clase",
- "enterSpace": "Introducir espacio",
"allSpaces": "Todos los espacios",
"deleteSpace": "Borrar espacio",
"areYouSureDeleteClass": "¿Seguro que quieres borrar este espacio?",
@@ -4604,60 +4403,81 @@
"suggestExchangeDesc": "Los intercambios sugeridos aparecerán en la lista de chat de {spaceName}.",
"acceptSelection": "Aceptar corrección",
"acceptSelectionAnyway": "Use esto de todos modos",
- "replace": "Corregir",
"makingActivity": "Actividad de fabricación",
"why": "¿Por qué?",
"definition": "Definición",
"exampleSentence": "Ejemplo de frase",
"addToClassTitle": "Añadir intercambio a la clase",
- "youUnbannedUser": "",
- "@youUnbannedUser": {
- "placeholders": {
- "user": {}
- }
- },
- "emojis": "",
- "@emojis": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "",
"@pleaseTryAgainLaterOrChooseDifferentServer": {},
"createGroup": "",
"@createGroup": {},
- "hydrateTorLong": "",
- "@hydrateTorLong": {},
- "custom": "",
- "@custom": {},
- "noBackupWarning": "",
"@noBackupWarning": {},
- "editWidgets": "",
- "@editWidgets": {},
- "storeInSecureStorageDescription": "",
- "@storeInSecureStorageDescription": {},
"kickUserDescription": "",
"@kickUserDescription": {},
- "pinMessage": "",
- "@pinMessage": {},
"invite": "",
"@invite": {},
"continueWith": "",
"@continueWith": {},
- "indexedDbErrorTitle": "",
- "@indexedDbErrorTitle": {},
- "googlyEyesContent": "",
- "@googlyEyesContent": {
- "type": "text",
- "placeholders": {
- "senderName": {}
- }
- },
- "cuddleContent": "",
- "@cuddleContent": {
- "type": "text",
- "placeholders": {
- "senderName": {}
- }
- },
- "commandHint_googly": "",
"@commandHint_googly": {},
- "placeCall": "",
- "@placeCall": {}
+ "notAnImage": "No es un archivo de imagen.",
+ "importNow": "Importar ahora",
+ "importEmojis": "Importar emojis",
+ "importFromZipFile": "Importar desde archivo .zip",
+ "importZipFile": "Importar archivo .zip",
+ "exportEmotePack": "Exportar Emote pack como .zip",
+ "savedEmotePack": "¡Paquete de emoticonos guardado en {path}!",
+ "@savedEmotePack": {
+ "type": "text",
+ "placeholders": {
+ "path": {}
+ }
+ },
+ "sendTypingNotifications": "Enviar notificaciones de mecanografía",
+ "reportToTeacher": "¿A quién desea informar de este mensaje?",
+ "reportMessageTitle": "{reportingUserId} ha informado de un mensaje de {reportedUserId} en el chat {roomName}.",
+ "@reportMessageTitle": {
+ "placeholders": {
+ "reportingUserId": {},
+ "reportedUserId": {},
+ "roomName": {}
+ }
+ },
+ "reportMessageBody": "Mensaje: {reportedMessage}\nMotivo: {reason}",
+ "@reportMessageBody": {
+ "placeholders": {
+ "reportedMessage": {},
+ "reason": {}
+ }
+ },
+ "noTeachersFound": "No se han encontrado profesores a los que informar",
+ "noAddToSpacePermissions": "No puedes añadir un chat a este espacio",
+ "alreadyInSpace": "El chat ya está en este espacio",
+ "yourGlobalUserIdIs": "Tu ID de usuario global es:",
+ "noUsersFoundWithQuery": "Lamentablemente no se ha encontrado ningún usuario con \"{query}\". Por favor, compruebe si ha cometido un error tipográfico.",
+ "@noUsersFoundWithQuery": {
+ "type": "text",
+ "placeholders": {
+ "query": {}
+ }
+ },
+ "searchChatsRooms": "Busca #chats, @users...",
+ "groupName": "Nombre del grupo",
+ "createGroupAndInviteUsers": "Crear un grupo e invitar a los usuarios",
+ "groupCanBeFoundViaSearch": "El grupo se puede encontrar a través de la búsqueda",
+ "inNoSpaces": "No es miembro de ninguna clase o bolsa",
+ "createClass": "Crear clase",
+ "createExchange": "Crear intercambio",
+ "viewArchive": "Ver archivo",
+ "trialExpiration": "Su prueba gratuita caduca el {expiration}.",
+ "@trialExpiration": {
+ "placeholders": {
+ "expiration": {}
+ }
+ },
+ "freeTrialDesc": "Los nuevos usuarios reciben una semana de prueba gratuita de Pangea Chat",
+ "activateTrial": "Activar prueba",
+ "successfullySubscribed": "Se ha suscrito correctamente.",
+ "clickToManageSubscription": "Haga clic aquí para gestionar su suscripción.",
+ "emptyInviteWarning": "Añade este chat a una clase o intercambio para invitar a otros usuarios."
}
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 546e02616..97f0234c4 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -45,6 +45,10 @@
LSRequiresIPhoneOS
+
+ FLTEnableImpeller
+
+
NSAppleMusicUsageDescription
Play audio and voice messages in the app.
NSBluetoothAlwaysUsageDescription
diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart
index ee14bda2d..94be46c57 100644
--- a/lib/pages/chat_details/chat_details_view.dart
+++ b/lib/pages/chat_details/chat_details_view.dart
@@ -1,10 +1,3 @@
-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/app_config.dart';
import 'package:fluffychat/pages/chat_details/chat_details.dart';
import 'package:fluffychat/pages/chat_details/participant_list_item.dart';
@@ -26,6 +19,11 @@ 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';
+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 ChatDetailsView extends StatelessWidget {
final ChatDetailsController controller;
@@ -459,7 +457,8 @@ class ChatDetailsView extends StatelessWidget {
color: Theme.of(context).dividerColor,
),
// #Pangea
- if (room.canInvite)
+ if (room.canInvite &&
+ (!room.isSpace || room.isRoomAdmin))
ListTile(
title: Text(
room.isSpace
diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart
index 3aff52a5e..1c3de7485 100644
--- a/lib/pages/chat_list/space_view.dart
+++ b/lib/pages/chat_list/space_view.dart
@@ -234,6 +234,7 @@ class _SpaceViewState extends State {
_refresh();
}
+ // @override
@override
void dispose() {
super.dispose();
@@ -330,7 +331,17 @@ class _SpaceViewState extends State {
// #Pangea
void refreshOnUpdate(SyncUpdate event) {
- if (event.isMembershipUpdate(Matrix.of(context).client.userID!) ||
+ /* refresh on leave, invite, and space child update
+ not join events, because there's already a listener on
+ onTapSpaceChild, and they interfere with each other */
+ if (event.isMembershipUpdateByType(
+ Membership.leave,
+ Matrix.of(context).client.userID!,
+ ) ||
+ event.isMembershipUpdateByType(
+ Membership.invite,
+ Matrix.of(context).client.userID!,
+ ) ||
event.isSpaceChildUpdate(activeSpaceId)) {
_refresh();
}
diff --git a/lib/pages/invitation_selection/invitation_selection.dart b/lib/pages/invitation_selection/invitation_selection.dart
index 6736f099a..4811934eb 100644
--- a/lib/pages/invitation_selection/invitation_selection.dart
+++ b/lib/pages/invitation_selection/invitation_selection.dart
@@ -1,19 +1,17 @@
import 'dart:async';
-import 'package:flutter/material.dart';
-
import 'package:adaptive_dialog/adaptive_dialog.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/invitation_selection/invitation_selection_view.dart';
import 'package:fluffychat/pangea/constants/class_default_values.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
-import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.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:matrix/matrix.dart';
+
import '../../utils/localized_exception_extension.dart';
//#Pangea
@@ -165,7 +163,6 @@ class InvitationSelectionController extends State {
]),
),
]),
- onError: (e) => ErrorHandler.logError(e: e, s: StackTrace.current),
// Pangea#
);
if (success.error == null) {
diff --git a/lib/pages/invitation_selection/invitation_selection_view.dart b/lib/pages/invitation_selection/invitation_selection_view.dart
index 5d5540084..bf3229515 100644
--- a/lib/pages/invitation_selection/invitation_selection_view.dart
+++ b/lib/pages/invitation_selection/invitation_selection_view.dart
@@ -1,12 +1,10 @@
-import 'package:flutter/material.dart';
-
-import 'package:flutter_gen/gen_l10n/l10n.dart';
-import 'package:matrix/matrix.dart';
-
import 'package:fluffychat/pages/invitation_selection/invitation_selection.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:matrix/matrix.dart';
class InvitationSelectionView extends StatelessWidget {
final InvitationSelectionController controller;
@@ -74,6 +72,18 @@ 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(),
diff --git a/lib/pages/new_space/new_space.dart b/lib/pages/new_space/new_space.dart
index 2ff854e2c..112519238 100644
--- a/lib/pages/new_space/new_space.dart
+++ b/lib/pages/new_space/new_space.dart
@@ -1,14 +1,5 @@
import 'dart:developer';
-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:go_router/go_router.dart';
-import 'package:matrix/matrix.dart' as sdk;
-import 'package:matrix/matrix.dart';
-
import 'package:fluffychat/pages/new_space/new_space_view.dart';
import 'package:fluffychat/pangea/constants/class_default_values.dart';
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
@@ -22,6 +13,13 @@ import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/space/class_settings.dart';
import 'package:fluffychat/widgets/matrix.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:go_router/go_router.dart';
+import 'package:matrix/matrix.dart' as sdk;
+import 'package:matrix/matrix.dart';
class NewSpace extends StatefulWidget {
const NewSpace({super.key});
@@ -46,18 +44,6 @@ class NewSpaceController extends State {
// #Pangea
bool newClassMode = true;
- //in initState, set newClassMode to true if parameter "newClass" is true
- //use Vrouter
- @override
- void initState() {
- super.initState();
- Future.delayed(Duration.zero, () {
- newClassMode =
- GoRouterState.of(context).pathParameters['newexchange'] != 'exchange';
- setState(() {});
- });
- }
-
List get initialState {
final events = [];
@@ -225,13 +211,13 @@ class NewSpaceController extends State {
// Pangea#
}
+ @override
// #Pangea
- //toggle newClassMode
- void toggleClassMode(bool newValue) {
- setState(() => newClassMode = newValue);
+ // Widget build(BuildContext context) => NewSpaceView(this);
+ Widget build(BuildContext context) {
+ newClassMode =
+ GoRouterState.of(context).pathParameters['newexchange'] != 'exchange';
+ return NewSpaceView(this);
}
// Pangea#
-
- @override
- Widget build(BuildContext context) => NewSpaceView(this);
}
diff --git a/lib/pages/new_space/new_space_view.dart b/lib/pages/new_space/new_space_view.dart
index 11cb9a542..fd9f861d1 100644
--- a/lib/pages/new_space/new_space_view.dart
+++ b/lib/pages/new_space/new_space_view.dart
@@ -10,6 +10,7 @@ import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
+import 'package:go_router/go_router.dart';
import 'new_space.dart';
@@ -40,14 +41,14 @@ class NewSpaceView extends StatelessWidget {
selectedIcon: const Icon(Icons.class_),
color: controller.newClassMode ? activeColor : null,
isSelected: controller.newClassMode,
- onPressed: () => controller.toggleClassMode(true),
+ onPressed: () => context.go('/rooms/newspace'),
),
IconButton(
icon: const Icon(Icons.connecting_airports),
selectedIcon: const Icon(Icons.connecting_airports),
color: !controller.newClassMode ? activeColor : null,
isSelected: !controller.newClassMode,
- onPressed: () => controller.toggleClassMode(false),
+ onPressed: () => context.go('/rooms/newspace/exchange'),
),
],
// title: Text(L10n.of(context)!.createNewSpace),
diff --git a/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart b/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart
index 9c7823e5b..56ab5c360 100644
--- a/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart
+++ b/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart
@@ -154,26 +154,22 @@ class RoomRulesState extends State {
),
subtitle: Text(setting.toolDescription(context)),
),
- Padding(
- padding:
- const EdgeInsets.symmetric(horizontal: 120.0),
- child: Slider(
- value: rules.getToolSettings(setting).toDouble(),
- onChanged: (value) {
- updatePermission(() {
- rules.setLanguageToolSetting(
- setting,
- value.toInt(),
- );
- });
- },
- divisions: 2,
- max: 2,
- min: 0,
- label: rules.languageToolPermissionsText(
- context,
- setting,
- ),
+ Slider(
+ value: rules.getToolSettings(setting).toDouble(),
+ onChanged: (value) {
+ updatePermission(() {
+ rules.setLanguageToolSetting(
+ setting,
+ value.toInt(),
+ );
+ });
+ },
+ divisions: 2,
+ max: 2,
+ min: 0,
+ label: rules.languageToolPermissionsText(
+ context,
+ setting,
),
),
],
diff --git a/lib/pangea/pages/find_partner/find_partner.dart b/lib/pangea/pages/find_partner/find_partner.dart
index 18fc71307..f2bd7e8c1 100644
--- a/lib/pangea/pages/find_partner/find_partner.dart
+++ b/lib/pangea/pages/find_partner/find_partner.dart
@@ -1,9 +1,10 @@
import 'dart:async';
-import 'package:flutter/material.dart';
-
+import 'package:country_picker/country_picker.dart';
import 'package:fluffychat/pangea/models/language_model.dart';
import 'package:fluffychat/pangea/models/user_model.dart';
+import 'package:flutter/material.dart';
+
import '../../../widgets/matrix.dart';
import '../../controllers/pangea_controller.dart';
import '../../models/user_profile_search_model.dart';
@@ -20,6 +21,7 @@ class FindPartner extends StatefulWidget {
class FindPartnerController extends State {
PangeaController pangeaController = MatrixState.pangeaController;
+ bool initialLoad = true;
bool loading = false;
String currentSearchTerm = "";
late LanguageModel targetLanguageSearch;
@@ -28,12 +30,15 @@ class FindPartnerController extends State {
String? flagEmoji;
//PTODO - implement pagination
- String? previousPage;
+ String? nextUrl = "";
+ int nextPage = 1;
Timer? coolDown;
final List _userProfilesCache = [];
+ final scrollController = ScrollController();
+
@override
void initState() {
targetLanguageSearch = pangeaController.languageController.userL1 ??
@@ -41,31 +46,29 @@ class FindPartnerController extends State {
sourceLanguageSearch = pangeaController.languageController.userL2 ??
pangeaController.pLanguageStore.targetOptions[0];
- searchUserProfiles();
+ scrollController.addListener(() {
+ if (scrollController.position.pixels ==
+ scrollController.position.maxScrollExtent) {
+ searchUserProfiles();
+ }
+ });
+
+ searchUserProfiles().then((_) => setState(() => initialLoad = false));
+
super.initState();
}
+ @override
+ void dispose() {
+ scrollController.dispose();
+ super.dispose();
+ }
+
@override
Widget build(BuildContext context) {
return FindPartnerView(this);
}
- // List get userProfiles => currentSearchTerm.isNotEmpty
- // ? _userProfilesCache
- // .where((p) =>
- // (p.fullName != null && p.fullName!.contains(currentSearchTerm)) ||
- // (p.pangeaUserId != null &&
- // p.pangeaUserId!.contains(currentSearchTerm)) ||
- // (p.sourceLanguage != null &&
- // p.sourceLanguage!.contains(currentSearchTerm)) ||
- // // (p.speaks != null &&
- // // p.speaks!.any((e) => e.contains(currentSearchTerm))) ||
- // (p.country != null && p.country!.contains(currentSearchTerm)) ||
- // // (p.interests != null &&
- // // p.interests!.any((e) => e.contains(currentSearchTerm))))
- // .toList()
- // : _userProfilesCache;
-
List get userProfiles => _userProfilesCache.where((p) {
return (p.targetLanguage != null &&
targetLanguageSearch.langCode == p.targetLanguage) &&
@@ -83,9 +86,9 @@ class FindPartnerController extends State {
);
}
- void searchUserProfiles() async {
+ Future searchUserProfiles() async {
coolDown?.cancel();
- if (loading) return;
+ if (loading || nextUrl == null) return;
setState(() => loading = true);
final UserProfileSearchResponse response =
@@ -94,15 +97,51 @@ class FindPartnerController extends State {
targetLanguage: targetLanguageSearch.langCode,
sourceLanguage: sourceLanguageSearch.langCode,
country: countrySearch,
- limit: 30,
+ limit: 15,
+ pageNumber: nextPage.toString(),
+ );
+
+ nextUrl = response.next;
+ nextPage++;
+
+ final String? currentUserId =
+ pangeaController.userController.userModel?.profile?.pangeaUserId;
+ _userProfilesCache.addAll(
+ response.results.where(
+ (p) =>
+ !_userProfilesCache.any(
+ (element) => p.pangeaUserId == element.pangeaUserId,
+ ) &&
+ p.pangeaUserId != currentUserId,
+ ),
);
- for (final p in response.results) {
- if (!_userProfilesCache
- .any((element) => p.pangeaUserId == element.pangeaUserId)) {
- _userProfilesCache.add(p);
- }
- }
setState(() => loading = false);
}
+
+ Future filterUserProfiles({
+ LanguageModel? targetLanguage,
+ LanguageModel? sourceLanguage,
+ Country? country,
+ }) async {
+ if (country != null) {
+ if (country.name != "World Wide") {
+ countrySearch = country.displayNameNoCountryCode;
+ flagEmoji = country.flagEmoji;
+ } else {
+ countrySearch = null;
+ flagEmoji = null;
+ }
+ }
+ if (targetLanguage != null) {
+ targetLanguageSearch = targetLanguage;
+ }
+ if (sourceLanguage != null) {
+ sourceLanguageSearch = sourceLanguage;
+ }
+ nextPage = 1;
+ nextUrl = "";
+ await searchUserProfiles();
+ setState(() {});
+ }
}
diff --git a/lib/pangea/pages/find_partner/find_partner_view.dart b/lib/pangea/pages/find_partner/find_partner_view.dart
index bbb163a69..afef95885 100644
--- a/lib/pangea/pages/find_partner/find_partner_view.dart
+++ b/lib/pangea/pages/find_partner/find_partner_view.dart
@@ -1,10 +1,4 @@
-import 'package:flutter/material.dart';
-
import 'package:country_picker/country_picker.dart';
-import 'package:flutter_gen/gen_l10n/l10n.dart';
-import 'package:go_router/go_router.dart';
-import 'package:matrix/matrix.dart' as matrix;
-
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pangea/models/user_model.dart';
import 'package:fluffychat/pangea/widgets/common/list_placeholder.dart';
@@ -12,6 +6,11 @@ import 'package:fluffychat/pangea/widgets/common/pangea_logo_svg.dart';
import 'package:fluffychat/pangea/widgets/user_settings/p_language_dropdown.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:go_router/go_router.dart';
+import 'package:matrix/matrix.dart' as matrix;
+
import '../../../widgets/profile_bottom_sheet.dart';
import 'find_partner.dart';
@@ -80,15 +79,9 @@ class FindPartnerView extends StatelessWidget {
context: context,
showPhoneCode: false,
onSelect: (Country country) {
- if (country.name != "World Wide") {
- controller.countrySearch =
- country.displayNameNoCountryCode;
- controller.flagEmoji = country.flagEmoji;
- } else {
- controller.countrySearch = null;
- controller.flagEmoji = null;
- }
- controller.searchUserProfiles();
+ controller.filterUserProfiles(
+ country: country,
+ );
},
),
),
@@ -97,16 +90,25 @@ class FindPartnerView extends StatelessWidget {
],
),
),
- controller.loading
+ controller.initialLoad
? const ExpandedContainer(body: ListPlaceholder())
: controller.userProfiles.isNotEmpty
? ExpandedContainer(
body: ListView.builder(
- itemCount: controller.userProfiles.length,
- itemBuilder: (context, i) => UserProfileEntry(
- pangeaProfile: controller.userProfiles[i],
- controller: controller,
- ),
+ controller: controller.scrollController,
+ itemCount: controller.userProfiles.length + 1,
+ itemBuilder: (context, i) => i !=
+ controller.userProfiles.length
+ ? UserProfileEntry(
+ pangeaProfile: controller.userProfiles[i],
+ controller: controller,
+ )
+ : controller.loading
+ ? const Center(
+ child: CircularProgressIndicator
+ .adaptive(),
+ )
+ : const SizedBox.shrink(),
),
)
: ExpandedContainer(
@@ -160,7 +162,7 @@ class ProfileSearchTextField extends StatelessWidget {
maxHeight: 48,
minWidth: 48,
),
- suffixIcon: controller.loading
+ suffixIcon: controller.initialLoad
? const CircularProgressIndicator.adaptive()
: const Icon(Icons.search_outlined),
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
@@ -225,10 +227,10 @@ class LanguageSelectionRow extends StatelessWidget {
? controller.pangeaController.pLanguageStore.baseOptions
: controller.pangeaController.pLanguageStore.targetOptions,
onChange: (language) {
- isSource
- ? controller.sourceLanguageSearch = language
- : controller.targetLanguageSearch = language;
- controller.searchUserProfiles();
+ controller.filterUserProfiles(
+ sourceLanguage: isSource ? language : null,
+ targetLanguage: isSource ? null : language,
+ );
},
initialLanguage: isSource
? controller.sourceLanguageSearch
diff --git a/lib/pangea/repo/user_repo.dart b/lib/pangea/repo/user_repo.dart
index 452120962..76b4104fc 100644
--- a/lib/pangea/repo/user_repo.dart
+++ b/lib/pangea/repo/user_repo.dart
@@ -1,9 +1,9 @@
import 'dart:convert';
import 'dart:developer';
+import 'package:fluffychat/pangea/constants/model_keys.dart';
import 'package:http/http.dart';
-import 'package:fluffychat/pangea/constants/model_keys.dart';
import '../../widgets/matrix.dart';
import '../models/user_model.dart';
import '../models/user_profile_search_model.dart';
@@ -106,14 +106,12 @@ class PUserRepo {
body[ModelKey.userSourceLanguage] = sourceLanguage;
}
if (country != null) body[ModelKey.userCountry] = country;
- // if (speaks != null) body[ModelKey.userSpeaks] = speaks;
- if (pageNumber != null) {
- body["page_number"] = pageNumber;
- }
- body["limit"] = limit;
+
+ final String searchUrl =
+ "${PApiUrls.searchUserProfiles}?limit=$limit${pageNumber != null ? '&page=$pageNumber' : ''}";
final Response res = await req.post(
- url: PApiUrls.searchUserProfiles,
+ url: searchUrl,
body: body,
);
diff --git a/lib/pangea/utils/chat_list_handle_space_tap.dart b/lib/pangea/utils/chat_list_handle_space_tap.dart
index 4ddb76129..b2c74ccbd 100644
--- a/lib/pangea/utils/chat_list_handle_space_tap.dart
+++ b/lib/pangea/utils/chat_list_handle_space_tap.dart
@@ -1,13 +1,13 @@
+import 'package:adaptive_dialog/adaptive_dialog.dart';
+import 'package:fluffychat/pages/chat_list/chat_list.dart';
+import 'package:fluffychat/pangea/extensions/pangea_room_extension.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';
-import 'package:fluffychat/pages/chat_list/chat_list.dart';
-import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
-import 'package:fluffychat/widgets/matrix.dart';
import 'error_handler.dart';
// ignore: curly_braces_in_flow_control_structures
@@ -43,74 +43,47 @@ void chatListHandleSpaceTap(
//if accepted, setActiveSpaceAndCloseChat()
//if rejected, leave space
// use standard alert diolog, not cupertino
- void showAlertDialog(BuildContext context) {
- // set up the AlertDialog
- final AlertDialog alert = AlertDialog(
- title: Text(L10n.of(context)!.youreInvited),
- content: Text(
- space.isSpace
- ? L10n.of(context)!
- .invitedToClassOrExchange(space.name, space.creatorId ?? "???")
- : L10n.of(context)!
- .invitedToChat(space.name, space.creatorId ?? "???"),
- ),
- actions: [
- TextButton(
- onPressed: () => showFutureLoadingDialog(
- context: context,
- future: () async {
- await space.leave();
- //show snackbar message that you've left
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(L10n.of(context)!.declinedInvitation),
- duration: const Duration(seconds: 3),
- ),
- );
- Navigator.of(context).pop();
- },
- onError: (exception) {
- ErrorHandler.logError(e: exception);
- Navigator.of(context).pop();
- return exception.toString();
- },
- ),
- child: Text(L10n.of(context)!.decline),
- ),
- TextButton(
- onPressed: () => showFutureLoadingDialog(
- context: context,
- future: () async {
- await space.join();
- setActiveSpaceAndCloseChat();
- ScaffoldMessenger.of(context).showSnackBar(
- SnackBar(
- content: Text(L10n.of(context)!.acceptedInvitation),
- duration: const Duration(seconds: 3),
- ),
- );
- context.go(
- '/rooms/join_exchange/${controller.activeSpaceId}',
- );
- },
- onError: (exception) {
- ErrorHandler.logError(e: exception);
- Navigator.of(context).pop();
- return exception.toString();
- },
- ),
- child: Text(L10n.of(context)!.accept),
- ),
- ],
+ Future showAlertDialog(BuildContext context) async {
+ final acceptInvite = await showOkCancelAlertDialog(
+ context: context,
+ title: L10n.of(context)!.youreInvited,
+ message: space.isSpace
+ ? L10n.of(context)!
+ .invitedToClassOrExchange(space.name, space.creatorId ?? "???")
+ : L10n.of(context)!
+ .invitedToChat(space.name, space.creatorId ?? "???"),
+ okLabel: L10n.of(context)!.accept,
+ cancelLabel: L10n.of(context)!.decline,
);
- // show the dialog
- showDialog(
- context: context,
- builder: (BuildContext context) {
- return alert;
- },
- );
+ if (acceptInvite == OkCancelResult.ok) {
+ await showFutureLoadingDialog(
+ context: context,
+ future: () async {
+ await space.join();
+ setActiveSpaceAndCloseChat();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(L10n.of(context)!.acceptedInvitation),
+ duration: const Duration(seconds: 3),
+ ),
+ );
+ if (space.isExchange) {
+ context.go(
+ '/rooms/join_exchange/${controller.activeSpaceId}',
+ );
+ }
+ },
+ );
+ } else {
+ await space.leave();
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(L10n.of(context)!.declinedInvitation),
+ duration: const Duration(seconds: 3),
+ ),
+ );
+ }
}
switch (space.membership) {
diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart
index 653fa339d..9103bad16 100644
--- a/lib/pangea/widgets/class/add_space_toggles.dart
+++ b/lib/pangea/widgets/class/add_space_toggles.dart
@@ -1,13 +1,12 @@
-import 'package:flutter/material.dart';
-
import 'package:collection/collection.dart';
+import 'package:fluffychat/config/app_config.dart';
+import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
+import 'package:fluffychat/pangea/utils/error_handler.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/config/app_config.dart';
-import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
-import 'package:fluffychat/pangea/utils/error_handler.dart';
import '../../../widgets/matrix.dart';
import '../../utils/firebase_analytics.dart';
import 'add_class_and_invite.dart';
@@ -71,7 +70,7 @@ class AddToSpaceState extends State {
if (widget.activeSpaceId != null) {
final activeSpace =
Matrix.of(context).client.getRoomById(widget.activeSpaceId!);
- if (activeSpace != null) {
+ if (activeSpace != null && activeSpace.canIAddSpaceChild(null)) {
parents.add(SuggestionStatus(false, activeSpace));
} else {
ErrorHandler.logError(
@@ -198,10 +197,13 @@ class AddToSpaceState extends State {
title: Row(
children: [
const SizedBox(width: 32),
- Text(
- L10n.of(context)!.suggestTo(possibleParentName),
- style: TextStyle(
- color: Theme.of(context).colorScheme.secondary,
+ Expanded(
+ child: Text(
+ L10n.of(context)!.suggestTo(possibleParentName),
+ style: TextStyle(
+ color: Theme.of(context).colorScheme.secondary,
+ ),
+ overflow: TextOverflow.ellipsis,
),
),
],
diff --git a/lib/widgets/profile_bottom_sheet.dart b/lib/widgets/profile_bottom_sheet.dart
index 3bfbb2029..c6dab9fbc 100644
--- a/lib/widgets/profile_bottom_sheet.dart
+++ b/lib/widgets/profile_bottom_sheet.dart
@@ -1,13 +1,11 @@
+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:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart';
-import 'package:fluffychat/widgets/avatar.dart';
-import 'package:fluffychat/widgets/matrix.dart';
-
class ProfileBottomSheet extends StatelessWidget {
final String userId;
final BuildContext outerContext;
@@ -46,17 +44,32 @@ class ProfileBottomSheet extends StatelessWidget {
leading: CloseButton(
onPressed: Navigator.of(context, rootNavigator: false).pop,
),
- title: ListTile(
- contentPadding: const EdgeInsets.only(right: 16.0),
- title: Text(
- profile?.displayName ?? userId.localpart ?? userId,
- style: const TextStyle(fontSize: 18),
- ),
- subtitle: Text(
- userId,
- style: const TextStyle(fontSize: 12),
- ),
+ // #Pangea
+ // title: ListTile(
+ // contentPadding: const EdgeInsets.only(right: 16.0),
+ // title: Text(
+ // profile?.displayName ?? userId.localpart ?? userId,
+ // style: const TextStyle(fontSize: 18),
+ // ),
+ // subtitle: Text(
+ // userId,
+ // style: const TextStyle(fontSize: 12),
+ // ),
+ // ),
+ title: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Text(
+ profile?.displayName ?? userId.localpart ?? userId,
+ style: const TextStyle(fontSize: 18),
+ ),
+ Text(
+ userId,
+ style: const TextStyle(fontSize: 12),
+ ),
+ ],
),
+ // Pangea#
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
diff --git a/pubspec.lock b/pubspec.lock
index 8b3ed1ace..fe5dc711f 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -245,10 +245,10 @@ packages:
dependency: "direct main"
description:
name: country_picker
- sha256: "931454ceb75c7e1230ac5620bfe601a5a293b4436d8de8bf7fea776a05a9568c"
+ sha256: c578292d7d3ec3132c6634f9c7aab96528f74d61fd363073d5f5a8562bede732
url: "https://pub.dev"
source: hosted
- version: "2.0.22"
+ version: "2.0.23"
cross_file:
dependency: transitive
description: