From d7d4f082f7d2dfe0b90ebda2ef9e90f46b3849cb Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Thu, 23 Feb 2017 14:39:58 -0300 Subject: [PATCH] Add spinning icon; Fix performance issues; --- .../client/lib/actionButton.js | 9 ++- .../client/lib/autotranslate.js | 62 ++++++++++++------- .../client/stylesheets/autotranslate.less | 5 ++ .../client/views/autoTranslateFlexTab.html | 3 + .../client/views/autoTranslateFlexTab.js | 36 ++++++++--- packages/rocketchat-autotranslate/package.js | 1 + .../server/autotranslate.js | 2 +- .../server/methods/translateMessage.js | 8 +++ .../server/models/Messages.js | 9 ++- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + .../rocketchat-theme/client/imports/base.less | 40 ++++++++++++ .../message/message.coffee | 2 +- .../message/message.html | 2 +- 13 files changed, 145 insertions(+), 35 deletions(-) create mode 100644 packages/rocketchat-autotranslate/server/methods/translateMessage.js diff --git a/packages/rocketchat-autotranslate/client/lib/actionButton.js b/packages/rocketchat-autotranslate/client/lib/actionButton.js index 869e1801e06..8003cd9e8c0 100644 --- a/packages/rocketchat-autotranslate/client/lib/actionButton.js +++ b/packages/rocketchat-autotranslate/client/lib/actionButton.js @@ -11,8 +11,15 @@ Meteor.startup(function() { ], action() { const message = this._arguments[1]; + const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid, 'u._id': Meteor.userId() }); RocketChat.MessageAction.hideDropDown(); - if (message.autoTranslateShowInverse) { + if (!message.translations || !message.translations[subscription && subscription.autoTranslateLanguage]) { + if (!subscription.autoTranslateDisplay) { + RocketChat.AutoTranslate.messageIdsToWait[message._id] = true; + } + RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateFetching: true } }); + Meteor.call('autoTranslate.translateMessage', message); + } else if (message.autoTranslateShowInverse) { RocketChat.models.Messages.update({ _id: message._id }, { $unset: { autoTranslateShowInverse: true } }); } else { RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateShowInverse: true } }); diff --git a/packages/rocketchat-autotranslate/client/lib/autotranslate.js b/packages/rocketchat-autotranslate/client/lib/autotranslate.js index 84c1028981d..4c4e465b387 100644 --- a/packages/rocketchat-autotranslate/client/lib/autotranslate.js +++ b/packages/rocketchat-autotranslate/client/lib/autotranslate.js @@ -1,24 +1,44 @@ -Meteor.startup(function() { - Tracker.autorun(function() { - if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) { - RocketChat.callbacks.add('renderMessage', (message) => { - if (message.u._id !== Meteor.userId()) { - const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } }); - if (subscription && subscription.autoTranslate === true && subscription.autoTranslateLanguage && !!subscription.autoTranslateDisplay !== !!message.autoTranslateShowInverse) { - const autoTranslateLanguage = subscription.autoTranslateLanguage; - if (!message.translations) { - message.translations = {}; +RocketChat.AutoTranslate = { + messageIdsToWait: {}, + + init() { + Tracker.autorun(() => { + if (RocketChat.settings.get('AutoTranslate_Enabled') && RocketChat.authz.hasAtLeastOnePermission(['auto-translate'])) { + RocketChat.callbacks.add('renderMessage', (message) => { + if (message.u._id !== Meteor.userId()) { + const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } }); + if (subscription && subscription.autoTranslate === true && subscription.autoTranslateLanguage && !!subscription.autoTranslateDisplay !== !!message.autoTranslateShowInverse) { + const autoTranslateLanguage = subscription.autoTranslateLanguage; + if (!message.translations) { + message.translations = {}; + } + message.translations['original'] = message.html; + if (message.translations[autoTranslateLanguage]) { + message.html = message.translations[autoTranslateLanguage]; + } + return message; } - message.translations['original'] = message.html; - if (message.translations[autoTranslateLanguage]) { - message.html = message.translations[autoTranslateLanguage]; - } - return message; } - } - }, RocketChat.callbacks.priority.HIGH - 3, 'autotranslate'); - } else { - RocketChat.callbacks.remove('renderMessage', 'autotranslate'); - } - }); + }, RocketChat.callbacks.priority.HIGH - 3, 'autotranslate'); + + RocketChat.callbacks.add('streamMessage', (message) => { + const subscription = RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } }); + if (subscription && subscription.autoTranslate === true && subscription.autoTranslateLanguage && subscription.autoTranslateDisplay && (!message.translations || !message.translations[subscription.autoTranslateLanguage])) { + RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateFetching: true } }); + } + if (this.messageIdsToWait[message._id] !== undefined) { + RocketChat.models.Messages.update({ _id: message._id }, { $set: { autoTranslateShowInverse: true }, $unset: { autoTranslateFetching: 1 } }); + delete this.messageIdsToWait[message._id]; + } + }, RocketChat.callbacks.priority.HIGH - 3, 'autotranslate-stream'); + } else { + RocketChat.callbacks.remove('renderMessage', 'autotranslate'); + RocketChat.callbacks.remove('streamMessage', 'autotranslate-stream'); + } + }); + } +}; + +Meteor.startup(function() { + RocketChat.AutoTranslate.init(); }); diff --git a/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less b/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less index 8982744481d..9a1905ef017 100644 --- a/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less +++ b/packages/rocketchat-autotranslate/client/stylesheets/autotranslate.less @@ -39,6 +39,11 @@ border-left: 1px dotted; padding-left: 3px; margin-left: 3px; + + i.icon-language.loading { + display: inline-block; + animation: spinh 2000ms infinite linear; + } } &.sequential { diff --git a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html index 1852591f12e..90e31e6c9b8 100644 --- a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html +++ b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.html @@ -28,6 +28,9 @@ {{/each}} +
+ {{_ "AutoTranslate_Change_Language_Description"}} +
{{else}} diff --git a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js index 1d192eb844a..c1507f8b199 100644 --- a/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js +++ b/packages/rocketchat-autotranslate/client/views/autoTranslateFlexTab.js @@ -4,7 +4,7 @@ import toastr from 'toastr'; Template.autoTranslateFlexTab.helpers({ autoTranslate() { const sub = ChatSubscription.findOne({ - rid: Session.get('openedRoom') + rid: Template.instance().rid }, { fields: { autoTranslate: 1 @@ -15,7 +15,7 @@ Template.autoTranslateFlexTab.helpers({ autoTranslateDisplay() { const sub = ChatSubscription.findOne({ - rid: Session.get('openedRoom') + rid: Template.instance().rid }, { fields: { autoTranslateDisplay: 1 @@ -26,7 +26,7 @@ Template.autoTranslateFlexTab.helpers({ autoTranslateValue() { const sub = ChatSubscription.findOne({ - rid: Session.get('openedRoom') + rid: Template.instance().rid }, { fields: { autoTranslate: 1 @@ -37,7 +37,7 @@ Template.autoTranslateFlexTab.helpers({ autoTranslateLanguage() { const sub = ChatSubscription.findOne({ - rid: Session.get('openedRoom') + rid: Template.instance().rid }, { fields: { autoTranslateLanguage: 1 @@ -65,6 +65,7 @@ Template.autoTranslateFlexTab.helpers({ }); Template.autoTranslateFlexTab.onCreated(function() { + this.rid = Template.currentData().rid; this.editing = new ReactiveVar(); this.supportedLanguages = new ReactiveVar([]); const userLanguage = Meteor.user().language || window.defaultUserLanguage(); @@ -90,6 +91,8 @@ Template.autoTranslateFlexTab.onCreated(function() { this.saveSetting = () => { const field = this.editing.get(); + const subscription = RocketChat.models.Subscriptions.findOne({ rid: this.rid, 'u._id': Meteor.userId() }); + const previousLanguage = subscription.autoTranslateLanguage; let value; switch (field) { case 'autoTranslate': @@ -102,16 +105,33 @@ Template.autoTranslateFlexTab.onCreated(function() { } if (this.validateSetting(field)) { - Meteor.call('autoTranslate.saveSettings', Session.get('openedRoom'), field, value, (err/*, result*/) => { + Meteor.call('autoTranslate.saveSettings', this.data.rid, field, value, (err/*, result*/) => { if (err) { return handleError(err); } - // Update all visible messages to reflect this setting - if (field === 'autoTranslate' || field === 'autoTranslateDisplay') { - RocketChat.models.Messages.update({ rid: Session.get('openedRoom') }, { $unset: { autoTranslateShowInverse: 1 }, $set: { random: Random.id() } }, { multi: true }); + const query = { rid: this.data.rid, 'u._id': { $ne: Meteor.userId() } }; + if (field === 'autoTranslateLanguage') { + query.$or = [ { [`translations.${previousLanguage}`]: { $exists: 1 } }, { [`translations.${value}`]: { $exists: 1 } } ]; + } else { + query[`translations.${subscription.autoTranslateLanguage}`] = { $exists: 1 }; } + const update = { $set: { random: Random.id() } }; + + if (field === 'autoTranslateDisplay' && value === '0') { + RocketChat.models.Messages.update(query, { $unset: { autoTranslateShowInverse: 1 } }, { multi: true }); + } + + const display = field === 'autoTranslateDisplay' ? true : subscription.autoTranslateDisplay; + if (display) { + query.autoTranslateShowInverse = { $ne: true }; + } else { + query.autoTranslateShowInverse = true; + } + + console.log(query, RocketChat.models.Messages.find(query).fetch(), update); + RocketChat.models.Messages.update(query, update, { multi: true }); this.editing.set(); }); } diff --git a/packages/rocketchat-autotranslate/package.js b/packages/rocketchat-autotranslate/package.js index e4a5eee2b03..24cac3d6431 100644 --- a/packages/rocketchat-autotranslate/package.js +++ b/packages/rocketchat-autotranslate/package.js @@ -31,6 +31,7 @@ Package.onUse(function(api) { 'server/models/Messages.js', 'server/models/Subscriptions.js', 'server/methods/saveSettings.js', + 'server/methods/translateMessage.js', 'server/methods/getSupportedLanguages.js' ], 'server'); }); diff --git a/packages/rocketchat-autotranslate/server/autotranslate.js b/packages/rocketchat-autotranslate/server/autotranslate.js index a757ab97a01..a0db1015aec 100644 --- a/packages/rocketchat-autotranslate/server/autotranslate.js +++ b/packages/rocketchat-autotranslate/server/autotranslate.js @@ -84,7 +84,7 @@ class AutoTranslate { } }); if (!_.isEmpty(translations)) { - RocketChat.models.Messages.setTranslations(message._id, translations); + RocketChat.models.Messages.addTranslations(message._id, translations); } }); } diff --git a/packages/rocketchat-autotranslate/server/methods/translateMessage.js b/packages/rocketchat-autotranslate/server/methods/translateMessage.js new file mode 100644 index 00000000000..0138158122d --- /dev/null +++ b/packages/rocketchat-autotranslate/server/methods/translateMessage.js @@ -0,0 +1,8 @@ +Meteor.methods({ + 'autoTranslate.translateMessage'(message) { + const room = RocketChat.models.Rooms.findOneById(message && message.rid); + if (message && room && RocketChat.AutoTranslate) { + return RocketChat.AutoTranslate.translateMessage(message, room); + } + } +}); diff --git a/packages/rocketchat-autotranslate/server/models/Messages.js b/packages/rocketchat-autotranslate/server/models/Messages.js index 5d7c3777ae7..49d0f70eed1 100644 --- a/packages/rocketchat-autotranslate/server/models/Messages.js +++ b/packages/rocketchat-autotranslate/server/models/Messages.js @@ -1,3 +1,8 @@ -RocketChat.models.Messages.setTranslations = function(messageId, translations) { - return this.update({ _id: messageId }, { $set: { translations: translations }}); +RocketChat.models.Messages.addTranslations = function(messageId, translations) { + const updateObj = {}; + Object.keys(translations).forEach((key) => { + const translation = translations[key]; + updateObj[`translations.${key}`] = translation; + }); + return this.update({ _id: messageId }, { $set: updateObj }); }; diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 6d58d412718..68d82ac3c0e 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -218,6 +218,7 @@ "Auto_Translate": "Auto-Translate", "AutoTranslate_Enabled": "Enable Auto-Translate", "AutoTranslate_Enabled_Description": "Enabling auto-translation will allow people with the auto-translate permission to have all messages automatically translated into their selected language. Fees may apply, see Google's Documentation", + "AutoTranslate_Change_Language_Description": "Changing the auto-translate language does not translate previous messages.", "AutoTranslate_GoogleAPIKey": "Google API Key", "Available": "Available", "Available_agents": "Available agents", diff --git a/packages/rocketchat-theme/client/imports/base.less b/packages/rocketchat-theme/client/imports/base.less index 78381af1c3c..841378120b5 100644 --- a/packages/rocketchat-theme/client/imports/base.less +++ b/packages/rocketchat-theme/client/imports/base.less @@ -491,6 +491,46 @@ blockquote { } } +@-ms-keyframes spinh { + from { + -ms-transform: rotateY(0deg); + } + + to { + -ms-transform: rotateY(360deg); + } +} + +@-moz-keyframes spinh { + from { + -moz-transform: rotateY(0deg); + } + + to { + -moz-transform: rotateY(360deg); + } +} + +@-webkit-keyframes spinh { + from { + -webkit-transform: rotateY(0deg); + } + + to { + -webkit-transform: rotateY(360deg); + } +} + +@keyframes spinh { + from { + transform: rotateY(0deg); + } + + to { + transform: rotateY(360deg); + } +} + .rocket-h2 { font-weight: 300; text-transform: uppercase; diff --git a/packages/rocketchat-ui-message/message/message.coffee b/packages/rocketchat-ui-message/message/message.coffee index 306ddb3f0ce..817d4388b37 100644 --- a/packages/rocketchat-ui-message/message/message.coffee +++ b/packages/rocketchat-ui-message/message/message.coffee @@ -42,7 +42,7 @@ Template.message.helpers showTranslated: -> if RocketChat.settings.get('AutoTranslate_Enabled') and this.u?._id isnt Meteor.userId() and !RocketChat.MessageTypes.isSystemMessage(this) subscription = RocketChat.models.Subscriptions.findOne({ rid: this.rid }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1, autoTranslateDisplay: 1 } }); - return subscription.autoTranslate && !!subscription?.autoTranslateDisplay isnt !!this.autoTranslateShowInverse + return subscription.autoTranslate && !!subscription?.autoTranslateDisplay isnt !!this.autoTranslateShowInverse && (this.autoTranslateFetching || this.translations && this.translations[subscription.autoTranslateLanguage]) edited: -> return Template.instance().wasEdited diff --git a/packages/rocketchat-ui-message/message/message.html b/packages/rocketchat-ui-message/message/message.html index 172fe0a1c75..4aba38182c9 100644 --- a/packages/rocketchat-ui-message/message/message.html +++ b/packages/rocketchat-ui-message/message/message.html @@ -36,7 +36,7 @@ {{time}} {{#if showTranslated}} - + {{/if}} {{#if edited}}