Remove autocomplete delay (#4819)
Этот коммит содержится в:
коммит произвёл
Christopher Speller
родитель
d4b890fff1
Коммит
bf3fec604f
@@ -4,7 +4,6 @@
|
||||
import Suggestion from './suggestion.jsx';
|
||||
|
||||
import ChannelStore from 'stores/channel_store.jsx';
|
||||
import SuggestionStore from 'stores/suggestion_store.jsx';
|
||||
|
||||
import {autocompleteUsersInChannel} from 'actions/user_actions.jsx';
|
||||
|
||||
@@ -104,79 +103,49 @@ class AtMentionSuggestion extends Suggestion {
|
||||
export default class AtMentionProvider {
|
||||
constructor(channelId) {
|
||||
this.channelId = channelId;
|
||||
this.timeoutId = '';
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.clearTimeout(this.timeoutId);
|
||||
}
|
||||
|
||||
clearTimeout() {
|
||||
if (this.timeoutId) {
|
||||
clearTimeout(this.timeoutId);
|
||||
this.timeoutId = '';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
handlePretextChanged(suggestionId, pretext) {
|
||||
const hadSuggestions = this.clearTimeout(this.timeoutId);
|
||||
|
||||
const captured = XRegExp.cache('(?:^|\\W)@([\\pL\\d\\-_.]*)$', 'i').exec(pretext.toLowerCase());
|
||||
if (captured) {
|
||||
const prefix = captured[1];
|
||||
|
||||
function autocomplete() {
|
||||
autocompleteUsersInChannel(
|
||||
prefix,
|
||||
this.channelId,
|
||||
(data) => {
|
||||
const members = data.in_channel;
|
||||
for (const id of Object.keys(members)) {
|
||||
members[id].type = Constants.MENTION_MEMBERS;
|
||||
}
|
||||
autocompleteUsersInChannel(
|
||||
prefix,
|
||||
this.channelId,
|
||||
(data) => {
|
||||
const members = data.in_channel;
|
||||
for (const id of Object.keys(members)) {
|
||||
members[id].type = Constants.MENTION_MEMBERS;
|
||||
}
|
||||
|
||||
const nonmembers = data.out_of_channel;
|
||||
for (const id of Object.keys(nonmembers)) {
|
||||
nonmembers[id].type = Constants.MENTION_NONMEMBERS;
|
||||
}
|
||||
const nonmembers = data.out_of_channel;
|
||||
for (const id of Object.keys(nonmembers)) {
|
||||
nonmembers[id].type = Constants.MENTION_NONMEMBERS;
|
||||
}
|
||||
|
||||
let specialMentions = [];
|
||||
if (!pretext.startsWith('/msg')) {
|
||||
specialMentions = ['here', 'channel', 'all'].filter((item) => {
|
||||
return item.startsWith(prefix);
|
||||
}).map((name) => {
|
||||
return {username: name, type: Constants.MENTION_SPECIAL};
|
||||
});
|
||||
}
|
||||
|
||||
const users = members.concat(specialMentions).concat(nonmembers);
|
||||
const mentions = users.map((user) => '@' + user.username);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: `@${captured[1]}`,
|
||||
terms: mentions,
|
||||
items: users,
|
||||
component: AtMentionSuggestion
|
||||
let specialMentions = [];
|
||||
if (!pretext.startsWith('/msg')) {
|
||||
specialMentions = ['here', 'channel', 'all'].filter((item) => {
|
||||
return item.startsWith(prefix);
|
||||
}).map((name) => {
|
||||
return {username: name, type: Constants.MENTION_SPECIAL};
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.timeoutId = setTimeout(
|
||||
autocomplete.bind(this),
|
||||
Constants.AUTOCOMPLETE_TIMEOUT
|
||||
const users = members.concat(specialMentions).concat(nonmembers);
|
||||
const mentions = users.map((user) => '@' + user.username);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: `@${captured[1]}`,
|
||||
terms: mentions,
|
||||
items: users,
|
||||
component: AtMentionSuggestion
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (hadSuggestions) {
|
||||
// Clear the suggestions since the user has now typed something invalid
|
||||
SuggestionStore.clearSuggestions(suggestionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,69 +50,54 @@ class ChannelMentionSuggestion extends Suggestion {
|
||||
}
|
||||
|
||||
export default class ChannelMentionProvider {
|
||||
constructor() {
|
||||
this.timeoutId = '';
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
|
||||
handlePretextChanged(suggestionId, pretext) {
|
||||
const captured = (/(^|\s)(~([^~]*))$/i).exec(pretext.toLowerCase());
|
||||
if (captured) {
|
||||
const prefix = captured[3];
|
||||
|
||||
function autocomplete() {
|
||||
autocompleteChannels(
|
||||
prefix,
|
||||
(data) => {
|
||||
const channels = data;
|
||||
autocompleteChannels(
|
||||
prefix,
|
||||
(data) => {
|
||||
const channels = data;
|
||||
|
||||
// Wrap channels in an outer object to avoid overwriting the 'type' property.
|
||||
const wrappedChannels = [];
|
||||
const wrappedMoreChannels = [];
|
||||
const moreChannels = [];
|
||||
channels.forEach((item) => {
|
||||
if (ChannelStore.get(item.id)) {
|
||||
wrappedChannels.push({
|
||||
type: Constants.MENTION_CHANNELS,
|
||||
channel: item
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
wrappedMoreChannels.push({
|
||||
type: Constants.MENTION_MORE_CHANNELS,
|
||||
// Wrap channels in an outer object to avoid overwriting the 'type' property.
|
||||
const wrappedChannels = [];
|
||||
const wrappedMoreChannels = [];
|
||||
const moreChannels = [];
|
||||
channels.forEach((item) => {
|
||||
if (ChannelStore.get(item.id)) {
|
||||
wrappedChannels.push({
|
||||
type: Constants.MENTION_CHANNELS,
|
||||
channel: item
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
moreChannels.push(item);
|
||||
wrappedMoreChannels.push({
|
||||
type: Constants.MENTION_MORE_CHANNELS,
|
||||
channel: item
|
||||
});
|
||||
|
||||
const wrapped = wrappedChannels.concat(wrappedMoreChannels);
|
||||
const mentions = wrapped.map((item) => '~' + item.channel.name);
|
||||
moreChannels.push(item);
|
||||
});
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_MORE_CHANNELS,
|
||||
channels: moreChannels
|
||||
});
|
||||
const wrapped = wrappedChannels.concat(wrappedMoreChannels);
|
||||
const mentions = wrapped.map((item) => '~' + item.channel.name);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: captured[2],
|
||||
terms: mentions,
|
||||
items: wrapped,
|
||||
component: ChannelMentionSuggestion
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_MORE_CHANNELS,
|
||||
channels: moreChannels
|
||||
});
|
||||
|
||||
this.timeoutId = setTimeout(
|
||||
autocomplete.bind(this),
|
||||
Constants.AUTOCOMPLETE_TIMEOUT
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: captured[2],
|
||||
terms: mentions,
|
||||
items: wrapped,
|
||||
component: ChannelMentionSuggestion
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,63 +33,48 @@ class SearchChannelSuggestion extends Suggestion {
|
||||
}
|
||||
|
||||
export default class SearchChannelProvider {
|
||||
constructor() {
|
||||
this.timeoutId = '';
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
|
||||
handlePretextChanged(suggestionId, pretext) {
|
||||
const captured = (/\b(?:in|channel):\s*(\S*)$/i).exec(pretext.toLowerCase());
|
||||
if (captured) {
|
||||
const channelPrefix = captured[1];
|
||||
|
||||
function autocomplete() {
|
||||
autocompleteChannels(
|
||||
channelPrefix,
|
||||
(data) => {
|
||||
const publicChannels = data;
|
||||
autocompleteChannels(
|
||||
channelPrefix,
|
||||
(data) => {
|
||||
const publicChannels = data;
|
||||
|
||||
const localChannels = ChannelStore.getAll();
|
||||
const privateChannels = [];
|
||||
const localChannels = ChannelStore.getAll();
|
||||
const privateChannels = [];
|
||||
|
||||
for (const id of Object.keys(localChannels)) {
|
||||
const channel = localChannels[id];
|
||||
if (channel.name.startsWith(channelPrefix) && channel.type === Constants.PRIVATE_CHANNEL) {
|
||||
privateChannels.push(channel);
|
||||
}
|
||||
for (const id of Object.keys(localChannels)) {
|
||||
const channel = localChannels[id];
|
||||
if (channel.name.startsWith(channelPrefix) && channel.type === Constants.PRIVATE_CHANNEL) {
|
||||
privateChannels.push(channel);
|
||||
}
|
||||
|
||||
const filteredPublicChannels = [];
|
||||
publicChannels.forEach((item) => {
|
||||
if (item.name.startsWith(channelPrefix)) {
|
||||
filteredPublicChannels.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
privateChannels.sort((a, b) => a.name.localeCompare(b.name));
|
||||
filteredPublicChannels.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
const channels = filteredPublicChannels.concat(privateChannels);
|
||||
const channelNames = channels.map((channel) => channel.name);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: channelPrefix,
|
||||
terms: channelNames,
|
||||
items: channels,
|
||||
component: SearchChannelSuggestion
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.timeoutId = setTimeout(
|
||||
autocomplete.bind(this),
|
||||
Constants.AUTOCOMPLETE_TIMEOUT
|
||||
const filteredPublicChannels = [];
|
||||
publicChannels.forEach((item) => {
|
||||
if (item.name.startsWith(channelPrefix)) {
|
||||
filteredPublicChannels.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
privateChannels.sort((a, b) => a.name.localeCompare(b.name));
|
||||
filteredPublicChannels.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
const channels = filteredPublicChannels.concat(privateChannels);
|
||||
const channelNames = channels.map((channel) => channel.name);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: channelPrefix,
|
||||
terms: channelNames,
|
||||
items: channels,
|
||||
component: SearchChannelSuggestion
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {autocompleteUsersInTeam} from 'actions/user_actions.jsx';
|
||||
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
|
||||
import Client from 'client/web_client.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
import {Constants, ActionTypes} from 'utils/constants.jsx';
|
||||
import {ActionTypes} from 'utils/constants.jsx';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@@ -57,43 +57,26 @@ class SearchUserSuggestion extends Suggestion {
|
||||
}
|
||||
|
||||
export default class SearchUserProvider {
|
||||
constructor() {
|
||||
this.timeoutId = '';
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
|
||||
handlePretextChanged(suggestionId, pretext) {
|
||||
clearTimeout(this.timeoutId);
|
||||
|
||||
const captured = (/\bfrom:\s*(\S*)$/i).exec(pretext.toLowerCase());
|
||||
if (captured) {
|
||||
const usernamePrefix = captured[1];
|
||||
|
||||
function autocomplete() {
|
||||
autocompleteUsersInTeam(
|
||||
usernamePrefix,
|
||||
(data) => {
|
||||
const users = data.in_team;
|
||||
const mentions = users.map((user) => user.username);
|
||||
autocompleteUsersInTeam(
|
||||
usernamePrefix,
|
||||
(data) => {
|
||||
const users = data.in_team;
|
||||
const mentions = users.map((user) => user.username);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: usernamePrefix,
|
||||
terms: mentions,
|
||||
items: users,
|
||||
component: SearchUserSuggestion
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.timeoutId = setTimeout(
|
||||
autocomplete.bind(this),
|
||||
Constants.AUTOCOMPLETE_TIMEOUT
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: usernamePrefix,
|
||||
terms: mentions,
|
||||
items: users,
|
||||
component: SearchUserSuggestion
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,94 +59,79 @@ class SwitchChannelSuggestion extends Suggestion {
|
||||
}
|
||||
|
||||
export default class SwitchChannelProvider {
|
||||
constructor() {
|
||||
this.timeoutId = '';
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
|
||||
handlePretextChanged(suggestionId, channelPrefix) {
|
||||
if (channelPrefix) {
|
||||
const allChannels = ChannelStore.getAll();
|
||||
const channels = [];
|
||||
|
||||
function autocomplete() {
|
||||
autocompleteUsers(
|
||||
channelPrefix,
|
||||
(users) => {
|
||||
const currentId = UserStore.getCurrentId();
|
||||
autocompleteUsers(
|
||||
channelPrefix,
|
||||
(users) => {
|
||||
const currentId = UserStore.getCurrentId();
|
||||
|
||||
for (const id of Object.keys(allChannels)) {
|
||||
const channel = allChannels[id];
|
||||
if (channel.display_name.toLowerCase().indexOf(channelPrefix.toLowerCase()) !== -1) {
|
||||
channels.push(channel);
|
||||
}
|
||||
for (const id of Object.keys(allChannels)) {
|
||||
const channel = allChannels[id];
|
||||
if (channel.display_name.toLowerCase().indexOf(channelPrefix.toLowerCase()) !== -1) {
|
||||
channels.push(channel);
|
||||
}
|
||||
|
||||
const userMap = {};
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
const user = users[i];
|
||||
let displayName = `@${user.username} `;
|
||||
|
||||
if (user.id === currentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((user.first_name || user.last_name) && user.nickname) {
|
||||
displayName += `- ${Utils.getFullName(user)} (${user.nickname})`;
|
||||
} else if (user.nickname) {
|
||||
displayName += `- (${user.nickname})`;
|
||||
} else if (user.first_name || user.last_name) {
|
||||
displayName += `- ${Utils.getFullName(user)}`;
|
||||
}
|
||||
|
||||
const newChannel = {
|
||||
display_name: displayName,
|
||||
name: user.username,
|
||||
id: user.id,
|
||||
update_at: user.update_at,
|
||||
type: Constants.DM_CHANNEL
|
||||
};
|
||||
channels.push(newChannel);
|
||||
userMap[user.id] = user;
|
||||
}
|
||||
|
||||
channels.sort((a, b) => {
|
||||
if (a.display_name === b.display_name) {
|
||||
if (a.type !== Constants.DM_CHANNEL && b.type === Constants.DM_CHANNEL) {
|
||||
return -1;
|
||||
} else if (a.type === Constants.DM_CHANNEL && b.type !== Constants.DM_CHANNEL) {
|
||||
return 1;
|
||||
}
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
return a.display_name.localeCompare(b.display_name);
|
||||
});
|
||||
|
||||
const channelNames = channels.map((channel) => channel.name);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: channelPrefix,
|
||||
terms: channelNames,
|
||||
items: channels,
|
||||
component: SwitchChannelSuggestion
|
||||
});
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_PROFILES,
|
||||
profiles: userMap
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.timeoutId = setTimeout(
|
||||
autocomplete.bind(this),
|
||||
Constants.AUTOCOMPLETE_TIMEOUT
|
||||
const userMap = {};
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
const user = users[i];
|
||||
let displayName = `@${user.username} `;
|
||||
|
||||
if (user.id === currentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((user.first_name || user.last_name) && user.nickname) {
|
||||
displayName += `- ${Utils.getFullName(user)} (${user.nickname})`;
|
||||
} else if (user.nickname) {
|
||||
displayName += `- (${user.nickname})`;
|
||||
} else if (user.first_name || user.last_name) {
|
||||
displayName += `- ${Utils.getFullName(user)}`;
|
||||
}
|
||||
|
||||
const newChannel = {
|
||||
display_name: displayName,
|
||||
name: user.username,
|
||||
id: user.id,
|
||||
update_at: user.update_at,
|
||||
type: Constants.DM_CHANNEL
|
||||
};
|
||||
channels.push(newChannel);
|
||||
userMap[user.id] = user;
|
||||
}
|
||||
|
||||
channels.sort((a, b) => {
|
||||
if (a.display_name === b.display_name) {
|
||||
if (a.type !== Constants.DM_CHANNEL && b.type === Constants.DM_CHANNEL) {
|
||||
return -1;
|
||||
} else if (a.type === Constants.DM_CHANNEL && b.type !== Constants.DM_CHANNEL) {
|
||||
return 1;
|
||||
}
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
return a.display_name.localeCompare(b.display_name);
|
||||
});
|
||||
|
||||
const channelNames = channels.map((channel) => channel.name);
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS,
|
||||
id: suggestionId,
|
||||
matchedPretext: channelPrefix,
|
||||
terms: channelNames,
|
||||
items: channels,
|
||||
component: SwitchChannelSuggestion
|
||||
});
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_PROFILES,
|
||||
profiles: userMap
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,7 +865,6 @@ export const Constants = {
|
||||
MENTION_SPECIAL: 'mention.special',
|
||||
DEFAULT_NOTIFICATION_DURATION: 5000,
|
||||
STATUS_INTERVAL: 60000,
|
||||
AUTOCOMPLETE_TIMEOUT: 100,
|
||||
SEARCH_TIMEOUT_MILLISECONDS: 100
|
||||
};
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user