mirror of
				https://github.com/vector-im/element-web.git
				synced 2025-11-04 02:02:14 +01:00 
			
		
		
		
	Merge pull request #7 from matrix-org/nick-completion
Implement nick completion (tab-complete).
This commit is contained in:
		
						commit
						41bab56133
					
				@ -19,10 +19,20 @@ limitations under the License.
 | 
				
			|||||||
var MatrixClientPeg = require("../../MatrixClientPeg");
 | 
					var MatrixClientPeg = require("../../MatrixClientPeg");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var dis = require("../../dispatcher");
 | 
					var dis = require("../../dispatcher");
 | 
				
			||||||
 | 
					var KeyCode = {
 | 
				
			||||||
 | 
					    ENTER: 13,
 | 
				
			||||||
 | 
					    TAB: 9,
 | 
				
			||||||
 | 
					    SHIFT: 16
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    componentDidMount: function() {
 | 
					    componentWillMount: function() {
 | 
				
			||||||
        this.dispatcherRef = dis.register(this.onAction);
 | 
					        this.dispatcherRef = dis.register(this.onAction);
 | 
				
			||||||
 | 
					        this.tabStruct = {
 | 
				
			||||||
 | 
					            completing: false,
 | 
				
			||||||
 | 
					            original: null,
 | 
				
			||||||
 | 
					            index: 0
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentWillUnmount: function() {
 | 
					    componentWillUnmount: function() {
 | 
				
			||||||
@ -38,9 +48,25 @@ module.exports = {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onKeyDown: function (ev) {
 | 
					    onKeyDown: function (ev) {
 | 
				
			||||||
        if (ev.keyCode == 13) {
 | 
					        if (ev.keyCode === KeyCode.ENTER) {
 | 
				
			||||||
            var contentText = this.refs.textarea.getDOMNode().value;
 | 
					            this.onEnter(ev);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (ev.keyCode === KeyCode.TAB) {
 | 
				
			||||||
 | 
					            var members = [];
 | 
				
			||||||
 | 
					            if (this.props.room) {
 | 
				
			||||||
 | 
					                members = this.props.room.getJoinedMembers();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            this.onTab(ev, members);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (ev.keyCode !== KeyCode.SHIFT && this.tabStruct.completing) {
 | 
				
			||||||
 | 
					            // they're resuming typing; reset tab complete state vars.
 | 
				
			||||||
 | 
					            this.tabStruct.completing = false;
 | 
				
			||||||
 | 
					            this.tabStruct.index = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onEnter: function(ev) {
 | 
				
			||||||
 | 
					        var contentText = this.refs.textarea.getDOMNode().value;
 | 
				
			||||||
        var content = null;
 | 
					        var content = null;
 | 
				
			||||||
        if (/^\/me /i.test(contentText)) {
 | 
					        if (/^\/me /i.test(contentText)) {
 | 
				
			||||||
            content = {
 | 
					            content = {
 | 
				
			||||||
@ -61,7 +87,104 @@ module.exports = {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
        this.refs.textarea.getDOMNode().value = '';
 | 
					        this.refs.textarea.getDOMNode().value = '';
 | 
				
			||||||
        ev.preventDefault();
 | 
					        ev.preventDefault();
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onTab: function(ev, sortedMembers) {
 | 
				
			||||||
 | 
					        var textArea = this.refs.textarea.getDOMNode();
 | 
				
			||||||
 | 
					        if (!this.tabStruct.completing) {
 | 
				
			||||||
 | 
					            this.tabStruct.completing = true;
 | 
				
			||||||
 | 
					            this.tabStruct.index = 0;
 | 
				
			||||||
 | 
					            // cache starting text
 | 
				
			||||||
 | 
					            this.tabStruct.original = textArea.value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // loop in the right direction
 | 
				
			||||||
 | 
					        if (ev.shiftKey) {
 | 
				
			||||||
 | 
					            this.tabStruct.index --;
 | 
				
			||||||
 | 
					            if (this.tabStruct.index < 0) {
 | 
				
			||||||
 | 
					                // wrap to the last search match, and fix up to a real index
 | 
				
			||||||
 | 
					                // value after we've matched.
 | 
				
			||||||
 | 
					                this.tabStruct.index = Number.MAX_VALUE;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            this.tabStruct.index++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var searchIndex = 0;
 | 
				
			||||||
 | 
					        var targetIndex = this.tabStruct.index;
 | 
				
			||||||
 | 
					        var text = this.tabStruct.original;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var search = /@?([a-zA-Z0-9_\-:\.]+)$/.exec(text);
 | 
				
			||||||
 | 
					        // console.log("Searched in '%s' - got %s", text, search);
 | 
				
			||||||
 | 
					        if (targetIndex === 0) { // 0 is always the original text
 | 
				
			||||||
 | 
					            textArea.value = text;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (search && search[1]) {
 | 
				
			||||||
 | 
					            // console.log("search found: " + search+" from "+text);
 | 
				
			||||||
 | 
					            var expansion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // FIXME: could do better than linear search here
 | 
				
			||||||
 | 
					            for (var i=0; i<sortedMembers.length; i++) {
 | 
				
			||||||
 | 
					                var member = sortedMembers[i];
 | 
				
			||||||
 | 
					                if (member.name && searchIndex < targetIndex) {
 | 
				
			||||||
 | 
					                    if (member.name.toLowerCase().indexOf(search[1].toLowerCase()) === 0) {
 | 
				
			||||||
 | 
					                        expansion = member.name;
 | 
				
			||||||
 | 
					                        searchIndex++;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (searchIndex < targetIndex) { // then search raw mxids
 | 
				
			||||||
 | 
					                for (var i=0; i<sortedMembers.length; i++) {
 | 
				
			||||||
 | 
					                    if (searchIndex >= targetIndex) {
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    var userId = sortedMembers[i].userId;
 | 
				
			||||||
 | 
					                    // === 1 because mxids are @username
 | 
				
			||||||
 | 
					                    if (userId.toLowerCase().indexOf(search[1].toLowerCase()) === 1) {
 | 
				
			||||||
 | 
					                        expansion = userId;
 | 
				
			||||||
 | 
					                        searchIndex++;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (searchIndex === targetIndex ||
 | 
				
			||||||
 | 
					                    targetIndex === Number.MAX_VALUE) {
 | 
				
			||||||
 | 
					                // xchat-style tab complete, add a colon if tab
 | 
				
			||||||
 | 
					                // completing at the start of the text
 | 
				
			||||||
 | 
					                if (search[0].length === text.length) {
 | 
				
			||||||
 | 
					                    expansion += ": ";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    expansion += " ";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                textArea.value = text.replace(
 | 
				
			||||||
 | 
					                    /@?([a-zA-Z0-9_\-:\.]+)$/, expansion
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // cancel blink
 | 
				
			||||||
 | 
					                textArea.style["background-color"] = "";
 | 
				
			||||||
 | 
					                if (targetIndex === Number.MAX_VALUE) {
 | 
				
			||||||
 | 
					                    // wrap the index around to the last index found
 | 
				
			||||||
 | 
					                    this.tabStruct.index = searchIndex;
 | 
				
			||||||
 | 
					                    targetIndex = searchIndex;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // console.log("wrapped!");
 | 
				
			||||||
 | 
					                textArea.style["background-color"] = "#faa";
 | 
				
			||||||
 | 
					                setTimeout(function() {
 | 
				
			||||||
 | 
					                     textArea.style["background-color"] = "";
 | 
				
			||||||
 | 
					                }, 150);
 | 
				
			||||||
 | 
					                textArea.value = text;
 | 
				
			||||||
 | 
					                this.tabStruct.index = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            this.tabStruct.index = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // prevent the default TAB operation (typically focus shifting)
 | 
				
			||||||
 | 
					        ev.preventDefault();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user