diff --git a/config/config.json b/config/config.json index f538e96865..330db637d8 100644 --- a/config/config.json +++ b/config/config.json @@ -38,7 +38,9 @@ "RestrictCustomEmojiCreation": "all", "RestrictPostDelete": "all", "AllowEditPost": "always", - "PostEditTimeLimit": 300 + "PostEditTimeLimit": 300, + "TimeBetweenUserTypingUpdatesMilliseconds": 5000, + "EnableUserTypingMessages": true }, "TeamSettings": { "SiteName": "Mattermost", diff --git a/i18n/en.json b/i18n/en.json index 4b254a42c9..7a8c24cbba 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -3535,6 +3535,10 @@ "id": "model.compliance.is_valid.start_end_at.app_error", "translation": "To must be greater than From" }, + { + "id": "model.config.is_valid.time_between_user_typing.app_error", + "translation": "Time btween user typing updates should not be set less than 1000 milliseconds." + }, { "id": "model.config.is_valid.cluster_email_batching.app_error", "translation": "Unable to enable email batching when clustering is enabled" diff --git a/model/config.go b/model/config.go index 13e795170e..4588731b62 100644 --- a/model/config.go +++ b/model/config.go @@ -64,45 +64,47 @@ const ( ) type ServiceSettings struct { - SiteURL *string - ListenAddress string - ConnectionSecurity *string - TLSCertFile *string - TLSKeyFile *string - UseLetsEncrypt *bool - LetsEncryptCertificateCacheFile *string - Forward80To443 *bool - ReadTimeout *int - WriteTimeout *int - MaximumLoginAttempts int - SegmentDeveloperKey string - GoogleDeveloperKey string - EnableOAuthServiceProvider bool - EnableIncomingWebhooks bool - EnableOutgoingWebhooks bool - EnableCommands *bool - EnableOnlyAdminIntegrations *bool - EnablePostUsernameOverride bool - EnablePostIconOverride bool - EnableTesting bool - EnableDeveloper *bool - EnableSecurityFixAlert *bool - EnableInsecureOutgoingConnections *bool - EnableMultifactorAuthentication *bool - EnforceMultifactorAuthentication *bool - AllowCorsFrom *string - SessionLengthWebInDays *int - SessionLengthMobileInDays *int - SessionLengthSSOInDays *int - SessionCacheInMinutes *int - WebsocketSecurePort *int - WebsocketPort *int - WebserverMode *string - EnableCustomEmoji *bool - RestrictCustomEmojiCreation *string - RestrictPostDelete *string - AllowEditPost *string - PostEditTimeLimit *int + SiteURL *string + ListenAddress string + ConnectionSecurity *string + TLSCertFile *string + TLSKeyFile *string + UseLetsEncrypt *bool + LetsEncryptCertificateCacheFile *string + Forward80To443 *bool + ReadTimeout *int + WriteTimeout *int + MaximumLoginAttempts int + SegmentDeveloperKey string + GoogleDeveloperKey string + EnableOAuthServiceProvider bool + EnableIncomingWebhooks bool + EnableOutgoingWebhooks bool + EnableCommands *bool + EnableOnlyAdminIntegrations *bool + EnablePostUsernameOverride bool + EnablePostIconOverride bool + EnableTesting bool + EnableDeveloper *bool + EnableSecurityFixAlert *bool + EnableInsecureOutgoingConnections *bool + EnableMultifactorAuthentication *bool + EnforceMultifactorAuthentication *bool + AllowCorsFrom *string + SessionLengthWebInDays *int + SessionLengthMobileInDays *int + SessionLengthSSOInDays *int + SessionCacheInMinutes *int + WebsocketSecurePort *int + WebsocketPort *int + WebserverMode *string + EnableCustomEmoji *bool + RestrictCustomEmojiCreation *string + RestrictPostDelete *string + AllowEditPost *string + PostEditTimeLimit *int + TimeBetweenUserTypingUpdatesMilliseconds *int64 + EnableUserTypingMessages *bool } type ClusterSettings struct { @@ -1072,6 +1074,16 @@ func (o *Config) SetDefaults() { *o.MetricsSettings.BlockProfileRate = 0 } + if o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds == nil { + o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds = new(int64) + *o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds = 5000 + } + + if o.ServiceSettings.EnableUserTypingMessages == nil { + o.ServiceSettings.EnableUserTypingMessages = new(bool) + *o.ServiceSettings.EnableUserTypingMessages = true + } + o.defaultWebrtcSettings() } @@ -1303,6 +1315,10 @@ func (o *Config) IsValid() *AppError { return NewLocAppError("Config.IsValid", "model.config.is_valid.write_timeout.app_error", nil, "") } + if *o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds < 1000 { + return NewLocAppError("Config.IsValid", "model.config.is_valid.time_between_user_typing.app_error", nil, "") + } + return nil } diff --git a/utils/config.go b/utils/config.go index 72c30c01b4..243e2b9849 100644 --- a/utils/config.go +++ b/utils/config.go @@ -311,6 +311,10 @@ func getClientConfig(c *model.Config) map[string]string { props["EnableWebrtc"] = strconv.FormatBool(*c.WebrtcSettings.Enable) + props["MaxNotificationsPerChannel"] = strconv.FormatInt(*c.TeamSettings.MaxNotificationsPerChannel, 10) + props["TimeBetweenUserTypingUpdatesMilliseconds"] = strconv.FormatInt(*c.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds, 10) + props["EnableUserTypingMessages"] = strconv.FormatBool(*c.ServiceSettings.EnableUserTypingMessages) + if IsLicensed { if *License.Features.CustomBrand { props["EnableCustomBrand"] = strconv.FormatBool(*c.TeamSettings.EnableCustomBrand) diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx index c8da43f24d..beca755099 100644 --- a/webapp/actions/global_actions.jsx +++ b/webapp/actions/global_actions.jsx @@ -454,7 +454,9 @@ export function viewLoggedIn() { let lastTimeTypingSent = 0; export function emitLocalUserTypingEvent(channelId, parentId) { const t = Date.now(); - if ((t - lastTimeTypingSent) > Constants.UPDATE_TYPING_MS) { + const membersInChannel = ChannelStore.getStats(channelId).member_count; + + if (((t - lastTimeTypingSent) > global.window.mm_config.TimeBetweenUserTypingUpdatesMilliseconds) && membersInChannel < global.window.mm_config.MaxNotificationsPerChannel && global.window.mm_config.EnableUserTypingMessages === 'true') { WebSocketClient.userTyping(channelId, parentId); lastTimeTypingSent = t; } diff --git a/webapp/stores/user_typing_store.jsx b/webapp/stores/user_typing_store.jsx index 85c10bfbe1..8bbce117fa 100644 --- a/webapp/stores/user_typing_store.jsx +++ b/webapp/stores/user_typing_store.jsx @@ -64,7 +64,7 @@ class UserTypingStoreClass extends EventEmitter { Reflect.deleteProperty(this.typingUsers, loc); } this.emitChange(); - }, Constants.UPDATE_TYPING_MS); + }, parseInt(window.mm_config.TimeBetweenUserTypingUpdatesMilliseconds, 10)); this.emitChange(); } diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index dd9a4486ea..bd50534f20 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -407,7 +407,6 @@ export const Constants = { REPLY_ICON: " ", SCROLL_BOTTOM_ICON: " ", VIDEO_ICON: " ", - UPDATE_TYPING_MS: 5000, THEMES: { default: { type: 'Organization',