403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/cvetdv.ru/bitrix/js/im/v2/component/textarea/src/classes/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/cvetdv.ru/bitrix/js/im/v2/component/textarea/src/classes/mention-manager.js
import { EventEmitter } from 'main.core.events';

import { EventType } from 'im.v2.const';
import { Utils } from 'im.v2.lib.utils';

type MentionTextToInsert = string;
type MentionReplacementMap = {[textToReplace: string]: MentionTextToInsert};

const MentionSymbols: Set<string> = new Set(['@', '+']);
const WAIT_FOR_NEXT_SYMBOL_TIME = 10;
const WAIT_FOR_LAST_SYMBOL_TIME = 10;

export const MentionManagerEvents = Object.freeze({
	showMentionPopup: 'showMentionPopup',
	hideMentionPopup: 'hideMentionPopup',
	insertMention: 'insertMention',
});

export class MentionManager extends EventEmitter
{
	#mentionPopupOpened: boolean = false;
	#mentionSymbol: string = '';
	#textarea: HTMLTextAreaElement;

	#mentionReplacementMap: MentionReplacementMap = {};

	static eventNamespace = 'BX.Messenger.v2.Textarea.MentionManager';

	constructor(textarea: HTMLTextAreaElement)
	{
		super();
		this.setEventNamespace(MentionManager.eventNamespace);
		this.#textarea = textarea;
	}

	// region 'popup'
	onActiveMentionKeyDown(event): void
	{
		if (!this.#mentionPopupOpened)
		{
			return;
		}

		this.#onOpenedMentionKeyDown(event);
	}

	onKeyDown(event): void
	{
		this.#onClosedMentionKeyDown(event);
	}

	onMentionPopupClose()
	{
		this.#mentionPopupOpened = false;
	}

	#onClosedMentionKeyDown(event: KeyboardEvent)
	{
		if (!this.#isOpenMentionCombination(event))
		{
			return;
		}

		setTimeout((): void => {
			if (!this.#checkMentionSymbol())
			{
				return;
			}

			this.#mentionPopupOpened = true;
			this.emit(MentionManagerEvents.showMentionPopup, {
				mentionQuery: '',
			});
		}, WAIT_FOR_NEXT_SYMBOL_TIME);
	}

	#onOpenedMentionKeyDown(event: KeyboardEvent)
	{
		if (this.#isCloseMentionCombination(event))
		{
			this.#sendHidePopupEvent();

			return;
		}

		if (this.#isNavigateCombination(event))
		{
			event.preventDefault();

			return;
		}

		if (this.#isInsertMentionCombination(event))
		{
			event.preventDefault();
			this.#sendInsertMentionEvent(event);

			return;
		}

		setTimeout((): void => {
			if (!this.#isValidQuery())
			{
				this.#sendHidePopupEvent();

				return;
			}

			this.emit(MentionManagerEvents.showMentionPopup, {
				mentionQuery: this.#getQueryWithoutMentionSymbol(),
			});
		}, WAIT_FOR_LAST_SYMBOL_TIME);
	}

	#checkMentionSymbol(): boolean
	{
		const cursorPosition = this.#textarea.selectionEnd;
		this.#mentionSymbol = this.#textarea.value.slice(cursorPosition - 1, cursorPosition);
		if (!MentionSymbols.has(this.#mentionSymbol))
		{
			return false;
		}

		const symbolBeforeMentionSymbol = this.#textarea.value.slice(cursorPosition - 2, cursorPosition - 1);

		return symbolBeforeMentionSymbol.length === 0 || this.#hasWhitespace(symbolBeforeMentionSymbol);
	}

	#isValidQuery(): boolean
	{
		const query = this.#getQuery();
		if (query.length === 0)
		{
			return false;
		}

		const firstQuerySymbol = this.#getQueryWithoutMentionSymbol().slice(0, 1);
		if (firstQuerySymbol.length === 0)
		{
			return true;
		}

		if (!this.#isValidFirstSymbol(firstQuerySymbol))
		{
			return false;
		}

		return !this.#hasWhitespace(firstQuerySymbol);
	}

	#isCloseMentionCombination(event: KeyboardEvent): boolean
	{
		return event.key === 'Escape';
	}

	#isInsertMentionCombination(event: KeyboardEvent): boolean
	{
		return event.key === 'Enter';
	}

	#isOpenMentionCombination(event: KeyboardEvent): boolean
	{
		return event.key === '+' || event.key === '@';
	}

	#sendHidePopupEvent()
	{
		this.#mentionPopupOpened = false;
		this.#mentionSymbol = '';

		this.emit(MentionManagerEvents.hideMentionPopup);
	}

	#sendInsertMentionEvent(event)
	{
		event.preventDefault();
		EventEmitter.emit(EventType.mention.selectItem);
		this.#sendHidePopupEvent();
	}

	#getTextBeforeCursor(): string
	{
		return this.#textarea.value.slice(0, Math.max(0, this.#textarea.selectionEnd));
	}

	#getMentionSymbolIndex(): number
	{
		const textBeforeCursor = this.#getTextBeforeCursor();

		return textBeforeCursor.lastIndexOf(this.#mentionSymbol);
	}

	#getQuery(): string
	{
		const textBeforeCursor = this.#getTextBeforeCursor();
		const mentionSymbolIndex = this.#getMentionSymbolIndex();
		if (mentionSymbolIndex < 0)
		{
			return '';
		}

		return textBeforeCursor.slice(mentionSymbolIndex, this.#textarea.selectionEnd);
	}

	#getQueryWithoutMentionSymbol(): string
	{
		return this.#getQuery().slice(1);
	}

	#isNavigateCombination(event: KeyboardEvent): boolean
	{
		return event.key === 'ArrowUp' || event.key === 'ArrowDown';
	}

	#isValidFirstSymbol(firstQuerySymbol: string): boolean
	{
		return !(this.#hasNumber(firstQuerySymbol)
			|| this.#hasWhitespace(firstQuerySymbol)
			|| this.#hasSpecialSymbol(firstQuerySymbol));
	}

	#hasWhitespace(text: string): boolean
	{
		return (/^\s/).test(text);
	}

	#hasNumber(text: string): boolean
	{
		return (/\d$/).test(text);
	}

	#hasSpecialSymbol(text: string): boolean
	{
		const regex = /[!"#$%&'()*+,./<>@\\^_|-]/;

		return regex.test(text);
	}
	// endregion 'popup'

	// region 'replace'
	setMentionReplacements(mentionsMap: MentionReplacementMap): void
	{
		this.#mentionReplacementMap = mentionsMap;
	}

	addMentionReplacement(textToReplace: string, textToInsert: string): MentionReplacementMap
	{
		this.#mentionReplacementMap[textToReplace] = textToInsert;

		return this.#mentionReplacementMap;
	}

	getMentionSymbol(): string
	{
		return this.#mentionSymbol;
	}

	replaceMentions(text: string): string
	{
		let resultText = text;
		Object.entries(this.#mentionReplacementMap).forEach(([textToReplace, textToInsert]) => {
			resultText = resultText.replaceAll(textToReplace, textToInsert);
		});

		return resultText;
	}

	extractMentions(text: string): MentionReplacementMap
	{
		const CHAT_MENTION_CODE = 'chat';

		const mentions = {};
		const mentionRegExp = /\[(?<type>user|chat)=(?<dialogId>\w+)](?<mentionText>.*?)\[\/(user|chat)]/gi;

		const matches = text.matchAll(mentionRegExp);
		for (const match of matches)
		{
			const { mentionText } = match.groups;
			let { type: mentionType, dialogId } = match.groups;

			mentionType = mentionType.toLowerCase();
			if (mentionType === CHAT_MENTION_CODE)
			{
				dialogId = `${mentionType}${dialogId}`;
			}

			mentions[mentionText] = Utils.text.getMentionBbCode(dialogId, mentionText);
		}

		return mentions;
	}

	clearMentionSymbol()
	{
		this.#mentionSymbol = '';
	}

	clearMentionReplacements(): void
	{
		this.#mentionReplacementMap = {};
	}
	// endregion 'replace'
}

Youez - 2016 - github.com/yon3zu
LinuXploit