more components are functional now
This commit is contained in:
+7
-2
@@ -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",
|
||||
@@ -38,7 +38,12 @@
|
||||
"sidepanel_title_newtpk": "Start New Chat",
|
||||
"sidepanel_title_cred": "Confirm Credentials",
|
||||
"sidepanel_title_reset": "Reset Password",
|
||||
"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",
|
||||
"tags_not_found": "No tags defined. Add some.",
|
||||
"tags_editor_no_tags": "Add some tags",
|
||||
"title_manage_tags": "Manage tags"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"en": {
|
||||
"contacts_not_found": "You have no chats<br />¯\\\\_(ツ)_/¯",
|
||||
"full_name_prompt": "Full name, e.g. John Doe",
|
||||
"email_prompt": "Email, e.g. jdoe@example.com",
|
||||
"button_sign_up": "Sign up",
|
||||
"label_your_name": "Your name",
|
||||
"label_password": "Password",
|
||||
"password_unchanged_prompt": "Unchanged",
|
||||
"label_user_id": "Address:",
|
||||
"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)",
|
||||
"title_tag_manager": "Tags (user discovery)",
|
||||
"button_logout": "Logout",
|
||||
"login_prompt": "Login",
|
||||
"password_prompt": "Password",
|
||||
"stay_logged_in": "Stay logged in",
|
||||
"forgot_password_link": "Forgot password?",
|
||||
"button_sign_in": "Sign in",
|
||||
"label_client": "Client:",
|
||||
"label_server": "Server:",
|
||||
"online_now": "online now",
|
||||
"last_seen_timestamp": "Last seen",
|
||||
"title_not_found": "Not found",
|
||||
"unnamed_topic": "Unnamed",
|
||||
"messages_not_readable": "no access to messages",
|
||||
"tabtitle_find_user": "find",
|
||||
"tabtitle_new_group": "new group",
|
||||
"tabtitle_group_by_id": "by id",
|
||||
"label_server_to_use": "Server to use:",
|
||||
"label_wire_transport": "Wire transport:",
|
||||
"button_update": "Update",
|
||||
"sidepanel_title_login": "Sign In",
|
||||
"sidepanel_title_register": "Create Account",
|
||||
"sidepanel_title_settings": "Settings",
|
||||
"sidepanel_title_edit_account": "Edit Account",
|
||||
"sidepanel_title_newtpk": "Start New Chat",
|
||||
"sidepanel_title_cred": "Confirm Credentials",
|
||||
"sidepanel_title_reset": "Reset Password",
|
||||
"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",
|
||||
"tags_not_found": "No tags defined. Add some.",
|
||||
"tags_editor_no_tags": "Add some tags",
|
||||
"title_manage_tags": "Manage tags"
|
||||
},
|
||||
"ru": {
|
||||
"contacts_not_found": "Чатов нет<br />¯\\\\_(ツ)_/¯",
|
||||
"full_name_prompt": "Полное имя, напр. Иван Петров",
|
||||
"email_prompt": "Email, напр. ivan@example.com",
|
||||
"button_sign_up": "Создать счет",
|
||||
"label_your_name": "Ваше имя",
|
||||
"label_password": "Пароль",
|
||||
"password_unchanged_prompt": "Не изменен",
|
||||
"label_user_id": "Адрес:",
|
||||
"label_default_access_mode": "Доступ по умолчанию:",
|
||||
"label_message_sound": "Звук нового сообщения:",
|
||||
"label_push_notifications": "Уведомления:",
|
||||
"label_push_notifications_disabled": "Уведомления (требуют HTTPS):",
|
||||
"title_tag_manager": "Таги для поиска",
|
||||
"button_logout": "Выйти",
|
||||
"login_prompt": "Логин",
|
||||
"password_prompt": "Пароль",
|
||||
"stay_logged_in": "Запомнить",
|
||||
"forgot_password_link": "Напомнить пароль",
|
||||
"button_sign_in": "Войти",
|
||||
"label_client": "Клиент:",
|
||||
"label_server": "Сервер:",
|
||||
"online_now": "онлайн",
|
||||
"last_seen_timestamp": "Был активен",
|
||||
"title_not_found": "Не найден",
|
||||
"unnamed_topic": "Без названия",
|
||||
"messages_not_readable": "нет доступа к сообщениям",
|
||||
"tabtitle_find_user": "найти",
|
||||
"tabtitle_new_group": "создать",
|
||||
"tabtitle_group_by_id": "по id",
|
||||
"label_server_to_use": "Использовать сервер:",
|
||||
"label_wire_transport": "Соединение:",
|
||||
"button_update": "Применить",
|
||||
"sidepanel_title_login": "Авторизация",
|
||||
"sidepanel_title_register": "Зарегистрироваться",
|
||||
"sidepanel_title_settings": "Настройки",
|
||||
"sidepanel_title_edit_account": "Редактировать счет",
|
||||
"sidepanel_title_newtpk": "Новый чат",
|
||||
"sidepanel_title_cred": "Подтвердить",
|
||||
"sidepanel_title_reset": "Сменить пароль",
|
||||
"tags_not_found": "Тагов нет. Добавьте",
|
||||
"tags_editor_no_tags": "Добавьте таги",
|
||||
"title_manage_tags": "Редактор тагов"
|
||||
}
|
||||
}
|
||||
@@ -192,12 +192,12 @@ export default class EditAccountView extends React.Component {
|
||||
<div className="panel-form-row">
|
||||
<label htmlFor="desktop-alerts">
|
||||
{this.props.desktopAlertsEnabled ?
|
||||
<FormattedMessage id="label_push_notifications" defaultMessage="Notification alerts"
|
||||
<FormattedMessage id="label_push_notifications" defaultMessage="Notification alerts:"
|
||||
description="Label for push notifications switch" />
|
||||
:
|
||||
<FormattedMessage id="label_push_notifications_disabled"
|
||||
defaultMessage="Notification alerts (requires HTTPS)"
|
||||
description="Label for push notifications switch (disabled)" />
|
||||
description="Label for push notifications switch (disabled):" />
|
||||
}
|
||||
</label>
|
||||
<CheckBox name="alert" id="desktop-alerts"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import Tinode from 'tinode-sdk';
|
||||
|
||||
import ChatMessage from '../widgets/chat-message.jsx';
|
||||
import ErrorPanel from '../widgets/error-panel.jsx';
|
||||
import GroupSubs from '../widgets/group-subs.jsx';
|
||||
@@ -10,6 +12,8 @@ import LoadSpinner from '../widgets/load-spinner.jsx';
|
||||
import LogoView from './logo-view.jsx';
|
||||
import SendMessage from '../widgets/send-message.jsx';
|
||||
|
||||
import { KEYPRESS_DELAY, MESSAGES_PAGE } from '../config.js';
|
||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||
import { shortDateFormat } from '../lib/strformat.js';
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -378,6 +382,7 @@ class MessagesView extends React.Component {
|
||||
let topic = this.props.tinode.getTopic(this.state.topic);
|
||||
let groupTopic = topic.getType() == 'grp';
|
||||
let previousFrom = null;
|
||||
let chatBoxClass = null;
|
||||
for (let i=0; i<this.state.messages.length; i++) {
|
||||
let msg = this.state.messages[i];
|
||||
let nextFrom = null;
|
||||
@@ -401,7 +406,7 @@ class MessagesView extends React.Component {
|
||||
let isReply = !(msg.from == this.props.myUserId);
|
||||
let deliveryStatus = topic.msgStatus(msg);
|
||||
|
||||
let userName, userAvatar, userFrom, chatBoxClass;
|
||||
let userName, userAvatar, userFrom;
|
||||
if (groupTopic) {
|
||||
let user = topic.userDesc(msg.from);
|
||||
if (user && user.public) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// The top-level class to hold all functionality together.
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import 'firebase/app';
|
||||
import 'firebase/messaging';
|
||||
@@ -12,14 +13,15 @@ import InfoView from './info-view.jsx';
|
||||
import MessagesView from './messages-view.jsx';
|
||||
import SidepanelView from './sidepanel-view.jsx';
|
||||
|
||||
import { API_KEY, APP_NAME, MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
||||
import { API_KEY, APP_NAME, MEDIA_BREAKPOINT, READ_DELAY, RECEIVED_DELAY } from '../config.js';
|
||||
import { makeImageUrl } from '../lib/blob-helpers.js';
|
||||
import { isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
||||
import LocalStorageUtil from '../lib/local-storage.js';
|
||||
import HashNavigation from '../lib/navigation.js';
|
||||
import { updateFavicon } from '../lib/utils.js';
|
||||
|
||||
// Sound to play on message received.
|
||||
export const POP_SOUND = new Audio('audio/msg.mp3');
|
||||
const POP_SOUND = new Audio('audio/msg.mp3');
|
||||
|
||||
export default class TinodeWeb extends React.Component {
|
||||
constructor(props) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* Context Menu: popup/dropdown menu */
|
||||
|
||||
// Context Menu: popup/dropdown menu.
|
||||
import React from 'react';
|
||||
import ReactDom from 'react-dom';
|
||||
|
||||
import { REM_SIZE } from '../config.js';
|
||||
|
||||
export default class ContextMenu extends React.Component {
|
||||
constructor(props) {
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
// Received/read indicator.
|
||||
|
||||
import React from 'react';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import Tinode from 'tinode-sdk';
|
||||
|
||||
export default class ReceivedMarker extends React.PureComponent {
|
||||
import { shortDateFormat } from '../lib/strformat.js';
|
||||
|
||||
const messages = defineMessages({
|
||||
'sending': {
|
||||
'id': 'message_sending',
|
||||
'defaultMessage': 'sending...',
|
||||
'description': 'Message being sent, in place of time stamp'
|
||||
},
|
||||
'failed': {
|
||||
'id': 'message_sending_failed',
|
||||
'defaultMessage': 'failed',
|
||||
'description': 'Failed to send message, in place of time stamp'
|
||||
}
|
||||
});
|
||||
|
||||
class ReceivedMarker extends React.PureComponent {
|
||||
render() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
let timestamp;
|
||||
if (this.props.received <= Tinode.MESSAGE_STATUS_SENDING) {
|
||||
timestamp = "sending ...";
|
||||
timestamp = formatMessage(messages.sending);
|
||||
} else if (this.props.received == Tinode.MESSAGE_STATUS_FAILED) {
|
||||
timestamp = "failed";
|
||||
timestamp = formatMessage(messages.failed);
|
||||
} else {
|
||||
timestamp = shortDateFormat(this.props.timestamp);
|
||||
}
|
||||
@@ -35,3 +51,5 @@ export default class ReceivedMarker extends React.PureComponent {
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default injectIntl(ReceivedMarker);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import Tinode from 'tinode-sdk';
|
||||
|
||||
export default class SearchContacts extends React.PureComponent {
|
||||
constructor(props) {
|
||||
@@ -53,10 +56,13 @@ export default class SearchContacts extends React.PureComponent {
|
||||
<div className="panel-form">
|
||||
<div className="panel-form-row">
|
||||
<i className="material-icons search">search</i>
|
||||
<input className="search" type="text"
|
||||
placeholder="List like email:alice@example.com, tel:17025550003..."
|
||||
value={this.state.search} onChange={this.handleSearchChange}
|
||||
onKeyDown={this.handleKeyDown} required autoFocus />
|
||||
<FormattedMessage id="search_placeholder" defaultMessage="List like email:alice@example.com, tel:17025550003..."
|
||||
description="Placeholder in contacts search field">{
|
||||
(search_placeholder) => <input className="search" type="text"
|
||||
placeholder={search_placeholder}
|
||||
value={this.state.search} onChange={this.handleSearchChange}
|
||||
onKeyDown={this.handleKeyDown} required autoFocus />
|
||||
}</FormattedMessage>
|
||||
<a href="javascript:;" onClick={this.handleClear}>
|
||||
<i className="material-icons">close</i>
|
||||
</a>
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
// Send message form.
|
||||
|
||||
import React from 'react';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
export default class SendMessage extends React.PureComponent {
|
||||
import { KEYPRESS_DELAY } from '../config.js';
|
||||
|
||||
const messages = defineMessages({
|
||||
'messaging_disabled': {
|
||||
id: 'messaging_disabled_prompt',
|
||||
defaultMessage: 'Messaging disabled',
|
||||
description: 'Prompt in SendMessage in read-only topic'
|
||||
},
|
||||
'type_new_message': {
|
||||
id: 'new_message_prompt',
|
||||
defaultMessage: 'New message',
|
||||
description: 'Prompt in SendMessage in read-only topic'
|
||||
}
|
||||
});
|
||||
|
||||
class SendMessage extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@@ -152,8 +167,11 @@ export default class SendMessage extends React.PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
var prompt = this.props.disabled ? "Messaging disabled" : "New message";
|
||||
var instance = this;
|
||||
const {formatMessage} = this.props.intl;
|
||||
const prompt = this.props.disabled ?
|
||||
formatMessage(messages.messaging_disabled) :
|
||||
formatMessage(messages.type_new_message);
|
||||
let instance = this;
|
||||
return (
|
||||
<div id="send-message-panel">
|
||||
{this.props.disabled ?
|
||||
@@ -173,7 +191,9 @@ export default class SendMessage extends React.PureComponent {
|
||||
autoFocus />
|
||||
{this.props.disabled ?
|
||||
<i className="material-icons disabled">send</i> :
|
||||
<a href="javascript:;" onClick={this.handleSend} title="Send"><i className="material-icons">send</i></a>}
|
||||
<a href="javascript:;" onClick={this.handleSend} title="Send">
|
||||
<i className="material-icons">send</i>
|
||||
</a>}
|
||||
<input type="file" ref={function(ref) {instance.attachFile = ref;}}
|
||||
onChange={this.handleAttachFile} style={{display: 'none'}} />
|
||||
<input type="file" ref={function(ref) {instance.attachImage = ref;}} accept="image/*"
|
||||
@@ -182,3 +202,5 @@ export default class SendMessage extends React.PureComponent {
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default injectIntl(SendMessage);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// The counter of unread messages in the topic.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default class UnreadBadge extends React.PureComponent {
|
||||
|
||||
+9
-9
File diff suppressed because one or more lines are too long
+5
-5
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user