diff --git a/src/autocomplete/Autocompleter.js b/src/autocomplete/Autocompleter.js index c8f3134a3b..95669d5e0f 100644 --- a/src/autocomplete/Autocompleter.js +++ b/src/autocomplete/Autocompleter.js @@ -5,12 +5,12 @@ import UserProvider from './UserProvider'; import EmojiProvider from './EmojiProvider'; const PROVIDERS = [ + UserProvider, CommandProvider, DuckDuckGoProvider, RoomProvider, - UserProvider, EmojiProvider -].map(completer => new completer()); +].map(completer => completer.getInstance()); export function getCompletions(query: String) { return PROVIDERS.map(provider => { diff --git a/src/autocomplete/CommandProvider.js b/src/autocomplete/CommandProvider.js index e2eac47d16..7b950c0ed0 100644 --- a/src/autocomplete/CommandProvider.js +++ b/src/autocomplete/CommandProvider.js @@ -39,6 +39,8 @@ const COMMANDS = [ } ]; +let instance = null; + export default class CommandProvider extends AutocompleteProvider { constructor() { super(); @@ -49,7 +51,7 @@ export default class CommandProvider extends AutocompleteProvider { getCompletions(query: String) { let completions = []; - const matches = query.match(/(^\/\w+)/); + const matches = query.match(/(^\/\w*)/); if(!!matches) { const command = matches[0]; completions = this.fuse.search(command).map(result => { @@ -66,4 +68,11 @@ export default class CommandProvider extends AutocompleteProvider { getName() { return 'Commands'; } + + static getInstance(): CommandProvider { + if(instance == null) + instance = new CommandProvider(); + + return instance; + } } diff --git a/src/autocomplete/DuckDuckGoProvider.js b/src/autocomplete/DuckDuckGoProvider.js index 2acd892498..496ce72e46 100644 --- a/src/autocomplete/DuckDuckGoProvider.js +++ b/src/autocomplete/DuckDuckGoProvider.js @@ -5,6 +5,8 @@ import 'whatwg-fetch'; const DDG_REGEX = /\/ddg\s+(.+)$/; const REFERER = 'vector'; +let instance = null; + export default class DuckDuckGoProvider extends AutocompleteProvider { static getQueryUri(query: String) { return `http://api.duckduckgo.com/?q=${encodeURIComponent(query)}` @@ -51,4 +53,11 @@ export default class DuckDuckGoProvider extends AutocompleteProvider { getName() { return 'Results from DuckDuckGo'; } + + static getInstance(): DuckDuckGoProvider { + if(instance == null) + instance = new DuckDuckGoProvider(); + + return instance; + } } diff --git a/src/autocomplete/EmojiProvider.js b/src/autocomplete/EmojiProvider.js index fefd00a7fd..684414d72a 100644 --- a/src/autocomplete/EmojiProvider.js +++ b/src/autocomplete/EmojiProvider.js @@ -6,19 +6,19 @@ import Fuse from 'fuse.js'; const EMOJI_REGEX = /:\w*:?/g; const EMOJI_SHORTNAMES = Object.keys(emojioneList); +let instance = null; + export default class EmojiProvider extends AutocompleteProvider { constructor() { super(); - console.log(EMOJI_SHORTNAMES); this.fuse = new Fuse(EMOJI_SHORTNAMES); } getCompletions(query: String) { let completions = []; - const matches = query.match(EMOJI_REGEX); - console.log(matches); - if(!!matches) { - const command = matches[0]; + let matches = query.match(EMOJI_REGEX); + let command = matches && matches[0]; + if(command) { completions = this.fuse.search(command).map(result => { let shortname = EMOJI_SHORTNAMES[result]; let imageHTML = shortnameToImage(shortname); @@ -38,4 +38,10 @@ export default class EmojiProvider extends AutocompleteProvider { getName() { return 'Emoji'; } + + static getInstance() { + if(instance == null) + instance = new EmojiProvider(); + return instance; + } } diff --git a/src/autocomplete/RoomProvider.js b/src/autocomplete/RoomProvider.js index 26dc5733da..c61541617d 100644 --- a/src/autocomplete/RoomProvider.js +++ b/src/autocomplete/RoomProvider.js @@ -1,9 +1,12 @@ import AutocompleteProvider from './AutocompleteProvider'; import Q from 'q'; import MatrixClientPeg from '../MatrixClientPeg'; +import Fuse from 'fuse.js'; const ROOM_REGEX = /(?=#)[^\s]*/g; +let instance = null; + export default class RoomProvider extends AutocompleteProvider { constructor() { super(); @@ -13,8 +16,8 @@ export default class RoomProvider extends AutocompleteProvider { let client = MatrixClientPeg.get(); let completions = []; const matches = query.match(ROOM_REGEX); - if(!!matches) { - const command = matches[0]; + const command = matches && matches[0]; + if(command) { completions = client.getRooms().map(room => { return { title: room.name, @@ -28,4 +31,11 @@ export default class RoomProvider extends AutocompleteProvider { getName() { return 'Rooms'; } + + static getInstance() { + if(instance == null) + instance = new RoomProvider(); + + return instance; + } } diff --git a/src/autocomplete/UserProvider.js b/src/autocomplete/UserProvider.js index 791dd55a33..c850cea7d9 100644 --- a/src/autocomplete/UserProvider.js +++ b/src/autocomplete/UserProvider.js @@ -4,20 +4,22 @@ import MatrixClientPeg from '../MatrixClientPeg'; const ROOM_REGEX = /@[^\s]*/g; +let instance = null; + export default class UserProvider extends AutocompleteProvider { constructor() { super(); + this.users = []; } getCompletions(query: String) { - let client = MatrixClientPeg.get(); let completions = []; const matches = query.match(ROOM_REGEX); if(!!matches) { const command = matches[0]; - completions = client.getUsers().map(user => { + completions = this.users.map(user => { return { - title: user.displayName, + title: user.displayName || user.userId, description: user.userId }; }); @@ -28,4 +30,15 @@ export default class UserProvider extends AutocompleteProvider { getName() { return 'Users'; } + + setUserList(users) { + console.log('setUserList'); + this.users = users; + } + + static getInstance(): UserProvider { + if(instance == null) + instance = new UserProvider(); + return instance; + } } diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index e1b4c00175..9d952e611e 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -41,6 +41,8 @@ var rate_limited_func = require('../../ratelimitedfunc'); var ObjectUtils = require('../../ObjectUtils'); var MatrixTools = require('../../MatrixTools'); +import UserProvider from '../../autocomplete/UserProvider'; + var DEBUG = false; if (DEBUG) { @@ -495,21 +497,26 @@ module.exports = React.createClass({ } }, - _updateTabCompleteList: new rate_limited_func(function() { + _updateTabCompleteList: function() { var cli = MatrixClientPeg.get(); + console.log('_updateTabCompleteList'); + console.log(this.state.room); + console.trace(); - if (!this.state.room || !this.tabComplete) { + if (!this.state.room) { return; } var members = this.state.room.getJoinedMembers().filter(function(member) { if (member.userId !== cli.credentials.userId) return true; }); + + UserProvider.getInstance().setUserList(members); this.tabComplete.setCompletionList( MemberEntry.fromMemberList(members).concat( CommandEntry.fromCommands(SlashCommands.getCommandList()) ) ); - }, 500), + }, componentDidUpdate: function() { if (this.refs.roomView) { diff --git a/src/components/views/rooms/Autocomplete.js b/src/components/views/rooms/Autocomplete.js index 673cdc5bf5..0218a88195 100644 --- a/src/components/views/rooms/Autocomplete.js +++ b/src/components/views/rooms/Autocomplete.js @@ -16,14 +16,14 @@ export default class Autocomplete extends React.Component { getCompletions(props.query).map(completionResult => { try { - console.log(`${completionResult.provider.getName()}: ${JSON.stringify(completionResult.completions)}`); + // console.log(`${completionResult.provider.getName()}: ${JSON.stringify(completionResult.completions)}`); completionResult.completions.then(completions => { let i = this.state.completions.findIndex( completion => completion.provider === completionResult.provider ); i = i == -1 ? this.state.completions.length : i; - console.log(completionResult); + // console.log(completionResult); let newCompletions = Object.assign([], this.state.completions); completionResult.completions = completions; newCompletions[i] = completionResult; @@ -42,13 +42,6 @@ export default class Autocomplete extends React.Component { } render() { - const pinElement = document.querySelector(this.props.pinSelector); - if(!pinElement) return null; - - const position = pinElement.getBoundingClientRect(); - - - const renderedCompletions = this.state.completions.map((completionResult, i) => { // console.log(completionResult); let completions = completionResult.completions.map((completion, i) => { @@ -58,10 +51,11 @@ export default class Autocomplete extends React.Component { } return ( -