|
|
@ -73,7 +73,7 @@ const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this |
|
|
|
type ChatInputHelperType = 'edit' | 'webpage' | 'forward' | 'reply'; |
|
|
|
type ChatInputHelperType = 'edit' | 'webpage' | 'forward' | 'reply'; |
|
|
|
|
|
|
|
|
|
|
|
export default class ChatInput { |
|
|
|
export default class ChatInput { |
|
|
|
private static AUTO_COMPLETE_REG_EXP = /(\s|^)((?::|.)(?!.*:).*|(?:(?:@|\/)(?:[\S]*)))$/; |
|
|
|
private static AUTO_COMPLETE_REG_EXP = /(\s|^)((?::|.)(?!.*[:@]).*|(?:[@\/]\S*))$/; |
|
|
|
public messageInput: HTMLElement; |
|
|
|
public messageInput: HTMLElement; |
|
|
|
public messageInputField: InputField; |
|
|
|
public messageInputField: InputField; |
|
|
|
private fileInput: HTMLInputElement; |
|
|
|
private fileInput: HTMLInputElement; |
|
|
@ -1144,8 +1144,7 @@ export default class ChatInput { |
|
|
|
this.updateSendBtn(); |
|
|
|
this.updateSendBtn(); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
public onEmojiSelected = (emoji: string, autocomplete: boolean) => { |
|
|
|
public insertAtCaret(insertText: string, insertEntity?: MessageEntity) { |
|
|
|
if(autocomplete) { |
|
|
|
|
|
|
|
const {value: fullValue, caretPos, entities} = getRichValueWithCaret(this.messageInput); |
|
|
|
const {value: fullValue, caretPos, entities} = getRichValueWithCaret(this.messageInput); |
|
|
|
const pos = caretPos >= 0 ? caretPos : fullValue.length; |
|
|
|
const pos = caretPos >= 0 ? caretPos : fullValue.length; |
|
|
|
const prefix = fullValue.substr(0, pos); |
|
|
|
const prefix = fullValue.substr(0, pos); |
|
|
@ -1155,25 +1154,30 @@ export default class ChatInput { |
|
|
|
|
|
|
|
|
|
|
|
const matchIndex = matches.index + (matches[0].length - matches[2].length); |
|
|
|
const matchIndex = matches.index + (matches[0].length - matches[2].length); |
|
|
|
const newPrefix = prefix.slice(0, matchIndex); |
|
|
|
const newPrefix = prefix.slice(0, matchIndex); |
|
|
|
const newValue = newPrefix + emoji + suffix; |
|
|
|
const newValue = newPrefix + insertText + suffix; |
|
|
|
|
|
|
|
|
|
|
|
// merge emojis
|
|
|
|
// merge emojis
|
|
|
|
const hadEntities = RichTextProcessor.parseEntities(fullValue); |
|
|
|
const hadEntities = RichTextProcessor.parseEntities(fullValue); |
|
|
|
RichTextProcessor.mergeEntities(entities, hadEntities); |
|
|
|
RichTextProcessor.mergeEntities(entities, hadEntities); |
|
|
|
|
|
|
|
|
|
|
|
const emojiEntity = RichTextProcessor.getEmojiEntityFromEmoji(emoji); |
|
|
|
// max for additional whitespace
|
|
|
|
const addEntities: MessageEntity[] = [emojiEntity]; |
|
|
|
const insertLength = insertEntity ? Math.max(insertEntity.length, insertText.length) : insertText.length; |
|
|
|
emojiEntity.offset = matchIndex; |
|
|
|
const addEntities: MessageEntity[] = []; |
|
|
|
|
|
|
|
if(insertEntity) { |
|
|
|
|
|
|
|
addEntities.push(insertEntity); |
|
|
|
|
|
|
|
insertEntity.offset = matchIndex; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
addEntities.push({ |
|
|
|
addEntities.push({ |
|
|
|
_: 'messageEntityCaret', |
|
|
|
_: 'messageEntityCaret', |
|
|
|
length: 0, |
|
|
|
length: 0, |
|
|
|
offset: emojiEntity.offset + emojiEntity.length |
|
|
|
offset: matchIndex + insertLength |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// add offset to entities next to emoji
|
|
|
|
// add offset to entities next to emoji
|
|
|
|
const diff = emojiEntity.length - matches[2].length; |
|
|
|
const diff = insertLength - matches[2].length; |
|
|
|
entities.forEach(entity => { |
|
|
|
entities.forEach(entity => { |
|
|
|
if(entity.offset >= emojiEntity.offset) { |
|
|
|
if(entity.offset >= matchIndex) { |
|
|
|
entity.offset += diff; |
|
|
|
entity.offset += diff; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
@ -1195,6 +1199,11 @@ export default class ChatInput { |
|
|
|
|
|
|
|
|
|
|
|
//document.execCommand('insertHTML', true, RichTextProcessor.wrapEmojiText(emoji));
|
|
|
|
//document.execCommand('insertHTML', true, RichTextProcessor.wrapEmojiText(emoji));
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public onEmojiSelected = (emoji: string, autocomplete: boolean) => { |
|
|
|
|
|
|
|
if(autocomplete) { |
|
|
|
|
|
|
|
this.insertAtCaret(emoji, RichTextProcessor.getEmojiEntityFromEmoji(emoji)); |
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
private checkAutocomplete(value?: string, caretPos?: number, entities?: MessageEntity[]) { |
|
|
|
private checkAutocomplete(value?: string, caretPos?: number, entities?: MessageEntity[]) { |
|
|
@ -1248,20 +1257,27 @@ export default class ChatInput { |
|
|
|
|
|
|
|
|
|
|
|
//console.log('autocomplete matches', matches);
|
|
|
|
//console.log('autocomplete matches', matches);
|
|
|
|
|
|
|
|
|
|
|
|
/* if(firstChar === '@') { // mentions |
|
|
|
if(firstChar === '@') { // mentions
|
|
|
|
if(this.chat.peerId < 0) { |
|
|
|
const trimmed = query.trim(); // check that there is no whitespace
|
|
|
|
|
|
|
|
if(this.chat.peerId < 0 && query.length === trimmed.length) { |
|
|
|
foundHelper = this.mentionsHelper; |
|
|
|
foundHelper = this.mentionsHelper; |
|
|
|
this.chat.appProfileManager.getMentions(-this.chat.peerId, query).then(peerIds => { |
|
|
|
const topMsgId = this.chat.threadId ? this.appMessagesManager.getServerMessageId(this.chat.threadId) : undefined; |
|
|
|
|
|
|
|
this.chat.appProfileManager.getMentions(-this.chat.peerId, trimmed, topMsgId).then(peerIds => { |
|
|
|
|
|
|
|
const username = trimmed.slice(1).toLowerCase(); |
|
|
|
this.mentionsHelper.render(peerIds.map(peerId => { |
|
|
|
this.mentionsHelper.render(peerIds.map(peerId => { |
|
|
|
const user = this.chat.appUsersManager.getUser(peerId); |
|
|
|
const user = this.chat.appUsersManager.getUser(peerId); |
|
|
|
|
|
|
|
if(user.username && user.username.toLowerCase() === username) { // hide full matched suggestion
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
return { |
|
|
|
peerId, |
|
|
|
peerId, |
|
|
|
description: user.username ? '@' + user.username : undefined |
|
|
|
description: user.username ? '@' + user.username : undefined |
|
|
|
}; |
|
|
|
}; |
|
|
|
})); |
|
|
|
}).filter(Boolean)); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} else */if(!matches[1] && firstChar === '/') { // commands
|
|
|
|
} else if(!matches[1] && firstChar === '/') { // commands
|
|
|
|
if(appUsersManager.isBot(this.chat.peerId)) { |
|
|
|
if(appUsersManager.isBot(this.chat.peerId)) { |
|
|
|
foundHelper = this.commandsHelper; |
|
|
|
foundHelper = this.commandsHelper; |
|
|
|
this.chat.appProfileManager.getProfileByPeerId(this.chat.peerId).then(full => { |
|
|
|
this.chat.appProfileManager.getProfileByPeerId(this.chat.peerId).then(full => { |
|
|
|