Этот коммит содержится в:
Joram Wilander
2016-12-20 09:08:58 -05:00
коммит произвёл Christopher Speller
родитель d4b890fff1
Коммит bf3fec604f
6 изменённых файлов: 175 добавлений и 269 удалений

Просмотреть файл

@@ -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
};