mirror of
				https://github.com/vector-im/element-web.git
				synced 2025-11-04 10:11:03 +01:00 
			
		
		
		
	PushRules settings: Translate matrix per-word rules into the global Vector rule for a list of keywords
This commit is contained in:
		
							parent
							
								
									6d510db2db
								
							
						
					
					
						commit
						7f95362dd2
					
				@ -16,9 +16,11 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
var React = require('react');
 | 
					var React = require('react');
 | 
				
			||||||
 | 
					var q = require("q");
 | 
				
			||||||
var sdk = require('matrix-react-sdk');
 | 
					var sdk = require('matrix-react-sdk');
 | 
				
			||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
					var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
 | 
				
			||||||
var UserSettingsStore = require('matrix-react-sdk/lib/UserSettingsStore');
 | 
					var UserSettingsStore = require('matrix-react-sdk/lib/UserSettingsStore');
 | 
				
			||||||
 | 
					var Modal = require('matrix-react-sdk/lib/Modal');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Enum for state of a push rule as defined by the Vector UI.
 | 
					 * Enum for state of a push rule as defined by the Vector UI.
 | 
				
			||||||
@ -47,7 +49,12 @@ module.exports = React.createClass({
 | 
				
			|||||||
    getInitialState: function() {
 | 
					    getInitialState: function() {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            phase: this.phases.LOADING,
 | 
					            phase: this.phases.LOADING,
 | 
				
			||||||
            vectorPushRules: []
 | 
					            vectorPushRules: [],            // HS default push rules displayed in Vector UI
 | 
				
			||||||
 | 
					            vectorContentRules: {           // Keyword push rules displayed in Vector UI
 | 
				
			||||||
 | 
					                state: PushRuleState.ON,
 | 
				
			||||||
 | 
					                rules: []
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            externalContentRules: []        // Keyword push rules that have been defined outside Vector UI
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -60,9 +67,51 @@ module.exports = React.createClass({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    onNotifStateButtonClicked: function(event) {
 | 
					    onNotifStateButtonClicked: function(event) {
 | 
				
			||||||
 | 
					        var self = this;
 | 
				
			||||||
 | 
					        var cli = MatrixClientPeg.get();
 | 
				
			||||||
        var vectorRuleId = event.target.className.split("-")[0];
 | 
					        var vectorRuleId = event.target.className.split("-")[0];
 | 
				
			||||||
        var newPushRuleState = event.target.className.split("-")[1];
 | 
					        var newPushRuleState = event.target.className.split("-")[1];
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        if ("keywords" === vectorRuleId 
 | 
				
			||||||
 | 
					                && this.state.vectorContentRules.state !== newPushRuleState 
 | 
				
			||||||
 | 
					                && this.state.vectorContentRules.rules.length) {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            this.setState({
 | 
				
			||||||
 | 
					                phase: this.phases.LOADING
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            var enabled = true;
 | 
				
			||||||
 | 
					            switch (newPushRuleState) {
 | 
				
			||||||
 | 
					                case PushRuleState.OFF:
 | 
				
			||||||
 | 
					                    enabled = false;
 | 
				
			||||||
 | 
					                    break
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Update all rules in self.state.vectorContentRules
 | 
				
			||||||
 | 
					            var deferreds = [];
 | 
				
			||||||
 | 
					            for (var i in this.state.vectorContentRules.rules) {
 | 
				
			||||||
 | 
					                var rule = this.state.vectorContentRules.rules[i];
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if (enabled) {
 | 
				
			||||||
 | 
					                    deferreds.push(cli.addPushRule('global', rule.kind, rule.rule_id, rule));                
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    deferreds.push(cli.setPushRuleEnabled('global', rule.kind, rule.rule_id, false));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            q.all(deferreds).done(function(resps) {
 | 
				
			||||||
 | 
					                self._refreshFromServer();
 | 
				
			||||||
 | 
					            }, function(error) {
 | 
				
			||||||
 | 
					                var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
 | 
				
			||||||
 | 
					                Modal.createDialog(ErrorDialog, {
 | 
				
			||||||
 | 
					                    title: "Can't update user notification settings",
 | 
				
			||||||
 | 
					                    description: error.toString()
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
            var rule = this.getRule(vectorRuleId);
 | 
					            var rule = this.getRule(vectorRuleId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // For now, we support only enabled/disabled. 
 | 
					            // For now, we support only enabled/disabled. 
 | 
				
			||||||
@ -73,12 +122,12 @@ module.exports = React.createClass({
 | 
				
			|||||||
                    phase: this.phases.LOADING
 | 
					                    phase: this.phases.LOADING
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var self = this;
 | 
					                cli.setPushRuleEnabled('global', rule.rule.kind, rule.rule.rule_id, (newPushRuleState !== PushRuleState.OFF)).done(function() {
 | 
				
			||||||
            MatrixClientPeg.get().setPushRuleEnabled('global', rule.rule.kind, rule.rule.rule_id, (newPushRuleState !== PushRuleState.OFF)).done(function() {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                   self._refreshFromServer();
 | 
					                   self._refreshFromServer();
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    getRule: function(vectorRuleId) {
 | 
					    getRule: function(vectorRuleId) {
 | 
				
			||||||
@ -106,7 +155,11 @@ module.exports = React.createClass({
 | 
				
			|||||||
                '.m.rule.call': 'vector',
 | 
					                '.m.rule.call': 'vector',
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // HS default rules
 | 
				
			||||||
            var defaultRules = {master: [], vector: {}, additional: [], fallthrough: [], suppression: []};
 | 
					            var defaultRules = {master: [], vector: {}, additional: [], fallthrough: [], suppression: []};
 | 
				
			||||||
 | 
					            //  Content/keyword rules
 | 
				
			||||||
 | 
					            var contentRules = {on: [], strong: [], off: [], other: []};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (var kind in rulesets.global) {
 | 
					            for (var kind in rulesets.global) {
 | 
				
			||||||
                for (var i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
 | 
					                for (var i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
 | 
				
			||||||
                    var r = rulesets.global[kind][i];
 | 
					                    var r = rulesets.global[kind][i];
 | 
				
			||||||
@ -126,13 +179,78 @@ module.exports = React.createClass({
 | 
				
			|||||||
                            defaultRules.additional.push(r);
 | 
					                            defaultRules.additional.push(r);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    else if (kind === 'content') {
 | 
				
			||||||
 | 
					                        if (r.enabled) {
 | 
				
			||||||
 | 
					                            // Count tweaks to determine if it is a ON or STRONG rule
 | 
				
			||||||
 | 
					                            var tweaks = 0;
 | 
				
			||||||
 | 
					                            for (var j in r.actions) {
 | 
				
			||||||
 | 
					                                var action = r.actions[j];
 | 
				
			||||||
 | 
					                                if (action.set_tweak === 'sound' ||
 | 
				
			||||||
 | 
					                                    (action.set_tweak === 'highlight' &&  action.value)) {
 | 
				
			||||||
 | 
					                                    tweaks++;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            switch (tweaks) {
 | 
				
			||||||
 | 
					                                case 0:
 | 
				
			||||||
 | 
					                                    contentRules.on.push(r);
 | 
				
			||||||
 | 
					                                    break;
 | 
				
			||||||
 | 
					                                case 2:
 | 
				
			||||||
 | 
					                                    contentRules.strong.push(r);
 | 
				
			||||||
 | 
					                                    break;
 | 
				
			||||||
 | 
					                                default:
 | 
				
			||||||
 | 
					                                    contentRules.other.push(r);
 | 
				
			||||||
 | 
					                                    break;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else {
 | 
				
			||||||
 | 
					                            contentRules.off.push(r);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Decide which content/keyword rules to display in Vector UI.
 | 
				
			||||||
 | 
					            // Vector displays a single global rule for a list of keywords
 | 
				
			||||||
 | 
					            // whereas Matrix has a push rule per keyword.
 | 
				
			||||||
 | 
					            // Vector can set the unique rule in ON, STRONG or OFF state.
 | 
				
			||||||
 | 
					            // Matrix has enabled/disabled plus a combination of (highlight, sound) tweaks.
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // The code below determines which set of user's content push rules can be 
 | 
				
			||||||
 | 
					            // displayed by the vector UI.
 | 
				
			||||||
 | 
					            // Push rules that does not fir, ie defined by another Matrix client, ends
 | 
				
			||||||
 | 
					            // in self.state.externalContentRules.
 | 
				
			||||||
 | 
					            // There is priority in the determination of which set will be the displayed one.
 | 
				
			||||||
 | 
					            // The set with rules that have STRONG tweaks is the first choice. Then, the ones
 | 
				
			||||||
 | 
					            // with ON tweaks (no tweaks).
 | 
				
			||||||
 | 
					            if (contentRules.strong.length) {
 | 
				
			||||||
 | 
					                self.state.vectorContentRules = {
 | 
				
			||||||
 | 
					                    state: PushRuleState.STRONG,
 | 
				
			||||||
 | 
					                    rules: contentRules.strong
 | 
				
			||||||
 | 
					                } 
 | 
				
			||||||
 | 
					               self.state.externalContentRules = [].concat(contentRules.on, contentRules.other, contentRules.off);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (contentRules.on.length) {
 | 
				
			||||||
 | 
					                self.state.vectorContentRules = {
 | 
				
			||||||
 | 
					                    state: PushRuleState.ON,
 | 
				
			||||||
 | 
					                    rules: contentRules.on
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                self.state.externalContentRules = [].concat(contentRules.strong, contentRules.other, contentRules.off);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (contentRules.off.length) {
 | 
				
			||||||
 | 
					                self.state.vectorContentRules = {
 | 
				
			||||||
 | 
					                    state: PushRuleState.OFF,
 | 
				
			||||||
 | 
					                    rules: contentRules.off
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                self.state.externalContentRules = [].concat(contentRules.strong, contentRules.on, contentRules.other);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Build the rules displayed by Vector UI
 | 
					            // Build the rules displayed by Vector UI
 | 
				
			||||||
            self.state.vectorPushRules = [];
 | 
					            self.state.vectorPushRules = [];
 | 
				
			||||||
            var rule, state;
 | 
					            var rule, state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Messages containing user's display name 
 | 
				
			||||||
 | 
					            // (skip contains_user_name which is too geeky)
 | 
				
			||||||
            rule = defaultRules.vector['.m.rule.contains_display_name'];
 | 
					            rule = defaultRules.vector['.m.rule.contains_display_name'];
 | 
				
			||||||
            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
					            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
				
			||||||
            self.state.vectorPushRules.push({
 | 
					            self.state.vectorPushRules.push({
 | 
				
			||||||
@ -143,10 +261,16 @@ module.exports = React.createClass({
 | 
				
			|||||||
                "disabled": PushRuleState.ON
 | 
					                "disabled": PushRuleState.ON
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TODO: Merge contains_user_name
 | 
					            // Messages containing keywords
 | 
				
			||||||
 | 
					            // For Vector UI, this is a single global push rule but translated in Matrix,
 | 
				
			||||||
            // TODO: Add "Messages containing keywords"
 | 
					            // it corresponds to all content push rules (stored in self.state.vectorContentRule)
 | 
				
			||||||
 | 
					            self.state.vectorPushRules.push({
 | 
				
			||||||
 | 
					                "vectorRuleId": "keywords",
 | 
				
			||||||
 | 
					                "description" : "Messages containing keywords",
 | 
				
			||||||
 | 
					                "state": self.state.vectorContentRules.state,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Messages just sent to the user
 | 
				
			||||||
            rule = defaultRules.vector['.m.rule.room_one_to_one'];
 | 
					            rule = defaultRules.vector['.m.rule.room_one_to_one'];
 | 
				
			||||||
            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
					            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
				
			||||||
            self.state.vectorPushRules.push({
 | 
					            self.state.vectorPushRules.push({
 | 
				
			||||||
@ -157,6 +281,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
                "disabled": PushRuleState.ON
 | 
					                "disabled": PushRuleState.ON
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Invitation for the user
 | 
				
			||||||
            rule = defaultRules.vector['.m.rule.invite_for_me'];
 | 
					            rule = defaultRules.vector['.m.rule.invite_for_me'];
 | 
				
			||||||
            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
					            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
				
			||||||
            self.state.vectorPushRules.push({
 | 
					            self.state.vectorPushRules.push({
 | 
				
			||||||
@ -167,6 +292,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
                "disabled": PushRuleState.ON
 | 
					                "disabled": PushRuleState.ON
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // When people join or leave a room
 | 
				
			||||||
            rule = defaultRules.vector['.m.rule.member_event'];
 | 
					            rule = defaultRules.vector['.m.rule.member_event'];
 | 
				
			||||||
            state = (rule && rule.enabled) ? PushRuleState.ON : PushRuleState.OFF;
 | 
					            state = (rule && rule.enabled) ? PushRuleState.ON : PushRuleState.OFF;
 | 
				
			||||||
            self.state.vectorPushRules.push({
 | 
					            self.state.vectorPushRules.push({
 | 
				
			||||||
@ -177,6 +303,7 @@ module.exports = React.createClass({
 | 
				
			|||||||
                "disabled": PushRuleState.STRONG
 | 
					                "disabled": PushRuleState.STRONG
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Incoming call
 | 
				
			||||||
            rule = defaultRules.vector['.m.rule.call'];
 | 
					            rule = defaultRules.vector['.m.rule.call'];
 | 
				
			||||||
            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
					            state = (rule && rule.enabled) ? PushRuleState.STRONG : PushRuleState.OFF;
 | 
				
			||||||
            self.state.vectorPushRules.push({
 | 
					            self.state.vectorPushRules.push({
 | 
				
			||||||
@ -246,7 +373,19 @@ module.exports = React.createClass({
 | 
				
			|||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Build the list of keywords rules that have been defined outside Vector UI
 | 
				
			||||||
 | 
					        var externalKeyWords = [];
 | 
				
			||||||
 | 
					        for (var i in this.state.externalContentRules) {
 | 
				
			||||||
 | 
					            var rule = this.state.externalContentRules[i];
 | 
				
			||||||
 | 
					            externalKeyWords.push(rule.pattern);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (externalKeyWords.length) {
 | 
				
			||||||
 | 
					            externalKeyWords = externalKeyWords.join(", ");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
                <div className="mx_UserSettings_notifTable">
 | 
					                <div className="mx_UserSettings_notifTable">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <div className="mx_UserNotifSettings_tableRow">
 | 
					                    <div className="mx_UserNotifSettings_tableRow">
 | 
				
			||||||
@ -285,6 +424,14 @@ module.exports = React.createClass({
 | 
				
			|||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <div>
 | 
				
			||||||
 | 
					                    <br/><br/>
 | 
				
			||||||
 | 
					                    Warning: Push rules on the following keywords has been defined: <br/>
 | 
				
			||||||
 | 
					                    { externalKeyWords }
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user