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',