Fixed channel autocomplete flickering (#5961)
Этот коммит содержится в:
коммит произвёл
Corey Hulen
родитель
5cd0d5b87e
Коммит
c4fd04efb6
@@ -6,7 +6,6 @@ import Provider from './provider.jsx';
|
|||||||
|
|
||||||
import ChannelStore from 'stores/channel_store.jsx';
|
import ChannelStore from 'stores/channel_store.jsx';
|
||||||
import UserStore from 'stores/user_store.jsx';
|
import UserStore from 'stores/user_store.jsx';
|
||||||
import SuggestionStore from 'stores/suggestion_store.jsx';
|
|
||||||
|
|
||||||
import {autocompleteUsersInChannel} from 'actions/user_actions.jsx';
|
import {autocompleteUsersInChannel} from 'actions/user_actions.jsx';
|
||||||
|
|
||||||
@@ -112,58 +111,60 @@ export default class AtMentionProvider extends Provider {
|
|||||||
|
|
||||||
handlePretextChanged(suggestionId, pretext) {
|
handlePretextChanged(suggestionId, pretext) {
|
||||||
const captured = XRegExp.cache('(?:^|\\W)@([\\pL\\d\\-_.]*)$', 'i').exec(pretext.toLowerCase());
|
const captured = XRegExp.cache('(?:^|\\W)@([\\pL\\d\\-_.]*)$', 'i').exec(pretext.toLowerCase());
|
||||||
if (captured) {
|
if (!captured) {
|
||||||
const prefix = captured[1];
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.startNewRequest(prefix);
|
const prefix = captured[1];
|
||||||
|
|
||||||
autocompleteUsersInChannel(
|
this.startNewRequest(prefix);
|
||||||
prefix,
|
|
||||||
this.channelId,
|
|
||||||
(data) => {
|
|
||||||
if (this.shouldCancelDispatch(prefix)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const members = data.in_channel;
|
autocompleteUsersInChannel(
|
||||||
for (const id of Object.keys(members)) {
|
prefix,
|
||||||
members[id].type = Constants.MENTION_MEMBERS;
|
this.channelId,
|
||||||
}
|
(data) => {
|
||||||
|
if (this.shouldCancelDispatch(prefix)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const nonmembers = data.out_of_channel;
|
const members = data.in_channel;
|
||||||
for (const id of Object.keys(nonmembers)) {
|
for (const id of Object.keys(members)) {
|
||||||
nonmembers[id].type = Constants.MENTION_NONMEMBERS;
|
members[id].type = Constants.MENTION_MEMBERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
let specialMentions = [];
|
const nonmembers = data.out_of_channel;
|
||||||
if (!pretext.startsWith('/msg')) {
|
for (const id of Object.keys(nonmembers)) {
|
||||||
specialMentions = ['here', 'channel', 'all'].filter((item) => {
|
nonmembers[id].type = Constants.MENTION_NONMEMBERS;
|
||||||
return item.startsWith(prefix);
|
}
|
||||||
}).map((name) => {
|
|
||||||
return {username: name, type: Constants.MENTION_SPECIAL};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let users = members.concat(specialMentions).concat(nonmembers);
|
let specialMentions = [];
|
||||||
const me = UserStore.getCurrentUser();
|
if (!pretext.startsWith('/msg')) {
|
||||||
users = users.filter((user) => {
|
specialMentions = ['here', 'channel', 'all'].filter((item) => {
|
||||||
return user.id !== me.id;
|
return item.startsWith(prefix);
|
||||||
});
|
}).map((name) => {
|
||||||
|
return {username: name, type: Constants.MENTION_SPECIAL};
|
||||||
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
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
|
||||||
} else {
|
let users = members.concat(specialMentions).concat(nonmembers);
|
||||||
SuggestionStore.clearSuggestions(suggestionId);
|
const me = UserStore.getCurrentUser();
|
||||||
}
|
users = users.filter((user) => {
|
||||||
|
return user.id !== me.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,12 +62,12 @@ export default class ChannelMentionProvider extends Provider {
|
|||||||
|
|
||||||
if (!captured) {
|
if (!captured) {
|
||||||
// Not a channel mention
|
// Not a channel mention
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastCompletedWord && captured[0].startsWith(this.lastCompletedWord)) {
|
if (this.lastCompletedWord && captured[0].startsWith(this.lastCompletedWord)) {
|
||||||
// It appears we're still matching a channel handle that we already completed
|
// It appears we're still matching a channel handle that we already completed
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the last completed word since we've started to match new text
|
// Clear the last completed word since we've started to match new text
|
||||||
@@ -125,6 +125,8 @@ export default class ChannelMentionProvider extends Provider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCompleteWord(term) {
|
handleCompleteWord(term) {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default class EmoticonProvider {
|
|||||||
|
|
||||||
if (partialName.length < MIN_EMOTICON_LENGTH) {
|
if (partialName.length < MIN_EMOTICON_LENGTH) {
|
||||||
SuggestionStore.clearSuggestions(suggestionId);
|
SuggestionStore.clearSuggestions(suggestionId);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const matched = [];
|
const matched = [];
|
||||||
@@ -117,6 +117,10 @@ export default class EmoticonProvider {
|
|||||||
if (hasSuggestions) {
|
if (hasSuggestions) {
|
||||||
// force the selection to be cleared since the order of elements may have changed
|
// force the selection to be cleared since the order of elements may have changed
|
||||||
SuggestionStore.clearSelection(suggestionId);
|
SuggestionStore.clearSelection(suggestionId);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,5 +85,7 @@ export default class SearchChannelProvider extends Provider {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Boolean(captured);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,5 +86,7 @@ export default class SearchUserProvider extends Provider {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Boolean(captured);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,8 +185,13 @@ export default class SuggestionBox extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handlePretextChanged(pretext) {
|
handlePretextChanged(pretext) {
|
||||||
|
let handled = false;
|
||||||
for (const provider of this.props.providers) {
|
for (const provider of this.props.providers) {
|
||||||
provider.handlePretextChanged(this.suggestionId, pretext);
|
handled = provider.handlePretextChanged(this.suggestionId, pretext) || handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
SuggestionStore.clearSuggestions(this.suggestionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -227,8 +227,8 @@ class SuggestionStore extends EventEmitter {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ActionTypes.SUGGESTION_PRETEXT_CHANGED:
|
case ActionTypes.SUGGESTION_PRETEXT_CHANGED:
|
||||||
// Clear the suggestions if the pretext is empty or has whitespace
|
// Clear the suggestions if the pretext is empty or ends with whitespace
|
||||||
if (other.pretext === '' || (/\s/g.test(other.pretext))) {
|
if (other.pretext === '') {
|
||||||
this.clearSuggestions(id);
|
this.clearSuggestions(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user