Merge branch 'devel' into features

This commit is contained in:
aforge
2021-08-03 16:27:10 +03:00
14 changed files with 438 additions and 55 deletions
+3 -2
View File
@@ -28,16 +28,17 @@ This is NOT a standalone app, this is just a frontend, a client. It requires a [
The app is fully internationalized using [React-Intl](https://github.com/formatjs/react-intl). The UI language is selected automatically from the language specified by the browser. A specific language can be forced by adding `#?hl=XX` parameter to the URL when starting the app, e.g. https://web.tinode.co/#?hl=ru.
As of the time of this writing the following translations exist:
The app is currently available in the following languages:
* English
* Chinese (simplified)
* Chinese (traditional)
* German
* Korean
* Romanian
* Russian
* Spanish
More translations are welcome. The source file with the original English strings and context explanations is located at [/src/i18n/ex/base-en.json](/src/i18n/ex/base-en.json). Only `defaultMessage` needs to be translated. Send a pull request with a json file with translated strings. Take a look at [Spanish](/src/i18n/es.json), [Russian](/src/i18n/ru.json), or [Simplified Chinese](/src/i18n/zh.json) translations for guidance.
More translations are welcome. See [instructions](https://github.com/tinode/chat/blob/devel/docs/translations.md#webapp).
## Not done yet
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "tinode-webapp",
"description": "Tinode messenger for the web",
"version": "0.17.6",
"version": "0.17.7-rc1",
"repository": {
"type": "git",
"url": "https://github.com/tinode/example-react-js.git"
@@ -67,7 +67,7 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-intl": "^5.20.2",
"tinode-sdk": "^0.17.6"
"tinode-sdk": "^0.17.7-rc1"
},
"devDependencies": {
"@babel/core": "^7.14.5",
+10 -3
View File
@@ -4,8 +4,9 @@ importScripts('https://cdn.jsdelivr.net/npm/firebase@8.7.1/firebase-messaging.js
importScripts('firebase-init.js');
importScripts('version.js');
// Channel to notify the webapp.
const webAppChannel = new BroadcastChannel('tinode-sw');
// Channel to notify the webapp. There is no BroadcastChannel in Safari.
const webAppChannel = (typeof BroadcastChannel == 'function') ?
new BroadcastChannel('tinode-sw') : null;
// Basic internationalization.
const i18n = {
@@ -36,6 +37,10 @@ const i18n = {
'zh': {
'new_message': "新讯息",
'new_chat': "新聊天",
},
'zh-TW': {
'new_message': "新訊息",
'new_chat': "新聊天",
}
};
self.i18nMessage = function(id) {
@@ -56,7 +61,9 @@ fbMessaging.onBackgroundMessage((payload) => {
}
// Notify webapp that a message was received.
webAppChannel.postMessage(payload.data);
if (webAppChannel) {
webAppChannel.postMessage(payload.data);
}
const pushType = payload.data.what || 'msg';
const title = payload.data.title || self.i18nMessage(pushType == 'msg' ? 'new_message' : 'new_chat');
+179
View File
@@ -0,0 +1,179 @@
{
"action_block_contact": "封鎖聯絡人",
"action_cancel": "取消",
"action_clear_messages": "清除訊息",
"action_delete_messages": "為所有人清除訊息",
"action_leave_chat": "離開對話",
"action_more": "更多",
"action_report_chat": "檢舉對話",
"archived_contacts": "已封存的聯絡人 ({count})",
"badge_owner": "擁有者",
"badge_you": "您",
"block_contact_warning": "您確定要封鎖此聯絡人嗎?",
"blocked_contacts_link": "已封鎖的聯絡人 ({count})",
"button_add_another": "新增其他人",
"button_add_members": "新增成員",
"button_cancel": "取消",
"button_confirm": "確認",
"button_create": "建立",
"button_delete_account": "刪除帳號",
"button_edit": "編輯",
"button_logout": "登出",
"button_ok": "OK",
"button_reset": "重設",
"button_send_request": "傳送要求",
"button_sign_in": "登入",
"button_sign_up": "註冊",
"button_subscribe": "訂閱",
"button_update": "更新",
"cannot_initiate_file_upload": "無法為檔案上傳初始化。",
"channel": "頻道",
"channel_prompt": "這是頻道",
"chat_invitation": "您已被邀請開始新對話。您接下來要做什麼呢?",
"chat_invitation_accept": "接受",
"chat_invitation_block": "封鎖",
"chat_invitation_ignore": "忽略",
"clear_messages_warning": "您確定要清除所有訊息嗎?此操作無法復原。",
"code_doesnot_match": "代碼不相符",
"contacts_not_found": "您沒有任何對話<br />¯∖_(ツ)_/¯",
"contacts_not_found_short": "沒有符合 ''{query}'' 的聯絡人",
"credential_email_prompt": "您的註冊電子郵件地址",
"delete_account": "刪除帳號",
"delete_account_arning": "您確定要刪除您的帳號嗎?此操作無法復原。",
"delete_messages_warning": "您確定要為所有人刪除所有訊息嗎?此操作無法復原。",
"deleted_content": "內容已被刪除",
"download_action": "下載",
"drafty_attachment": "附加檔案",
"drafty_form": "表單:",
"drafty_image": "圖片",
"email_dative": "電子郵件地址",
"email_prompt": "電子郵件地址,例如:jdoe@example.com",
"enable_peers_messaging": "啟用",
"enter_confirmation_code_prompt": "輸入透過 {method} 傳送給您的確認碼:",
"error_invalid_id": "ID 無效",
"file_attachment_too_large": "檔案大小 {size} 超出 {limit} 限制。",
"forgot_password_link": "忘記密碼?",
"full_name_prompt": "全名,例如:王小明",
"granted_permissions": "已授權",
"group_has_no_members": "無成員",
"group_user_id_prompt": "群組或使用者 ID",
"image_caption_prompt": "圖片說明",
"invalid_content": "內容無效",
"invalid_security_token": "安全權杖無效",
"label_client": "客戶端:",
"label_content_type": "類型:",
"label_default_access": "預設存取模式:",
"label_default_access_mode": "預設存取模式:",
"label_file_name": "檔名:",
"label_group_members": "群組成員:",
"label_incognito_mode": "無痕模式:",
"label_message_sound": "訊息提示聲:",
"label_muting_topic": "靜音:",
"label_other_user": "其他",
"label_password": "密碼",
"label_permissions": "權限:",
"label_private": "私人留言",
"label_push_notifications": "通知:",
"label_push_notifications_disabled": "通知 (需要 HTTPS):",
"label_reset_password": "傳送重設密碼郵件:",
"label_sdk": "SDK:",
"label_server": "伺服器:",
"label_server_address": "伺服器位址:",
"label_server_to_use": "使用的伺服器:",
"label_size": "大小:",
"label_topic_name": "名稱",
"label_user_contacts": "聯絡人:",
"label_user_id": "ID:",
"label_wire_transport": "Wire transport:",
"label_you": "您:",
"label_your_name": "您的名字",
"label_your_permissions": "您的權限:",
"last_seen_timestamp": "最後上線",
"leave_chat_warning": "您確定要離開此對話嗎?",
"link_contact_us": "聯絡我們",
"link_privacy_policy": "隱私權政策",
"link_terms_of_service": "服務條款",
"login_prompt": "登入",
"menu_item_archive_topic": "封存",
"menu_item_block": "封鎖",
"menu_item_clear_messages": "清除訊息",
"menu_item_clear_messages_for_all": "為所有人清除訊息",
"menu_item_delete": "刪除",
"menu_item_delete_for_all": "為所有人刪除",
"menu_item_delete_topic": "刪除",
"menu_item_edit_permissions": "編輯權限",
"menu_item_info": "Info",
"menu_item_member_delete": "移除",
"menu_item_mute": "靜音",
"menu_item_send_retry": "重試",
"menu_item_unblock": "解除封鎖",
"menu_item_unmute": "解除靜音",
"message_sending": "正在傳送...",
"message_sending_failed": "失敗",
"messages_not_readable": "沒有存取訊息的權限",
"messaging_disabled_prompt": "停用訊息",
"more_online_members": "+{overflow}",
"new_message_prompt": "新訊息",
"new_password_placeholder": "輸入新的密碼",
"no_connection": "無連線",
"no_contacts": "您沒有任何聯絡人 :-(",
"numeric_confirmation_code_prompt": "僅數字",
"online_now": "上線中",
"password_prompt": "密碼",
"password_unchanged_prompt": "未修改",
"peers_messaging_disabled": "Peer 已停用訊息。",
"permission_admin": "核可 ({val})",
"permission_delete": "刪除 ({val})",
"permission_join": "加入 ({val})",
"permission_owner": "擁有者 ({val})",
"permission_pres": "收到通知 ({val})",
"permission_read": "讀取 ({val})",
"permission_share": "分享 ({val})",
"permission_write": "撰寫 ({val})",
"phone_dative": "phone",
"private_editing_placeholder": "僅您可見",
"push_init_failed": "初始化通知失敗。",
"reconnect_countdown": "已斷線。將在 {seconds} 秒後重新連線…",
"reconnect_now": "現在重試",
"reload_update": "重新載入",
"report_chat_warning": "您確定要封鎖並檢舉此對話嗎?",
"requested_permissions": "重新請求",
"save_attachment": "儲存",
"search_for_contacts": "使用搜尋來尋找聯絡人",
"search_no_results": "搜尋無結果",
"search_placeholder": "例如 email:alice@example.com, tel:17025550003... 的清單",
"sidepanel_title_acc_general": "一般",
"sidepanel_title_acc_notifications": "通知",
"sidepanel_title_acc_security": "安全性",
"sidepanel_title_acc_support": "支援",
"sidepanel_title_account_settings": "帳號設定",
"sidepanel_title_archive": "已封存的對話",
"sidepanel_title_blocked": "已封鎖的對話",
"sidepanel_title_cred": "確認認證",
"sidepanel_title_login": "登入",
"sidepanel_title_newtpk": "開始新對話",
"sidepanel_title_register": "建立帳號",
"sidepanel_title_reset": "重設密碼",
"sidepanel_title_settings": "設定",
"stay_logged_in": "保持登入",
"tabtitle_find_user": "尋找",
"tabtitle_group_by_id": "以 id",
"tabtitle_new_group": "新群組",
"tags_editor_no_tags": "新增一些標籤",
"tags_not_found": "未定義任何標籤。請新增一些標籤。",
"title_all_contacts": "所有聯絡人",
"title_group_members": "群組成員",
"title_info": "資訊",
"title_manage_tags": "管理",
"title_not_found": "找不到",
"title_permissions": "權限",
"title_tag_manager": "標籤 (使用者探索)",
"topic_block_warning": "您確定要封鎖此對話嗎?",
"topic_delete_warning": "您確定要刪除此對話嗎?",
"topic_name_editing_placeholder": "群組的任意名稱",
"unnamed_topic": "未命名",
"update_available": "有可用的更新。",
"upload_finishing": "正在完成...",
"user_not_found": "找不到",
"validate_credential_action": "確認"
}
+179
View File
@@ -1074,6 +1074,185 @@
"drafty_form": "Форма:",
"drafty_image": "Картинка"
},
"zh-TW": {
"action_block_contact": "封鎖聯絡人",
"action_cancel": "取消",
"action_clear_messages": "清除訊息",
"action_delete_messages": "為所有人清除訊息",
"action_leave_chat": "離開對話",
"action_more": "更多",
"action_report_chat": "檢舉對話",
"archived_contacts": "已封存的聯絡人 ({count})",
"badge_owner": "擁有者",
"badge_you": "您",
"block_contact_warning": "您確定要封鎖此聯絡人嗎?",
"blocked_contacts_link": "已封鎖的聯絡人 ({count})",
"button_add_another": "新增其他人",
"button_add_members": "新增成員",
"button_cancel": "取消",
"button_confirm": "確認",
"button_create": "建立",
"button_delete_account": "刪除帳號",
"button_edit": "編輯",
"button_logout": "登出",
"button_ok": "OK",
"button_reset": "重設",
"button_send_request": "傳送要求",
"button_sign_in": "登入",
"button_sign_up": "註冊",
"button_subscribe": "訂閱",
"button_update": "更新",
"cannot_initiate_file_upload": "無法為檔案上傳初始化。",
"channel": "頻道",
"channel_prompt": "這是頻道",
"chat_invitation": "您已被邀請開始新對話。您接下來要做什麼呢?",
"chat_invitation_accept": "接受",
"chat_invitation_block": "封鎖",
"chat_invitation_ignore": "忽略",
"clear_messages_warning": "您確定要清除所有訊息嗎?此操作無法復原。",
"code_doesnot_match": "代碼不相符",
"contacts_not_found": "您沒有任何對話<br />¯∖_(ツ)_/¯",
"contacts_not_found_short": "沒有符合 ''{query}'' 的聯絡人",
"credential_email_prompt": "您的註冊電子郵件地址",
"delete_account": "刪除帳號",
"delete_account_arning": "您確定要刪除您的帳號嗎?此操作無法復原。",
"delete_messages_warning": "您確定要為所有人刪除所有訊息嗎?此操作無法復原。",
"deleted_content": "內容已被刪除",
"download_action": "下載",
"drafty_attachment": "附加檔案",
"drafty_form": "表單:",
"drafty_image": "圖片",
"email_dative": "電子郵件地址",
"email_prompt": "電子郵件地址,例如:jdoe@example.com",
"enable_peers_messaging": "啟用",
"enter_confirmation_code_prompt": "輸入透過 {method} 傳送給您的確認碼:",
"error_invalid_id": "ID 無效",
"file_attachment_too_large": "檔案大小 {size} 超出 {limit} 限制。",
"forgot_password_link": "忘記密碼?",
"full_name_prompt": "全名,例如:王小明",
"granted_permissions": "已授權",
"group_has_no_members": "無成員",
"group_user_id_prompt": "群組或使用者 ID",
"image_caption_prompt": "圖片說明",
"invalid_content": "內容無效",
"invalid_security_token": "安全權杖無效",
"label_client": "客戶端:",
"label_content_type": "類型:",
"label_default_access": "預設存取模式:",
"label_default_access_mode": "預設存取模式:",
"label_file_name": "檔名:",
"label_group_members": "群組成員:",
"label_incognito_mode": "無痕模式:",
"label_message_sound": "訊息提示聲:",
"label_muting_topic": "靜音:",
"label_other_user": "其他",
"label_password": "密碼",
"label_permissions": "權限:",
"label_private": "私人留言",
"label_push_notifications": "通知:",
"label_push_notifications_disabled": "通知 (需要 HTTPS):",
"label_reset_password": "傳送重設密碼郵件:",
"label_sdk": "SDK:",
"label_server": "伺服器:",
"label_server_address": "伺服器位址:",
"label_server_to_use": "使用的伺服器:",
"label_size": "大小:",
"label_topic_name": "名稱",
"label_user_contacts": "聯絡人:",
"label_user_id": "ID:",
"label_wire_transport": "Wire transport:",
"label_you": "您:",
"label_your_name": "您的名字",
"label_your_permissions": "您的權限:",
"last_seen_timestamp": "最後上線",
"leave_chat_warning": "您確定要離開此對話嗎?",
"link_contact_us": "聯絡我們",
"link_privacy_policy": "隱私權政策",
"link_terms_of_service": "服務條款",
"login_prompt": "登入",
"menu_item_archive_topic": "封存",
"menu_item_block": "封鎖",
"menu_item_clear_messages": "清除訊息",
"menu_item_clear_messages_for_all": "為所有人清除訊息",
"menu_item_delete": "刪除",
"menu_item_delete_for_all": "為所有人刪除",
"menu_item_delete_topic": "刪除",
"menu_item_edit_permissions": "編輯權限",
"menu_item_info": "Info",
"menu_item_member_delete": "移除",
"menu_item_mute": "靜音",
"menu_item_send_retry": "重試",
"menu_item_unblock": "解除封鎖",
"menu_item_unmute": "解除靜音",
"message_sending": "正在傳送...",
"message_sending_failed": "失敗",
"messages_not_readable": "沒有存取訊息的權限",
"messaging_disabled_prompt": "停用訊息",
"more_online_members": "+{overflow}",
"new_message_prompt": "新訊息",
"new_password_placeholder": "輸入新的密碼",
"no_connection": "無連線",
"no_contacts": "您沒有任何聯絡人 :-(",
"numeric_confirmation_code_prompt": "僅數字",
"online_now": "上線中",
"password_prompt": "密碼",
"password_unchanged_prompt": "未修改",
"peers_messaging_disabled": "Peer 已停用訊息。",
"permission_admin": "核可 ({val})",
"permission_delete": "刪除 ({val})",
"permission_join": "加入 ({val})",
"permission_owner": "擁有者 ({val})",
"permission_pres": "收到通知 ({val})",
"permission_read": "讀取 ({val})",
"permission_share": "分享 ({val})",
"permission_write": "撰寫 ({val})",
"phone_dative": "phone",
"private_editing_placeholder": "僅您可見",
"push_init_failed": "初始化通知失敗。",
"reconnect_countdown": "已斷線。將在 {seconds} 秒後重新連線…",
"reconnect_now": "現在重試",
"reload_update": "重新載入",
"report_chat_warning": "您確定要封鎖並檢舉此對話嗎?",
"requested_permissions": "重新請求",
"save_attachment": "儲存",
"search_for_contacts": "使用搜尋來尋找聯絡人",
"search_no_results": "搜尋無結果",
"search_placeholder": "例如 email:alice@example.com, tel:17025550003... 的清單",
"sidepanel_title_acc_general": "一般",
"sidepanel_title_acc_notifications": "通知",
"sidepanel_title_acc_security": "安全性",
"sidepanel_title_acc_support": "支援",
"sidepanel_title_account_settings": "帳號設定",
"sidepanel_title_archive": "已封存的對話",
"sidepanel_title_blocked": "已封鎖的對話",
"sidepanel_title_cred": "確認認證",
"sidepanel_title_login": "登入",
"sidepanel_title_newtpk": "開始新對話",
"sidepanel_title_register": "建立帳號",
"sidepanel_title_reset": "重設密碼",
"sidepanel_title_settings": "設定",
"stay_logged_in": "保持登入",
"tabtitle_find_user": "尋找",
"tabtitle_group_by_id": "以 id",
"tabtitle_new_group": "新群組",
"tags_editor_no_tags": "新增一些標籤",
"tags_not_found": "未定義任何標籤。請新增一些標籤。",
"title_all_contacts": "所有聯絡人",
"title_group_members": "群組成員",
"title_info": "資訊",
"title_manage_tags": "管理",
"title_not_found": "找不到",
"title_permissions": "權限",
"title_tag_manager": "標籤 (使用者探索)",
"topic_block_warning": "您確定要封鎖此對話嗎?",
"topic_delete_warning": "您確定要刪除此對話嗎?",
"topic_name_editing_placeholder": "群組的任意名稱",
"unnamed_topic": "未命名",
"update_available": "有可用的更新。",
"upload_finishing": "正在完成...",
"user_not_found": "找不到",
"validate_credential_action": "確認"
},
"zh": {
"archived_contacts": "已归档联系人 ({count})",
"contacts_not_found": "你尚无会话<br />¯∖_(ツ)_/¯",
+1 -1
View File
@@ -1,3 +1,3 @@
// This is a generated file. Don't edit.
export const PACKAGE_VERSION = "0.17.6";
export const PACKAGE_VERSION = "0.17.7-rc1";
+28 -20
View File
@@ -313,7 +313,7 @@ class TinodeWeb extends React.Component {
initFCMessaging() {
const {formatMessage, locale} = this.props.intl;
const onError = (msg, err) => {
console.log(msg, err);
console.error(msg, err);
this.handleError(formatMessage(messages.push_init_failed), 'err');
this.setState({desktopAlertsEnabled: false});
}
@@ -389,24 +389,28 @@ class TinodeWeb extends React.Component {
'cred','reset','newtpk','archive','blocked','contacts',''].includes(hash.path[0])) {
this.setState({sidePanelSelected: hash.path[0]});
} else {
console.log("Unknown sidepanel view", hash.path[0]);
console.warn("Unknown sidepanel view", hash.path[0]);
}
// Topic for MessagesView selector.
const topicName = hash.path[1];
if (Tinode.topicType(topicName) && topicName != this.state.topicSelected) {
const newState = {
topicSelected: topicName
};
const acs = this.tinode.getTopicAccessMode(topicName);
if (acs) {
newState.topicSelectedAcs = acs;
}
this.setState(newState);
let topicName = hash.path[1] || null;
if (topicName != this.state.topicSelected) {
if (!Tinode.topicType(topicName)) {
// Clear invalid topic name.
topicName = null;
}
const newState = {
topicSelected: topicName
};
const acs = this.tinode.getTopicAccessMode(topicName);
if (acs) {
newState.topicSelectedAcs = acs;
}
this.setState(newState);
}
} else {
// Empty hashpath
this.setState({sidePanelSelected: ''});
this.setState({sidePanelSelected: '', topicSelected: null});
}
// Save validation credentials, if available.
@@ -469,13 +473,11 @@ class TinodeWeb extends React.Component {
handlePersistenceChange(persist) {
if (persist) {
this.tinode.initStorage().then(() => {
console.log("storage initialized");
LocalStorageUtil.setObject('keep-logged-in', true);
this.setState({persist: true});
});
} else {
this.tinode.clearStorage().then(() => {
console.log("storage cleared");
LocalStorageUtil.setObject('keep-logged-in', false);
this.setState({persist: false});
});
@@ -715,7 +717,7 @@ class TinodeWeb extends React.Component {
} else {
// TODO(gene): handle other types of notifications:
// * ua -- user agent changes (maybe display a pictogram for mobile/desktop).
console.log("Unsupported (yet) presence update:" + what + " in: " + cont.topic);
console.info("Unsupported (yet) presence update:" + what + " in: " + cont.topic);
}
}
@@ -772,6 +774,12 @@ class TinodeWeb extends React.Component {
newState.topicSelectedAcs = c.acs;
}
});
const past = new Date(0);
newState.chatList.sort((a, b) => {
return (a.touched || past).getTime() - (b.touched || past).getTime();
});
// Merge search results and chat list.
newState.searchableContacts = TinodeWeb.prepareSearchableContacts(newState.chatList, this.state.searchResults);
this.setState(newState);
@@ -938,7 +946,7 @@ class TinodeWeb extends React.Component {
});
break;
default:
console.log("Unknown invitation action", '"' + action + '""');
console.warn("Unknown invitation action", '"' + action + '""');
}
if (response != null) {
@@ -1070,7 +1078,7 @@ class TinodeWeb extends React.Component {
}).then(() => {
this.requestPushToken();
}).catch((err) => {
console.log("Failed to get notification permission.", err);
console.warn("Failed to get notification permission.", err);
this.handleError(err.message, 'err');
this.setState({desktopAlerts: false, firebaseToken: null});
LocalStorageUtil.updateObject('settings', {desktopAlerts: false});
@@ -1083,7 +1091,7 @@ class TinodeWeb extends React.Component {
}
} else if (this.state.firebaseToken && this.fbPush) {
this.fbPush.deleteToken(this.state.firebaseToken).catch((err) => {
console.log("Unable to delete token.", err);
console.warn("Unable to delete token.", err);
}).finally(() => {
LocalStorageUtil.updateObject('settings', {desktopAlerts: false});
localStorage.removeItem('firebase-token');
@@ -1112,7 +1120,7 @@ class TinodeWeb extends React.Component {
}
}).catch((err) => {
this.handleError(err.message, 'err');
console.log("Failed to retrieve firebase token", err);
console.warn("Failed to retrieve firebase token", err);
});
}
+29 -16
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -6
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,3 +1,3 @@
// This is a generated file. Don't edit.
const PACKAGE_VERSION = "0.17.6";
const PACKAGE_VERSION = "0.17.7-rc1";