Merge branch 'develop' into new.add-discusions-roomactionsview

This commit is contained in:
Gerzon Z 2021-10-13 11:46:50 -04:00
commit 714608cc36
55 changed files with 16096 additions and 13038 deletions

View File

@ -23,3 +23,4 @@ SECURITY.md
npm-debug.log npm-debug.log
yarn-error.log yarn-error.log
app/i18n/locales/

File diff suppressed because it is too large Load Diff

View File

@ -144,7 +144,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode VERSIONCODE as Integer versionCode VERSIONCODE as Integer
versionName "4.20.0" versionName "4.21.0"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
if (!isFoss) { if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String] manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
@ -292,6 +292,8 @@ dependencies {
implementation "com.github.bumptech.glide:glide:4.9.0" implementation "com.github.bumptech.glide:glide:4.9.0"
annotationProcessor "com.github.bumptech.glide:compiler:4.9.0" annotationProcessor "com.github.bumptech.glide:compiler:4.9.0"
implementation "com.tencent:mmkv-static:1.2.1" implementation "com.tencent:mmkv-static:1.2.1"
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.9.0"
} }
// Run this once to be able to run the application with BUCK // Run this once to be able to run the application with BUCK

View File

@ -3,7 +3,6 @@
package="chat.rocket.reactnative"> package="chat.rocket.reactnative">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application <application

View File

@ -10,8 +10,8 @@ buildscript {
ext { ext {
buildToolsVersion = "29.0.3" buildToolsVersion = "29.0.3"
minSdkVersion = 23 minSdkVersion = 23
compileSdkVersion = 29 compileSdkVersion = 30
targetSdkVersion = 29 targetSdkVersion = 30
ndkVersion = "20.1.5948944" ndkVersion = "20.1.5948944"
glideVersion = "4.11.0" glideVersion = "4.11.0"
kotlin_version = "1.3.50" kotlin_version = "1.3.50"
@ -68,10 +68,10 @@ subprojects { subproject ->
afterEvaluate { afterEvaluate {
if ((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) { if ((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
android { android {
compileSdkVersion 29 compileSdkVersion 30
buildToolsVersion "29.0.3" buildToolsVersion "29.0.3"
defaultConfig { defaultConfig {
targetSdkVersion 29 targetSdkVersion 30
} }
variantFilter { variant -> variantFilter { variant ->
def names = variant.flavors*.name def names = variant.flavors*.name

View File

@ -18,8 +18,6 @@ export const ROOMS = createRequestTypes('ROOMS', [
'SET_SEARCH', 'SET_SEARCH',
'CLOSE_SERVER_DROPDOWN', 'CLOSE_SERVER_DROPDOWN',
'TOGGLE_SERVER_DROPDOWN', 'TOGGLE_SERVER_DROPDOWN',
'CLOSE_SORT_DROPDOWN',
'TOGGLE_SORT_DROPDOWN',
'OPEN_SEARCH_HEADER', 'OPEN_SEARCH_HEADER',
'CLOSE_SEARCH_HEADER' 'CLOSE_SEARCH_HEADER'
]); ]);

View File

@ -45,18 +45,6 @@ export function toggleServerDropdown() {
}; };
} }
export function closeSortDropdown() {
return {
type: types.ROOMS.CLOSE_SORT_DROPDOWN
};
}
export function toggleSortDropdown() {
return {
type: types.ROOMS.TOGGLE_SORT_DROPDOWN
};
}
export function openSearchHeader() { export function openSearchHeader() {
return { return {
type: types.ROOMS.OPEN_SEARCH_HEADER type: types.ROOMS.OPEN_SEARCH_HEADER

View File

@ -0,0 +1,2 @@
export const DISPLAY_MODE_CONDENSED = 'condensed';
export const DISPLAY_MODE_EXPANDED = 'expanded';

View File

@ -85,7 +85,7 @@ const Avatar = React.memo(
} }
return ( return (
<View style={[avatarStyle, style]}> <View style={[avatarStyle, style]} testID='avatar'>
{image} {image}
{children} {children}
</View> </View>

View File

@ -51,7 +51,9 @@ class QueueListView extends React.Component {
server: PropTypes.string, server: PropTypes.string,
useRealName: PropTypes.bool, useRealName: PropTypes.bool,
navigation: PropTypes.object, navigation: PropTypes.object,
theme: PropTypes.string theme: PropTypes.string,
showAvatar: PropTypes.bool,
displayMode: PropTypes.string
}; };
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
@ -95,7 +97,9 @@ class QueueListView extends React.Component {
useRealName, useRealName,
theme, theme,
isMasterDetail, isMasterDetail,
width width,
showAvatar,
displayMode
} = this.props; } = this.props;
const id = this.getUidDirectMessage(item); const id = this.getUidDirectMessage(item);
@ -117,6 +121,8 @@ class QueueListView extends React.Component {
getRoomAvatar={this.getRoomAvatar} getRoomAvatar={this.getRoomAvatar}
visitor={item.v} visitor={item.v}
swipeEnabled={false} swipeEnabled={false}
showAvatar={showAvatar}
displayMode={displayMode}
/> />
); );
}; };
@ -151,6 +157,8 @@ const mapStateToProps = state => ({
isMasterDetail: state.app.isMasterDetail, isMasterDetail: state.app.isMasterDetail,
server: state.server.server, server: state.server.server,
useRealName: state.settings.UI_Use_Real_Name, useRealName: state.settings.UI_Use_Real_Name,
queued: getInquiryQueueSelector(state) queued: getInquiryQueueSelector(state),
showAvatar: state.sortPreferences.showAvatar,
displayMode: state.sortPreferences.displayMode
}); });
export default connect(mapStateToProps)(withDimensions(withTheme(QueueListView))); export default connect(mapStateToProps)(withDimensions(withTheme(QueueListView)));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,454 +1,445 @@
{ {
"1_person_reacted": "1 persona reaccionó", "1_person_reacted": "1 persona reaccionó",
"1_user": "1 usuario", "1_user": "1 usuario",
"error-action-not-allowed": "{{action}} no permitida", "error-action-not-allowed": "{{action}} no permitida",
"error-application-not-found": "Aplicación no encontrada", "error-application-not-found": "Aplicación no encontrada",
"error-archived-duplicate-name": "Hay un canal archivado con nombre {{room_name}}", "error-archived-duplicate-name": "Hay un canal archivado con nombre {{room_name}}",
"error-avatar-invalid-url": "URL de avatar inválida: {{url}}", "error-avatar-invalid-url": "URL de avatar inválida: {{url}}",
"error-avatar-url-handling": "Error durante el procesamiento de ajuste de imagen de usuario desde una dirección URL ({{url}}) para {{username}}", "error-avatar-url-handling": "Error durante el procesamiento de ajuste de imagen de usuario desde una dirección URL ({{url}}) para {{username}}",
"error-cant-invite-for-direct-room": "No se puede invitar a los usuarios a salas de chat directas", "error-cant-invite-for-direct-room": "No se puede invitar a los usuarios a salas de chat directas",
"error-could-not-change-email": "No es posible cambiar la dirección de correo electrónico", "error-could-not-change-email": "No es posible cambiar la dirección de correo electrónico",
"error-could-not-change-name": "No es posible cambiar el nombre", "error-could-not-change-name": "No es posible cambiar el nombre",
"error-could-not-change-username": "No es posible cambiar el nombre de usuario", "error-could-not-change-username": "No es posible cambiar el nombre de usuario",
"error-delete-protected-role": "No se puede eliminar un rol protegido", "error-delete-protected-role": "No se puede eliminar un rol protegido",
"error-department-not-found": "Departamento no encontrado", "error-department-not-found": "Departamento no encontrado",
"error-direct-message-file-upload-not-allowed": "No se permite compartir archivos en mensajes directos", "error-direct-message-file-upload-not-allowed": "No se permite compartir archivos en mensajes directos",
"error-duplicate-channel-name": "Ya existe un canal con nombre {{room_name}}", "error-duplicate-channel-name": "Ya existe un canal con nombre {{room_name}}",
"error-email-domain-blacklisted": "El dominio del correo electrónico está en la lista negra", "error-email-domain-blacklisted": "El dominio del correo electrónico está en la lista negra",
"error-email-send-failed": "Error al enviar el correo electrónico: {{message}}", "error-email-send-failed": "Error al enviar el correo electrónico: {{message}}",
"error-field-unavailable": "{{field}} ya está en uso :(", "error-field-unavailable": "{{field}} ya está en uso :(",
"error-file-too-large": "El archivo es demasiado grande", "error-file-too-large": "El archivo es demasiado grande",
"error-importer-not-defined": "El importador no se configuró correctamente. Falta la clase de importación", "error-importer-not-defined": "El importador no se configuró correctamente. Falta la clase de importación",
"error-input-is-not-a-valid-field": "{{input}} no es válido {{field}}", "error-input-is-not-a-valid-field": "{{input}} no es válido {{field}}",
"error-invalid-actionlink": "Enlace de acción inválido", "error-invalid-actionlink": "Enlace de acción inválido",
"error-invalid-arguments": "Los argumentos no son correctos", "error-invalid-arguments": "Los argumentos no son correctos",
"error-invalid-asset": "El archivo archivo no es correcto", "error-invalid-asset": "El archivo archivo no es correcto",
"error-invalid-channel": "El canal no es correcto.", "error-invalid-channel": "El canal no es correcto.",
"error-invalid-channel-start-with-chars": "Canal incorrecto. Debe comenzar con @ o #", "error-invalid-channel-start-with-chars": "Canal incorrecto. Debe comenzar con @ o #",
"error-invalid-custom-field": "Campo personalizado no válido", "error-invalid-custom-field": "Campo personalizado no válido",
"error-invalid-custom-field-name": "Nombre no válido para el campo personalizado. Utilice sólo letras, números, guiones o guión bajo", "error-invalid-custom-field-name": "Nombre no válido para el campo personalizado. Utilice sólo letras, números, guiones o guión bajo",
"error-invalid-date": "La fecha proporcionada no es correcta.", "error-invalid-date": "La fecha proporcionada no es correcta.",
"error-invalid-description": "La descripción no es correcta", "error-invalid-description": "La descripción no es correcta",
"error-invalid-domain": "El dominio no es correcto", "error-invalid-domain": "El dominio no es correcto",
"error-invalid-email": "El email {{email}} no es correcto", "error-invalid-email": "El email {{email}} no es correcto",
"error-invalid-email-address": "La dirección de correo no es correcta", "error-invalid-email-address": "La dirección de correo no es correcta",
"error-invalid-file-height": "La altura de la imagen no es correcta", "error-invalid-file-height": "La altura de la imagen no es correcta",
"error-invalid-file-type": "El formato del archivo no es correcto", "error-invalid-file-type": "El formato del archivo no es correcto",
"error-invalid-file-width": "El ancho de la imagen o es correcto", "error-invalid-file-width": "El ancho de la imagen o es correcto",
"error-invalid-from-address": "La dirección del remitente (FROM) no es correcta.", "error-invalid-from-address": "La dirección del remitente (FROM) no es correcta.",
"error-invalid-integration": "La integración no es correcta", "error-invalid-integration": "La integración no es correcta",
"error-invalid-message": "El mensaje no es correcto", "error-invalid-message": "El mensaje no es correcto",
"error-invalid-method": "El método no es correcto", "error-invalid-method": "El método no es correcto",
"error-invalid-name": "El nombre no es correcto", "error-invalid-name": "El nombre no es correcto",
"error-invalid-password": "La contraseña no es correcta", "error-invalid-password": "La contraseña no es correcta",
"error-invalid-redirectUri": "La URL de redirección no es correcta.", "error-invalid-redirectUri": "La URL de redirección no es correcta.",
"error-invalid-role": "El rol no es correcto", "error-invalid-role": "El rol no es correcto",
"error-invalid-room": "La sala no es correcta", "error-invalid-room": "La sala no es correcta",
"error-invalid-room-name": "No se puede asignar el nombre {{room_name}} a una sala.", "error-invalid-room-name": "No se puede asignar el nombre {{room_name}} a una sala.",
"error-invalid-room-type": "No se puede asignar el tipo {{type}} a una sala.", "error-invalid-room-type": "No se puede asignar el tipo {{type}} a una sala.",
"error-invalid-settings": "La configuración proporcionada no es correcta", "error-invalid-settings": "La configuración proporcionada no es correcta",
"error-invalid-subscription": "La suscripción no es correcta", "error-invalid-subscription": "La suscripción no es correcta",
"error-invalid-token": "El token no es correcto", "error-invalid-token": "El token no es correcto",
"error-invalid-triggerWords": "El triggerWords no es correcto", "error-invalid-triggerWords": "El triggerWords no es correcto",
"error-invalid-urls": "Las URLs no son correctas", "error-invalid-urls": "Las URLs no son correctas",
"error-invalid-user": "El usuario no es correcto", "error-invalid-user": "El usuario no es correcto",
"error-invalid-username": "El nombre de usuario no es correcto", "error-invalid-username": "El nombre de usuario no es correcto",
"error-invalid-webhook-response": "El webhook no ha respondido con código de estado HTTP 200.", "error-invalid-webhook-response": "El webhook no ha respondido con código de estado HTTP 200.",
"error-message-deleting-blocked": "No está permitido eliminar mensajes", "error-message-deleting-blocked": "No está permitido eliminar mensajes",
"error-message-editing-blocked": "No está permitido editar mensajes", "error-message-editing-blocked": "No está permitido editar mensajes",
"error-message-size-exceeded": "El mensaje supera el tamaño máximo permitido", "error-message-size-exceeded": "El mensaje supera el tamaño máximo permitido",
"error-missing-unsubscribe-link": "Debes proporcionar el enlace para cancelar la suscripción [unsubscribe].", "error-missing-unsubscribe-link": "Debes proporcionar el enlace para cancelar la suscripción [unsubscribe].",
"error-no-tokens-for-this-user": "No hay tokens asignados para el usuario", "error-no-tokens-for-this-user": "No hay tokens asignados para el usuario",
"error-not-allowed": "No permitido", "error-not-allowed": "No permitido",
"error-not-authorized": "No autorizado", "error-not-authorized": "No autorizado",
"error-push-disabled": "El Push está desactivado", "error-push-disabled": "El Push está desactivado",
"error-remove-last-owner": "El usuario es el único propietario existente. Debes establecer un nuevo propietario antes de eliminarlo.", "error-remove-last-owner": "El usuario es el único propietario existente. Debes establecer un nuevo propietario antes de eliminarlo.",
"error-role-in-use": "No puedes eliminar el rol dado que está en uso", "error-role-in-use": "No puedes eliminar el rol dado que está en uso",
"error-role-name-required": "Debes indicar el nombre del rol", "error-role-name-required": "Debes indicar el nombre del rol",
"error-the-field-is-required": "El campo {{field}} es obligatorio.", "error-the-field-is-required": "El campo {{field}} es obligatorio.",
"error-too-many-requests": "Error, demasiadas peticiones. Debes esperar {{seconds}} segundos antes de continuar. Por favor, sé paciente.", "error-too-many-requests": "Error, demasiadas peticiones. Debes esperar {{seconds}} segundos antes de continuar. Por favor, sé paciente.",
"error-user-is-not-activated": "El usuario no está activo", "error-user-is-not-activated": "El usuario no está activo",
"error-user-has-no-roles": "El usuario no tiene roles", "error-user-has-no-roles": "El usuario no tiene roles",
"error-user-limit-exceeded": "El número de usuarios que quieres invitar al canal #channel_name supera el límite establecido por el administrador.", "error-user-limit-exceeded": "El número de usuarios que quieres invitar al canal #channel_name supera el límite establecido por el administrador.",
"error-user-not-in-room": "El usuario no está en la sala", "error-user-not-in-room": "El usuario no está en la sala",
"error-user-registration-custom-field": "error-user-registration-custom-field", "error-user-registration-custom-field": "error-user-registration-custom-field",
"error-user-registration-disabled": "El registro de usuario está deshabilitado", "error-user-registration-disabled": "El registro de usuario está deshabilitado",
"error-user-registration-secret": "El registro de usuarios sólo está permitido por URL secretas", "error-user-registration-secret": "El registro de usuarios sólo está permitido por URL secretas",
"error-you-are-last-owner": "Eres el único propietario existente. Debes establecer un nuevo propietario antes de abandonar la sala.", "error-you-are-last-owner": "Eres el único propietario existente. Debes establecer un nuevo propietario antes de abandonar la sala.",
"Actions": "Acciones", "Actions": "Acciones",
"activity": "actividad", "Activity": "Actividad",
"Activity": "Actividad", "Add_Reaction": "Añadir reacción",
"Add_Reaction": "Añadir reacción", "Add_Server": "Añadir servidor",
"Add_Server": "Añadir servidor", "Admin_Panel": "Panel de Control",
"Admin_Panel": "Panel de Control", "Alert": "Alerta",
"Alert": "Alerta", "alert": "alerta",
"alert": "alerta", "alerts": "alertas",
"alerts": "alertas", "All_users_in_the_channel_can_write_new_messages": "Todos los usuarios en el canal pueden escribir mensajes",
"All_users_in_the_channel_can_write_new_messages": "Todos los usuarios en el canal pueden escribir mensajes", "All": "Todos",
"All": "Todos", "All_Messages": "Todos los mensajes",
"All_Messages": "Todos los mensajes", "Allow_Reactions": "Permitir reacciones",
"Allow_Reactions": "Permitir reacciones", "Alphabetical": "Alfabético",
"Alphabetical": "Alfabético", "and_more": "y más",
"and_more": "y más", "and": "y",
"and": "y", "announcement": "anuncio",
"announcement": "anuncio", "Announcement": "Anuncio",
"Announcement": "Anuncio", "Apply_Your_Certificate": "Aplica tu certificado",
"Apply_Your_Certificate": "Aplica tu certificado", "ARCHIVE": "FICHERO",
"ARCHIVE": "FICHERO", "archive": "fichero",
"archive": "fichero", "are_typing": "están escribiendo",
"are_typing": "están escribiendo", "Are_you_sure_question_mark": "¿Estás seguro?",
"Are_you_sure_question_mark": "¿Estás seguro?", "Are_you_sure_you_want_to_leave_the_room": "¿Deseas salir de la sala {{room}}?",
"Are_you_sure_you_want_to_leave_the_room": "¿Deseas salir de la sala {{room}}?", "Audio": "Audio",
"Audio": "Audio", "Authenticating": "Autenticando",
"Authenticating": "Autenticando", "Automatic": "Automático",
"Automatic": "Automático", "Auto_Translate": "Traducción automática",
"Auto_Translate": "Traducción automática", "Avatar_changed_successfully": "¡Avatar modificado correctamente!",
"Avatar_changed_successfully": "¡Avatar modificado correctamente!", "Avatar_Url": "URL del Avatar",
"Avatar_Url": "URL del Avatar", "Away": "Ausente",
"Away": "Ausente", "Back": "Volver",
"Back": "Volver", "Black": "Negro",
"Black": "Negro", "Block_user": "Bloquear usuario",
"Block_user": "Bloquear usuario", "Broadcast_channel_Description": "Sólo los usuarios autorizados pueden escribir nuevos mensajes, el resto podrán responder sobre los mismos.",
"Broadcast_channel_Description": "Sólo los usuarios autorizados pueden escribir nuevos mensajes, el resto podrán responder sobre los mismos.", "Broadcast_Channel": "Canal de Transmisión",
"Broadcast_Channel": "Canal de Transmisión", "Busy": "Ocupado",
"Busy": "Ocupado", "By_proceeding_you_are_agreeing": "Al proceder estarás de acuerdo",
"By_proceeding_you_are_agreeing": "Al proceder estarás de acuerdo", "Cancel_editing": "Cancelar edición",
"Cancel_editing": "Cancelar edición", "Cancel_recording": "Cancelar grabación",
"Cancel_recording": "Cancelar grabación", "Cancel": "Cancelar",
"Cancel": "Cancelar", "changing_avatar": "cambiando avatar",
"changing_avatar": "cambiando avatar", "creating_channel": "creando channel",
"creating_channel": "creando channel", "Channel_Name": "Nombre sala",
"Channel_Name": "Nombre sala", "Channels": "Salas",
"Channels": "Salas", "Chats": "Chats",
"Chats": "Chats", "Call_already_ended": "¡!La llamada ya ha finalizado!",
"Call_already_ended": "¡!La llamada ya ha finalizado!", "Click_to_join": "¡Unirme!",
"Click_to_join": "¡Unirme!", "Close": "Cerrar",
"Close": "Cerrar", "Close_emoji_selector": "Cerrar selector de emojis",
"Close_emoji_selector": "Cerrar selector de emojis", "Choose": "Seleccionar",
"Choose": "Seleccionar", "Choose_from_library": "Seleccionar desde galería",
"Choose_from_library": "Seleccionar desde galería", "Choose_file": "Seleccionar archivo",
"Choose_file": "Seleccionar archivo", "Code": "Código",
"Code": "Código", "Collaborative": "Colaborativo",
"Collaborative": "Colaborativo", "Confirm": "Confirmar",
"Confirm": "Confirmar", "Connect": "Conectar",
"Connect": "Conectar", "Connected": "Conectado",
"Connected": "Conectado", "connecting_server": "conectando al servidor",
"connecting_server": "conectando al servidor", "Connecting": "Conectando...",
"Connecting": "Conectando...", "Contact_us": "Contacta con nosotros",
"Contact_us": "Contacta con nosotros", "Contact_your_server_admin": "Contacta con el administrador.",
"Contact_your_server_admin": "Contacta con el administrador.", "Continue_with": "Continuar con",
"Continue_with": "Continuar con", "Copied_to_clipboard": "¡Copiado al portapapeles!",
"Copied_to_clipboard": "¡Copiado al portapapeles!", "Copy": "Copiar",
"Copy": "Copiar", "Permalink": "Enlace permanente",
"Permalink": "Enlace permanente", "Certificate_password": "Contraseña del certificado",
"Certificate_password": "Contraseña del certificado", "Whats_the_password_for_your_certificate": "¿Cuál es la contraseña de tu certificado?",
"Whats_the_password_for_your_certificate": "¿Cuál es la contraseña de tu certificado?", "Create_account": "Crear una cuenta",
"Create_account": "Crear una cuenta", "Create_Channel": "Crear sala",
"Create_Channel": "Crear sala", "Created_snippet": "crear mensaje en bloque",
"Created_snippet": "crear mensaje en bloque", "Create_a_new_workspace": "Crear un nuevo espacio de trabajo",
"Create_a_new_workspace": "Crear un nuevo espacio de trabajo", "Create": "Crear",
"Create": "Crear", "Dark": "Oscuro",
"Dark": "Oscuro", "Dark_level": "Nivel de oscuridad",
"Dark_level": "Nivel de oscuridad", "Default": "Por defecto",
"Default": "Por defecto", "Delete_Room_Warning": "Eliminar a un usuario causará la eliminación de todos los mensajes creados por dicho usuario. Esta operación no se puede deshacer.",
"Delete_Room_Warning": "Eliminar a un usuario causará la eliminación de todos los mensajes creados por dicho usuario. Esta operación no se puede deshacer.", "delete": "eliminar",
"delete": "eliminar", "Delete": "Eliminar",
"Delete": "Eliminar", "DELETE": "ELIMINAR",
"DELETE": "ELIMINAR", "deleting_room": "eliminando sala",
"deleting_room": "eliminando sala", "description": "descripción",
"description": "descripción", "Description": "Descripción",
"Description": "Descripción", "Desktop_Options": "Opciones de escritorio",
"Desktop_Options": "Opciones de escritorio", "Directory": "Directorio",
"Directory": "Directorio", "Direct_Messages": "Mensajes directos",
"Direct_Messages": "Mensajes directos", "Disable_notifications": "Desactivar notificaciones",
"Disable_notifications": "Desactivar notificaciones", "Discussions": "Conversaciones",
"Discussions": "Conversaciones", "Dont_Have_An_Account": "¿Todavía no tienes una cuenta?",
"Dont_Have_An_Account": "¿Todavía no tienes una cuenta?", "Do_you_have_a_certificate": "¿Tienes un certificado?",
"Do_you_have_a_certificate": "¿Tienes un certificado?", "Do_you_really_want_to_key_this_room_question_mark": "¿Deseas {{key}} de esta sala?",
"Do_you_really_want_to_key_this_room_question_mark": "¿Deseas {{key}} de esta sala?", "edit": "editar",
"edit": "editar", "edited": "editado",
"edited": "editado", "Edit": "Editar",
"Edit": "Editar", "Email_or_password_field_is_empty": "El email o la contraseña están vacíos",
"Email_or_password_field_is_empty": "El email o la contraseña están vacíos", "Email": "E-mail",
"Email": "E-mail", "email": "e-mail",
"email": "e-mail", "Enable_Auto_Translate": "Permitir Auto-Translate",
"Enable_Auto_Translate": "Permitir Auto-Translate", "Enable_notifications": "Permitir notificaciones",
"Enable_notifications": "Permitir notificaciones", "Everyone_can_access_this_channel": "Todos los usuarios pueden acceder a este canal",
"Everyone_can_access_this_channel": "Todos los usuarios pueden acceder a este canal", "Error_uploading": "Error en la subida",
"Error_uploading": "Error en la subida", "Favorites": "Favoritos",
"Favorite": "Favorito", "Files": "Archivos",
"Favorites": "Favoritos", "File_description": "Descripción del archivo",
"Files": "Archivos", "File_name": "Nombre del archivo",
"File_description": "Descripción del archivo", "Finish_recording": "Finalizar grabación",
"File_name": "Nombre del archivo", "Following_thread": "Siguiendo hilo",
"Finish_recording": "Finalizar grabación", "For_your_security_you_must_enter_your_current_password_to_continue": "Por seguridad, debes introducir tu contraseña para continuar",
"Following_thread": "Siguiendo hilo", "Forgot_password_If_this_email_is_registered": "Si este email está registrado, te enviaremos las instrucciones para resetear tu contraseña. Si no recibes un email en breve, vuelve aquí e inténtalo de nuevo.",
"For_your_security_you_must_enter_your_current_password_to_continue": "Por seguridad, debes introducir tu contraseña para continuar", "Forgot_password": "¿Ha olvidado su contraseña?",
"Forgot_password_If_this_email_is_registered": "Si este email está registrado, te enviaremos las instrucciones para resetear tu contraseña. Si no recibes un email en breve, vuelve aquí e inténtalo de nuevo.", "Forgot_Password": "Olvidé la contraseña",
"Forgot_password": "¿Ha olvidado su contraseña?", "Full_table": "Click para ver la tabla completa",
"Forgot_Password": "Olvidé la contraseña", "Has_joined_the_channel": "se ha unido al canal",
"Full_table": "Click para ver la tabla completa", "Has_joined_the_conversation": "se ha unido a la conversación",
"Group_by_favorites": "Agrupar por favoritos", "Has_left_the_channel": "ha dejado el canal",
"Group_by_type": "Agrupar por tipo", "In_App_And_Desktop": "En la aplicación y en el escritorio",
"Hide": "Ocultar", "In_App_and_Desktop_Alert_info": "Muestra un banner en la parte superior de la pantalla cuando la aplicación esté abierta y muestra una notificación en el escritorio",
"Has_joined_the_channel": "se ha unido al canal", "Invisible": "Invisible",
"Has_joined_the_conversation": "se ha unido a la conversación", "Invite": "Invitar",
"Has_left_the_channel": "ha dejado el canal", "is_a_valid_RocketChat_instance": "es una instancia válida de Rocket.Chat",
"In_App_And_Desktop": "En la aplicación y en el escritorio", "is_not_a_valid_RocketChat_instance": "no es una instancia válida de Rocket.Chat",
"In_App_and_Desktop_Alert_info": "Muestra un banner en la parte superior de la pantalla cuando la aplicación esté abierta y muestra una notificación en el escritorio", "is_typing": "escribiendo",
"Invisible": "Invisible", "Invalid_server_version": "El servidor que intentas conectar está usando una versión que ya no está soportada por la aplicación : {{currentVersion}}. Se requiere una versión {{minVersion}}.",
"Invite": "Invitar", "Join": "Conectar",
"is_a_valid_RocketChat_instance": "es una instancia válida de Rocket.Chat", "Just_invited_people_can_access_this_channel": "Sólo gente invitada puede acceder a este canal.",
"is_not_a_valid_RocketChat_instance": "no es una instancia válida de Rocket.Chat", "Language": "Idioma",
"is_typing": "escribiendo", "last_message": "último mensaje",
"Invalid_server_version": "El servidor que intentas conectar está usando una versión que ya no está soportada por la aplicación : {{currentVersion}}. Se requiere una versión {{minVersion}}.", "Leave_channel": "Abandonar el canal",
"Join": "Conectar", "leaving_room": "abandonando sala",
"Just_invited_people_can_access_this_channel": "Sólo gente invitada puede acceder a este canal.", "leave": "abandonar",
"Language": "Idioma", "Legal": "Legal",
"last_message": "último mensaje", "Light": "Claro",
"Leave_channel": "Abandonar el canal", "License": "Licencia",
"leaving_room": "abandonando sala", "Livechat": "LiveChat",
"leave": "abandonar", "Login": "Inicio de sesión",
"Legal": "Legal", "Login_error": "¡Sus credenciales fueron rechazadas! Por favor, inténtelo de nuevo.",
"Light": "Claro", "Login_with": "Iniciar sesión con",
"License": "Licencia", "Logout": "Cerrar sesión",
"Livechat": "LiveChat", "members": "miembros",
"Login": "Inicio de sesión", "Members": "Miembros",
"Login_error": "¡Sus credenciales fueron rechazadas! Por favor, inténtelo de nuevo.", "Mentioned_Messages": "Mensajes mencionados",
"Login_with": "Iniciar sesión con", "mentioned": "mencionado",
"Logout": "Cerrar sesión", "Mentions": "Menciones",
"members": "miembros", "Message_accessibility": "Mensaje de {{user}} a las {{time}}: {{message}}",
"Members": "Miembros", "Message_actions": "Acciones de mensaje",
"Mentioned_Messages": "Mensajes mencionados", "Message_pinned": "Mensaje fijado",
"mentioned": "mencionado", "Message_removed": "Mensaje eliminado",
"Mentions": "Menciones", "message": "mensaje",
"Message_accessibility": "Mensaje de {{user}} a las {{time}}: {{message}}", "messages": "mensajes",
"Message_actions": "Acciones de mensaje", "Messages": "Mensajes",
"Message_pinned": "Mensaje fijado", "Message_Reported": "Mensaje notificado",
"Message_removed": "Mensaje eliminado", "Microphone_Permission_Message": "Rocket.Chat necesita acceso a su micrófono para que pueda enviar un mensaje de audio.",
"message": "mensaje", "Microphone_Permission": "Permiso de micrófono",
"messages": "mensajes", "Mute": "Mutear",
"Messages": "Mensajes", "muted": "muteado",
"Message_Reported": "Mensaje notificado", "My_servers": "Mis servidores",
"Microphone_Permission_Message": "Rocket.Chat necesita acceso a su micrófono para que pueda enviar un mensaje de audio.", "N_people_reacted": "Han reaccionado {{n}} personas",
"Microphone_Permission": "Permiso de micrófono", "N_users": "{{n}} usuarios",
"Mute": "Mutear", "Name": "Nombre",
"muted": "muteado", "New_Message": "Nuevo mensaje",
"My_servers": "Mis servidores", "New_Password": "Nueva contraseña",
"N_people_reacted": "Han reaccionado {{n}} personas", "New_Server": "Nuevo servidor",
"N_users": "{{n}} usuarios", "Next": "Siguiente",
"name": "nombre", "No_files": "No hay archivos",
"Name": "Nombre", "No_mentioned_messages": "No hay mensajes mencionados",
"New_Message": "Nuevo mensaje", "No_pinned_messages": "No hay mensajes fijados",
"New_Password": "Nueva contraseña", "No_results_found": "No hay resultados",
"New_Server": "Nuevo servidor", "No_starred_messages": "No hay mensajes destacados",
"Next": "Siguiente", "No_thread_messages": "No hay hilos",
"No_files": "No hay archivos", "No_Message": "Sin mensajes",
"No_mentioned_messages": "No hay mensajes mencionados", "No_messages_yet": "No hay mensajes todavía",
"No_pinned_messages": "No hay mensajes fijados", "No_Reactions": "No hay reacciones",
"No_results_found": "No hay resultados", "No_Read_Receipts": "No hay confirmaciones de lectura",
"No_starred_messages": "No hay mensajes destacados", "Not_logged": "No ha iniciado sesión",
"No_thread_messages": "No hay hilos", "Not_RC_Server": "Esto no es un servidor de Rocket.Chat.\n{{contact}}",
"No_Message": "Sin mensajes", "Nothing": "Nada",
"No_messages_yet": "No hay mensajes todavía", "Nothing_to_save": "¡No hay nada por guardar!",
"No_Reactions": "No hay reacciones", "Notify_active_in_this_room": "Notificar a los usuarios activos en esta sala",
"No_Read_Receipts": "No hay confirmaciones de lectura", "Notify_all_in_this_room": "Notificar a todos en esta sala",
"Not_logged": "No ha iniciado sesión", "Notifications": "Notificaciones",
"Not_RC_Server": "Esto no es un servidor de Rocket.Chat.\n{{contact}}", "Notification_Duration": "Duración de la notificación",
"Nothing": "Nada", "Notification_Preferences": "Configuración de notificaciones",
"Nothing_to_save": "¡No hay nada por guardar!", "Offline": "Sin conexión",
"Notify_active_in_this_room": "Notificar a los usuarios activos en esta sala", "Oops": "Oops!",
"Notify_all_in_this_room": "Notificar a todos en esta sala", "Onboarding_title": "Bienvenido a Rocket.Chat",
"Notifications": "Notificaciones", "Online": "Conectado",
"Notification_Duration": "Duración de la notificación", "Only_authorized_users_can_write_new_messages": "Sólo pueden escribir mensajes usuarios autorizados",
"Notification_Preferences": "Configuración de notificaciones", "Open_emoji_selector": "Abrir selector de emojis",
"Offline": "Sin conexión", "Open_Source_Communication": "Comunicación Open Source",
"Oops": "Oops!", "Password": "Contraseña",
"Onboarding_title": "Bienvenido a Rocket.Chat", "Permalink_copied_to_clipboard": "¡Enlace permanente copiado al portapapeles!",
"Online": "Conectado", "Pin": "Fijar",
"Only_authorized_users_can_write_new_messages": "Sólo pueden escribir mensajes usuarios autorizados", "Pinned_Messages": "Mensajes fijados",
"Open_emoji_selector": "Abrir selector de emojis", "pinned": "fijado",
"Open_Source_Communication": "Comunicación Open Source", "Pinned": "Fijado",
"Password": "Contraseña", "Please_enter_your_password": "Por favor introduce la contraseña",
"Permalink_copied_to_clipboard": "¡Enlace permanente copiado al portapapeles!", "Preferences": "Preferencias",
"Pin": "Fijar", "Preferences_saved": "¡Preferencias guardadas!",
"Pinned_Messages": "Mensajes fijados", "Privacy_Policy": "Política de privacidad",
"pinned": "fijado", "Private_Channel": "Canal privado",
"Pinned": "Fijado", "Private": "Privado",
"Please_enter_your_password": "Por favor introduce la contraseña", "Processing": "Procesando...",
"Preferences": "Preferencias", "Profile_saved_successfully": "¡Perfil guardado correctamente!",
"Preferences_saved": "¡Preferencias guardadas!", "Profile": "Perfil",
"Privacy_Policy": "Política de privacidad", "Public_Channel": "Canal público",
"Private_Channel": "Canal privado", "Public": "Público",
"Private": "Privado", "Push_Notifications": "Notificaciones Push",
"Processing": "Procesando...", "Push_Notifications_Alert_Info": "Estas notificaciones se le entregan cuando la aplicación no está abierta",
"Profile_saved_successfully": "¡Perfil guardado correctamente!", "Quote": "Citar",
"Profile": "Perfil", "Reactions_are_disabled": "Las reacciones están desactivadas",
"Public_Channel": "Canal público", "Reactions_are_enabled": "Las reacciones están activadas",
"Public": "Público", "Reactions": "Reacciones",
"Push_Notifications": "Notificaciones Push", "Read_Only_Channel": "Canal de sólo lectura",
"Push_Notifications_Alert_Info": "Estas notificaciones se le entregan cuando la aplicación no está abierta", "Read_Only": "Sólo lectura ",
"Quote": "Citar", "Read_Receipt": "Comprobante de lectura",
"Reactions_are_disabled": "Las reacciones están desactivadas", "Receive_Group_Mentions": "Recibir menciones de grupo",
"Reactions_are_enabled": "Las reacciones están activadas", "Receive_Group_Mentions_Info": "Recibir menciones @all y @here",
"Reactions": "Reacciones", "Register": "Registrar",
"Read": "Leer", "Repeat_Password": "Repetir contraseña",
"Read_Only_Channel": "Canal de sólo lectura", "Replied_on": "Respondido el:",
"Read_Only": "Sólo lectura ", "replies": "respuestas",
"Read_Receipt": "Comprobante de lectura", "reply": "respuesta",
"Receive_Group_Mentions": "Recibir menciones de grupo", "Reply": "Respuesta",
"Receive_Group_Mentions_Info": "Recibir menciones @all y @here", "Report": "Informe",
"Register": "Registrar", "Receive_Notification": "Recibir notificación",
"Repeat_Password": "Repetir contraseña", "Receive_notifications_from": "Recibir notificación de {{name}}",
"Replied_on": "Respondido el:", "Resend": "Reenviar",
"replies": "respuestas", "Reset_password": "Resetear contraseña",
"reply": "respuesta", "resetting_password": "reseteando contraseña",
"Reply": "Respuesta", "RESET": "RESET",
"Report": "Informe", "Roles": "Roles",
"Receive_Notification": "Recibir notificación", "Room_actions": "Acciones de sala",
"Receive_notifications_from": "Recibir notificación de {{name}}", "Room_changed_announcement": "El anuncio de la sala cambió a: {{announcement}} por {{userBy}}",
"Resend": "Reenviar", "Room_changed_description": "La descripción de la sala cambió a: {{description}} por {{userBy}}",
"Reset_password": "Resetear contraseña", "Room_changed_privacy": "El tipo de la sala cambió a: {{type}} por {{userBy}}",
"resetting_password": "reseteando contraseña", "Room_changed_topic": "El asunto de la sala cambió a: {{topic}} por {{userBy}}",
"RESET": "RESET", "Room_Files": "Archivos",
"Roles": "Roles", "Room_Info_Edit": "Editar información de la sala",
"Room_actions": "Acciones de sala", "Room_Info": "Información de la sala",
"Room_changed_announcement": "El anuncio de la sala cambió a: {{announcement}} por {{userBy}}", "Room_Members": "Miembros de la sala",
"Room_changed_description": "La descripción de la sala cambió a: {{description}} por {{userBy}}", "Room_name_changed": "El nombre de la sala cambió a: {{name}} por {{userBy}}",
"Room_changed_privacy": "El tipo de la sala cambió a: {{type}} por {{userBy}}", "SAVE": "GUARDAR",
"Room_changed_topic": "El asunto de la sala cambió a: {{topic}} por {{userBy}}", "Save_Changes": "Guardar cambios",
"Room_Files": "Archivos", "Save": "Guardar",
"Room_Info_Edit": "Editar información de la sala", "saving_preferences": "guardando preferencias",
"Room_Info": "Información de la sala", "saving_profile": "guardando perfil",
"Room_Members": "Miembros de la sala", "saving_settings": "guardando configuración",
"Room_name_changed": "El nombre de la sala cambió a: {{name}} por {{userBy}}", "Search_Messages": "Buscar mensajes",
"SAVE": "GUARDAR", "Search": "Buscar",
"Save_Changes": "Guardar cambios", "Search_by": "Buscar por",
"Save": "Guardar", "Search_global_users": "Buscar por usuarios globales",
"saving_preferences": "guardando preferencias", "Search_global_users_description": "Si lo activas, puedes buscar cualquier usuario de otras empresas o servidores.",
"saving_profile": "guardando perfil", "Seconds": "{{second}} segundos",
"saving_settings": "guardando configuración", "Select_Avatar": "Selecciona avatar",
"Search_Messages": "Buscar mensajes", "Select_Server": "Selecciona servidor",
"Search": "Buscar", "Select_Users": "Selecciona usuarios",
"Search_by": "Buscar por", "Send": "Enviar",
"Search_global_users": "Buscar por usuarios globales", "Send_audio_message": "Enviar nota de audio",
"Search_global_users_description": "Si lo activas, puedes buscar cualquier usuario de otras empresas o servidores.", "Send_crash_report": "Enviar informe errores",
"Seconds": "{{second}} segundos", "Send_message": "Enviar mensaje",
"Select_Avatar": "Selecciona avatar", "Send_to": "Enviar a..",
"Select_Server": "Selecciona servidor", "Sent_an_attachment": "Enviar un adjunto",
"Select_Users": "Selecciona usuarios", "Server": "Servidor",
"Send": "Enviar", "Servers": "Servidores",
"Send_audio_message": "Enviar nota de audio", "Server_version": "Versión servidor: {{version}}",
"Send_crash_report": "Enviar informe errores", "Set_username_subtitle": "El nombre de usuario se utiliza para permitir que otros le mencionen en los mensajes",
"Send_message": "Enviar mensaje", "Settings": "Configuración",
"Send_to": "Enviar a..", "Settings_succesfully_changed": "¡Configuración cambiada correctamente!",
"Sent_an_attachment": "Enviar un adjunto", "Share": "Compartir",
"Server": "Servidor", "Share_this_app": "Compartir esta aplicación",
"Servers": "Servidores", "Show_Unread_Counter": "Mostrar contador de no leídos",
"Server_version": "Versión servidor: {{version}}", "Show_Unread_Counter_Info": "El contador de no leídos se muestra como una insignia a la derecha del canal, en la lista",
"Set_username_subtitle": "El nombre de usuario se utiliza para permitir que otros le mencionen en los mensajes", "Sign_in_your_server": "Accede a tu servidor",
"Settings": "Configuración", "Sign_Up": "Registrarse",
"Settings_succesfully_changed": "¡Configuración cambiada correctamente!", "Some_field_is_invalid_or_empty": "Algún campo no es correcto o está vacío",
"Share": "Compartir", "Sound": "Sonido",
"Share_this_app": "Compartir esta aplicación", "Star_room": "Destacar sala",
"Show_Unread_Counter": "Mostrar contador de no leídos", "Star": "Destacar",
"Show_Unread_Counter_Info": "El contador de no leídos se muestra como una insignia a la derecha del canal, en la lista", "Starred_Messages": "Mensajes destacados",
"Sign_in_your_server": "Accede a tu servidor", "starred": "destacado",
"Sign_Up": "Registrarse", "Starred": "Destacado",
"Some_field_is_invalid_or_empty": "Algún campo no es correcto o está vacío", "Start_of_conversation": "Comienzo de la conversación",
"Sorting_by": "Ordenado por {{key}}", "Started_discussion": "Comenzar una conversación:",
"Sound": "Sonido", "Started_call": "Llamada iniciada por {{userBy}}",
"Star_room": "Destacar sala", "Submit": "Enviar",
"Star": "Destacar", "Table": "Tabla",
"Starred_Messages": "Mensajes destacados", "Take_a_photo": "Enviar una foto",
"starred": "destacado", "Take_a_video": "Enviar un vídeo",
"Starred": "Destacado", "tap_to_change_status": "pulsa para cambiar el estado",
"Start_of_conversation": "Comienzo de la conversación", "Tap_to_view_servers_list": "Pulsa para ver la lista de servidores",
"Started_discussion": "Comenzar una conversación:", "Terms_of_Service": "Términos de servicio",
"Started_call": "Llamada iniciada por {{userBy}}", "Theme": "Tema",
"Submit": "Enviar", "There_was_an_error_while_action": "¡Ha habido un error mientras {{action}}!",
"Table": "Tabla", "This_room_is_blocked": "La sala está bloqueada",
"Take_a_photo": "Enviar una foto", "This_room_is_read_only": "Esta sala es de sólo lectura",
"Take_a_video": "Enviar un vídeo", "Thread": "Hilo",
"tap_to_change_status": "pulsa para cambiar el estado", "Threads": "Hilos",
"Tap_to_view_servers_list": "Pulsa para ver la lista de servidores", "Timezone": "Zona horaria",
"Terms_of_Service": "Términos de servicio", "To": "Para",
"Theme": "Tema", "topic": "asunto",
"There_was_an_error_while_action": "¡Ha habido un error mientras {{action}}!", "Topic": "Asunto",
"This_room_is_blocked": "La sala está bloqueada", "Translate": "Traducir",
"This_room_is_read_only": "Esta sala es de sólo lectura", "Try_again": "Intentar de nuevo",
"Thread": "Hilo", "Two_Factor_Authentication": "Autenticación de doble factor",
"Threads": "Hilos", "Type_the_channel_name_here": "Escribe el nombre del canal aquí",
"Timezone": "Zona horaria", "unarchive": "desarchivar",
"To": "Para", "UNARCHIVE": "DESARCHIVAR",
"topic": "asunto", "Unblock_user": "Desbloquear usuario",
"Topic": "Asunto", "Unfollowed_thread": "Dejar de seguir el hilo",
"Translate": "Traducir", "Unmute": "Desmutear",
"Try_again": "Intentar de nuevo", "unmuted": "Desmuteado",
"Two_Factor_Authentication": "Autenticación de doble factor", "Unpin": "Quitar estado fijado",
"Type_the_channel_name_here": "Escribe el nombre del canal aquí", "unread_messages": "marcar como no leído",
"unarchive": "desarchivar", "Unread": "Marcar como no leído",
"UNARCHIVE": "DESARCHIVAR", "Unread_on_top": "Mensajes no leídos en la parte superior",
"Unblock_user": "Desbloquear usuario", "Unstar": "Quitar destacado",
"Unfavorite": "Quitar favorito", "Updating": "Actualizando...",
"Unfollowed_thread": "Dejar de seguir el hilo", "Uploading": "Subiendo",
"Unmute": "Desmutear", "Upload_file_question_mark": "¿Subir fichero?",
"unmuted": "Desmuteado", "Users": "Usuarios",
"Unpin": "Quitar estado fijado", "User_added_by": "Usuario {{userAdded}} añadido por {{userBy}}",
"unread_messages": "marcar como no leído", "User_has_been_key": "El usuario ha sido {{key}}",
"Unread": "Marcar como no leído", "User_is_no_longer_role_by_": "{{user}} ha dejado de ser {{role}} por {{userBy}}",
"Unread_on_top": "Mensajes no leídos en la parte superior", "User_muted_by": "Usuario {{userMuted}} muteado por {{userBy}}",
"Unstar": "Quitar destacado", "User_removed_by": "Usuario {{userRemoved}} eliminado por {{userBy}}",
"Updating": "Actualizando...", "User_sent_an_attachment": "{{user}} envío un adjunto",
"Uploading": "Subiendo", "User_unmuted_by": "Usuario {{userUnmuted}} desmuteado por {{userBy}}",
"Upload_file_question_mark": "¿Subir fichero?", "User_was_set_role_by_": "{{user}} ha comenzado a ser {{role}} por {{userBy}}",
"Users": "Usuarios", "Username_is_empty": "Nombre de usuario está vacío",
"User_added_by": "Usuario {{userAdded}} añadido por {{userBy}}", "Username": "Nombre de usuario",
"User_has_been_key": "El usuario ha sido {{key}}", "Username_or_email": "Nombre de usuario o email",
"User_is_no_longer_role_by_": "{{user}} ha dejado de ser {{role}} por {{userBy}}", "Validating": "Validando",
"User_muted_by": "Usuario {{userMuted}} muteado por {{userBy}}", "Video_call": "Vídeo llamada",
"User_removed_by": "Usuario {{userRemoved}} eliminado por {{userBy}}", "View_Original": "Ver original",
"User_sent_an_attachment": "{{user}} envío un adjunto", "Voice_call": "Llamada de voz",
"User_unmuted_by": "Usuario {{userUnmuted}} desmuteado por {{userBy}}", "Websocket_disabled": "Websocket está deshabilitado para este servidor.\n{{contact}}",
"User_was_set_role_by_": "{{user}} ha comenzado a ser {{role}} por {{userBy}}", "Welcome": "Bienvenido",
"Username_is_empty": "Nombre de usuario está vacío", "Whats_your_2fa": "¿Cuál es tu código 2FA?",
"Username": "Nombre de usuario", "Without_Servers": "Sin servidores",
"Username_or_email": "Nombre de usuario o email", "Yes_action_it": "Sí, ¡{{action}}!",
"Validating": "Validando", "Yesterday": "Ayer",
"Video_call": "Vídeo llamada", "You_are_in_preview_mode": "Estás en modo vista previa",
"View_Original": "Ver original", "You_are_offline": "Estás desconectado",
"Voice_call": "Llamada de voz", "You_can_search_using_RegExp_eg": "Puedes usar expresiones regulares. Por ejemplo, `/^text$/i`",
"Websocket_disabled": "Websocket está deshabilitado para este servidor.\n{{contact}}", "You_colon": "Tú: ",
"Welcome": "Bienvenido", "you_were_mentioned": "has sido mencionado",
"Whats_your_2fa": "¿Cuál es tu código 2FA?", "you": "tú",
"Without_Servers": "Sin servidores", "You": "Tú",
"Yes_action_it": "Sí, ¡{{action}}!", "You_need_to_access_at_least_one_RocketChat_server_to_share_something": "Necesita acceder al menos a un servidor Rocket.Chat para compartir algo.",
"Yesterday": "Ayer", "Your_certificate": "Tu certificado",
"You_are_in_preview_mode": "Estás en modo vista previa", "Version_no": "Versión: {{version}}",
"You_are_offline": "Estás desconectado", "You_will_not_be_able_to_recover_this_message": "¡No podrás recuperar este mensaje!",
"You_can_search_using_RegExp_eg": "Puedes usar expresiones regulares. Por ejemplo, `/^text$/i`", "Change_Language": "Cambiar idioma",
"You_colon": "Tú: ", "Crash_report_disclaimer": "Nunca rastreamos el contenido de sus conversaciones. El informe del error sólo contiene información relevante para nosotros con el fin de identificar los problemas y solucionarlos.",
"you_were_mentioned": "has sido mencionado", "Type_message": "Escribir mensaje",
"you": "tú", "Room_search": "Búsqueda de salas",
"You": "Tú", "Room_selection": "Selecciona sala 1...9",
"You_need_to_access_at_least_one_RocketChat_server_to_share_something": "Necesita acceder al menos a un servidor Rocket.Chat para compartir algo.", "Next_room": "Siguiente sala",
"Your_certificate": "Tu certificado", "Previous_room": "Sala anterior",
"Version_no": "Versión: {{version}}", "New_room": "Nueva sala",
"You_will_not_be_able_to_recover_this_message": "¡No podrás recuperar este mensaje!", "Upload_room": "Subir a sala",
"Change_Language": "Cambiar idioma", "Search_messages": "Buscar mensajes",
"Crash_report_disclaimer": "Nunca rastreamos el contenido de sus conversaciones. El informe del error sólo contiene información relevante para nosotros con el fin de identificar los problemas y solucionarlos.", "Scroll_messages": "Scroll mensajes",
"Type_message": "Escribir mensaje", "Reply_latest": "Responder al último",
"Room_search": "Búsqueda de salas", "Server_selection": "Seleccionar servidor",
"Room_selection": "Selecciona sala 1...9", "Server_selection_numbers": "Seleccionar servidor 1...9",
"Next_room": "Siguiente sala", "Add_server": "Añadir servidor",
"Previous_room": "Sala anterior", "New_line": "Nueva línea"
"New_room": "Nueva sala",
"Upload_room": "Subir a sala",
"Search_messages": "Buscar mensajes",
"Scroll_messages": "Scroll mensajes",
"Reply_latest": "Responder al último",
"Server_selection": "Seleccionar servidor",
"Server_selection_numbers": "Seleccionar servidor 1...9",
"Add_server": "Añadir servidor",
"New_line": "Nueva línea"
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,492 +1,483 @@
{ {
"1_person_reacted": "1人がリアクション", "1_person_reacted": "1人がリアクション",
"1_user": "1人", "1_user": "1人",
"error-action-not-allowed": "{{action}}の権限がありません。", "error-action-not-allowed": "{{action}}の権限がありません。",
"error-application-not-found": "アプリケーションがありません。", "error-application-not-found": "アプリケーションがありません。",
"error-archived-duplicate-name": "アーカイブ名が重複しています: {{room_name}}", "error-archived-duplicate-name": "アーカイブ名が重複しています: {{room_name}}",
"error-avatar-invalid-url": "画像のURLが正しくありません: {{url}}", "error-avatar-invalid-url": "画像のURLが正しくありません: {{url}}",
"error-avatar-url-handling": "アバターをURL({{url}})から{{username}}に設定中にエラーが発生しました。", "error-avatar-url-handling": "アバターをURL({{url}})から{{username}}に設定中にエラーが発生しました。",
"error-cant-invite-for-direct-room": "ユーザーを直接ルームに招待することができません。", "error-cant-invite-for-direct-room": "ユーザーを直接ルームに招待することができません。",
"error-could-not-change-email": "メールアドレスを変更できません。", "error-could-not-change-email": "メールアドレスを変更できません。",
"error-could-not-change-name": "名前を変更できません。", "error-could-not-change-name": "名前を変更できません。",
"error-could-not-change-username": "ユーザー名を変更できません。", "error-could-not-change-username": "ユーザー名を変更できません。",
"error-delete-protected-role": "保護されたロールは削除できません。", "error-delete-protected-role": "保護されたロールは削除できません。",
"error-department-not-found": "ロールが存在しません。", "error-department-not-found": "ロールが存在しません。",
"error-direct-message-file-upload-not-allowed": "ダイレクトメッセージでのファイルのアップロードは許可されていません。", "error-direct-message-file-upload-not-allowed": "ダイレクトメッセージでのファイルのアップロードは許可されていません。",
"error-duplicate-channel-name": "{{channel_name}}と同名のチャンネルが存在します。", "error-duplicate-channel-name": "{{channel_name}}と同名のチャンネルが存在します。",
"error-email-domain-blacklisted": "このドメインのメールアドレスはブラックリストに登録されています。", "error-email-domain-blacklisted": "このドメインのメールアドレスはブラックリストに登録されています。",
"error-email-send-failed": "次のメールアドレスの送信に失敗しました: {{message}}", "error-email-send-failed": "次のメールアドレスの送信に失敗しました: {{message}}",
"error-save-image": "画像の保存に失敗しました。", "error-save-image": "画像の保存に失敗しました。",
"error-field-unavailable": "{{field}}は既に使用されています。", "error-field-unavailable": "{{field}}は既に使用されています。",
"error-file-too-large": "ファイルが大きすぎます。", "error-file-too-large": "ファイルが大きすぎます。",
"error-importer-not-defined": "インポータが正しく定義されていません。Importクラスが見つかりません。", "error-importer-not-defined": "インポータが正しく定義されていません。Importクラスが見つかりません。",
"error-input-is-not-a-valid-field": "{{input}}は{{field}}の入力として正しくありません。", "error-input-is-not-a-valid-field": "{{input}}は{{field}}の入力として正しくありません。",
"error-invalid-actionlink": "アクションリンクが正しくありません。", "error-invalid-actionlink": "アクションリンクが正しくありません。",
"error-invalid-arguments": "引数が正しくありません。", "error-invalid-arguments": "引数が正しくありません。",
"error-invalid-asset": "アセットが不正です。", "error-invalid-asset": "アセットが不正です。",
"error-invalid-channel": "チャンネル名が不正です。", "error-invalid-channel": "チャンネル名が不正です。",
"error-invalid-channel-start-with-chars": "不正なチャンネルです。チャンネル名は@か#から開始します。", "error-invalid-channel-start-with-chars": "不正なチャンネルです。チャンネル名は@か#から開始します。",
"error-invalid-custom-field": "カスタムフィールドが不正です。", "error-invalid-custom-field": "カスタムフィールドが不正です。",
"error-invalid-custom-field-name": "カスタムフィールド名が不正です。半角英数字、ハイフン、アンダースコアのみを使用してください。", "error-invalid-custom-field-name": "カスタムフィールド名が不正です。半角英数字、ハイフン、アンダースコアのみを使用してください。",
"error-invalid-date": "不正な日時です", "error-invalid-date": "不正な日時です",
"error-invalid-description": "不正な詳細です", "error-invalid-description": "不正な詳細です",
"error-invalid-domain": "不正なドメインです", "error-invalid-domain": "不正なドメインです",
"error-invalid-email": "不正なメールアドレスです。 {{email}}", "error-invalid-email": "不正なメールアドレスです。 {{email}}",
"error-invalid-email-address": "不正なメールアドレスです", "error-invalid-email-address": "不正なメールアドレスです",
"error-invalid-file-height": "ファイルの高さが不正です", "error-invalid-file-height": "ファイルの高さが不正です",
"error-invalid-file-type": "ファイルの種類が不正です", "error-invalid-file-type": "ファイルの種類が不正です",
"error-invalid-file-width": "ファイルの幅が不正です", "error-invalid-file-width": "ファイルの幅が不正です",
"error-invalid-from-address": "不正なアドレスから通知しました", "error-invalid-from-address": "不正なアドレスから通知しました",
"error-invalid-integration": "不正なインテグレーションです。", "error-invalid-integration": "不正なインテグレーションです。",
"error-invalid-message": "不正なメッセージです。", "error-invalid-message": "不正なメッセージです。",
"error-invalid-method": "不正なメソッドです。", "error-invalid-method": "不正なメソッドです。",
"error-invalid-name": "不正な名前です", "error-invalid-name": "不正な名前です",
"error-invalid-password": "不正なパスワードです", "error-invalid-password": "不正なパスワードです",
"error-invalid-redirectUri": "不正なリダイレクトURIです", "error-invalid-redirectUri": "不正なリダイレクトURIです",
"error-invalid-role": "不正なロールです", "error-invalid-role": "不正なロールです",
"error-invalid-room": "不正なルームです", "error-invalid-room": "不正なルームです",
"error-invalid-room-name": "{{room_name}}は正しいルーム名ではありません。", "error-invalid-room-name": "{{room_name}}は正しいルーム名ではありません。",
"error-invalid-room-type": "{{type}}は正しいルームタイプではありません。", "error-invalid-room-type": "{{type}}は正しいルームタイプではありません。",
"error-invalid-settings": "不正な設定が送信されました", "error-invalid-settings": "不正な設定が送信されました",
"error-invalid-subscription": "不正な購読です", "error-invalid-subscription": "不正な購読です",
"error-invalid-token": "トークンが正しくありません", "error-invalid-token": "トークンが正しくありません",
"error-invalid-triggerWords": "トリガーワードが正しくありません", "error-invalid-triggerWords": "トリガーワードが正しくありません",
"error-invalid-urls": "URLが正しくありません", "error-invalid-urls": "URLが正しくありません",
"error-invalid-user": "ユーザーが正しくありません", "error-invalid-user": "ユーザーが正しくありません",
"error-invalid-username": "ユーザー名が正しくありません", "error-invalid-username": "ユーザー名が正しくありません",
"error-invalid-webhook-response": "WebhookのURLが200以外のステータスを返しています", "error-invalid-webhook-response": "WebhookのURLが200以外のステータスを返しています",
"error-message-deleting-blocked": "メッセージの削除をブロックされています。", "error-message-deleting-blocked": "メッセージの削除をブロックされています。",
"error-message-editing-blocked": "メッセージの編集をブロックされています。", "error-message-editing-blocked": "メッセージの編集をブロックされています。",
"error-message-size-exceeded": "メッセージの大きさが Message_MaxAllowedSize を超えています。", "error-message-size-exceeded": "メッセージの大きさが Message_MaxAllowedSize を超えています。",
"error-missing-unsubscribe-link": "購読停止リンクを入れてください。", "error-missing-unsubscribe-link": "購読停止リンクを入れてください。",
"error-no-tokens-for-this-user": "このユーザーにはトークンがありません。", "error-no-tokens-for-this-user": "このユーザーにはトークンがありません。",
"error-not-allowed": "許可されていません。", "error-not-allowed": "許可されていません。",
"error-not-authorized": "有効化されていません。", "error-not-authorized": "有効化されていません。",
"error-push-disabled": "プッシュは無効化されています。", "error-push-disabled": "プッシュは無効化されています。",
"error-remove-last-owner": "ルームの最後のオーナーです。ルームを退出する前に新しいオーナーを設定してください。", "error-remove-last-owner": "ルームの最後のオーナーです。ルームを退出する前に新しいオーナーを設定してください。",
"error-role-in-use": "使用中のロールを削除することはできません。", "error-role-in-use": "使用中のロールを削除することはできません。",
"error-role-name-required": "ロール名を入力してください。", "error-role-name-required": "ロール名を入力してください。",
"error-the-field-is-required": "{{field}}の入力欄は必須です。", "error-the-field-is-required": "{{field}}の入力欄は必須です。",
"error-too-many-requests": "エラーです。リクエストが多すぎます。リクエストの頻度を落としてください。{{seconds}} 秒以上待ってから再度お試しください。", "error-too-many-requests": "エラーです。リクエストが多すぎます。リクエストの頻度を落としてください。{{seconds}} 秒以上待ってから再度お試しください。",
"error-user-is-not-activated": "アカウントが有効化されていません。", "error-user-is-not-activated": "アカウントが有効化されていません。",
"error-user-has-no-roles": "ロールがありません。", "error-user-has-no-roles": "ロールがありません。",
"error-user-limit-exceeded": "#channel_name に招待できるユーザー数の上限を超えています。管理者にお問い合わせください。", "error-user-limit-exceeded": "#channel_name に招待できるユーザー数の上限を超えています。管理者にお問い合わせください。",
"error-user-not-in-room": "ユーザーがルームにいません。", "error-user-not-in-room": "ユーザーがルームにいません。",
"error-user-registration-custom-field": "error-user-registration-custom-field", "error-user-registration-custom-field": "error-user-registration-custom-field",
"error-user-registration-disabled": "ユーザー登録は無効化されています", "error-user-registration-disabled": "ユーザー登録は無効化されています",
"error-user-registration-secret": "ユーザーの登録は登録用URLからのみ許可されています", "error-user-registration-secret": "ユーザーの登録は登録用URLからのみ許可されています",
"error-you-are-last-owner": "あなたは最後のオーナーです。ルームを退出する前に別のオーナーを設定してください。", "error-you-are-last-owner": "あなたは最後のオーナーです。ルームを退出する前に別のオーナーを設定してください。",
"Actions": "アクション", "Actions": "アクション",
"activity": "アクティビティ", "Activity": "アクティビティ順",
"Activity": "アクティビティ順", "Add_Reaction": "リアクションを追加",
"Add_Reaction": "リアクションを追加", "Add_Server": "サーバーを追加",
"Add_Server": "サーバーを追加", "Add_users": "ユーザーを追加",
"Add_users": "ユーザーを追加", "Admin_Panel": "管理者パネル",
"Admin_Panel": "管理者パネル", "Alert": "アラート",
"Alert": "アラート", "alert": "アラート",
"alert": "アラート", "alerts": "アラート",
"alerts": "アラート", "All_users_in_the_channel_can_write_new_messages": "すべてのユーザーが新しいメッセージを書き込みできます",
"All_users_in_the_channel_can_write_new_messages": "すべてのユーザーが新しいメッセージを書き込みできます", "All": "すべての",
"All": "すべての", "All_Messages": "全メッセージ",
"All_Messages": "全メッセージ", "Allow_Reactions": "リアクションを許可",
"Allow_Reactions": "リアクションを許可", "Alphabetical": "アルファベット順",
"Alphabetical": "アルファベット順", "and_more": "さらに表示",
"and_more": "さらに表示", "and": "と",
"and": "と", "announcement": "アナウンス",
"announcement": "アナウンス", "Announcement": "アナウンス",
"Announcement": "アナウンス", "Apply_Your_Certificate": "証明書を適用する",
"Apply_Your_Certificate": "証明書を適用する", "ARCHIVE": "アーカイブ",
"ARCHIVE": "アーカイブ", "archive": "アーカイブ",
"archive": "アーカイブ", "are_typing": "が入力中",
"are_typing": "が入力中", "Are_you_sure_question_mark": "よろしいですか?",
"Are_you_sure_question_mark": "よろしいですか?", "Are_you_sure_you_want_to_leave_the_room": "{{room}}を退出してもよろしいですか?",
"Are_you_sure_you_want_to_leave_the_room": "{{room}}を退出してもよろしいですか?", "Audio": "音声",
"Audio": "音声", "Authenticating": "認証",
"Authenticating": "認証", "Automatic": "自動",
"Automatic": "自動", "Auto_Translate": "自動翻訳",
"Auto_Translate": "自動翻訳", "Avatar_changed_successfully": "アバターを変更しました!",
"Avatar_changed_successfully": "アバターを変更しました!", "Avatar_Url": "アバターURL",
"Avatar_Url": "アバターURL", "Away": "退出中",
"Away": "退出中", "Back": "戻る",
"Back": "戻る", "Black": "ブラック",
"Black": "ブラック", "Block_user": "ブロックしたユーザー",
"Block_user": "ブロックしたユーザー", "Broadcast_channel_Description": "許可されたユーザーのみが新しいメッセージを書き込めます。他のユーザーは返信することができます",
"Broadcast_channel_Description": "許可されたユーザーのみが新しいメッセージを書き込めます。他のユーザーは返信することができます", "Broadcast_Channel": "配信チャンネル",
"Broadcast_Channel": "配信チャンネル", "Busy": "取り込み中",
"Busy": "取り込み中", "By_proceeding_you_are_agreeing": "続行することにより、私達を承認します",
"By_proceeding_you_are_agreeing": "続行することにより、私達を承認します", "Cancel_editing": "編集をキャンセル",
"Cancel_editing": "編集をキャンセル", "Cancel_recording": "録音をキャンセル",
"Cancel_recording": "録音をキャンセル", "Cancel": "キャンセル",
"Cancel": "キャンセル", "changing_avatar": "アバターを変更",
"changing_avatar": "アバターを変更", "creating_channel": "チャンネルを作成",
"creating_channel": "チャンネルを作成", "creating_invite": "招待を作成",
"creating_invite": "招待を作成", "Channel_Name": "チャンネル名",
"Channel_Name": "チャンネル名", "Channels": "チャンネル",
"Channels": "チャンネル", "Chats": "チャット",
"Chats": "チャット", "Call_already_ended": "通話は終了しています。",
"Call_already_ended": "通話は終了しています。", "Click_to_join": "クリックして参加!",
"Click_to_join": "クリックして参加!", "Close": "閉じる",
"Close": "閉じる", "Close_emoji_selector": "絵文字ピッカーを閉じる",
"Close_emoji_selector": "絵文字ピッカーを閉じる", "Choose": "選択",
"Choose": "選択", "Choose_from_library": "ライブラリから選択",
"Choose_from_library": "ライブラリから選択", "Choose_file": "ファイルを選択",
"Choose_file": "ファイルを選択", "Code": "コード",
"Code": "コード", "Collaborative": "コラボ",
"Collaborative": "コラボ", "Confirm": "承認",
"Confirm": "承認", "Connect": "接続",
"Connect": "接続", "Connected": "接続しました",
"Connected": "接続しました", "connecting_server": "サーバーに接続中",
"connecting_server": "サーバーに接続中", "Connecting": "接続中...",
"Connecting": "接続中...", "Contact_us": "お問い合わせ",
"Contact_us": "お問い合わせ", "Contact_your_server_admin": "サーバー管理者にお問い合わせください。",
"Contact_your_server_admin": "サーバー管理者にお問い合わせください。", "Continue_with": "次でログイン: ",
"Continue_with": "次でログイン: ", "Copied_to_clipboard": "クリップボードにコピー!",
"Copied_to_clipboard": "クリップボードにコピー!", "Copy": "コピー",
"Copy": "コピー", "Permalink": "パーマリンク",
"Permalink": "パーマリンク", "Certificate_password": "パスワード証明書",
"Certificate_password": "パスワード証明書", "Clear_cache": "ローカルのサーバーキャッシュをクリア",
"Clear_cache": "ローカルのサーバーキャッシュをクリア", "Whats_the_password_for_your_certificate": "証明書のパスワードはなんですか?",
"Whats_the_password_for_your_certificate": "証明書のパスワードはなんですか?", "Create_account": "アカウントを作成",
"Create_account": "アカウントを作成", "Create_Channel": "チャンネルを作成",
"Create_Channel": "チャンネルを作成", "Created_snippet": "スニペットを作成",
"Created_snippet": "スニペットを作成", "Create_a_new_workspace": "新しいワークスペースを作成",
"Create_a_new_workspace": "新しいワークスペースを作成", "Create": "作成",
"Create": "作成", "Dark": "ダーク",
"Dark": "ダーク", "Dark_level": "ダークレベル",
"Dark_level": "ダークレベル", "Default": "デフォルト",
"Default": "デフォルト", "Default_browser": "デフォルトのブラウザ",
"Default_browser": "デフォルトのブラウザ", "Delete_Room_Warning": "ルームを削除すると、ルームに投稿されたすべてのメッセージが削除されます。この操作は取り消せません。",
"Delete_Room_Warning": "ルームを削除すると、ルームに投稿されたすべてのメッセージが削除されます。この操作は取り消せません。", "delete": "削除",
"delete": "削除", "Delete": "削除",
"Delete": "削除", "DELETE": "削除",
"DELETE": "削除", "deleting_room": "ルームを削除",
"deleting_room": "ルームを削除", "description": "概要",
"description": "概要", "Description": "概要",
"Description": "概要", "Desktop_Options": "デスクトップオプション",
"Desktop_Options": "デスクトップオプション", "Directory": "ディレクトリ",
"Directory": "ディレクトリ", "Direct_Messages": "ダイレクトメッセージ",
"Direct_Messages": "ダイレクトメッセージ", "Disable_notifications": "通知を無効化",
"Disable_notifications": "通知を無効化", "Discussions": "ディスカッション",
"Discussions": "ディスカッション", "Dont_Have_An_Account": "アカウントがありませんか?",
"Dont_Have_An_Account": "アカウントがありませんか?", "Do_you_have_a_certificate": "証明書を持っていますか?",
"Do_you_have_a_certificate": "証明書を持っていますか?", "Do_you_really_want_to_key_this_room_question_mark": "本当にこのルームを{{key}}しますか?",
"Do_you_really_want_to_key_this_room_question_mark": "本当にこのルームを{{key}}しますか?", "edit": "編集",
"edit": "編集", "edited": "編集済",
"edited": "編集済", "Edit": "編集",
"Edit": "編集", "Edit_Invite": "編集に招待",
"Edit_Invite": "編集に招待", "Email_or_password_field_is_empty": "メールアドレスかパスワードの入力欄が空です",
"Email_or_password_field_is_empty": "メールアドレスかパスワードの入力欄が空です", "Email": "メールアドレス",
"Email": "メールアドレス", "email": "メールアドレス",
"email": "メールアドレス", "Enable_Auto_Translate": "自動翻訳を有効にする",
"Enable_Auto_Translate": "自動翻訳を有効にする", "Enable_notifications": "通知を有効にする",
"Enable_notifications": "通知を有効にする", "Everyone_can_access_this_channel": "全員このチャンネルにアクセスできます",
"Everyone_can_access_this_channel": "全員このチャンネルにアクセスできます", "Error_uploading": "アップロードエラー",
"Error_uploading": "アップロードエラー", "Expiration_Days": "期限切れ (日)",
"Expiration_Days": "期限切れ (日)", "Favorites": "お気に入り",
"Favorite": "お気に入り", "Files": "ファイル",
"Favorites": "お気に入り", "File_description": "ファイルの説明",
"Files": "ファイル", "File_name": "ファイル名",
"File_description": "ファイルの説明", "Finish_recording": "録音停止",
"File_name": "ファイル名", "Following_thread": "スレッド更新時に通知",
"Finish_recording": "録音停止", "For_your_security_you_must_enter_your_current_password_to_continue": "セキュリティのため、続けるには現在のパスワードを入力してください。",
"Following_thread": "スレッド更新時に通知", "Forgot_password_If_this_email_is_registered": "送信したメールアドレスが登録されていれば、パスワードのリセット方法を送信しました。メールアドレスがすぐに来ない場合はやり直してください。",
"For_your_security_you_must_enter_your_current_password_to_continue": "セキュリティのため、続けるには現在のパスワードを入力してください。", "Forgot_password": "パスワードを忘れた",
"Forgot_password_If_this_email_is_registered": "送信したメールアドレスが登録されていれば、パスワードのリセット方法を送信しました。メールアドレスがすぐに来ない場合はやり直してください。", "Forgot_Password": "パスワードを忘れた",
"Forgot_password": "パスワードを忘れた", "Full_table": "クリックしてテーブル全体を見る",
"Forgot_Password": "パスワードを忘れた", "Generate_New_Link": "新しいリンクを生成",
"Full_table": "クリックしてテーブル全体を見る", "Has_joined_the_channel": "はチャンネルに参加しました",
"Generate_New_Link": "新しいリンクを生成", "Has_joined_the_conversation": "は会話に参加しました",
"Group_by_favorites": "お気に入りをグループ化", "Has_left_the_channel": "はチャンネルを退出しました",
"Group_by_type": "タイプ別にグループ化", "In_App_And_Desktop": "アプリ内とデスクトップ",
"Hide": "隠す", "In_App_and_Desktop_Alert_info": "アプリを表示中にはバナーを上部に表示し、デスクトップには通知を送ります。",
"Has_joined_the_channel": "はチャンネルに参加しました", "Invisible": "状態を隠す",
"Has_joined_the_conversation": "は会話に参加しました", "Invite": "招待",
"Has_left_the_channel": "はチャンネルを退出しました", "is_a_valid_RocketChat_instance": "は正しいRocket.Chatのインスタンスです",
"In_App_And_Desktop": "アプリ内とデスクトップ", "is_not_a_valid_RocketChat_instance": "はRocket.Chatのインスタンスではありません",
"In_App_and_Desktop_Alert_info": "アプリを表示中にはバナーを上部に表示し、デスクトップには通知を送ります。", "is_typing": "が入力中",
"Invisible": "状態を隠す", "Invalid_or_expired_invite_token": "招待トークンが無効か、期限が切れています",
"Invite": "招待", "Invalid_server_version": "接続しようとしているサーバーのバージョン({{currentVersion}})はサポートされていません。\n\nサポートする最低バージョンは {{minVersion}} です",
"is_a_valid_RocketChat_instance": "は正しいRocket.Chatのインスタンスです", "Invite_Link": "招待リンク",
"is_not_a_valid_RocketChat_instance": "はRocket.Chatのインスタンスではありません", "Invite_users": "ユーザーを招待",
"is_typing": "が入力中", "Join": "参加",
"Invalid_or_expired_invite_token": "招待トークンが無効か、期限が切れています", "Just_invited_people_can_access_this_channel": "招待されたユーザーだけがこのチャンネルに参加できます",
"Invalid_server_version": "接続しようとしているサーバーのバージョン({{currentVersion}})はサポートされていません。\n\nサポートする最低バージョンは {{minVersion}} です", "Language": "言語",
"Invite_Link": "招待リンク", "last_message": "最後のメッセージ",
"Invite_users": "ユーザーを招待", "Leave_channel": "チャンネルを退出",
"Join": "参加", "leaving_room": "チャンネルを退出",
"Just_invited_people_can_access_this_channel": "招待されたユーザーだけがこのチャンネルに参加できます", "Leave": "ルームを退出",
"Language": "言語", "leave": "退出",
"last_message": "最後のメッセージ", "Legal": "法的項目",
"Leave_channel": "チャンネルを退出", "Light": "ライト",
"leaving_room": "チャンネルを退出", "License": "ライセンス",
"Leave": "ルームを退出", "Livechat": "ライブチャット",
"leave": "退出", "Login": "ログイン",
"Legal": "法的項目", "Login_error": "証明書が承認されませんでした。再度お試しください。",
"Light": "ライト", "Login_with": "次でログイン: ",
"License": "ライセンス", "Logout": "ログアウト",
"Livechat": "ライブチャット", "Max_number_of_uses": "最大利用数",
"Login": "ログイン", "members": "メンバー",
"Login_error": "証明書が承認されませんでした。再度お試しください。", "Members": "メンバー",
"Login_with": "次でログイン: ", "Mentioned_Messages": "メンションされたメッセージ",
"Logout": "ログアウト", "mentioned": "メンション",
"Max_number_of_uses": "最大利用数", "Mentions": "メンション",
"members": "メンバー", "Message_accessibility": "{{user}} から {{time}} にメッセージ: {{message}}",
"Members": "メンバー", "Message_actions": "メッセージアクション",
"Mentioned_Messages": "メンションされたメッセージ", "Message_pinned": "メッセージをピン留め",
"mentioned": "メンション", "Message_removed": "メッセージを除く",
"Mentions": "メンション", "message": "メッセージ",
"Message_accessibility": "{{user}} から {{time}} にメッセージ: {{message}}", "messages": "メッセージ",
"Message_actions": "メッセージアクション", "Message": "メッセージ",
"Message_pinned": "メッセージをピン留め", "Messages": "メッセージ",
"Message_removed": "メッセージを除く", "Message_Reported": "メッセージを報告しました",
"message": "メッセージ", "Microphone_Permission_Message": "Rocket.Chatは音声メッセージを送信するのにマイクのアクセスの許可が必要です。",
"messages": "メッセージ", "Microphone_Permission": "マイクの許可",
"Message": "メッセージ", "Mute": "ミュート",
"Messages": "メッセージ", "muted": "ミュートした",
"Message_Reported": "メッセージを報告しました", "My_servers": "自分のサーバー",
"Microphone_Permission_Message": "Rocket.Chatは音声メッセージを送信するのにマイクのアクセスの許可が必要です。", "N_people_reacted": "{{n}}人がリアクションしました",
"Microphone_Permission": "マイクの許可", "N_users": "{{n}}人",
"Mute": "ミュート", "Name": "名前",
"muted": "ミュートした", "Never": "ずっと受け取らない",
"My_servers": "自分のサーバー", "New_Message": "メッセージ",
"N_people_reacted": "{{n}}人がリアクションしました", "New_Password": "新しいパスワード",
"N_users": "{{n}}人", "New_Server": "新規サーバー",
"name": "アルファベット", "Next": "次へ",
"Name": "名前", "No_files": "ファイルがありません",
"Never": "ずっと受け取らない", "No_limit": "制限なし",
"New_Message": "メッセージ", "No_mentioned_messages": "メンションされたメッセージはありません",
"New_Password": "新しいパスワード", "No_pinned_messages": "ピン留めされたメッセージはありません",
"New_Server": "新規サーバー", "No_results_found": "結果なし",
"Next": "次へ", "No_starred_messages": "お気に入りされたメッセージはありません",
"No_files": "ファイルがありません", "No_thread_messages": "スレッドのメッセージはありません",
"No_limit": "制限なし", "No_Message": "メッセージなし",
"No_mentioned_messages": "メンションされたメッセージはありません", "No_messages_yet": "まだメッセージはありません",
"No_pinned_messages": "ピン留めされたメッセージはありません", "No_Reactions": "リアクションなし",
"No_results_found": "結果なし", "No_Read_Receipts": "未読通知はありません",
"No_starred_messages": "お気に入りされたメッセージはありません", "Not_logged": "ログされていません",
"No_thread_messages": "スレッドのメッセージはありません", "Not_RC_Server": "Rocket.Chatサーバーではありません。\n{{contact}}",
"No_Message": "メッセージなし", "Nothing": "何もなし",
"No_messages_yet": "まだメッセージはありません", "Nothing_to_save": "保存するものはありません!",
"No_Reactions": "リアクションなし", "Notify_active_in_this_room": "このルームのアクティブなユーザーに通知する",
"No_Read_Receipts": "未読通知はありません", "Notify_all_in_this_room": "このルームのユーザー全員に通知する",
"Not_logged": "ログされていません", "Notifications": "通知",
"Not_RC_Server": "Rocket.Chatサーバーではありません。\n{{contact}}", "Notification_Duration": "通知の期間",
"Nothing": "何もなし", "Notification_Preferences": "通知設定",
"Nothing_to_save": "保存するものはありません!", "Offline": "オフライン",
"Notify_active_in_this_room": "このルームのアクティブなユーザーに通知する", "Oops": "おっと!",
"Notify_all_in_this_room": "このルームのユーザー全員に通知する", "Onboarding_title": "Rocket.Chatへようこそ",
"Notifications": "通知", "Online": "オンライン",
"Notification_Duration": "通知の期間", "Only_authorized_users_can_write_new_messages": "承認されたユーザーだけが新しいメッセージを書き込めます",
"Notification_Preferences": "通知設定", "Open_emoji_selector": "絵文字ピッカーを開く",
"Offline": "オフライン", "Open_Source_Communication": "オープンソースコミュニケーション",
"Oops": "おっと!", "Password": "パスワード",
"Onboarding_title": "Rocket.Chatへようこそ", "Permalink_copied_to_clipboard": "リンクをクリップボードにコピーしました!",
"Online": "オンライン", "Pin": "ピン留め",
"Only_authorized_users_can_write_new_messages": "承認されたユーザーだけが新しいメッセージを書き込めます", "Pinned_Messages": "ピン留めされたメッセージ",
"Open_emoji_selector": "絵文字ピッカーを開く", "pinned": "ピン留めされた",
"Open_Source_Communication": "オープンソースコミュニケーション", "Pinned": "ピン留めされました",
"Password": "パスワード", "Please_enter_your_password": "パスワードを入力してください",
"Permalink_copied_to_clipboard": "リンクをクリップボードにコピーしました!", "Preferences": "設定",
"Pin": "ピン留め", "Preferences_saved": "設定が保存されました。",
"Pinned_Messages": "ピン留めされたメッセージ", "Privacy_Policy": " プライバシーポリシー",
"pinned": "ピン留めされた", "Private_Channel": "プライベートチャンネル",
"Pinned": "ピン留めされました", "Private": "プライベート",
"Please_enter_your_password": "パスワードを入力してください", "Processing": "処理中...",
"Preferences": "設定", "Profile_saved_successfully": "プロフィールが保存されました!",
"Preferences_saved": "設定が保存されました。", "Profile": "プロフィール",
"Privacy_Policy": " プライバシーポリシー", "Public_Channel": "パブリックチャンネル",
"Private_Channel": "プライベートチャンネル", "Public": "パブリック",
"Private": "プライベート", "Push_Notifications": "プッシュ通知",
"Processing": "処理中...", "Push_Notifications_Alert_Info": "通知はアプリを開いていない時に送られます。",
"Profile_saved_successfully": "プロフィールが保存されました!", "Quote": "引用",
"Profile": "プロフィール", "Reactions_are_disabled": "リアクションは無効化されています",
"Public_Channel": "パブリックチャンネル", "Reactions_are_enabled": "リアクションは有効化されています",
"Public": "パブリック", "Reactions": "リアクション",
"Push_Notifications": "プッシュ通知", "Read_Only_Channel": "読み取り専用チャンネル",
"Push_Notifications_Alert_Info": "通知はアプリを開いていない時に送られます。", "Read_Only": "読み取り専用",
"Quote": "引用", "Read_Receipt": "レシートを見る",
"Reactions_are_disabled": "リアクションは無効化されています", "Receive_Group_Mentions": "グループの通知を受け取る",
"Reactions_are_enabled": "リアクションは有効化されています", "Receive_Group_Mentions_Info": "@all と @here の通知を受け取る",
"Reactions": "リアクション", "Register": "登録",
"Read": "読む", "Repeat_Password": "パスワードを再入力",
"Read_Only_Channel": "読み取り専用チャンネル", "Replied_on": "返信:",
"Read_Only": "読み取り専用", "replies": "返信",
"Read_Receipt": "レシートを見る", "reply": "返信",
"Receive_Group_Mentions": "グループの通知を受け取る", "Reply": "返信",
"Receive_Group_Mentions_Info": "@all と @here の通知を受け取る", "Report": "報告",
"Register": "登録", "Receive_Notification": "通知を受け取る",
"Repeat_Password": "パスワードを再入力", "Receive_notifications_from": "{{name}}からの通知を受け取る",
"Replied_on": "返信:", "Resend": "再送信",
"replies": "返信", "Reset_password": "パスワードをリセット",
"reply": "返信", "resetting_password": "パスワードを再設定",
"Reply": "返信", "RESET": "リセット",
"Report": "報告", "Review_app_title": "アプリにご満足いただけておりますか?",
"Receive_Notification": "通知を受け取る", "Review_app_desc": "{{store}}で5段階で評価をお願いします",
"Receive_notifications_from": "{{name}}からの通知を受け取る", "Review_app_yes": "はい!",
"Resend": "再送信", "Review_app_no": "いいえ",
"Reset_password": "パスワードをリセット", "Review_app_later": "あとで",
"resetting_password": "パスワードを再設定", "Review_app_unable_store": "{{store}}を開けません。",
"RESET": "リセット", "Review_this_app": "アプリをレビューする",
"Review_app_title": "アプリにご満足いただけておりますか?", "Roles": "ロール",
"Review_app_desc": "{{store}}で5段階で評価をお願いします", "Room_actions": "ルームアクション",
"Review_app_yes": "はい!", "Room_changed_announcement": "{{userBy}}がアナウンスを変更しました: {{announcement}}",
"Review_app_no": "いいえ", "Room_changed_description": "{{userBy}}が概要を変更しました: {{description}}",
"Review_app_later": "あとで", "Room_changed_privacy": "{{userBy}}がルームタイプを変更しました。: {{type}}",
"Review_app_unable_store": "{{store}}を開けません。", "Room_changed_topic": "{{userBy}}がトピックを変更しました: {{topic}}",
"Review_this_app": "アプリをレビューする", "Room_Files": "ルームのファイル",
"Roles": "ロール", "Room_Info_Edit": "ルーム情報を編集",
"Room_actions": "ルームアクション", "Room_Info": "ルーム情報",
"Room_changed_announcement": "{{userBy}}がアナウンスを変更しました: {{announcement}}", "Room_Members": "ルームのメンバー",
"Room_changed_description": "{{userBy}}が概要を変更しました: {{description}}", "Room_name_changed": "ルーム名が{{userBy}}により変更されました: {{name}}",
"Room_changed_privacy": "{{userBy}}がルームタイプを変更しました。: {{type}}", "SAVE": "保存",
"Room_changed_topic": "{{userBy}}がトピックを変更しました: {{topic}}", "Save_Changes": "変更を保存",
"Room_Files": "ルームのファイル", "Save": "保存",
"Room_Info_Edit": "ルーム情報を編集", "saving_preferences": "設定を保存中",
"Room_Info": "ルーム情報", "saving_profile": "プロフィールを設定中",
"Room_Members": "ルームのメンバー", "saving_settings": "サーバー設定を保存中",
"Room_name_changed": "ルーム名が{{userBy}}により変更されました: {{name}}", "saved_to_gallery": "ギャラリーに保存しました",
"SAVE": "保存", "Search_Messages": "メッセージを検索",
"Save_Changes": "変更を保存", "Search": "検索",
"Save": "保存", "Search_by": "検索種別: ",
"saving_preferences": "設定を保存中", "Search_global_users": "グローバルユーザーのための検索",
"saving_profile": "プロフィールを設定中", "Search_global_users_description": "有効にした場合、他の会社やサーバーの誰もがあなたを検索可能になります。",
"saving_settings": "サーバー設定を保存中", "Seconds": "{{second}} 秒",
"saved_to_gallery": "ギャラリーに保存しました", "Select_Avatar": "アバターを選択",
"Search_Messages": "メッセージを検索", "Select_Server": "サーバーを選択",
"Search": "検索", "Select_Users": "ユーザーを選択",
"Search_by": "検索種別: ", "Send": "送信",
"Search_global_users": "グローバルユーザーのための検索", "Send_audio_message": "録音メッセージを送信",
"Search_global_users_description": "有効にした場合、他の会社やサーバーの誰もがあなたを検索可能になります。", "Send_crash_report": "クラッシュレポートを送信",
"Seconds": "{{second}} 秒", "Send_message": "メッセージを送信",
"Select_Avatar": "アバターを選択", "Send_to": "送信先...",
"Select_Server": "サーバーを選択", "Sent_an_attachment": "添付ファイルを送信しました",
"Select_Users": "ユーザーを選択", "Server": "サーバー",
"Send": "送信", "Servers": "サーバー",
"Send_audio_message": "録音メッセージを送信", "Server_version": "サーバーバージョン: {{version}}",
"Send_crash_report": "クラッシュレポートを送信", "Set_username_subtitle": "ユーザー名はメッセージ中であなたにメンションするのに使われます。",
"Send_message": "メッセージを送信", "Settings": "設定",
"Send_to": "送信先...", "Settings_succesfully_changed": "設定が更新されました!",
"Sent_an_attachment": "添付ファイルを送信しました", "Share": "シェア",
"Server": "サーバー", "Share_Link": "リンクをシェアする",
"Servers": "サーバー", "Share_this_app": "このアプリをシェアする",
"Server_version": "サーバーバージョン: {{version}}", "Show_more": "Show more..",
"Set_username_subtitle": "ユーザー名はメッセージ中であなたにメンションするのに使われます。", "Show_Unread_Counter": "未読件数を表示する",
"Settings": "設定", "Show_Unread_Counter_Info": "未読件数はリスト上で、チャンネルの右側にバッジで表示されます。",
"Settings_succesfully_changed": "設定が更新されました!", "Sign_in_your_server": "サーバーに接続",
"Share": "シェア", "Sign_Up": "登録",
"Share_Link": "リンクをシェアする", "Some_field_is_invalid_or_empty": "不正、または空の入力欄があります。",
"Share_this_app": "このアプリをシェアする", "Sound": "音",
"Show_more": "Show more..", "Star_room": "お気に入りルーム",
"Show_Unread_Counter": "未読件数を表示する", "Star": "お気に入り",
"Show_Unread_Counter_Info": "未読件数はリスト上で、チャンネルの右側にバッジで表示されます。", "Starred_Messages": "お気に入りされたメッセージ",
"Sign_in_your_server": "サーバーに接続", "starred": "お気に入りされています",
"Sign_Up": "登録", "Starred": "お気に入りされています",
"Some_field_is_invalid_or_empty": "不正、または空の入力欄があります。", "Start_of_conversation": "会話を開始する",
"Sorting_by": "{{key}}順", "Started_discussion": "ディスカッションを開始する:",
"Sound": "音", "Started_call": "{{userBy}}と通話する",
"Star_room": "お気に入りルーム", "Submit": "送信",
"Star": "お気に入り", "Table": "表",
"Starred_Messages": "お気に入りされたメッセージ", "Take_a_photo": "写真を撮影",
"starred": "お気に入りされています", "Take_a_video": "動画を撮影",
"Starred": "お気に入りされています", "tap_to_change_status": "タップしてステータスを変更",
"Start_of_conversation": "会話を開始する", "Tap_to_view_servers_list": "タップしてサーバーリストを見る",
"Started_discussion": "ディスカッションを開始する:", "Terms_of_Service": " 利用規約 ",
"Started_call": "{{userBy}}と通話する", "Theme": "テーマ",
"Submit": "送信", "There_was_an_error_while_action": "{{action}}の最中にエラーが発生しました!",
"Table": "表", "This_room_is_blocked": "このルームはブロックされています。",
"Take_a_photo": "写真を撮影", "This_room_is_read_only": "このルームは読み取り専用です。",
"Take_a_video": "動画を撮影", "Thread": "スレッド",
"tap_to_change_status": "タップしてステータスを変更", "Threads": "スレッド",
"Tap_to_view_servers_list": "タップしてサーバーリストを見る", "Timezone": "タイムゾーン",
"Terms_of_Service": " 利用規約 ", "To": "To",
"Theme": "テーマ", "topic": "トピック",
"There_was_an_error_while_action": "{{action}}の最中にエラーが発生しました!", "Topic": "トピック",
"This_room_is_blocked": "このルームはブロックされています。", "Translate": "翻訳",
"This_room_is_read_only": "このルームは読み取り専用です。", "Try_again": "再度お試しください。",
"Thread": "スレッド", "Two_Factor_Authentication": "2段階認証",
"Threads": "スレッド", "Type_the_channel_name_here": "ここにチャンネル名を入力",
"Timezone": "タイムゾーン", "unarchive": "アーカイブ解除",
"To": "To", "UNARCHIVE": "アーカイブ解除",
"topic": "トピック", "Unblock_user": "ブロックを解除",
"Topic": "トピック", "Unfollowed_thread": "スレッド更新時に通知しない",
"Translate": "翻訳", "Unmute": "ミュート解除",
"Try_again": "再度お試しください。", "unmuted": "ミュート解除しました",
"Two_Factor_Authentication": "2段階認証", "Unpin": "ピン留めを解除",
"Type_the_channel_name_here": "ここにチャンネル名を入力", "unread_messages": "未読",
"unarchive": "アーカイブ解除", "Unread": "未読",
"UNARCHIVE": "アーカイブ解除", "Unread_on_top": "未読メッセージを上に表示",
"Unblock_user": "ブロックを解除", "Unstar": "お気に入り解除",
"Unfavorite": "お気に入り解除", "Updating": "更新中...",
"Unfollowed_thread": "スレッド更新時に通知しない", "Uploading": "アップロード中",
"Unmute": "ミュート解除", "Upload_file_question_mark": "ファイルをアップロードしますか?",
"unmuted": "ミュート解除しました", "Users": "ユーザー",
"Unpin": "ピン留めを解除", "User_added_by": "{{userBy}} が {{userAdded}} を追加しました",
"unread_messages": "未読", "User_Info": "ユーザー情報",
"Unread": "未読", "User_has_been_key": "ユーザーは{{key}}",
"Unread_on_top": "未読メッセージを上に表示", "User_is_no_longer_role_by_": "{{userBy}} は {{user}} のロール {{role}} を削除しました。",
"Unstar": "お気に入り解除", "User_muted_by": "{{userBy}} は {{userMuted}} をミュートしました。",
"Updating": "更新中...", "User_removed_by": "{{userBy}} は {{userRemoved}} を退出させました。",
"Uploading": "アップロード中", "User_sent_an_attachment": "{{user}}は添付ファイルを送信しました",
"Upload_file_question_mark": "ファイルをアップロードしますか?", "User_unmuted_by": "{{userUnmuted}} は {{userBy}} にミュート解除されました。",
"Users": "ユーザー", "User_was_set_role_by_": "{{user}} was set {{role}} by {{userBy}}",
"User_added_by": "{{userBy}} が {{userAdded}} を追加しました", "Username_is_empty": "ユーザー名が空です。",
"User_Info": "ユーザー情報", "Username": "ユーザー名",
"User_has_been_key": "ユーザーは{{key}}", "Username_or_email": "ユーザー名かメールアドレス",
"User_is_no_longer_role_by_": "{{userBy}} は {{user}} のロール {{role}} を削除しました。", "Validating": "検証中",
"User_muted_by": "{{userBy}} は {{userMuted}} をミュートしました。", "Video_call": "ビデオ通話",
"User_removed_by": "{{userBy}} は {{userRemoved}} を退出させました。", "View_Original": "オリジナルを見る",
"User_sent_an_attachment": "{{user}}は添付ファイルを送信しました", "Voice_call": "音声通話",
"User_unmuted_by": "{{userUnmuted}} は {{userBy}} にミュート解除されました。", "Websocket_disabled": "Websocketはこのサーバーでは無効化されています。\n{{contact}}",
"User_was_set_role_by_": "{{user}} was set {{role}} by {{userBy}}", "Welcome": "ようこそ",
"Username_is_empty": "ユーザー名が空です。", "Whats_your_2fa": "2段階認証のコードを入力してください",
"Username": "ユーザー名", "Without_Servers": "サーバーを除く",
"Username_or_email": "ユーザー名かメールアドレス", "Write_External_Permission_Message": "Rocket.Chatは画像を保存するためにギャラリーへのアクセスを求めています。",
"Validating": "検証中", "Write_External_Permission": "ギャラリーへのアクセス許可",
"Video_call": "ビデオ通話", "Yes_action_it": "はい、{{action}}します!",
"View_Original": "オリジナルを見る", "Yesterday": "昨日",
"Voice_call": "音声通話", "You_are_in_preview_mode": "プレビューモードです。",
"Websocket_disabled": "Websocketはこのサーバーでは無効化されています。\n{{contact}}", "You_are_offline": "オフラインです。",
"Welcome": "ようこそ", "You_can_search_using_RegExp_eg": "正規表現を利用できます。 例: `/^text$/i`",
"Whats_your_2fa": "2段階認証のコードを入力してください", "You_colon": "あなた: ",
"Without_Servers": "サーバーを除く", "you_were_mentioned": "あなたがメンションしました",
"Write_External_Permission_Message": "Rocket.Chatは画像を保存するためにギャラリーへのアクセスを求めています。", "you": "あなた",
"Write_External_Permission": "ギャラリーへのアクセス許可", "You": "あなた",
"Yes_action_it": "はい、{{action}}します!", "Logged_out_by_server": "サーバーからログアウトします。もう一度ログインしてください。",
"Yesterday": "昨日", "You_need_to_access_at_least_one_RocketChat_server_to_share_something": "シェアするためには1つ以上のサーバーにアクセスする必要があります。",
"You_are_in_preview_mode": "プレビューモードです。", "Your_certificate": "あなたの認証情報",
"You_are_offline": "オフラインです。", "Your_invite_link_will_expire_after__usesLeft__uses": "招待リンクはあと{{usesLeft}}回で使用できなくなります。",
"You_can_search_using_RegExp_eg": "正規表現を利用できます。 例: `/^text$/i`", "Your_invite_link_will_expire_on__date__or_after__usesLeft__uses": "招待リンクは{{date}}までか、あと{{usesLeft}}回で使用できなくなります。",
"You_colon": "あなた: ", "Your_invite_link_will_expire_on__date__": "招待リンクは{{date}}に使用できなくなります。",
"you_were_mentioned": "あなたがメンションしました", "Your_invite_link_will_never_expire": "招待リンクはずっと有効です。",
"you": "あなた", "Version_no": "バージョン: {{version}}",
"You": "あなた", "You_will_not_be_able_to_recover_this_message": "このメッセージは復元できません!",
"Logged_out_by_server": "サーバーからログアウトします。もう一度ログインしてください。", "Change_Language": "言語を変更",
"You_need_to_access_at_least_one_RocketChat_server_to_share_something": "シェアするためには1つ以上のサーバーにアクセスする必要があります。", "Crash_report_disclaimer": "クラッシュレポートには問題を特定し、修正するために必要な情報のみが含まれます。チャット内のコンテンツは送信されません。",
"Your_certificate": "あなたの認証情報", "Type_message": "メッセージを入力",
"Your_invite_link_will_expire_after__usesLeft__uses": "招待リンクはあと{{usesLeft}}回で使用できなくなります。", "Room_search": "ルームを検索",
"Your_invite_link_will_expire_on__date__or_after__usesLeft__uses": "招待リンクは{{date}}までか、あと{{usesLeft}}回で使用できなくなります。", "Room_selection": "ルームを選択 1...9",
"Your_invite_link_will_expire_on__date__": "招待リンクは{{date}}に使用できなくなります。", "Next_room": "次のルーム",
"Your_invite_link_will_never_expire": "招待リンクはずっと有効です。", "Previous_room": "前のルーム",
"Version_no": "バージョン: {{version}}", "New_room": "新しいルーム",
"You_will_not_be_able_to_recover_this_message": "このメッセージは復元できません!", "Upload_room": "ルームにアップロード",
"Change_Language": "言語を変更", "Search_messages": "メッセージを検索",
"Crash_report_disclaimer": "クラッシュレポートには問題を特定し、修正するために必要な情報のみが含まれます。チャット内のコンテンツは送信されません。", "Scroll_messages": "メッセージをスクロール",
"Type_message": "メッセージを入力", "Reply_latest": "最新のメッセージにリプライ",
"Room_search": "ルームを検索", "Server_selection": "サーバー選択",
"Room_selection": "ルームを選択 1...9", "Server_selection_numbers": "サーバー選択 1...9",
"Next_room": "次のルーム", "Add_server": "サーバーを追加",
"Previous_room": "前のルーム", "New_line": "新しい行",
"New_room": "新しいルーム", "You_will_be_logged_out_of_this_application": "アプリからログアウトします。",
"Upload_room": "ルームにアップロード", "Clear": "クリア",
"Search_messages": "メッセージを検索", "This_will_clear_all_your_offline_data": "オフラインデータをすべて削除します。",
"Scroll_messages": "メッセージをスクロール", "invalid-room": "無効なルーム"
"Reply_latest": "最新のメッセージにリプライ",
"Server_selection": "サーバー選択",
"Server_selection_numbers": "サーバー選択 1...9",
"Add_server": "サーバーを追加",
"New_line": "新しい行",
"You_will_be_logged_out_of_this_application": "アプリからログアウトします。",
"Clear": "クリア",
"This_will_clear_all_your_offline_data": "オフラインデータをすべて削除します。",
"invalid-room": "無効なルーム"
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,12 @@
import React from 'react'; import React from 'react';
import { Animated, Text, View } from 'react-native'; import { Animated, View } from 'react-native';
import { RectButton } from 'react-native-gesture-handler'; import { RectButton } from 'react-native-gesture-handler';
import I18n, { isRTL } from '../../i18n'; import { isRTL } from '../../i18n';
import styles, { ACTION_WIDTH, LONG_SWIPE } from './styles';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { DISPLAY_MODE_CONDENSED } from '../../constants/constantDisplayMode';
import styles, { ACTION_WIDTH, LONG_SWIPE, ROW_HEIGHT_CONDENSED } from './styles';
interface ILeftActions { interface ILeftActions {
theme: string; theme: string;
@ -13,6 +14,7 @@ interface ILeftActions {
isRead: boolean; isRead: boolean;
width: number; width: number;
onToggleReadPress(): void; onToggleReadPress(): void;
displayMode: string;
} }
interface IRightActions { interface IRightActions {
@ -22,11 +24,14 @@ interface IRightActions {
width: number; width: number;
toggleFav(): void; toggleFav(): void;
onHidePress(): void; onHidePress(): void;
displayMode: string;
} }
const reverse = new Animated.Value(isRTL() ? -1 : 1); const reverse = new Animated.Value(isRTL() ? -1 : 1);
const CONDENSED_ICON_SIZE = 24;
const EXPANDED_ICON_SIZE = 28;
export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleReadPress }: ILeftActions) => { export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleReadPress, displayMode }: ILeftActions) => {
const translateX = Animated.multiply( const translateX = Animated.multiply(
transX.interpolate({ transX.interpolate({
inputRange: [0, ACTION_WIDTH], inputRange: [0, ACTION_WIDTH],
@ -34,6 +39,10 @@ export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleR
}), }),
reverse reverse
); );
const isCondensed = displayMode === DISPLAY_MODE_CONDENSED;
const viewHeight = isCondensed ? { height: ROW_HEIGHT_CONDENSED } : null;
return ( return (
<View style={[styles.actionsContainer, styles.actionLeftContainer]} pointerEvents='box-none'> <View style={[styles.actionsContainer, styles.actionLeftContainer]} pointerEvents='box-none'>
<Animated.View <Animated.View
@ -44,14 +53,16 @@ export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleR
width, width,
transform: [{ translateX }], transform: [{ translateX }],
backgroundColor: themes[theme].tintColor backgroundColor: themes[theme].tintColor
} },
viewHeight
]}> ]}>
<View style={styles.actionLeftButtonContainer}> <View style={[styles.actionLeftButtonContainer, viewHeight]}>
<RectButton style={styles.actionButton} onPress={onToggleReadPress}> <RectButton style={styles.actionButton} onPress={onToggleReadPress}>
<> <CustomIcon
<CustomIcon size={20} name={isRead ? 'flag' : 'check'} color='white' /> size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
<Text style={[styles.actionText, { color: themes[theme].buttonText }]}>{I18n.t(isRead ? 'Unread' : 'Read')}</Text> name={isRead ? 'flag' : 'check'}
</> color={themes[theme].buttonText}
/>
</RectButton> </RectButton>
</View> </View>
</Animated.View> </Animated.View>
@ -59,64 +70,64 @@ export const LeftActions = React.memo(({ theme, transX, isRead, width, onToggleR
); );
}); });
export const RightActions = React.memo(({ transX, favorite, width, toggleFav, onHidePress, theme }: IRightActions) => { export const RightActions = React.memo(
const translateXFav = Animated.multiply( ({ transX, favorite, width, toggleFav, onHidePress, theme, displayMode }: IRightActions) => {
transX.interpolate({ const translateXFav = Animated.multiply(
inputRange: [-width / 2, -ACTION_WIDTH * 2, 0], transX.interpolate({
outputRange: [width / 2, width - ACTION_WIDTH * 2, width] inputRange: [-width / 2, -ACTION_WIDTH * 2, 0],
}), outputRange: [width / 2, width - ACTION_WIDTH * 2, width]
reverse }),
); reverse
const translateXHide = Animated.multiply( );
transX.interpolate({ const translateXHide = Animated.multiply(
inputRange: [-width, -LONG_SWIPE, -ACTION_WIDTH * 2, 0], transX.interpolate({
outputRange: [0, width - LONG_SWIPE, width - ACTION_WIDTH, width] inputRange: [-width, -LONG_SWIPE, -ACTION_WIDTH * 2, 0],
}), outputRange: [0, width - LONG_SWIPE, width - ACTION_WIDTH, width]
reverse }),
); reverse
return ( );
<View
style={{ const isCondensed = displayMode === DISPLAY_MODE_CONDENSED;
position: 'absolute', const viewHeight = isCondensed ? { height: ROW_HEIGHT_CONDENSED } : null;
left: 0,
right: 0, return (
height: 75, <View style={[styles.actionsLeftContainer, viewHeight]} pointerEvents='box-none'>
flexDirection: 'row' <Animated.View
}} style={[
pointerEvents='box-none'> styles.actionRightButtonContainer,
<Animated.View {
style={[ width,
styles.actionRightButtonContainer, transform: [{ translateX: translateXFav }],
{ backgroundColor: themes[theme].hideBackground
width, },
transform: [{ translateX: translateXFav }], viewHeight
backgroundColor: themes[theme].hideBackground ]}>
} <RectButton style={[styles.actionButton, { backgroundColor: themes[theme].favoriteBackground }]} onPress={toggleFav}>
]}> <CustomIcon
<RectButton style={[styles.actionButton, { backgroundColor: themes[theme].favoriteBackground }]} onPress={toggleFav}> size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
<> name={favorite ? 'star-filled' : 'star'}
<CustomIcon size={20} name={favorite ? 'star-filled' : 'star'} color={themes[theme].buttonText} /> color={themes[theme].buttonText}
<Text style={[styles.actionText, { color: themes[theme].buttonText }]}> />
{I18n.t(favorite ? 'Unfavorite' : 'Favorite')} </RectButton>
</Text> </Animated.View>
</> <Animated.View
</RectButton> style={[
</Animated.View> styles.actionRightButtonContainer,
<Animated.View {
style={[ width,
styles.actionRightButtonContainer, transform: [{ translateX: translateXHide }]
{ },
width, isCondensed && { height: ROW_HEIGHT_CONDENSED }
transform: [{ translateX: translateXHide }] ]}>
} <RectButton style={[styles.actionButton, { backgroundColor: themes[theme].hideBackground }]} onPress={onHidePress}>
]}> <CustomIcon
<RectButton style={[styles.actionButton, { backgroundColor: themes[theme].hideBackground }]} onPress={onHidePress}> size={isCondensed ? CONDENSED_ICON_SIZE : EXPANDED_ICON_SIZE}
<> name='unread-on-top-disabled'
<CustomIcon size={20} name='unread-on-top-disabled' color={themes[theme].buttonText} /> color={themes[theme].buttonText}
<Text style={[styles.actionText, { color: themes[theme].buttonText }]}>{I18n.t('Hide')}</Text> />
</> </RectButton>
</RectButton> </Animated.View>
</Animated.View> </View>
</View> );
); }
}); );

View File

@ -0,0 +1,63 @@
import React from 'react';
import { View } from 'react-native';
import PropTypes from 'prop-types';
import Avatar from '../../containers/Avatar';
import { DISPLAY_MODE_CONDENSED, DISPLAY_MODE_EXPANDED } from '../../constants/constantDisplayMode';
import TypeIcon from './TypeIcon';
import styles from './styles';
const IconOrAvatar = ({
avatar,
type,
rid,
showAvatar,
prid,
status,
isGroupChat,
teamMain,
showLastMessage,
theme,
displayMode
}) => {
if (showAvatar) {
return (
<Avatar text={avatar} size={displayMode === DISPLAY_MODE_CONDENSED ? 36 : 48} type={type} style={styles.avatar} rid={rid} />
);
}
if (displayMode === DISPLAY_MODE_EXPANDED && showLastMessage) {
return (
<View style={styles.typeIcon}>
<TypeIcon
type={type}
prid={prid}
status={status}
isGroupChat={isGroupChat}
theme={theme}
teamMain={teamMain}
size={24}
style={{ marginRight: 12 }}
/>
</View>
);
}
return null;
};
IconOrAvatar.propTypes = {
avatar: PropTypes.string,
type: PropTypes.string,
theme: PropTypes.string,
rid: PropTypes.string,
showAvatar: PropTypes.bool,
displayMode: PropTypes.string,
prid: PropTypes.string,
status: PropTypes.string,
isGroupChat: PropTypes.bool,
teamMain: PropTypes.bool,
showLastMessage: PropTypes.bool
};
export default IconOrAvatar;

View File

@ -80,6 +80,7 @@ const LastMessage = React.memo(
numberOfLines={2} numberOfLines={2}
preview preview
theme={theme} theme={theme}
testID='room-item-last-message'
/> />
), ),
arePropsEqual arePropsEqual

View File

@ -11,6 +11,7 @@ import UpdatedAt from './UpdatedAt';
import Touchable from './Touchable'; import Touchable from './Touchable';
import Tag from './Tag'; import Tag from './Tag';
import I18n from '../../i18n'; import I18n from '../../i18n';
import { DISPLAY_MODE_EXPANDED } from '../../constants/constantDisplayMode';
interface IRoomItem { interface IRoomItem {
rid: string; rid: string;
@ -57,6 +58,8 @@ interface IRoomItem {
hideChannel(): void; hideChannel(): void;
autoJoin: boolean; autoJoin: boolean;
size?: number; size?: number;
showAvatar: boolean;
displayMode: string;
} }
const RoomItem = ({ const RoomItem = ({
@ -95,7 +98,9 @@ const RoomItem = ({
toggleRead, toggleRead,
hideChannel, hideChannel,
teamMain, teamMain,
autoJoin autoJoin,
showAvatar,
displayMode
}: IRoomItem) => ( }: IRoomItem) => (
<Touchable <Touchable
onPress={onPress} onPress={onPress}
@ -111,12 +116,28 @@ const RoomItem = ({
type={type} type={type}
theme={theme} theme={theme}
isFocused={isFocused} isFocused={isFocused}
swipeEnabled={swipeEnabled}> swipeEnabled={swipeEnabled}
<Wrapper accessibilityLabel={accessibilityLabel} avatar={avatar} avatarSize={avatarSize} type={type} theme={theme} rid={rid}> displayMode={displayMode}>
{showLastMessage ? ( <Wrapper
accessibilityLabel={accessibilityLabel}
avatar={avatar}
avatarSize={avatarSize}
type={type}
theme={theme}
rid={rid}
prid={prid}
status={status}
isGroupChat={isGroupChat}
teamMain={teamMain}
displayMode={displayMode}
showAvatar={showAvatar}
showLastMessage={showLastMessage}>
{showLastMessage && displayMode === DISPLAY_MODE_EXPANDED ? (
<> <>
<View style={styles.titleContainer}> <View style={styles.titleContainer}>
<TypeIcon type={type} prid={prid} status={status} isGroupChat={isGroupChat} theme={theme} teamMain={teamMain} /> {showAvatar ? (
<TypeIcon type={type} prid={prid} status={status} isGroupChat={isGroupChat} theme={theme} teamMain={teamMain} />
) : null}
<Title name={name} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} /> <Title name={name} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
{autoJoin ? <Tag testID='auto-join-tag' name={I18n.t('Auto-join')} /> : null} {autoJoin ? <Tag testID='auto-join-tag' name={I18n.t('Auto-join')} /> : null}
<UpdatedAt date={date} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} /> <UpdatedAt date={date} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
@ -143,17 +164,29 @@ const RoomItem = ({
</> </>
) : ( ) : (
<View style={[styles.titleContainer, styles.flex]}> <View style={[styles.titleContainer, styles.flex]}>
<TypeIcon type={type} prid={prid} status={status} isGroupChat={isGroupChat} theme={theme} teamMain={teamMain} /> <TypeIcon
type={type}
prid={prid}
status={status}
isGroupChat={isGroupChat}
theme={theme}
teamMain={teamMain}
size={22}
style={{ marginRight: 8 }}
/>
<Title name={name} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} /> <Title name={name} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
{autoJoin ? <Tag name={I18n.t('Auto-join')} /> : null} {autoJoin ? <Tag name={I18n.t('Auto-join')} /> : null}
<UnreadBadge <View style={styles.wrapUpdatedAndBadge}>
unread={unread} <UpdatedAt date={date} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
userMentions={userMentions} <UnreadBadge
groupMentions={groupMentions} unread={unread}
tunread={tunread} userMentions={userMentions}
tunreadUser={tunreadUser} groupMentions={groupMentions}
tunreadGroup={tunreadGroup} tunread={tunread}
/> tunreadUser={tunreadUser}
tunreadGroup={tunreadGroup}
/>
</View>
</View> </View>
)} )}
</Wrapper> </Wrapper>

View File

@ -24,6 +24,7 @@ interface ITouchableProps {
theme: string; theme: string;
isFocused: boolean; isFocused: boolean;
swipeEnabled: boolean; swipeEnabled: boolean;
displayMode: string;
} }
class Touchable extends React.Component<ITouchableProps, any> { class Touchable extends React.Component<ITouchableProps, any> {
@ -227,7 +228,7 @@ class Touchable extends React.Component<ITouchableProps, any> {
}; };
render() { render() {
const { testID, isRead, width, favorite, children, theme, isFocused, swipeEnabled } = this.props; const { testID, isRead, width, favorite, children, theme, isFocused, swipeEnabled, displayMode } = this.props;
return ( return (
<LongPressGestureHandler onHandlerStateChange={this.onLongPressHandlerStateChange}> <LongPressGestureHandler onHandlerStateChange={this.onLongPressHandlerStateChange}>
@ -244,6 +245,7 @@ class Touchable extends React.Component<ITouchableProps, any> {
width={width} width={width}
onToggleReadPress={this.onToggleReadPress} onToggleReadPress={this.onToggleReadPress}
theme={theme} theme={theme}
displayMode={displayMode}
/> />
<RightActions <RightActions
transX={this.transXReverse} transX={this.transXReverse}
@ -252,6 +254,7 @@ class Touchable extends React.Component<ITouchableProps, any> {
toggleFav={this.toggleFav} toggleFav={this.toggleFav}
onHidePress={this.onHidePress} onHidePress={this.onHidePress}
theme={theme} theme={theme}
displayMode={displayMode}
/> />
<Animated.View <Animated.View
style={{ style={{

View File

@ -9,10 +9,19 @@ interface ITypeIcon {
isGroupChat: boolean; isGroupChat: boolean;
teamMain: boolean; teamMain: boolean;
theme?: string; theme?: string;
size?: number;
style?: object;
} }
const TypeIcon = React.memo(({ type, prid, status, isGroupChat, teamMain }: ITypeIcon) => ( const TypeIcon = React.memo(({ type, prid, status, isGroupChat, teamMain, size, style }: ITypeIcon) => (
<RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} /> <RoomTypeIcon
type={prid ? 'discussion' : type}
isGroupChat={isGroupChat}
status={status}
teamMain={teamMain}
size={size}
style={style}
/>
)); ));
export default TypeIcon; export default TypeIcon;

View File

@ -1,9 +1,10 @@
import React from 'react'; import React from 'react';
import { View } from 'react-native'; import { View } from 'react-native';
import styles from './styles';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import Avatar from '../../containers/Avatar'; import { DISPLAY_MODE_CONDENSED } from '../../constants/constantDisplayMode';
import IconOrAvatar from './IconOrAvatar';
import styles from './styles';
interface IWrapper { interface IWrapper {
accessibilityLabel: string; accessibilityLabel: string;
@ -13,17 +14,27 @@ interface IWrapper {
theme: string; theme: string;
rid: string; rid: string;
children: JSX.Element; children: JSX.Element;
displayMode: string;
prid: string;
showLastMessage: boolean;
status: string;
isGroupChat: boolean;
teamMain: boolean;
showAvatar: boolean;
} }
const Wrapper = ({ accessibilityLabel, avatar, avatarSize, type, theme, rid, children }: IWrapper) => ( const Wrapper = ({ accessibilityLabel, theme, children, displayMode, ...props }: IWrapper) => (
<View style={styles.container} accessibilityLabel={accessibilityLabel}> <View
<Avatar text={avatar} size={avatarSize} type={type} style={styles.avatar} rid={rid} /> style={[styles.container, displayMode === DISPLAY_MODE_CONDENSED && styles.containerCondensed]}
accessibilityLabel={accessibilityLabel}>
<IconOrAvatar theme={theme} displayMode={displayMode} {...props} />
<View <View
style={[ style={[
styles.centerContainer, styles.centerContainer,
{ {
borderColor: themes[theme].separatorColor borderColor: themes[theme].separatorColor
} },
displayMode === DISPLAY_MODE_CONDENSED && styles.condensedPaddingVertical
]}> ]}>
{children} {children}
</View> </View>

View File

@ -2,12 +2,11 @@ import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import I18n from '../../i18n'; import I18n from '../../i18n';
import { ROW_HEIGHT } from './styles'; import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
import { formatDate } from '../../utils/room'; import { formatDate } from '../../utils/room';
import RoomItem from './RoomItem'; import RoomItem from './RoomItem';
export { ROW_HEIGHT }; export { ROW_HEIGHT, ROW_HEIGHT_CONDENSED };
interface IRoomItemContainerProps { interface IRoomItemContainerProps {
item: any; item: any;
showLastMessage: boolean; showLastMessage: boolean;
@ -32,9 +31,22 @@ interface IRoomItemContainerProps {
getIsRead: Function; getIsRead: Function;
swipeEnabled: boolean; swipeEnabled: boolean;
autoJoin: boolean; autoJoin: boolean;
showAvatar: boolean;
displayMode: string;
} }
const attrs = ['width', 'status', 'connected', 'theme', 'isFocused', 'forceUpdate', 'showLastMessage', 'autoJoin']; const attrs = [
'width',
'status',
'connected',
'theme',
'isFocused',
'forceUpdate',
'showLastMessage',
'autoJoin',
'showAvatar',
'displayMode'
];
class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> { class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
private mounted: boolean; private mounted: boolean;
@ -137,7 +149,9 @@ class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
username, username,
useRealName, useRealName,
swipeEnabled, swipeEnabled,
autoJoin autoJoin,
showAvatar,
displayMode
} = this.props; } = this.props;
const name = getRoomTitle(item); const name = getRoomTitle(item);
const testID = `rooms-list-view-item-${name}`; const testID = `rooms-list-view-item-${name}`;
@ -200,6 +214,8 @@ class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
swipeEnabled={swipeEnabled} swipeEnabled={swipeEnabled}
teamMain={item.teamMain} teamMain={item.teamMain}
autoJoin={autoJoin} autoJoin={autoJoin}
showAvatar={showAvatar}
displayMode={displayMode}
/> />
); );
} }

View File

@ -3,6 +3,7 @@ import { PixelRatio, StyleSheet } from 'react-native';
import sharedStyles from '../../views/Styles'; import sharedStyles from '../../views/Styles';
export const ROW_HEIGHT = 75 * PixelRatio.getFontScale(); export const ROW_HEIGHT = 75 * PixelRatio.getFontScale();
export const ROW_HEIGHT_CONDENSED = 60 * PixelRatio.getFontScale();
export const ACTION_WIDTH = 80; export const ACTION_WIDTH = 80;
export const SMALL_SWIPE = ACTION_WIDTH / 2; export const SMALL_SWIPE = ACTION_WIDTH / 2;
export const LONG_SWIPE = ACTION_WIDTH * 3; export const LONG_SWIPE = ACTION_WIDTH * 3;
@ -17,6 +18,12 @@ export default StyleSheet.create<any>({
paddingLeft: 14, paddingLeft: 14,
height: ROW_HEIGHT height: ROW_HEIGHT
}, },
containerCondensed: {
height: ROW_HEIGHT_CONDENSED
},
condensedPaddingVertical: {
paddingVertical: 20
},
centerContainer: { centerContainer: {
flex: 1, flex: 1,
paddingVertical: 10, paddingVertical: 10,
@ -37,6 +44,9 @@ export default StyleSheet.create<any>({
flexDirection: 'row', flexDirection: 'row',
alignItems: 'flex-start' alignItems: 'flex-start'
}, },
wrapUpdatedAndBadge: {
alignItems: 'flex-end'
},
titleContainer: { titleContainer: {
width: '100%', width: '100%',
flexDirection: 'row', flexDirection: 'row',
@ -72,11 +82,12 @@ export default StyleSheet.create<any>({
right: 0, right: 0,
height: ROW_HEIGHT height: ROW_HEIGHT
}, },
actionText: { actionsLeftContainer: {
fontSize: 15, flexDirection: 'row',
justifyContent: 'center', position: 'absolute',
marginTop: 4, left: 0,
...sharedStyles.textSemibold right: 0,
height: ROW_HEIGHT
}, },
actionLeftButtonContainer: { actionLeftButtonContainer: {
position: 'absolute', position: 'absolute',
@ -107,5 +118,9 @@ export default StyleSheet.create<any>({
fontSize: 13, fontSize: 13,
paddingHorizontal: 4, paddingHorizontal: 4,
...sharedStyles.textSemibold ...sharedStyles.textSemibold
},
typeIcon: {
height: ROW_HEIGHT,
justifyContent: 'center'
} }
}); });

View File

@ -8,7 +8,6 @@ const initialState = {
searchText: '', searchText: '',
showServerDropdown: false, showServerDropdown: false,
closeServerDropdown: false, closeServerDropdown: false,
showSortDropdown: false,
showSearchHeader: false showSearchHeader: false
}; };
@ -56,16 +55,6 @@ export default function login(state = initialState, action) {
...state, ...state,
showServerDropdown: !state.showServerDropdown showServerDropdown: !state.showServerDropdown
}; };
case types.ROOMS.CLOSE_SORT_DROPDOWN:
return {
...state,
closeSortDropdown: !state.closeSortDropdown
};
case types.ROOMS.TOGGLE_SORT_DROPDOWN:
return {
...state,
showSortDropdown: !state.showSortDropdown
};
case types.ROOMS.OPEN_SEARCH_HEADER: case types.ROOMS.OPEN_SEARCH_HEADER:
return { return {
...state, ...state,

View File

@ -1,10 +1,13 @@
import { SORT_PREFERENCES } from '../actions/actionsTypes'; import { SORT_PREFERENCES } from '../actions/actionsTypes';
import { DISPLAY_MODE_EXPANDED } from '../constants/constantDisplayMode';
const initialState = { const initialState = {
sortBy: 'activity', sortBy: 'activity',
groupByType: false, groupByType: false,
showFavorites: false, showFavorites: false,
showUnread: false showUnread: false,
showAvatar: true,
displayMode: DISPLAY_MODE_EXPANDED
}; };
export default (state = initialState, action) => { export default (state = initialState, action) => {

View File

@ -38,6 +38,9 @@ import ProfileView from '../views/ProfileView';
import UserPreferencesView from '../views/UserPreferencesView'; import UserPreferencesView from '../views/UserPreferencesView';
import UserNotificationPrefView from '../views/UserNotificationPreferencesView'; import UserNotificationPrefView from '../views/UserNotificationPreferencesView';
// Display Preferences View
import DisplayPrefsView from '../views/DisplayPrefsView';
// Settings Stack // Settings Stack
import SettingsView from '../views/SettingsView'; import SettingsView from '../views/SettingsView';
import SecurityPrivacyView from '../views/SecurityPrivacyView'; import SecurityPrivacyView from '../views/SecurityPrivacyView';
@ -222,6 +225,18 @@ const AdminPanelStackNavigator = () => {
); );
}; };
// DisplayPreferenceNavigator
const DisplayPrefStack = createStackNavigator();
const DisplayPrefStackNavigator = () => {
const { theme } = React.useContext(ThemeContext);
return (
<DisplayPrefStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
<DisplayPrefStack.Screen name='DisplayPrefsView' component={DisplayPrefsView} />
</DisplayPrefStack.Navigator>
);
};
// DrawerNavigator // DrawerNavigator
const Drawer = createDrawerNavigator(); const Drawer = createDrawerNavigator();
const DrawerNavigator = () => { const DrawerNavigator = () => {
@ -238,6 +253,7 @@ const DrawerNavigator = () => {
<Drawer.Screen name='ProfileStackNavigator' component={ProfileStackNavigator} /> <Drawer.Screen name='ProfileStackNavigator' component={ProfileStackNavigator} />
<Drawer.Screen name='SettingsStackNavigator' component={SettingsStackNavigator} /> <Drawer.Screen name='SettingsStackNavigator' component={SettingsStackNavigator} />
<Drawer.Screen name='AdminPanelStackNavigator' component={AdminPanelStackNavigator} /> <Drawer.Screen name='AdminPanelStackNavigator' component={AdminPanelStackNavigator} />
<Drawer.Screen name='DisplayPrefStackNavigator' component={DisplayPrefStackNavigator} />
</Drawer.Navigator> </Drawer.Navigator>
); );
}; };

View File

@ -33,6 +33,7 @@ import TeamChannelsView from '../../views/TeamChannelsView';
import MarkdownTableView from '../../views/MarkdownTableView'; import MarkdownTableView from '../../views/MarkdownTableView';
import ReadReceiptsView from '../../views/ReadReceiptView'; import ReadReceiptsView from '../../views/ReadReceiptView';
import ProfileView from '../../views/ProfileView'; import ProfileView from '../../views/ProfileView';
import DisplayPrefsView from '../../views/DisplayPrefsView';
import SettingsView from '../../views/SettingsView'; import SettingsView from '../../views/SettingsView';
import LanguageView from '../../views/LanguageView'; import LanguageView from '../../views/LanguageView';
import ThemeView from '../../views/ThemeView'; import ThemeView from '../../views/ThemeView';
@ -206,6 +207,7 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
component={ProfileView} component={ProfileView}
options={props => ProfileView.navigationOptions({ ...props, isMasterDetail: true })} options={props => ProfileView.navigationOptions({ ...props, isMasterDetail: true })}
/> />
<ModalStack.Screen name='DisplayPrefsView' component={DisplayPrefsView} />
<ModalStack.Screen <ModalStack.Screen
name='AdminPanelView' name='AdminPanelView'
component={AdminPanelView} component={AdminPanelView}

View File

@ -66,15 +66,18 @@ export default {
RL_TOGGLE_READ_F: 'rl_toggle_read_f', RL_TOGGLE_READ_F: 'rl_toggle_read_f',
RL_HIDE_CHANNEL: 'rl_hide_channel', RL_HIDE_CHANNEL: 'rl_hide_channel',
RL_HIDE_CHANNEL_F: 'rl_hide_channel_f', RL_HIDE_CHANNEL_F: 'rl_hide_channel_f',
RL_TOGGLE_SORT_DROPDOWN: 'rl_toggle_sort_dropdown',
RL_SORT_CHANNELS_BY_NAME: 'rl_sort_channels_by_name',
RL_SORT_CHANNELS_BY_ACTIVITY: 'rl_sort_channels_by_activity',
RL_SORT_CHANNELS_F: 'rl_sort_channels_f',
RL_GROUP_CHANNELS_BY_TYPE: 'rl_group_channels_by_type',
RL_GROUP_CHANNELS_BY_FAVORITE: 'rl_group_channels_by_favorite',
RL_GROUP_CHANNELS_BY_UNREAD: 'rl_group_channels_by_unread',
RL_CREATE_NEW_WORKSPACE: 'rl_create_new_workspace', RL_CREATE_NEW_WORKSPACE: 'rl_create_new_workspace',
// DISPLAY PREFERENCES VIEW
DP_SORT_CHANNELS_BY_NAME: 'dp_sort_channels_by_name',
DP_SORT_CHANNELS_BY_ACTIVITY: 'dp_sort_channels_by_activity',
DP_GROUP_CHANNELS_BY_TYPE: 'dp_group_channels_by_type',
DP_GROUP_CHANNELS_BY_FAVORITE: 'dp_group_channels_by_favorite',
DP_GROUP_CHANNELS_BY_UNREAD: 'dp_group_channels_by_unread',
DP_TOGGLE_AVATAR: 'dp_toggle_avatar',
DP_DISPLAY_EXPANDED: 'dp_display_expanded',
DP_DISPLAY_CONDENSED: 'dp_display_condensed',
// QUEUE LIST VIEW // QUEUE LIST VIEW
QL_GO_ROOM: 'ql_go_room', QL_GO_ROOM: 'ql_go_room',

View File

@ -0,0 +1,192 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { Switch } from 'react-native';
import { RadioButton } from 'react-native-ui-lib';
import { useDispatch, useSelector } from 'react-redux';
import { setPreference } from '../actions/sortPreferences';
import RocketChat from '../lib/rocketchat';
import StatusBar from '../containers/StatusBar';
import I18n from '../i18n';
import * as List from '../containers/List';
import { useTheme } from '../theme';
import { themes } from '../constants/colors';
import * as HeaderButton from '../containers/HeaderButton';
import SafeAreaView from '../containers/SafeAreaView';
import { ICON_SIZE } from '../containers/List/constants';
import log, { events, logEvent } from '../utils/log';
import { DISPLAY_MODE_CONDENSED, DISPLAY_MODE_EXPANDED } from '../constants/constantDisplayMode';
const DisplayPrefsView = props => {
const { theme } = useTheme();
const { sortBy, groupByType, showFavorites, showUnread, showAvatar, displayMode } = useSelector(state => state.sortPreferences);
const dispatch = useDispatch();
useEffect(() => {
const { navigation, isMasterDetail } = props;
navigation.setOptions({
title: I18n.t('Display'),
headerLeft: () =>
isMasterDetail ? (
<HeaderButton.CloseModal navigation={navigation} testID='display-view-close' />
) : (
<HeaderButton.Drawer navigation={navigation} testID='display-view-drawer' />
)
});
}, []);
const setSortPreference = async param => {
try {
dispatch(setPreference(param));
await RocketChat.saveSortPreference(param);
} catch (e) {
log(e);
}
};
const sortByName = async () => {
logEvent(events.DP_SORT_CHANNELS_BY_NAME);
await setSortPreference({ sortBy: 'alphabetical' });
};
const sortByActivity = async () => {
logEvent(events.DP_SORT_CHANNELS_BY_ACTIVITY);
await setSortPreference({ sortBy: 'activity' });
};
const toggleGroupByType = async () => {
logEvent(events.DP_GROUP_CHANNELS_BY_TYPE);
await setSortPreference({ groupByType: !groupByType });
};
const toggleGroupByFavorites = async () => {
logEvent(events.DP_GROUP_CHANNELS_BY_FAVORITE);
await setSortPreference({ showFavorites: !showFavorites });
};
const toggleUnread = async () => {
logEvent(events.DP_GROUP_CHANNELS_BY_UNREAD);
await setSortPreference({ showUnread: !showUnread });
};
const toggleAvatar = async () => {
logEvent(events.DP_TOGGLE_AVATAR);
await setSortPreference({ showAvatar: !showAvatar });
};
const displayExpanded = async () => {
logEvent(events.DP_DISPLAY_EXPANDED);
await setSortPreference({ displayMode: DISPLAY_MODE_EXPANDED });
};
const displayCondensed = async () => {
logEvent(events.DP_DISPLAY_CONDENSED);
await setSortPreference({ displayMode: DISPLAY_MODE_CONDENSED });
};
const renderCheckBox = value => (
<List.Icon name={value ? 'checkbox-checked' : 'checkbox-unchecked'} color={value ? themes[theme].actionTintColor : null} />
);
const renderAvatarSwitch = value => (
<Switch value={value} onValueChange={() => toggleAvatar()} testID='display-pref-view-avatar-switch' />
);
const renderRadio = value => (
<RadioButton
selected={!!value}
color={value ? themes[theme].actionTintColor : themes[theme].auxiliaryText}
size={ICON_SIZE}
/>
);
return (
<SafeAreaView>
<StatusBar />
<List.Container testID='display-view-list'>
<List.Section title='Display'>
<List.Separator />
<List.Item
left={() => <List.Icon name='view-extended' />}
title='Expanded'
testID='display-pref-view-expanded'
right={() => renderRadio(displayMode === DISPLAY_MODE_EXPANDED)}
onPress={displayExpanded}
/>
<List.Separator />
<List.Item
left={() => <List.Icon name='view-medium' />}
title='Condensed'
testID='display-pref-view-condensed'
right={() => renderRadio(displayMode === DISPLAY_MODE_CONDENSED)}
onPress={displayCondensed}
/>
<List.Separator />
<List.Item
left={() => <List.Icon name='avatar' />}
title='Avatars'
testID='display-pref-view-avatars'
right={() => renderAvatarSwitch(showAvatar)}
/>
<List.Separator />
</List.Section>
<List.Section title='Sort_by'>
<List.Separator />
<List.Item
title='Activity'
testID='display-pref-view-activity'
left={() => <List.Icon name='clock' />}
onPress={sortByActivity}
right={() => renderRadio(sortBy === 'activity')}
/>
<List.Separator />
<List.Item
title='Name'
testID='display-pref-view-name'
left={() => <List.Icon name='sort-az' />}
onPress={sortByName}
right={() => renderRadio(sortBy === 'alphabetical')}
/>
<List.Separator />
</List.Section>
<List.Section title='Group_by'>
<List.Separator />
<List.Item
title='Unread_on_top'
testID='display-pref-view-unread'
left={() => <List.Icon name='flag' />}
onPress={toggleUnread}
right={() => renderCheckBox(showUnread)}
/>
<List.Separator />
<List.Item
title='Favorites'
testID='display-pref-view-favorites'
left={() => <List.Icon name='star' />}
onPress={toggleGroupByFavorites}
right={() => renderCheckBox(showFavorites)}
/>
<List.Separator />
<List.Item
title='Types'
testID='display-pref-view-types'
left={() => <List.Icon name='group-by-type' />}
onPress={toggleGroupByType}
right={() => renderCheckBox(groupByType)}
/>
<List.Separator />
</List.Section>
</List.Container>
</SafeAreaView>
);
};
DisplayPrefsView.propTypes = {
navigation: PropTypes.object,
isMasterDetail: PropTypes.bool
};
export default DisplayPrefsView;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { StackNavigationOptions } from '@react-navigation/stack';
import I18n from '../i18n'; import I18n from '../i18n';
import StatusBar from '../containers/StatusBar'; import StatusBar from '../containers/StatusBar';
@ -9,13 +9,17 @@ import { withTheme } from '../theme';
import SafeAreaView from '../containers/SafeAreaView'; import SafeAreaView from '../containers/SafeAreaView';
import * as List from '../containers/List'; import * as List from '../containers/List';
class LegalView extends React.Component { interface ILegalView {
static propTypes = { server: string;
server: PropTypes.string, theme: string;
theme: PropTypes.string }
class LegalView extends React.Component<ILegalView, any> {
static navigationOptions: StackNavigationOptions = {
title: I18n.t('Legal')
}; };
onPressItem = ({ route }) => { onPressItem = ({ route }: { route: string }) => {
const { server, theme } = this.props; const { server, theme } = this.props;
if (!server) { if (!server) {
return; return;
@ -51,12 +55,8 @@ class LegalView extends React.Component {
} }
} }
const mapStateToProps = state => ({ const mapStateToProps = (state: any) => ({
server: state.server.server server: state.server.server
}); });
LegalView.navigationOptions = {
title: I18n.t('Legal')
};
export default connect(mapStateToProps)(withTheme(LegalView)); export default connect(mapStateToProps)(withTheme(LegalView));

View File

@ -2,12 +2,7 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import { toggleServerDropdown, closeServerDropdown, setSearch as setSearchAction } from '../../../actions/rooms';
closeServerDropdown,
closeSortDropdown,
setSearch as setSearchAction,
toggleServerDropdown
} from '../../../actions/rooms';
import { withTheme } from '../../../theme'; import { withTheme } from '../../../theme';
import EventEmitter from '../../../utils/events'; import EventEmitter from '../../../utils/events';
import { KEY_COMMAND, handleCommandOpenServerDropdown } from '../../../commands'; import { KEY_COMMAND, handleCommandOpenServerDropdown } from '../../../commands';
@ -18,7 +13,6 @@ import Header from './Header';
class RoomsListHeaderView extends PureComponent { class RoomsListHeaderView extends PureComponent {
static propTypes = { static propTypes = {
showServerDropdown: PropTypes.bool, showServerDropdown: PropTypes.bool,
showSortDropdown: PropTypes.bool,
showSearchHeader: PropTypes.bool, showSearchHeader: PropTypes.bool,
serverName: PropTypes.string, serverName: PropTypes.string,
connecting: PropTypes.bool, connecting: PropTypes.bool,
@ -28,7 +22,6 @@ class RoomsListHeaderView extends PureComponent {
server: PropTypes.string, server: PropTypes.string,
open: PropTypes.func, open: PropTypes.func,
close: PropTypes.func, close: PropTypes.func,
closeSort: PropTypes.func,
setSearch: PropTypes.func setSearch: PropTypes.func
}; };
@ -58,14 +51,9 @@ class RoomsListHeaderView extends PureComponent {
onPress = () => { onPress = () => {
logEvent(events.RL_TOGGLE_SERVER_DROPDOWN); logEvent(events.RL_TOGGLE_SERVER_DROPDOWN);
const { showServerDropdown, showSortDropdown, close, open, closeSort } = this.props; const { showServerDropdown, close, open } = this.props;
if (showServerDropdown) { if (showServerDropdown) {
close(); close();
} else if (showSortDropdown) {
closeSort();
setTimeout(() => {
open();
}, 300);
} else { } else {
open(); open();
} }
@ -93,7 +81,6 @@ class RoomsListHeaderView extends PureComponent {
const mapStateToProps = state => ({ const mapStateToProps = state => ({
showServerDropdown: state.rooms.showServerDropdown, showServerDropdown: state.rooms.showServerDropdown,
showSortDropdown: state.rooms.showSortDropdown,
showSearchHeader: state.rooms.showSearchHeader, showSearchHeader: state.rooms.showSearchHeader,
connecting: state.meteor.connecting || state.server.loading, connecting: state.meteor.connecting || state.server.loading,
connected: state.meteor.connected, connected: state.meteor.connected,
@ -105,7 +92,6 @@ const mapStateToProps = state => ({
const mapDispatchtoProps = dispatch => ({ const mapDispatchtoProps = dispatch => ({
close: () => dispatch(closeServerDropdown()), close: () => dispatch(closeServerDropdown()),
open: () => dispatch(toggleServerDropdown()), open: () => dispatch(toggleServerDropdown()),
closeSort: () => dispatch(closeSortDropdown()),
setSearch: searchText => dispatch(setSearchAction(searchText)) setSearch: searchText => dispatch(setSearchAction(searchText))
}); });

View File

@ -2,16 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { withTheme } from '../../../theme'; import { withTheme } from '../../../theme';
import I18n from '../../../i18n';
import * as List from '../../../containers/List'; import * as List from '../../../containers/List';
import { E2E_BANNER_TYPE } from '../../../lib/encryption/constants'; import { E2E_BANNER_TYPE } from '../../../lib/encryption/constants';
import { themes } from '../../../constants/colors'; import { themes } from '../../../constants/colors';
import OmnichannelStatus from '../../../ee/omnichannel/containers/OmnichannelStatus'; import OmnichannelStatus from '../../../ee/omnichannel/containers/OmnichannelStatus';
const ListHeader = React.memo( const ListHeader = React.memo(
({ searching, sortBy, toggleSort, goEncryption, goQueue, queueSize, inquiryEnabled, encryptionBanner, user, theme }) => { ({ searching, goEncryption, goQueue, queueSize, inquiryEnabled, encryptionBanner, user, theme }) => {
const sortTitle = I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') });
if (searching) { if (searching) {
return null; return null;
} }
@ -36,13 +33,6 @@ const ListHeader = React.memo(
<List.Separator /> <List.Separator />
</> </>
) : null} ) : null}
<List.Item
title={sortTitle}
left={() => <List.Icon name='sort' />}
color={themes[theme].auxiliaryText}
onPress={toggleSort}
translateTitle={false}
/>
<List.Separator /> <List.Separator />
<OmnichannelStatus <OmnichannelStatus
searching={searching} searching={searching}
@ -58,8 +48,6 @@ const ListHeader = React.memo(
ListHeader.propTypes = { ListHeader.propTypes = {
searching: PropTypes.bool, searching: PropTypes.bool,
sortBy: PropTypes.string,
toggleSort: PropTypes.func,
goEncryption: PropTypes.func, goEncryption: PropTypes.func,
goQueue: PropTypes.func, goQueue: PropTypes.func,
queueSize: PropTypes.number, queueSize: PropTypes.number,

View File

@ -1,207 +0,0 @@
import React, { PureComponent } from 'react';
import { Animated, Easing, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withSafeAreaInsets } from 'react-native-safe-area-context';
import styles from '../styles';
import * as List from '../../../containers/List';
import RocketChat from '../../../lib/rocketchat';
import { setPreference } from '../../../actions/sortPreferences';
import log, { events, logEvent } from '../../../utils/log';
import I18n from '../../../i18n';
import { withTheme } from '../../../theme';
import { themes } from '../../../constants/colors';
import { headerHeight } from '../../../containers/Header';
const ANIMATION_DURATION = 200;
class Sort extends PureComponent {
static propTypes = {
closeSortDropdown: PropTypes.bool,
close: PropTypes.func,
sortBy: PropTypes.string,
groupByType: PropTypes.bool,
showFavorites: PropTypes.bool,
showUnread: PropTypes.bool,
isMasterDetail: PropTypes.bool,
theme: PropTypes.string,
insets: PropTypes.object,
setSortPreference: PropTypes.func
};
constructor(props) {
super(props);
this.animatedValue = new Animated.Value(0);
}
componentDidMount() {
Animated.timing(this.animatedValue, {
toValue: 1,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
}).start();
}
componentDidUpdate(prevProps) {
const { closeSortDropdown } = this.props;
if (prevProps.closeSortDropdown !== closeSortDropdown) {
this.close();
}
}
setSortPreference = param => {
const { setSortPreference } = this.props;
try {
setSortPreference(param);
RocketChat.saveSortPreference(param);
} catch (e) {
logEvent(events.RL_SORT_CHANNELS_F);
log(e);
}
};
sortByName = () => {
logEvent(events.RL_SORT_CHANNELS_BY_NAME);
this.setSortPreference({ sortBy: 'alphabetical' });
this.close();
};
sortByActivity = () => {
logEvent(events.RL_SORT_CHANNELS_BY_ACTIVITY);
this.setSortPreference({ sortBy: 'activity' });
this.close();
};
toggleGroupByType = () => {
logEvent(events.RL_GROUP_CHANNELS_BY_TYPE);
const { groupByType } = this.props;
this.setSortPreference({ groupByType: !groupByType });
};
toggleGroupByFavorites = () => {
logEvent(events.RL_GROUP_CHANNELS_BY_FAVORITE);
const { showFavorites } = this.props;
this.setSortPreference({ showFavorites: !showFavorites });
};
toggleUnread = () => {
logEvent(events.RL_GROUP_CHANNELS_BY_UNREAD);
const { showUnread } = this.props;
this.setSortPreference({ showUnread: !showUnread });
};
close = () => {
const { close } = this.props;
Animated.timing(this.animatedValue, {
toValue: 0,
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
}).start(() => close());
};
renderCheck = () => {
const { theme } = this.props;
return <List.Icon name='check' color={themes[theme].tintColor} />;
};
render() {
const { isMasterDetail, insets } = this.props;
const statusBarHeight = insets?.top ?? 0;
const heightDestination = isMasterDetail ? headerHeight + statusBarHeight : 0;
const translateY = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-326, heightDestination]
});
const { sortBy, groupByType, showFavorites, showUnread, theme } = this.props;
const backdropOpacity = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, themes[theme].backdropOpacity]
});
return (
<>
<TouchableWithoutFeedback onPress={this.close}>
<Animated.View
style={[
styles.backdrop,
{
backgroundColor: themes[theme].backdropColor,
opacity: backdropOpacity,
top: heightDestination
}
]}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
styles.dropdownContainer,
{
transform: [{ translateY }],
backgroundColor: themes[theme].backgroundColor,
borderColor: themes[theme].separatorColor
}
]}>
<List.Item
title={I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}
left={() => <List.Icon name='sort' />}
color={themes[theme].auxiliaryText}
onPress={this.close}
translateTitle={false}
/>
<List.Separator />
<List.Item
title='Alphabetical'
left={() => <List.Icon name='sort-az' />}
color={themes[theme].auxiliaryText}
onPress={this.sortByName}
right={() => (sortBy === 'alphabetical' ? this.renderCheck() : null)}
/>
<List.Item
title='Activity'
left={() => <List.Icon name='clock' />}
color={themes[theme].auxiliaryText}
onPress={this.sortByActivity}
right={() => (sortBy === 'activity' ? this.renderCheck() : null)}
/>
<List.Separator />
<List.Item
title='Group_by_type'
left={() => <List.Icon name='group-by-type' />}
color={themes[theme].auxiliaryText}
onPress={this.toggleGroupByType}
right={() => (groupByType ? this.renderCheck() : null)}
/>
<List.Item
title='Group_by_favorites'
left={() => <List.Icon name='star' />}
color={themes[theme].auxiliaryText}
onPress={this.toggleGroupByFavorites}
right={() => (showFavorites ? this.renderCheck() : null)}
/>
<List.Item
title='Unread_on_top'
left={() => <List.Icon name='unread-on-top-disabled' />}
color={themes[theme].auxiliaryText}
onPress={this.toggleUnread}
right={() => (showUnread ? this.renderCheck() : null)}
/>
</Animated.View>
</>
);
}
}
const mapStateToProps = state => ({
closeSortDropdown: state.rooms.closeSortDropdown,
isMasterDetail: state.app.isMasterDetail
});
const mapDispatchToProps = dispatch => ({
setSortPreference: preference => dispatch(setPreference(preference))
});
export default connect(mapStateToProps, mapDispatchToProps)(withSafeAreaInsets(withTheme(Sort)));

View File

@ -9,15 +9,14 @@ import { withSafeAreaInsets } from 'react-native-safe-area-context';
import database from '../../lib/database'; import database from '../../lib/database';
import RocketChat from '../../lib/rocketchat'; import RocketChat from '../../lib/rocketchat';
import RoomItem, { ROW_HEIGHT } from '../../presentation/RoomItem'; import RoomItem, { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from '../../presentation/RoomItem';
import log, { events, logEvent } from '../../utils/log'; import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n'; import I18n from '../../i18n';
import { import {
closeSearchHeader as closeSearchHeaderAction, closeSearchHeader as closeSearchHeaderAction,
closeServerDropdown as closeServerDropdownAction, closeServerDropdown as closeServerDropdownAction,
openSearchHeader as openSearchHeaderAction, openSearchHeader as openSearchHeaderAction,
roomsRequest as roomsRequestAction, roomsRequest as roomsRequestAction
toggleSortDropdown as toggleSortDropdownAction
} from '../../actions/rooms'; } from '../../actions/rooms';
import { appStart as appStartAction, ROOT_OUTSIDE } from '../../actions/app'; import { appStart as appStartAction, ROOT_OUTSIDE } from '../../actions/app';
import debounce from '../../utils/debounce'; import debounce from '../../utils/debounce';
@ -50,11 +49,11 @@ import { showConfirmationAlert, showErrorAlert } from '../../utils/info';
import { E2E_BANNER_TYPE } from '../../lib/encryption/constants'; import { E2E_BANNER_TYPE } from '../../lib/encryption/constants';
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry'; import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
import { changeLivechatStatus, isOmnichannelStatusAvailable } from '../../ee/omnichannel/lib'; import { changeLivechatStatus, isOmnichannelStatusAvailable } from '../../ee/omnichannel/lib';
import { DISPLAY_MODE_CONDENSED } from '../../constants/constantDisplayMode';
import styles from './styles';
import ServerDropdown from './ServerDropdown';
import ListHeader from './ListHeader'; import ListHeader from './ListHeader';
import RoomsListHeaderView from './Header'; import RoomsListHeaderView from './Header';
import ServerDropdown from './ServerDropdown';
import SortDropdown from './SortDropdown';
import styles from './styles';
const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12; const INITIAL_NUM_TO_RENDER = isTablet ? 20 : 12;
const CHATS_HEADER = 'Chats'; const CHATS_HEADER = 'Chats';
@ -77,11 +76,6 @@ const shouldUpdateProps = [
'searchText', 'searchText',
'loadingServer', 'loadingServer',
'showServerDropdown', 'showServerDropdown',
'showSortDropdown',
'sortBy',
'groupByType',
'showFavorites',
'showUnread',
'useRealName', 'useRealName',
'StoreLastMessage', 'StoreLastMessage',
'theme', 'theme',
@ -96,9 +90,14 @@ const shouldUpdateProps = [
'createPrivateChannelPermission', 'createPrivateChannelPermission',
'createDiscussionPermission' 'createDiscussionPermission'
]; ];
const getItemLayout = (data, index) => ({
length: ROW_HEIGHT, const sortPreferencesShouldUpdate = ['sortBy', 'groupByType', 'showFavorites', 'showUnread'];
offset: ROW_HEIGHT * index,
const displayPropsShouldUpdate = ['showAvatar', 'displayMode'];
const getItemLayout = (data, index, height) => ({
length: height,
offset: height * index,
index index
}); });
const keyExtractor = item => item.rid; const keyExtractor = item => item.rid;
@ -118,7 +117,6 @@ class RoomsListView extends React.Component {
changingServer: PropTypes.bool, changingServer: PropTypes.bool,
loadingServer: PropTypes.bool, loadingServer: PropTypes.bool,
showServerDropdown: PropTypes.bool, showServerDropdown: PropTypes.bool,
showSortDropdown: PropTypes.bool,
sortBy: PropTypes.string, sortBy: PropTypes.string,
groupByType: PropTypes.bool, groupByType: PropTypes.bool,
showFavorites: PropTypes.bool, showFavorites: PropTypes.bool,
@ -126,7 +124,6 @@ class RoomsListView extends React.Component {
refreshing: PropTypes.bool, refreshing: PropTypes.bool,
StoreLastMessage: PropTypes.bool, StoreLastMessage: PropTypes.bool,
theme: PropTypes.string, theme: PropTypes.string,
toggleSortDropdown: PropTypes.func,
openSearchHeader: PropTypes.func, openSearchHeader: PropTypes.func,
closeSearchHeader: PropTypes.func, closeSearchHeader: PropTypes.func,
appStart: PropTypes.func, appStart: PropTypes.func,
@ -140,6 +137,8 @@ class RoomsListView extends React.Component {
queueSize: PropTypes.number, queueSize: PropTypes.number,
inquiryEnabled: PropTypes.bool, inquiryEnabled: PropTypes.bool,
encryptionBanner: PropTypes.string, encryptionBanner: PropTypes.string,
showAvatar: PropTypes.bool,
displayMode: PropTypes.string,
createTeamPermission: PropTypes.array, createTeamPermission: PropTypes.array,
createDirectMessagePermission: PropTypes.array, createDirectMessagePermission: PropTypes.array,
createPublicChannelPermission: PropTypes.array, createPublicChannelPermission: PropTypes.array,
@ -180,6 +179,11 @@ class RoomsListView extends React.Component {
this.unsubscribeFocus = navigation.addListener('focus', () => { this.unsubscribeFocus = navigation.addListener('focus', () => {
Orientation.unlockAllOrientations(); Orientation.unlockAllOrientations();
this.animated = true; this.animated = true;
// Check if there were changes with sort preference, then call getSubscription to remount the list
if (this.sortPreferencesChanged) {
this.getSubscriptions();
this.sortPreferencesChanged = false;
}
// Check if there were changes while not focused (it's set on sCU) // Check if there were changes while not focused (it's set on sCU)
if (this.shouldUpdate) { if (this.shouldUpdate) {
this.forceUpdate(); this.forceUpdate();
@ -222,6 +226,20 @@ class RoomsListView extends React.Component {
return true; return true;
} }
// check if some display props are changed to force update when focus this view again
// eslint-disable-next-line react/destructuring-assignment
const displayUpdated = displayPropsShouldUpdate.some(key => nextProps[key] !== this.props[key]);
if (displayUpdated) {
this.shouldUpdate = true;
}
// check if some sort preferences are changed to getSubscription() when focus this view again
// eslint-disable-next-line react/destructuring-assignment
const sortPreferencesUpdate = sortPreferencesShouldUpdate.some(key => nextProps[key] !== this.props[key]);
if (sortPreferencesUpdate) {
this.sortPreferencesChanged = true;
}
// Compare changes only once // Compare changes only once
const chatsNotEqual = !dequal(nextState.chatsUpdate, chatsUpdate); const chatsNotEqual = !dequal(nextState.chatsUpdate, chatsUpdate);
@ -285,7 +303,9 @@ class RoomsListView extends React.Component {
createPublicChannelPermission, createPublicChannelPermission,
createPrivateChannelPermission, createPrivateChannelPermission,
createDirectMessagePermission, createDirectMessagePermission,
createDiscussionPermission createDiscussionPermission,
showAvatar,
displayMode
} = this.props; } = this.props;
const { item } = this.state; const { item } = this.state;
@ -294,7 +314,9 @@ class RoomsListView extends React.Component {
prevProps.sortBy === sortBy && prevProps.sortBy === sortBy &&
prevProps.groupByType === groupByType && prevProps.groupByType === groupByType &&
prevProps.showFavorites === showFavorites && prevProps.showFavorites === showFavorites &&
prevProps.showUnread === showUnread prevProps.showUnread === showUnread &&
prevProps.showAvatar === showAvatar &&
prevProps.displayMode === displayMode
) )
) { ) {
this.getSubscriptions(); this.getSubscriptions();
@ -616,16 +638,6 @@ class RoomsListView extends React.Component {
} }
}; };
toggleSort = () => {
logEvent(events.RL_TOGGLE_SORT_DROPDOWN);
const { toggleSortDropdown } = this.props;
this.scrollToTop();
setTimeout(() => {
toggleSortDropdown();
}, 100);
};
toggleFav = async (rid, favorite) => { toggleFav = async (rid, favorite) => {
logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL); logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL);
try { try {
@ -874,12 +886,10 @@ class RoomsListView extends React.Component {
renderListHeader = () => { renderListHeader = () => {
const { searching } = this.state; const { searching } = this.state;
const { sortBy, queueSize, inquiryEnabled, encryptionBanner, user } = this.props; const { queueSize, inquiryEnabled, encryptionBanner, user } = this.props;
return ( return (
<ListHeader <ListHeader
searching={searching} searching={searching}
sortBy={sortBy}
toggleSort={this.toggleSort}
goEncryption={this.goEncryption} goEncryption={this.goEncryption}
goQueue={this.goQueue} goQueue={this.goQueue}
queueSize={queueSize} queueSize={queueSize}
@ -913,7 +923,9 @@ class RoomsListView extends React.Component {
useRealName, useRealName,
theme, theme,
isMasterDetail, isMasterDetail,
width width,
showAvatar,
displayMode
} = this.props; } = this.props;
const id = this.getUidDirectMessage(item); const id = this.getUidDirectMessage(item);
@ -938,6 +950,8 @@ class RoomsListView extends React.Component {
getIsRead={this.isRead} getIsRead={this.isRead}
visitor={item.visitor} visitor={item.visitor}
isFocused={currentItem?.rid === item.rid} isFocused={currentItem?.rid === item.rid}
showAvatar={showAvatar}
displayMode={displayMode}
/> />
); );
}; };
@ -953,7 +967,9 @@ class RoomsListView extends React.Component {
renderScroll = () => { renderScroll = () => {
const { loading, chats, search, searching } = this.state; const { loading, chats, search, searching } = this.state;
const { theme, refreshing } = this.props; const { theme, refreshing, displayMode } = this.props;
const height = displayMode === DISPLAY_MODE_CONDENSED ? ROW_HEIGHT_CONDENSED : ROW_HEIGHT;
if (loading) { if (loading) {
return <ActivityIndicator theme={theme} />; return <ActivityIndicator theme={theme} />;
@ -968,7 +984,7 @@ class RoomsListView extends React.Component {
style={[styles.list, { backgroundColor: themes[theme].backgroundColor }]} style={[styles.list, { backgroundColor: themes[theme].backgroundColor }]}
renderItem={this.renderItem} renderItem={this.renderItem}
ListHeaderComponent={this.renderListHeader} ListHeaderComponent={this.renderListHeader}
getItemLayout={getItemLayout} getItemLayout={(data, index) => getItemLayout(data, index, height)}
removeClippedSubviews={isIOS} removeClippedSubviews={isIOS}
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
initialNumToRender={INITIAL_NUM_TO_RENDER} initialNumToRender={INITIAL_NUM_TO_RENDER}
@ -984,23 +1000,13 @@ class RoomsListView extends React.Component {
render = () => { render = () => {
console.count(`${this.constructor.name}.render calls`); console.count(`${this.constructor.name}.render calls`);
const { sortBy, groupByType, showFavorites, showUnread, showServerDropdown, showSortDropdown, theme, navigation } = const { showServerDropdown, theme, navigation } = this.props;
this.props;
return ( return (
<SafeAreaView testID='rooms-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}> <SafeAreaView testID='rooms-list-view' style={{ backgroundColor: themes[theme].backgroundColor }}>
<StatusBar /> <StatusBar />
{this.renderHeader()} {this.renderHeader()}
{this.renderScroll()} {this.renderScroll()}
{showSortDropdown ? (
<SortDropdown
close={this.toggleSort}
sortBy={sortBy}
groupByType={groupByType}
showFavorites={showFavorites}
showUnread={showUnread}
/>
) : null}
{showServerDropdown ? <ServerDropdown navigation={navigation} /> : null} {showServerDropdown ? <ServerDropdown navigation={navigation} /> : null}
</SafeAreaView> </SafeAreaView>
); );
@ -1015,7 +1021,6 @@ const mapStateToProps = state => ({
searchText: state.rooms.searchText, searchText: state.rooms.searchText,
loadingServer: state.server.loading, loadingServer: state.server.loading,
showServerDropdown: state.rooms.showServerDropdown, showServerDropdown: state.rooms.showServerDropdown,
showSortDropdown: state.rooms.showSortDropdown,
refreshing: state.rooms.refreshing, refreshing: state.rooms.refreshing,
sortBy: state.sortPreferences.sortBy, sortBy: state.sortPreferences.sortBy,
groupByType: state.sortPreferences.groupByType, groupByType: state.sortPreferences.groupByType,
@ -1027,6 +1032,8 @@ const mapStateToProps = state => ({
queueSize: getInquiryQueueSelector(state).length, queueSize: getInquiryQueueSelector(state).length,
inquiryEnabled: state.inquiry.enabled, inquiryEnabled: state.inquiry.enabled,
encryptionBanner: state.encryption.banner, encryptionBanner: state.encryption.banner,
showAvatar: state.sortPreferences.showAvatar,
displayMode: state.sortPreferences.displayMode,
createTeamPermission: state.permissions['create-team'], createTeamPermission: state.permissions['create-team'],
createDirectMessagePermission: state.permissions['create-d'], createDirectMessagePermission: state.permissions['create-d'],
createPublicChannelPermission: state.permissions['create-c'], createPublicChannelPermission: state.permissions['create-c'],
@ -1035,7 +1042,6 @@ const mapStateToProps = state => ({
}); });
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
toggleSortDropdown: () => dispatch(toggleSortDropdownAction()),
openSearchHeader: () => dispatch(openSearchHeaderAction()), openSearchHeader: () => dispatch(openSearchHeaderAction()),
closeSearchHeader: () => dispatch(closeSearchHeaderAction()), closeSearchHeader: () => dispatch(closeSearchHeaderAction()),
roomsRequest: params => dispatch(roomsRequestAction(params)), roomsRequest: params => dispatch(roomsRequestAction(params)),

View File

@ -185,6 +185,8 @@ class SettingsView extends React.Component {
<List.Separator /> <List.Separator />
</List.Section> </List.Section>
<List.Section> <List.Section>
<List.Separator />
<List.Item title='Display' onPress={() => this.navigateToScreen('DisplayPrefsView')} showActionIndicator />
<List.Separator /> <List.Separator />
<List.Item <List.Item
title='Profile' title='Profile'

View File

@ -193,6 +193,13 @@ class Sidebar extends Component {
testID='sidebar-profile' testID='sidebar-profile'
current={this.currentItemKey === 'ProfileStackNavigator'} current={this.currentItemKey === 'ProfileStackNavigator'}
/> />
<SidebarItem
text={I18n.t('Display')}
left={<CustomIcon name='sort' size={20} color={themes[theme].titleText} />}
onPress={() => this.sidebarNavigate('DisplayPrefStackNavigator')}
testID='sidebar-display'
current={this.currentItemKey === 'DisplayPrefStackNavigator'}
/>
<SidebarItem <SidebarItem
text={I18n.t('Settings')} text={I18n.t('Settings')}
left={<CustomIcon name='administration' size={20} color={themes[theme].titleText} />} left={<CustomIcon name='administration' size={20} color={themes[theme].titleText} />}

View File

@ -61,7 +61,9 @@ class TeamChannelsView extends React.Component {
deleteCPermission: PropTypes.array, deleteCPermission: PropTypes.array,
deletePPermission: PropTypes.array, deletePPermission: PropTypes.array,
showActionSheet: PropTypes.func, showActionSheet: PropTypes.func,
deleteRoom: PropTypes.func deleteRoom: PropTypes.func,
showAvatar: PropTypes.bool,
displayMode: PropTypes.string
}; };
constructor(props) { constructor(props) {
@ -470,7 +472,7 @@ class TeamChannelsView extends React.Component {
}; };
renderItem = ({ item }) => { renderItem = ({ item }) => {
const { StoreLastMessage, useRealName, theme, width } = this.props; const { StoreLastMessage, useRealName, theme, width, showAvatar, displayMode } = this.props;
return ( return (
<RoomItem <RoomItem
item={item} item={item}
@ -485,6 +487,8 @@ class TeamChannelsView extends React.Component {
getRoomAvatar={this.getRoomAvatar} getRoomAvatar={this.getRoomAvatar}
swipeEnabled={false} swipeEnabled={false}
autoJoin={item.teamDefault} autoJoin={item.teamDefault}
showAvatar={showAvatar}
displayMode={displayMode}
/> />
); );
}; };
@ -547,7 +551,9 @@ const mapStateToProps = state => ({
editTeamChannelPermission: state.permissions[PERMISSION_EDIT_TEAM_CHANNEL], editTeamChannelPermission: state.permissions[PERMISSION_EDIT_TEAM_CHANNEL],
removeTeamChannelPermission: state.permissions[PERMISSION_REMOVE_TEAM_CHANNEL], removeTeamChannelPermission: state.permissions[PERMISSION_REMOVE_TEAM_CHANNEL],
deleteCPermission: state.permissions[PERMISSION_DELETE_C], deleteCPermission: state.permissions[PERMISSION_DELETE_C],
deletePPermission: state.permissions[PERMISSION_DELETE_P] deletePPermission: state.permissions[PERMISSION_DELETE_P],
showAvatar: state.sortPreferences.showAvatar,
displayMode: state.sortPreferences.displayMode
}); });
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({

View File

@ -0,0 +1,96 @@
const { login, navigateToLogin } = require('../../helpers/app');
const data = require('../../data');
const goToDisplayPref = async () => {
await expect(element(by.id('rooms-list-view-sidebar'))).toBeVisible();
await element(by.id('rooms-list-view-sidebar')).tap();
await expect(element(by.id('sidebar-display'))).toBeVisible();
await element(by.id('sidebar-display')).tap();
};
const goToRoomList = async () => {
await expect(element(by.id('display-view-drawer'))).toBeVisible();
await element(by.id('display-view-drawer')).tap();
await expect(element(by.id('sidebar-chats'))).toBeVisible();
await element(by.id('sidebar-chats')).tap();
};
describe('Rooms list screen', () => {
before(async () => {
await device.launchApp({ permissions: { notifications: 'YES' }, newInstance: true, delete: true });
await navigateToLogin();
await login(data.users.regular.username, data.users.regular.password);
});
describe('Render', () => {
it('should have rooms list screen', async () => {
await expect(element(by.id('rooms-list-view'))).toBeVisible();
});
it('should have room item', async () => {
await expect(element(by.id('rooms-list-view-item-general'))).toExist();
});
// Render - Header
describe('Header', () => {
it('should have create channel button', async () => {
await expect(element(by.id('rooms-list-view-create-channel'))).toBeVisible();
});
it('should have sidebar button', async () => {
await expect(element(by.id('rooms-list-view-sidebar'))).toBeVisible();
});
});
describe('DisplayPrefView', () => {
it('should go to Display Preferences', async () => {
await goToDisplayPref();
});
it('should have Displays button, expanded, condensed, avatars', async () => {
await expect(element(by.id('display-pref-view-expanded'))).toBeVisible();
await expect(element(by.id('display-pref-view-condensed'))).toBeVisible();
await expect(element(by.id('display-pref-view-avatars'))).toBeVisible();
});
it('should have Sort By button', async () => {
await expect(element(by.id('display-pref-view-activity'))).toBeVisible();
await expect(element(by.id('display-pref-view-name'))).toBeVisible();
});
it('should have Group by button', async () => {
await expect(element(by.id('display-pref-view-unread'))).toBeVisible();
await expect(element(by.id('display-pref-view-favorites'))).toBeVisible();
await expect(element(by.id('display-pref-view-types'))).toBeVisible();
});
});
describe('Change display', () => {
it('should appear the last message in RoomList when is Expanded', async () => {
await element(by.id('display-pref-view-expanded')).tap();
await goToRoomList();
await expect(element(by.id('room-item-last-message')).atIndex(0)).toBeVisible();
});
it('should not appear the last message in RoomList when is Condensed', async () => {
await goToDisplayPref();
await element(by.id('display-pref-view-condensed')).tap();
await goToRoomList();
await expect(element(by.id('room-item-last-message'))).not.toBeVisible();
});
});
describe('Change the avatar visible', () => {
it('should have avatar as default in room list', async () => {
await expect(element(by.id('avatar')).atIndex(0)).toExist();
});
it('should hide the avatar', async () => {
await goToDisplayPref();
await expect(element(by.id('display-pref-view-avatar-switch'))).toBeVisible();
await element(by.id('display-pref-view-avatar-switch')).tap();
await goToRoomList();
await expect(element(by.id('avatar'))).not.toBeVisible();
});
});
});
});

View File

@ -530,12 +530,12 @@ PODS:
- RNFBApp - RNFBApp
- RNGestureHandler (1.10.3): - RNGestureHandler (1.10.3):
- React-Core - React-Core
- RNImageCropPicker (0.31.1): - RNImageCropPicker (0.36.3):
- React-Core - React-Core
- React-RCTImage - React-RCTImage
- RNImageCropPicker/QBImagePickerController (= 0.31.1) - RNImageCropPicker/QBImagePickerController (= 0.36.3)
- TOCropViewController - TOCropViewController
- RNImageCropPicker/QBImagePickerController (0.31.1): - RNImageCropPicker/QBImagePickerController (0.36.3):
- React-Core - React-Core
- React-RCTImage - React-RCTImage
- TOCropViewController - TOCropViewController
@ -977,7 +977,7 @@ SPEC CHECKSUMS:
EXVideoThumbnails: cd257fc6e07884a704a5674d362a6410933acb68 EXVideoThumbnails: cd257fc6e07884a704a5674d362a6410933acb68
EXWebBrowser: d37a5ffdea1b65947352bc001dd9f732463725d4 EXWebBrowser: d37a5ffdea1b65947352bc001dd9f732463725d4
FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b
FBReactNativeSpec: 686ac17e193dcf7d5df4d772b224504dd2f3ad81 FBReactNativeSpec: 110d69378fce79af38271c39894b59fec7890221
Firebase: 919186c8e119dd9372a45fd1dd17a8a942bc1892 Firebase: 919186c8e119dd9372a45fd1dd17a8a942bc1892
FirebaseAnalytics: 5fa308e1b13f838d0f6dc74719ac2a72e8c5afc4 FirebaseAnalytics: 5fa308e1b13f838d0f6dc74719ac2a72e8c5afc4
FirebaseCore: 8cd4f8ea22075e0ee582849b1cf79d8816506085 FirebaseCore: 8cd4f8ea22075e0ee582849b1cf79d8816506085
@ -1061,7 +1061,7 @@ SPEC CHECKSUMS:
RNFBApp: 6fd8a7e757135d4168bf033a8812c241af7363a0 RNFBApp: 6fd8a7e757135d4168bf033a8812c241af7363a0
RNFBCrashlytics: 88de72c2476b5868a892d9523b89b86c527c540e RNFBCrashlytics: 88de72c2476b5868a892d9523b89b86c527c540e
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211 RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNImageCropPicker: 38865ab4af1b0b2146ad66061196bc0184946855 RNImageCropPicker: 97289cd94fb01ab79db4e5c92938be4d0d63415d
RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b RNLocalize: 82a569022724d35461e2dc5b5d015a13c3ca995b
RNReanimated: 241c586663f44f19a53883c63375fdd041253960 RNReanimated: 241c586663f44f19a53883c63375fdd041253960
RNRootView: 895a4813dedeaca82db2fa868ca1c333d790e494 RNRootView: 895a4813dedeaca82db2fa868ca1c333d790e494

View File

@ -1689,7 +1689,7 @@
INFOPLIST_FILE = NotificationService/Info.plist; INFOPLIST_FILE = NotificationService/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 4.20.0; MARKETING_VERSION = 4.21.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative.NotificationService; PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative.NotificationService;
@ -1726,7 +1726,7 @@
INFOPLIST_FILE = NotificationService/Info.plist; INFOPLIST_FILE = NotificationService/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 4.20.0; MARKETING_VERSION = 4.21.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative.NotificationService; PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative.NotificationService;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -26,7 +26,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>4.20.0</string> <string>4.21.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>

View File

@ -26,7 +26,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>XPC!</string> <string>XPC!</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>4.20.0</string> <string>4.21.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>KeychainGroup</key> <key>KeychainGroup</key>

View File

@ -1,6 +1,6 @@
{ {
"name": "rocket-chat-reactnative", "name": "rocket-chat-reactnative",
"version": "4.20.0", "version": "4.21.0",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "react-native start", "start": "react-native start",
@ -56,7 +56,6 @@
"commonmark-react-renderer": "git+https://github.com/RocketChat/commonmark-react-renderer.git", "commonmark-react-renderer": "git+https://github.com/RocketChat/commonmark-react-renderer.git",
"dequal": "^2.0.2", "dequal": "^2.0.2",
"ejson": "2.2.1", "ejson": "2.2.1",
"eslint-config-airbnb": "^18.1.0",
"expo-apple-authentication": "^2.2.1", "expo-apple-authentication": "^2.2.1",
"expo-av": "8.2.1", "expo-av": "8.2.1",
"expo-file-system": "9.0.1", "expo-file-system": "9.0.1",

View File

@ -1,12 +0,0 @@
diff --git a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
index 3500542..94e45b6 100644
--- a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
+++ b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
@@ -584,6 +584,7 @@ class PickerModule extends ReactContextBaseJavaModule implements ActivityEventLi
image.putInt("height", options.outHeight);
image.putString("mime", options.outMimeType);
image.putInt("size", (int) new File(compressedImagePath).length());
+ image.putString("filename", compressedImage.getName());
image.putString("modificationDate", String.valueOf(modificationDate));
if (includeBase64) {

View File

@ -7,6 +7,7 @@ import { Provider } from 'react-redux';
import { themes } from '../../app/constants/colors'; import { themes } from '../../app/constants/colors';
import RoomItemComponent from '../../app/presentation/RoomItem/RoomItem'; import RoomItemComponent from '../../app/presentation/RoomItem/RoomItem';
import { longText } from '../utils'; import { longText } from '../utils';
import { DISPLAY_MODE_CONDENSED, DISPLAY_MODE_EXPANDED } from '../../app/constants/constantDisplayMode';
import { store } from './index'; import { store } from './index';
const baseUrl = 'https://open.rocket.chat'; const baseUrl = 'https://open.rocket.chat';
@ -30,6 +31,8 @@ const RoomItem = props => (
baseUrl={baseUrl} baseUrl={baseUrl}
width={width} width={width}
theme={_theme} theme={_theme}
showAvatar
displayMode={DISPLAY_MODE_EXPANDED}
{...updatedAt} {...updatedAt}
{...props} {...props}
/> />
@ -126,3 +129,57 @@ stories.add('Last Message', () => (
<RoomItem showLastMessage alert tunread={[1]} lastMessage={lastMessage} /> <RoomItem showLastMessage alert tunread={[1]} lastMessage={lastMessage} />
</> </>
)); ));
stories.add('Condensed Room Item', () => (
<>
<RoomItem showLastMessage alert tunread={[1]} lastMessage={lastMessage} displayMode={DISPLAY_MODE_CONDENSED} />
<RoomItem showLastMessage alert name='unread' unread={1000} displayMode={DISPLAY_MODE_CONDENSED} />
<RoomItem type='c' displayMode={DISPLAY_MODE_CONDENSED} autoJoin />
</>
));
stories.add('Condensed Room Item without Avatar', () => (
<>
<RoomItem
showLastMessage
alert
tunread={[1]}
lastMessage={lastMessage}
displayMode={DISPLAY_MODE_CONDENSED}
showAvatar={false}
/>
<RoomItem type='p' displayMode={DISPLAY_MODE_CONDENSED} showAvatar={false} />
<RoomItem name={longText} autoJoin displayMode={DISPLAY_MODE_CONDENSED} showAvatar={false} />
</>
));
stories.add('Expanded Room Item without Avatar', () => (
<>
<RoomItem
showLastMessage
alert
tunread={[1]}
lastMessage={lastMessage}
displayMode={DISPLAY_MODE_EXPANDED}
showAvatar={false}
/>
<RoomItem
status='online'
showLastMessage
alert
tunread={[1]}
lastMessage={lastMessage}
displayMode={DISPLAY_MODE_EXPANDED}
showAvatar={false}
/>
<RoomItem
status='online'
showLastMessage
alert
lastMessage={lastMessage}
displayMode={DISPLAY_MODE_EXPANDED}
showAvatar={false}
/>
</>
));

View File

@ -6389,11 +6389,6 @@ concat-stream@^2.0.0:
readable-stream "^3.0.2" readable-stream "^3.0.2"
typedarray "^0.0.6" typedarray "^0.0.6"
confusing-browser-globals@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd"
integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==
connect@^3.6.5: connect@^3.6.5:
version "3.7.0" version "3.7.0"
resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
@ -7505,24 +7500,6 @@ escodegen@^2.0.0:
optionalDependencies: optionalDependencies:
source-map "~0.6.1" source-map "~0.6.1"
eslint-config-airbnb-base@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.1.0.tgz#2ba4592dd6843258221d9bff2b6831bd77c874e4"
integrity sha512-+XCcfGyCnbzOnktDVhwsCAx+9DmrzEmuwxyHUJpw+kqBVT744OUBrB09khgFKlK1lshVww6qXGsYPZpavoNjJw==
dependencies:
confusing-browser-globals "^1.0.9"
object.assign "^4.1.0"
object.entries "^1.1.1"
eslint-config-airbnb@^18.1.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.1.0.tgz#724d7e93dadd2169492ff5363c5aaa779e01257d"
integrity sha512-kZFuQC/MPnH7KJp6v95xsLBf63G/w7YqdPfQ0MUanxQ7zcKUNG8j+sSY860g3NwCBOa62apw16J6pRN+AOgXzw==
dependencies:
eslint-config-airbnb-base "^14.1.0"
object.assign "^4.1.0"
object.entries "^1.1.1"
eslint-config-prettier@^8.3.0: eslint-config-prettier@^8.3.0:
version "8.3.0" version "8.3.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a"
@ -12322,7 +12299,7 @@ object.assign@^4.1.2:
has-symbols "^1.0.1" has-symbols "^1.0.1"
object-keys "^1.1.1" object-keys "^1.1.1"
object.entries@^1.1.0, object.entries@^1.1.1: object.entries@^1.1.0:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add"
integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==
@ -13702,8 +13679,8 @@ react-native-gesture-handler@^1.10.3:
prop-types "^15.7.2" prop-types "^15.7.2"
react-native-image-crop-picker@RocketChat/react-native-image-crop-picker: react-native-image-crop-picker@RocketChat/react-native-image-crop-picker:
version "0.31.1" version "0.36.3"
resolved "https://codeload.github.com/RocketChat/react-native-image-crop-picker/tar.gz/db1040b57e8536bd64db699897361167009b359c" resolved "https://codeload.github.com/RocketChat/react-native-image-crop-picker/tar.gz/f347776247afb5cbd1400dde215689d7ca8fd6f2"
react-native-image-progress@^1.1.1: react-native-image-progress@^1.1.1:
version "1.1.1" version "1.1.1"