more components updated/translated
This commit is contained in:
+15
-1
@@ -10,7 +10,7 @@
|
||||
"label_default_access_mode": "Default access mode:",
|
||||
"label_message_sound": "Message sound:",
|
||||
"label_push_notifications": "Notification alerts:",
|
||||
"label_push_notifications_disabled": "Notification alerts (requires HTTPS)",
|
||||
"label_push_notifications_disabled": "Notification alerts (requires HTTPS):",
|
||||
"title_tag_manager": "Tags (user discovery)",
|
||||
"button_logout": "Logout",
|
||||
"login_prompt": "Login",
|
||||
@@ -28,6 +28,7 @@
|
||||
"tabtitle_find_user": "find",
|
||||
"tabtitle_new_group": "new group",
|
||||
"tabtitle_group_by_id": "by id",
|
||||
"search_for_contacts": "Use search to find contacts",
|
||||
"label_server_to_use": "Server to use:",
|
||||
"label_wire_transport": "Wire transport:",
|
||||
"button_update": "Update",
|
||||
@@ -38,11 +39,24 @@
|
||||
"sidepanel_title_newtpk": "Start New Chat",
|
||||
"sidepanel_title_cred": "Confirm Credentials",
|
||||
"sidepanel_title_reset": "Reset Password",
|
||||
"phone": "phone",
|
||||
"email": "email",
|
||||
"enter_confirmation_code_prompt": "Enter confirmation code sent to you by {method}:",
|
||||
"numeric_confirmation_code_prompt": "Numbers only",
|
||||
"button_confirm": "Confirm",
|
||||
"invalid_content": "invalid content",
|
||||
"button_ok": "OK",
|
||||
"button_cancel": "Cancel",
|
||||
"label_file_name": "File name:",
|
||||
"label_content_type": "Content type:",
|
||||
"label_size": "Size:",
|
||||
"message_sending": "sending...",
|
||||
"message_sending_failed": "failed",
|
||||
"search_placeholder": "List like email:alice@example.com, tel:17025550003...",
|
||||
"messaging_disabled_prompt": "Messaging disabled",
|
||||
"new_message_prompt": "New message",
|
||||
"file_attachment_too_large": "The file size {size} exceeds the {limit} limit.",
|
||||
"cannot_initiate_file_upload": "Cannot initiate file upload.",
|
||||
"tags_not_found": "No tags defined. Add some.",
|
||||
"tags_editor_no_tags": "Add some tags",
|
||||
"title_manage_tags": "Manage tags"
|
||||
|
||||
+21
-2
@@ -40,5 +40,24 @@
|
||||
"sidepanel_title_reset": "Сменить пароль",
|
||||
"tags_not_found": "Тагов нет. Добавьте",
|
||||
"tags_editor_no_tags": "Добавьте таги",
|
||||
"title_manage_tags": "Редактор тагов"
|
||||
}
|
||||
"title_manage_tags": "Редактор тагов",
|
||||
"message_sending": "шлём...",
|
||||
"message_sending_failed": "ошибка",
|
||||
"search_placeholder": "Список, напр. email:alice@example.com, tel:17025550003...",
|
||||
"messaging_disabled_prompt": "Отправка недоступна",
|
||||
"new_message_prompt": "Новое сообщение",
|
||||
"file_attachment_too_large": "Размер файла {size} превышает {limit} лимит.",
|
||||
"cannot_initiate_file_upload": "Ошибка загрузки файла.",
|
||||
"search_for_contacts": ":!![MISSING]!!:Use search to find contacts",
|
||||
"phone": "телефон",
|
||||
"email": "емейл",
|
||||
"enter_confirmation_code_prompt": "Введите код подтверждения {method}:",
|
||||
"numeric_confirmation_code_prompt": "Только цифры",
|
||||
"button_confirm": "Подтвердить",
|
||||
"button_ok": "OK",
|
||||
"button_cancel": "Отменить",
|
||||
"invalid_content": "сообщение не читается",
|
||||
"label_file_name": "Имя файла:",
|
||||
"label_content_type": "Тип:",
|
||||
"label_size": "Размер:"
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
// File and image helper functions.
|
||||
import { MAX_INBAND_ATTACHMENT_SIZE, MAX_IMAGE_DIM } from '../config.js';
|
||||
|
||||
// Supported image MIME types and corresponding file extensions.
|
||||
export const SUPPORTED_IMAGE_FORMATS = ['image/jpeg', 'image/gif', 'image/png', 'image/svg', 'image/svg+xml'];
|
||||
@@ -204,7 +205,7 @@ export function base64ReEncode(str) {
|
||||
try {
|
||||
str = btoa(atob(str));
|
||||
} catch(err) {
|
||||
console.log("Failed to base64 re-decode string");
|
||||
console.log("Failed to base64 re-encode string");
|
||||
str = null;
|
||||
}
|
||||
}
|
||||
|
||||
+34
-2
@@ -11,7 +11,7 @@
|
||||
"label_default_access_mode": "Default access mode:",
|
||||
"label_message_sound": "Message sound:",
|
||||
"label_push_notifications": "Notification alerts:",
|
||||
"label_push_notifications_disabled": "Notification alerts (requires HTTPS)",
|
||||
"label_push_notifications_disabled": "Notification alerts (requires HTTPS):",
|
||||
"title_tag_manager": "Tags (user discovery)",
|
||||
"button_logout": "Logout",
|
||||
"login_prompt": "Login",
|
||||
@@ -29,6 +29,7 @@
|
||||
"tabtitle_find_user": "find",
|
||||
"tabtitle_new_group": "new group",
|
||||
"tabtitle_group_by_id": "by id",
|
||||
"search_for_contacts": "Use search to find contacts",
|
||||
"label_server_to_use": "Server to use:",
|
||||
"label_wire_transport": "Wire transport:",
|
||||
"button_update": "Update",
|
||||
@@ -39,11 +40,24 @@
|
||||
"sidepanel_title_newtpk": "Start New Chat",
|
||||
"sidepanel_title_cred": "Confirm Credentials",
|
||||
"sidepanel_title_reset": "Reset Password",
|
||||
"phone": "phone",
|
||||
"email": "email",
|
||||
"enter_confirmation_code_prompt": "Enter confirmation code sent to you by {method}:",
|
||||
"numeric_confirmation_code_prompt": "Numbers only",
|
||||
"button_confirm": "Confirm",
|
||||
"invalid_content": "invalid content",
|
||||
"button_ok": "OK",
|
||||
"button_cancel": "Cancel",
|
||||
"label_file_name": "File name:",
|
||||
"label_content_type": "Content type:",
|
||||
"label_size": "Size:",
|
||||
"message_sending": "sending...",
|
||||
"message_sending_failed": "failed",
|
||||
"search_placeholder": "List like email:alice@example.com, tel:17025550003...",
|
||||
"messaging_disabled_prompt": "Messaging disabled",
|
||||
"new_message_prompt": "New message",
|
||||
"file_attachment_too_large": "The file size {size} exceeds the {limit} limit.",
|
||||
"cannot_initiate_file_upload": "Cannot initiate file upload.",
|
||||
"tags_not_found": "No tags defined. Add some.",
|
||||
"tags_editor_no_tags": "Add some tags",
|
||||
"title_manage_tags": "Manage tags"
|
||||
@@ -90,6 +104,24 @@
|
||||
"sidepanel_title_reset": "Сменить пароль",
|
||||
"tags_not_found": "Тагов нет. Добавьте",
|
||||
"tags_editor_no_tags": "Добавьте таги",
|
||||
"title_manage_tags": "Редактор тагов"
|
||||
"title_manage_tags": "Редактор тагов",
|
||||
"message_sending": "шлём...",
|
||||
"message_sending_failed": "ошибка",
|
||||
"search_placeholder": "Список, напр. email:alice@example.com, tel:17025550003...",
|
||||
"messaging_disabled_prompt": "Отправка недоступна",
|
||||
"new_message_prompt": "Новое сообщение",
|
||||
"file_attachment_too_large": "Размер файла {size} превышает {limit} лимит.",
|
||||
"cannot_initiate_file_upload": "Ошибка загрузки файла.",
|
||||
"phone": "телефон",
|
||||
"email": "емейл",
|
||||
"enter_confirmation_code_prompt": "Введите код подтверждения {method}:",
|
||||
"numeric_confirmation_code_prompt": "Только цифры",
|
||||
"button_confirm": "Подтвердить",
|
||||
"button_ok": "OK",
|
||||
"button_cancel": "Отменить",
|
||||
"invalid_content": "сообщение не читается",
|
||||
"label_file_name": "Имя файла:",
|
||||
"label_content_type": "Тип:",
|
||||
"label_size": "Размер:"
|
||||
}
|
||||
}
|
||||
@@ -196,8 +196,8 @@ export default class EditAccountView extends React.Component {
|
||||
description="Label for push notifications switch" />
|
||||
:
|
||||
<FormattedMessage id="label_push_notifications_disabled"
|
||||
defaultMessage="Notification alerts (requires HTTPS)"
|
||||
description="Label for push notifications switch (disabled):" />
|
||||
defaultMessage="Notification alerts (requires HTTPS):"
|
||||
description="Label for push notifications switch (disabled)" />
|
||||
}
|
||||
</label>
|
||||
<CheckBox name="alert" id="desktop-alerts"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* InfoView: panel with topic/user info */
|
||||
|
||||
// InfoView: panel with topic/user info.
|
||||
import React from 'react';
|
||||
|
||||
import AvatarUpload from '../widgets/avatar-upload.jsx';
|
||||
import CheckBox from '../widgets/checkbox.jsx';
|
||||
import ContactList from '../widgets/contact-list.jsx';
|
||||
import GroupManager from '../widgets/group-manager.jsx';
|
||||
import InPlaceEdit from '../widgets/in-place-edit.jsx';
|
||||
@@ -11,6 +11,8 @@ import MoreButton from '../widgets/more-button.jsx';
|
||||
import PermissionsEditor from '../widgets/permissions-editor.jsx';
|
||||
import TagManager from '../widgets/tag-manager.jsx';
|
||||
|
||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||
|
||||
export default class InfoView extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -90,15 +90,18 @@ export default class NewTopicView extends React.Component {
|
||||
<div className="flex-column">
|
||||
<SearchContacts type="p2p"
|
||||
onSearchContacts={this.props.onSearchContacts} />
|
||||
<ContactList
|
||||
contacts={this.state.contactList}
|
||||
myUserId={this.props.myUserId}
|
||||
emptyListMessage="Use search to find contacts"
|
||||
topicSelected={this.state.selectedContact}
|
||||
showOnline={false}
|
||||
showUnread={false}
|
||||
showContextMenu={false}
|
||||
onTopicSelected={this.handleContactSelected} />
|
||||
<FormattedMessage id="search_for_contacts" defaultMessage="Use search to find contacts"
|
||||
description="Prompt in search field.">{
|
||||
(search_for_contacts) => <ContactList
|
||||
contacts={this.state.contactList}
|
||||
myUserId={this.props.myUserId}
|
||||
emptyListMessage={search_for_contacts}
|
||||
topicSelected={this.state.selectedContact}
|
||||
showOnline={false}
|
||||
showUnread={false}
|
||||
showContextMenu={false}
|
||||
onTopicSelected={this.handleContactSelected} />
|
||||
}</FormattedMessage>
|
||||
</div>}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* A password reset form */
|
||||
// A password reset form.
|
||||
import React from 'react';
|
||||
|
||||
import VisiblePassword from '../widgets/visible-password.jsx';
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
// ValidationView: panel for confirming credentials, like email or phone.
|
||||
import React from 'react';
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
export default class ValidationView extends React.PureComponent {
|
||||
const messages = defineMessages({
|
||||
phone: {
|
||||
id: 'phone',
|
||||
defaultMessage: 'phone',
|
||||
description: "The word 'phone'",
|
||||
},
|
||||
email: {
|
||||
id: 'email',
|
||||
defaultMessage: 'email',
|
||||
description: "The word 'email'",
|
||||
}
|
||||
});
|
||||
|
||||
class ValidationView extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -32,24 +46,35 @@ export default class ValidationView extends React.PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
var methods = {'email': "email", 'tel': "phone"};
|
||||
var method = methods[this.props.credMethod] || this.props.credMethod;
|
||||
const { formatMessage } = this.props.intl;
|
||||
const methods = {'email': formatMessage(messages.email), 'tel': formatMessage(messages.phone)};
|
||||
let method = methods[this.props.credMethod] || this.props.credMethod;
|
||||
return (
|
||||
<div className="panel-form">
|
||||
<div className="panel-form-row">
|
||||
<label className="small" htmlFor="enter-confirmation-code">
|
||||
Enter confirmation code sent to you by {method}:
|
||||
<FormattedMessage id="enter_confirmation_code_prompt"
|
||||
defaultMessage="Enter confirmation code sent to you by {method}:"
|
||||
description="Request to enter confirmation code" />
|
||||
</label>
|
||||
</div>
|
||||
<div className="panel-form-row">
|
||||
<input type="text" id="enter-confirmation-code" placeholder="Numbers only"
|
||||
value={this.state.code} onChange={this.handleChange}
|
||||
onKeyPress={this.handleKeyPress} required />
|
||||
<FormattedMessage id="numeric_confirmation_code_prompt"
|
||||
defaultMessage="Numbers only" description="Prompt for numeric conformation code">{
|
||||
(numbers_only) => <input type="text" id="enter-confirmation-code"
|
||||
placeholder={numbers_only}
|
||||
value={this.state.code} onChange={this.handleChange}
|
||||
onKeyPress={this.handleKeyPress} required />
|
||||
}</FormattedMessage>
|
||||
</div>
|
||||
<div className="dialog-buttons">
|
||||
<button className="blue" onClick={this.handleSubmit}>Confirm</button>
|
||||
<button className="blue" onClick={this.handleSubmit}>
|
||||
<FormattedMessage id="button_confirm" defaultMessage="Confirm" description="Button [Confirm]" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default injectIntl(ValidationView);
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
// Single message, sent or received.
|
||||
import React from 'react';
|
||||
import {Drafty} from 'tinode-sdk'
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Drafty } from 'tinode-sdk'
|
||||
|
||||
import Attachment from './attachment.jsx';
|
||||
import LetterTile from './letter-tile.jsx';
|
||||
import ReceivedMarker from './received-marker.jsx'
|
||||
|
||||
/* Single message, sent or received. */
|
||||
import { REM_SIZE } from '../config.js';
|
||||
import { fitImageSize } from '../lib/blob-helpers.js';
|
||||
|
||||
export default class ChatMessage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -50,17 +54,16 @@ export default class ChatMessage extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
var elementKey = 0;
|
||||
|
||||
var formatter = function(style, data, values) {
|
||||
let elementKey = 0;
|
||||
const formatter = function(style, data, values) {
|
||||
elementKey += 1;
|
||||
var el = Drafty.tagName(style);
|
||||
let el = Drafty.tagName(style);
|
||||
if (el) {
|
||||
var attr = Drafty.attrValue(style, data) || {};
|
||||
let attr = Drafty.attrValue(style, data) || {};
|
||||
attr.key = elementKey;
|
||||
if (style == 'IM') {
|
||||
// Additional processing for images
|
||||
var dim = fitImageSize(data.width, data.height,
|
||||
let dim = fitImageSize(data.width, data.height,
|
||||
Math.min(this.props.viewportWidth - REM_SIZE * 4, REM_SIZE * 36), REM_SIZE * 24, false);
|
||||
attr.className = 'inline-image';
|
||||
attr.style = dim ? { width: dim.dstWidth + 'px', height: dim.dstHeight + 'px' } : null;
|
||||
@@ -95,7 +98,10 @@ export default class ChatMessage extends React.Component {
|
||||
}, this);
|
||||
content = React.createElement('span', null, Drafty.format(content, formatter, this));
|
||||
} else if (typeof content != 'string') {
|
||||
content = <span><i className="material-icons">error_outline</i> <i>invalid content</i></span>
|
||||
content = <span><i className="material-icons">error_outline</i> <i>
|
||||
<FormattedMessage id="invalid_content"
|
||||
defaultMessage="invalid content" description="Shown when message is unreadable" />
|
||||
</i></span>
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
+10
-10
@@ -1,10 +1,10 @@
|
||||
// A single topic or user.
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import LetterTile from './letter-tile.jsx';
|
||||
import UnreadBadge from './unread-badge.jsx';
|
||||
|
||||
/* A single topic or user */
|
||||
|
||||
export default class Contact extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -28,20 +28,20 @@ export default class Contact extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
var title = this.props.title;
|
||||
let title = this.props.title;
|
||||
if (!title) {
|
||||
title = <i>unknown</i>;
|
||||
title = <i><FormattedMessage id="unnamed_topic" /></i>;
|
||||
} else if (title.length > 30) {
|
||||
// FIXME: this is wrong for RTL languages.
|
||||
// FIXME: this is probably wrong for RTL languages.
|
||||
title = title.substring(0, 28) + '...';
|
||||
}
|
||||
var online = this.props.now ? 'online' : 'offline';
|
||||
var avatar = this.props.avatar ? this.props.avatar : true;
|
||||
var badges = [];
|
||||
let online = this.props.now ? 'online' : 'offline';
|
||||
let avatar = this.props.avatar ? this.props.avatar : true;
|
||||
let badges = [];
|
||||
if (this.props.badges && this.props.badges.length > 0) {
|
||||
var count = 0;
|
||||
let count = 0;
|
||||
this.props.badges.map(function(b) {
|
||||
var style = 'badge' + (b.color ? ' ' + b.color : '');
|
||||
let style = 'badge' + (b.color ? ' ' + b.color : '');
|
||||
badges.push(<span className={style} key={count}>{b.name}</span>);
|
||||
count ++;
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Context Menu: popup/dropdown menu.
|
||||
import React from 'react';
|
||||
import ReactDom from 'react-dom';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import { REM_SIZE } from '../config.js';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* GroupMembers: control for managing a list of group members */
|
||||
|
||||
// GroupMembers: control for managing a list of group members.
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import ChipInput from './chip-input.jsx';
|
||||
import ContactList from './contact-list.jsx';
|
||||
@@ -156,8 +156,12 @@ export default class GroupManager extends React.Component {
|
||||
showUnread={false}
|
||||
onTopicSelected={this.handleContactSelected} />
|
||||
<div id="group-manager-buttons" className="panel-form-row">
|
||||
<button className="blue" onClick={this.handleSubmit}>OK</button>
|
||||
<button className="white" onClick={this.handleCancel}>Cancel</button>
|
||||
<button className="blue" onClick={this.handleSubmit}>
|
||||
<FormattedMessage id="button_ok" defaultMessage="OK" description="Button [OK]" />
|
||||
</button>
|
||||
<button className="white" onClick={this.handleCancel}>
|
||||
<FormattedMessage id="button_cancel" defaultMessage="Cancel" description="Button [Cancel]" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { REM_SIZE } from '../config.js';
|
||||
import { fitImageSize } from '../lib/blob-helpers.js';
|
||||
import { bytesToHumanSize } from '../lib/strformat.js';
|
||||
|
||||
export default class ImagePreview extends React.PureComponent {
|
||||
constructor(props) {
|
||||
@@ -43,10 +48,19 @@ export default class ImagePreview extends React.PureComponent {
|
||||
<img src={this.props.content.url} style={size} />
|
||||
</div>
|
||||
<div id="image-preview-footer">
|
||||
<div><div><b>File name</b>:</div><div><span title={this.props.content.filename}>{filename}</span></div></div>
|
||||
<div><div><b>Content type</b>:</div><div>{this.props.content.type}</div></div>
|
||||
<div>
|
||||
<div><b>Size</b>:</div>
|
||||
<div><b><FormattedMessage id="label_file_name" defaultMessage="File name:"
|
||||
description="Label for a file name" /></b></div>
|
||||
<div><span title={this.props.content.filename}>{filename}</span></div>
|
||||
</div>
|
||||
<div>
|
||||
<div><b><FormattedMessage id="label_content_type" defaultMessage="Content type:"
|
||||
description="Label for file content type (mime)" /></b></div>
|
||||
<div>{this.props.content.type}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div><b><FormattedMessage id="label_size" defaultMessage="Size:"
|
||||
description="Label for file size" /></b></div>
|
||||
<div>{this.props.content.width} × {this.props.content.height} px; {bytesToHumanSize(this.props.content.size)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// In-place text editor. Shows text with an icon which toggles it into an input field.
|
||||
import React from 'react';
|
||||
import ReactDom from 'react-dom';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import VisiblePassword from './visible-password.jsx';
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
// Send message form.
|
||||
import React from 'react';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { Drafty } from 'tinode-sdk';
|
||||
|
||||
import { KEYPRESS_DELAY } from '../config.js';
|
||||
import { KEYPRESS_DELAY, MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM, MAX_INBAND_ATTACHMENT_SIZE } from '../config.js';
|
||||
import { SUPPORTED_IMAGE_FORMATS, filePasted, imageFileToBase64, imageFileScaledToBase64 } from '../lib/blob-helpers.js';
|
||||
import { bytesToHumanSize } from '../lib/strformat.js';
|
||||
|
||||
const messages = defineMessages({
|
||||
'messaging_disabled': {
|
||||
@@ -14,7 +17,17 @@ const messages = defineMessages({
|
||||
id: 'new_message_prompt',
|
||||
defaultMessage: 'New message',
|
||||
description: 'Prompt in SendMessage in read-only topic'
|
||||
}
|
||||
},
|
||||
'file_attachment_too_large': {
|
||||
id: 'file_attachment_too_large',
|
||||
defaultMessage: 'The file size {size} exceeds the {limit} limit.',
|
||||
description: 'Error message when attachment is too large'
|
||||
},
|
||||
'cannot_initiate_upload': {
|
||||
id: 'cannot_initiate_file_upload',
|
||||
defaultMessage: 'Cannot initiate file upload.',
|
||||
description: 'Generic error messagewhen attachment fails'
|
||||
},
|
||||
});
|
||||
|
||||
class SendMessage extends React.PureComponent {
|
||||
@@ -99,17 +112,18 @@ class SendMessage extends React.PureComponent {
|
||||
}
|
||||
|
||||
handleAttachFile(e) {
|
||||
const {formatMessage} = this.props.intl;
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
var file = e.target.files[0];
|
||||
if (file.size > MAX_EXTERN_ATTACHMENT_SIZE) {
|
||||
// Too large.
|
||||
this.props.onError("The file size " + bytesToHumanSize(file.size) +
|
||||
" exceeds the " + bytesToHumanSize(MAX_EXTERN_ATTACHMENT_SIZE) + " limit.", 'err');
|
||||
this.props.onError(formatMessage(messages.file_attachment_too_large,
|
||||
{size: bytesToHumanSize(file.size), limit: bytesToHumanSize(MAX_EXTERN_ATTACHMENT_SIZE)}), 'err');
|
||||
} else if (file.size > MAX_INBAND_ATTACHMENT_SIZE) {
|
||||
// Too large to send inband - uploading out of band and sending as a link.
|
||||
let uploader = this.props.tinode.getLargeFileHelper();
|
||||
if (!uploader) {
|
||||
this.props.onError("Cannot initiate file upload.");
|
||||
this.props.onError(formatMessage(messages.cannot_initiate_upload));
|
||||
return;
|
||||
}
|
||||
// Format data and initiate upload.
|
||||
|
||||
Reference in New Issue
Block a user