New bot commands menu
This commit is contained in:
parent
7f9c298a05
commit
d6b987eba4
@ -16,6 +16,7 @@ import AutocompleteHelperController from "./autocompleteHelperController";
|
|||||||
export default class AutocompleteHelper extends EventListenerBase<{
|
export default class AutocompleteHelper extends EventListenerBase<{
|
||||||
hidden: () => void,
|
hidden: () => void,
|
||||||
visible: () => void,
|
visible: () => void,
|
||||||
|
hiding: () => void
|
||||||
}> {
|
}> {
|
||||||
protected hidden = true;
|
protected hidden = true;
|
||||||
protected container: HTMLElement;
|
protected container: HTMLElement;
|
||||||
@ -34,7 +35,7 @@ export default class AutocompleteHelper extends EventListenerBase<{
|
|||||||
|
|
||||||
constructor(options: {
|
constructor(options: {
|
||||||
appendTo: HTMLElement,
|
appendTo: HTMLElement,
|
||||||
controller: AutocompleteHelper['controller'],
|
controller?: AutocompleteHelper['controller'],
|
||||||
listType: AutocompleteHelper['listType'],
|
listType: AutocompleteHelper['listType'],
|
||||||
onSelect: AutocompleteHelper['onSelect'],
|
onSelect: AutocompleteHelper['onSelect'],
|
||||||
waitForKey?: AutocompleteHelper['waitForKey']
|
waitForKey?: AutocompleteHelper['waitForKey']
|
||||||
@ -50,7 +51,7 @@ export default class AutocompleteHelper extends EventListenerBase<{
|
|||||||
|
|
||||||
this.attachNavigation();
|
this.attachNavigation();
|
||||||
|
|
||||||
this.controller.addHelper(this);
|
this.controller && this.controller.addHelper(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleListNavigation(enabled: boolean) {
|
public toggleListNavigation(enabled: boolean) {
|
||||||
@ -110,7 +111,7 @@ export default class AutocompleteHelper extends EventListenerBase<{
|
|||||||
this.addEventListener('visible', this.onVisible);
|
this.addEventListener('visible', this.onVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggle(hide?: boolean, fromController = false) {
|
public toggle(hide?: boolean, fromController = false, skipAnimation?: boolean) {
|
||||||
if(this.init) {
|
if(this.init) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -130,7 +131,7 @@ export default class AutocompleteHelper extends EventListenerBase<{
|
|||||||
this.hidden = hide;
|
this.hidden = hide;
|
||||||
|
|
||||||
if(!hide) {
|
if(!hide) {
|
||||||
this.controller.hideOtherHelpers(this);
|
this.controller && this.controller.hideOtherHelpers(this);
|
||||||
this.dispatchEvent('visible'); // fire it before so target will be set
|
this.dispatchEvent('visible'); // fire it before so target will be set
|
||||||
} else {
|
} else {
|
||||||
if(this.navigationItem) {
|
if(this.navigationItem) {
|
||||||
@ -138,7 +139,7 @@ export default class AutocompleteHelper extends EventListenerBase<{
|
|||||||
this.navigationItem = undefined;
|
this.navigationItem = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!fromController) {
|
if(!fromController && this.controller) {
|
||||||
this.controller.hideOtherHelpers();
|
this.controller.hideOtherHelpers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,8 +148,21 @@ export default class AutocompleteHelper extends EventListenerBase<{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTransition(this.container, 'is-visible', !hide, rootScope.settings.animationsEnabled ? 200 : 0, () => {
|
const useRafs = this.controller || hide ? 0 : 2;
|
||||||
this.hidden && this.dispatchEvent('hidden');
|
|
||||||
});
|
if(hide) {
|
||||||
|
this.dispatchEvent('hiding');
|
||||||
|
}
|
||||||
|
|
||||||
|
SetTransition(
|
||||||
|
this.container,
|
||||||
|
'is-visible',
|
||||||
|
!hide,
|
||||||
|
rootScope.settings.animationsEnabled && !skipAnimation ? 300 : 0,
|
||||||
|
() => {
|
||||||
|
this.hidden && this.dispatchEvent('hidden');
|
||||||
|
},
|
||||||
|
useRafs
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,12 @@ export default class AutocompletePeerHelper extends AutocompleteHelper {
|
|||||||
protected static BASE_CLASS_LIST_ELEMENT = AutocompletePeerHelper.BASE_CLASS + '-list-element';
|
protected static BASE_CLASS_LIST_ELEMENT = AutocompletePeerHelper.BASE_CLASS + '-list-element';
|
||||||
private scrollable: Scrollable;
|
private scrollable: Scrollable;
|
||||||
|
|
||||||
constructor(appendTo: HTMLElement, controller: AutocompleteHelperController, protected className: string, onSelect: (target: Element) => boolean | void) {
|
constructor(
|
||||||
|
appendTo: HTMLElement,
|
||||||
|
controller: AutocompleteHelperController,
|
||||||
|
protected className: string,
|
||||||
|
onSelect: (target: Element) => boolean | void
|
||||||
|
) {
|
||||||
super({
|
super({
|
||||||
appendTo,
|
appendTo,
|
||||||
controller,
|
controller,
|
||||||
@ -29,7 +34,7 @@ export default class AutocompletePeerHelper extends AutocompleteHelper {
|
|||||||
|
|
||||||
protected init() {
|
protected init() {
|
||||||
this.list = document.createElement('div');
|
this.list = document.createElement('div');
|
||||||
this.list.classList.add(AutocompletePeerHelper.BASE_CLASS + '-list');
|
this.list.classList.add(AutocompletePeerHelper.BASE_CLASS + '-list', this.className + '-list');
|
||||||
|
|
||||||
this.container.append(this.list);
|
this.container.append(this.list);
|
||||||
|
|
||||||
@ -42,7 +47,7 @@ export default class AutocompletePeerHelper extends AutocompleteHelper {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(data: {peerId: PeerId, name?: string, description?: string}[]) {
|
public render(data: {peerId: PeerId, name?: string, description?: string}[], doNotShow?: boolean) {
|
||||||
if(this.init) {
|
if(this.init) {
|
||||||
if(!data.length) {
|
if(!data.length) {
|
||||||
return;
|
return;
|
||||||
@ -66,7 +71,9 @@ export default class AutocompletePeerHelper extends AutocompleteHelper {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toggle(!data.length);
|
if(!doNotShow) {
|
||||||
|
this.toggle(!data.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static listElement(options: {
|
public static listElement(options: {
|
||||||
|
54
src/components/chat/botCommands.ts
Normal file
54
src/components/chat/botCommands.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { AppProfileManager } from "../../lib/appManagers/appProfileManager";
|
||||||
|
import type ChatInput from "./input";
|
||||||
|
import callbackify from "../../helpers/callbackify";
|
||||||
|
import AutocompletePeerHelper from "./autocompletePeerHelper";
|
||||||
|
import { processPeerFullForCommands } from "./commandsHelper";
|
||||||
|
|
||||||
|
const CLASS_NAME = 'bot-commands';
|
||||||
|
export default class ChatBotCommands extends AutocompletePeerHelper {
|
||||||
|
private userId: UserId;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
appendTo: HTMLElement,
|
||||||
|
private chatInput: ChatInput,
|
||||||
|
private appProfileManager: AppProfileManager
|
||||||
|
) {
|
||||||
|
super(appendTo, undefined, CLASS_NAME, (target) => {
|
||||||
|
const innerHTML = target.querySelector(`.${AutocompletePeerHelper.BASE_CLASS_LIST_ELEMENT}-name`).innerHTML;
|
||||||
|
return chatInput.getReadyToSend(() => {
|
||||||
|
chatInput.messageInput.innerHTML = innerHTML;
|
||||||
|
chatInput.sendMessage(true);
|
||||||
|
this.toggle(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public setUserId(userId: UserId, middleware: () => boolean) {
|
||||||
|
if(this.userId === userId && this.list?.childElementCount) {
|
||||||
|
this.toggle(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userId = userId;
|
||||||
|
return callbackify(this.appProfileManager.getProfile(userId), (full) => {
|
||||||
|
if(!middleware()) return;
|
||||||
|
const filtered = processPeerFullForCommands(full);
|
||||||
|
|
||||||
|
const PADDING_TOP = 8;
|
||||||
|
// const PADDING_BOTTOM = 8;
|
||||||
|
const PADDING_BOTTOM = 24;
|
||||||
|
const height = filtered.length * 50 + PADDING_TOP + PADDING_BOTTOM;
|
||||||
|
this.container.style.setProperty('--height', height + 'px');
|
||||||
|
|
||||||
|
this.render(filtered);
|
||||||
|
|
||||||
|
// this.container.style.top =
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -7,11 +7,46 @@
|
|||||||
import type ChatInput from "./input";
|
import type ChatInput from "./input";
|
||||||
import type { AppProfileManager } from "../../lib/appManagers/appProfileManager";
|
import type { AppProfileManager } from "../../lib/appManagers/appProfileManager";
|
||||||
import type { AppUsersManager } from "../../lib/appManagers/appUsersManager";
|
import type { AppUsersManager } from "../../lib/appManagers/appUsersManager";
|
||||||
import type { BotInfo } from "../../layer";
|
import type { BotInfo, ChatFull, UserFull } from "../../layer";
|
||||||
import AutocompleteHelperController from "./autocompleteHelperController";
|
import AutocompleteHelperController from "./autocompleteHelperController";
|
||||||
import AutocompletePeerHelper from "./autocompletePeerHelper";
|
import AutocompletePeerHelper from "./autocompletePeerHelper";
|
||||||
import SearchIndex from "../../lib/searchIndex";
|
import SearchIndex from "../../lib/searchIndex";
|
||||||
|
|
||||||
|
export function processPeerFullForCommands(full: ChatFull.chatFull | ChatFull.channelFull | UserFull.userFull, query?: string) {
|
||||||
|
const botInfos: BotInfo.botInfo[] = [].concat(full.bot_info);
|
||||||
|
let index: SearchIndex<string>;
|
||||||
|
|
||||||
|
if(query !== undefined) {
|
||||||
|
index = new SearchIndex<string>({
|
||||||
|
ignoreCase: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const commands: Map<string, {peerId: PeerId, name: string, description: string}> = new Map();
|
||||||
|
botInfos.forEach(botInfo => {
|
||||||
|
botInfo.commands.forEach(botCommand => {
|
||||||
|
const c = '/' + botCommand.command;
|
||||||
|
commands.set(botCommand.command, {
|
||||||
|
peerId: botInfo.user_id.toPeerId(false),
|
||||||
|
name: c,
|
||||||
|
description: botCommand.description
|
||||||
|
});
|
||||||
|
|
||||||
|
if(index) {
|
||||||
|
index.indexObject(botCommand.command, c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!index) {
|
||||||
|
return [...commands.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
const found = index.search(query);
|
||||||
|
const filtered = Array.from(found).map(command => commands.get(command));
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
export default class CommandsHelper extends AutocompletePeerHelper {
|
export default class CommandsHelper extends AutocompletePeerHelper {
|
||||||
constructor(appendTo: HTMLElement,
|
constructor(appendTo: HTMLElement,
|
||||||
controller: AutocompleteHelperController,
|
controller: AutocompleteHelperController,
|
||||||
@ -42,27 +77,7 @@ export default class CommandsHelper extends AutocompletePeerHelper {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const botInfos: BotInfo.botInfo[] = [].concat(full.bot_info);
|
const filtered = processPeerFullForCommands(full, query);
|
||||||
const index = new SearchIndex<string>({
|
|
||||||
ignoreCase: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const commands: Map<string, {peerId: PeerId, name: string, description: string}> = new Map();
|
|
||||||
botInfos.forEach(botInfo => {
|
|
||||||
botInfo.commands.forEach(botCommand => {
|
|
||||||
const c = '/' + botCommand.command;
|
|
||||||
commands.set(botCommand.command, {
|
|
||||||
peerId: botInfo.user_id.toPeerId(false),
|
|
||||||
name: c,
|
|
||||||
description: botCommand.description
|
|
||||||
});
|
|
||||||
|
|
||||||
index.indexObject(botCommand.command, c);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const found = index.search(query);
|
|
||||||
const filtered = Array.from(found).map(command => commands.get(command));
|
|
||||||
this.render(filtered);
|
this.render(filtered);
|
||||||
// console.log('found commands', found, filtered);
|
// console.log('found commands', found, filtered);
|
||||||
});
|
});
|
||||||
|
@ -32,7 +32,7 @@ import PopupNewMedia from '../popups/newMedia';
|
|||||||
import { toast } from "../toast";
|
import { toast } from "../toast";
|
||||||
import { wrapReply } from "../wrappers";
|
import { wrapReply } from "../wrappers";
|
||||||
import InputField from '../inputField';
|
import InputField from '../inputField';
|
||||||
import { MessageEntity, DraftMessage, WebPage, Message, ChatFull } from '../../layer';
|
import { MessageEntity, DraftMessage, WebPage, Message, ChatFull, UserFull } from '../../layer';
|
||||||
import StickersHelper from './stickersHelper';
|
import StickersHelper from './stickersHelper';
|
||||||
import ButtonIcon from '../buttonIcon';
|
import ButtonIcon from '../buttonIcon';
|
||||||
import ButtonMenuToggle from '../buttonMenuToggle';
|
import ButtonMenuToggle from '../buttonMenuToggle';
|
||||||
@ -91,6 +91,7 @@ import AvatarElement from '../avatar';
|
|||||||
import type { AppProfileManager } from '../../lib/appManagers/appProfileManager';
|
import type { AppProfileManager } from '../../lib/appManagers/appProfileManager';
|
||||||
import { indexOfAndSplice } from '../../helpers/array';
|
import { indexOfAndSplice } from '../../helpers/array';
|
||||||
import callbackify from '../../helpers/callbackify';
|
import callbackify from '../../helpers/callbackify';
|
||||||
|
import ChatBotCommands from './botCommands';
|
||||||
|
|
||||||
const RECORD_MIN_TIME = 500;
|
const RECORD_MIN_TIME = 500;
|
||||||
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
|
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
|
||||||
@ -222,6 +223,11 @@ export default class ChatInput {
|
|||||||
public sendAsPeerId: PeerId;
|
public sendAsPeerId: PeerId;
|
||||||
private updatingSendAsPromise: Promise<void>;
|
private updatingSendAsPromise: Promise<void>;
|
||||||
|
|
||||||
|
private botCommandsToggle: HTMLElement;
|
||||||
|
private botCommands: ChatBotCommands;
|
||||||
|
private botCommandsIcon: HTMLDivElement;
|
||||||
|
hasBotCommands: number;
|
||||||
|
|
||||||
// private activeContainer: HTMLElement;
|
// private activeContainer: HTMLElement;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -573,6 +579,38 @@ export default class ChatInput {
|
|||||||
});
|
});
|
||||||
this.listenerSetter.add(this.replyKeyboard)('open', () => this.btnToggleReplyMarkup.classList.add('active'));
|
this.listenerSetter.add(this.replyKeyboard)('open', () => this.btnToggleReplyMarkup.classList.add('active'));
|
||||||
this.listenerSetter.add(this.replyKeyboard)('close', () => this.btnToggleReplyMarkup.classList.remove('active'));
|
this.listenerSetter.add(this.replyKeyboard)('close', () => this.btnToggleReplyMarkup.classList.remove('active'));
|
||||||
|
|
||||||
|
this.botCommands = new ChatBotCommands(this.rowsWrapper, this, this.appProfileManager);
|
||||||
|
this.botCommandsToggle = document.createElement('div');
|
||||||
|
this.botCommandsToggle.classList.add('new-message-bot-commands');
|
||||||
|
|
||||||
|
const scaler = document.createElement('div');
|
||||||
|
scaler.classList.add('new-message-bot-commands-icon-scale');
|
||||||
|
|
||||||
|
const icon = this.botCommandsIcon = document.createElement('div');
|
||||||
|
icon.classList.add('animated-menu-icon', 'animated-menu-close-icon');
|
||||||
|
scaler.append(icon);
|
||||||
|
this.botCommandsToggle.append(scaler);
|
||||||
|
|
||||||
|
attachClickEvent(this.botCommandsToggle, (e) => {
|
||||||
|
cancelEvent(e);
|
||||||
|
const isShown = icon.classList.contains('state-back');
|
||||||
|
if(isShown) {
|
||||||
|
this.botCommands.toggle(true);
|
||||||
|
icon.classList.remove('state-back');
|
||||||
|
} else {
|
||||||
|
this.botCommands.setUserId(this.chat.peerId.toUserId(), this.chat.bubbles.getMiddleware());
|
||||||
|
icon.classList.add('state-back');
|
||||||
|
}
|
||||||
|
}, {listenerSetter: this.listenerSetter});
|
||||||
|
|
||||||
|
this.botCommands.addEventListener('visible', () => {
|
||||||
|
icon.classList.add('state-back');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.botCommands.addEventListener('hiding', () => {
|
||||||
|
icon.classList.remove('state-back');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.attachMenuButtons = [{
|
this.attachMenuButtons = [{
|
||||||
@ -619,7 +657,7 @@ export default class ChatInput {
|
|||||||
this.fileInput.multiple = true;
|
this.fileInput.multiple = true;
|
||||||
this.fileInput.style.display = 'none';
|
this.fileInput.style.display = 'none';
|
||||||
|
|
||||||
this.newMessageWrapper.append(...[this.sendAsContainer, this.btnToggleEmoticons, this.inputMessageContainer, this.btnScheduled, this.btnToggleReplyMarkup, this.attachMenu, this.recordTimeEl, this.fileInput].filter(Boolean));
|
this.newMessageWrapper.append(...[this.sendAsContainer, this.botCommandsToggle, this.btnToggleEmoticons, this.inputMessageContainer, this.btnScheduled, this.btnToggleReplyMarkup, this.attachMenu, this.recordTimeEl, this.fileInput].filter(Boolean));
|
||||||
|
|
||||||
this.rowsWrapper.append(this.replyElements.container);
|
this.rowsWrapper.append(this.replyElements.container);
|
||||||
this.autocompleteHelperController = new AutocompleteHelperController();
|
this.autocompleteHelperController = new AutocompleteHelperController();
|
||||||
@ -1194,7 +1232,7 @@ export default class ChatInput {
|
|||||||
public finishPeerChange(startParam?: string) {
|
public finishPeerChange(startParam?: string) {
|
||||||
const peerId = this.chat.peerId;
|
const peerId = this.chat.peerId;
|
||||||
|
|
||||||
const {forwardElements, btnScheduled, replyKeyboard, sendMenu, goDownBtn, chatInput, sendAsContainer} = this;
|
const {forwardElements, btnScheduled, replyKeyboard, sendMenu, goDownBtn, chatInput, sendAsContainer, botCommandsToggle} = this;
|
||||||
chatInput.style.display = '';
|
chatInput.style.display = '';
|
||||||
|
|
||||||
const isBroadcast = this.appPeersManager.isBroadcast(peerId);
|
const isBroadcast = this.appPeersManager.isBroadcast(peerId);
|
||||||
@ -1225,6 +1263,24 @@ export default class ChatInput {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateOffset(null, false, true);
|
||||||
|
|
||||||
|
if(botCommandsToggle) {
|
||||||
|
this.hasBotCommands = undefined;
|
||||||
|
this.botCommands.toggle(true, undefined, true);
|
||||||
|
this.updateBotCommandsToggle(true);
|
||||||
|
botCommandsToggle.remove();
|
||||||
|
if(this.appPeersManager.isBot(peerId)) {
|
||||||
|
const userId = peerId.toUserId();
|
||||||
|
const middleware = this.chat.bubbles.getMiddleware();
|
||||||
|
const getUserFullResult = this.appProfileManager.getProfile(userId);
|
||||||
|
callbackify(getUserFullResult, (userFull) => {
|
||||||
|
if(!middleware()) return;
|
||||||
|
this.updateBotCommands(userFull, !(getUserFullResult instanceof Promise));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(sendAsContainer) {
|
if(sendAsContainer) {
|
||||||
if(this.sendAsAvatar) {
|
if(this.sendAsAvatar) {
|
||||||
this.sendAsAvatar.remove();
|
this.sendAsAvatar.remove();
|
||||||
@ -1232,7 +1288,6 @@ export default class ChatInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendAsContainer.remove();
|
sendAsContainer.remove();
|
||||||
SetTransition(this.newMessageWrapper, 'has-send-as', false, 0);
|
|
||||||
this.sendAsPeerId = undefined;
|
this.sendAsPeerId = undefined;
|
||||||
this.updatingSendAsPromise = undefined;
|
this.updatingSendAsPromise = undefined;
|
||||||
|
|
||||||
@ -1261,6 +1316,39 @@ export default class ChatInput {
|
|||||||
this.center(false);
|
this.center(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateOffset(type: 'commands' | 'as', forwards: boolean, skipAnimation?: boolean, useRafs?: number) {
|
||||||
|
if(type) {
|
||||||
|
this.newMessageWrapper.dataset.offset = type;
|
||||||
|
} else {
|
||||||
|
delete this.newMessageWrapper.dataset.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetTransition(this.newMessageWrapper, 'has-offset', forwards, skipAnimation ? 0 : 300, undefined, useRafs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateBotCommands(userFull: UserFull.userFull, skipAnimation?: boolean) {
|
||||||
|
this.hasBotCommands = userFull.bot_info && userFull.bot_info.commands.length;
|
||||||
|
this.updateBotCommandsToggle(skipAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateBotCommandsToggle(skipAnimation?: boolean) {
|
||||||
|
const {botCommandsToggle, hasBotCommands} = this;
|
||||||
|
|
||||||
|
const show = hasBotCommands && this.isInputEmpty();
|
||||||
|
if(!hasBotCommands) {
|
||||||
|
botCommandsToggle.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
const forwards = show;
|
||||||
|
const useRafs = botCommandsToggle.parentElement ? 0 : 2;
|
||||||
|
|
||||||
|
if(!botCommandsToggle.parentElement) {
|
||||||
|
this.newMessageWrapper.prepend(botCommandsToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateOffset('commands', forwards, skipAnimation, useRafs);
|
||||||
|
}
|
||||||
|
|
||||||
private updateSendAsButtons(peerIds: PeerId[]) {
|
private updateSendAsButtons(peerIds: PeerId[]) {
|
||||||
const buttons: ButtonMenuItemOptions[] = peerIds.map((sendAsPeerId, idx) => {
|
const buttons: ButtonMenuItemOptions[] = peerIds.map((sendAsPeerId, idx) => {
|
||||||
const textElement = document.createElement('div');
|
const textElement = document.createElement('div');
|
||||||
@ -1415,7 +1503,7 @@ export default class ChatInput {
|
|||||||
useRafs = 2;
|
useRafs = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTransition(this.newMessageWrapper, 'has-send-as', true, skipAnimation ? 0 : SEND_AS_ANIMATION_DURATION, undefined, useRafs);
|
this.updateOffset('as', true, skipAnimation, useRafs);
|
||||||
|
|
||||||
this.updatingSendAsPromise = undefined;
|
this.updatingSendAsPromise = undefined;
|
||||||
});
|
});
|
||||||
@ -1850,7 +1938,8 @@ export default class ChatInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!richValue.trim()) {
|
const isEmpty = !richValue.trim();
|
||||||
|
if(isEmpty) {
|
||||||
if(this.lastTimeType) {
|
if(this.lastTimeType) {
|
||||||
this.appMessagesManager.setTyping(this.chat.peerId, {_: 'sendMessageCancelAction'});
|
this.appMessagesManager.setTyping(this.chat.peerId, {_: 'sendMessageCancelAction'});
|
||||||
}
|
}
|
||||||
@ -1864,6 +1953,14 @@ export default class ChatInput {
|
|||||||
this.lastTimeType = time;
|
this.lastTimeType = time;
|
||||||
this.appMessagesManager.setTyping(this.chat.peerId, {_: 'sendMessageTypingAction'});
|
this.appMessagesManager.setTyping(this.chat.peerId, {_: 'sendMessageTypingAction'});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.botCommands) {
|
||||||
|
this.botCommands.toggle(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.botCommands) {
|
||||||
|
this.updateBotCommandsToggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.editMsgId) {
|
if(!this.editMsgId) {
|
||||||
|
@ -96,7 +96,11 @@ Utility Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
.no-transition {
|
.no-transition {
|
||||||
transition: none !important;
|
&,
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* &-all, &-all * {
|
/* &-all, &-all * {
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
|
@ -31,12 +31,6 @@
|
|||||||
&, &:before, &:after {
|
&, &:before, &:after {
|
||||||
transition: transform var(--slide-header-transition);
|
transition: transform var(--slide-header-transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.no-transition {
|
|
||||||
&, &:before, &:after {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.state-back {
|
&.state-back {
|
||||||
@ -53,13 +47,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.animated-menu-icon {
|
.animated-menu-icon {
|
||||||
|
--color: var(--secondary-text-color);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
||||||
&, &:before, &:after {
|
&, &:before, &:after {
|
||||||
width: 1.125rem;
|
width: 1.125rem;
|
||||||
height: .125rem;
|
height: .125rem;
|
||||||
border-radius: .125rem;
|
border-radius: .125rem;
|
||||||
background-color: var(--secondary-text-color);
|
background-color: var(--color);
|
||||||
transform: rotate(0);
|
transform: rotate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +91,48 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.animated-menu-close-icon {
|
||||||
|
margin-top: -.625rem;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
top: .3125rem;
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
@include animation-level(2) {
|
||||||
|
transition: transform .25s, opacity .125s 0s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
top: .625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.state-back {
|
||||||
|
transform: translate(0, .3125rem) rotate(135deg);
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
transform: translate(-.0rem, -.625rem) rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* &.state-back {
|
||||||
|
transform: rotate(135deg) translate(.25rem, -.1875rem);
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
transform: rotate(90deg) translate(-.625rem, 0rem);
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
.animated-button-icon {
|
.animated-button-icon {
|
||||||
> .tgico {
|
> .tgico {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$btn-send-margin: .5rem;
|
$btn-send-margin: .5rem;
|
||||||
$chat-helper-size: 36px;
|
$chat-helper-size: 45px;
|
||||||
|
$chat-input-box-shadow: 0px 1px 8px 1px rgb(0 0 0 / 18%);
|
||||||
|
|
||||||
$input-transition-time: .2s;
|
$input-transition-time: .2s;
|
||||||
$input-half-transition-time: #{$input-transition-time / 2};
|
$input-half-transition-time: #{$input-transition-time / 2};
|
||||||
@ -765,7 +766,7 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
box-shadow: 0px 1px 8px 1px rgb(0 0 0 / 18%);
|
box-shadow: $chat-input-box-shadow;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
background-color: var(--surface-color);
|
background-color: var(--surface-color);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@ -1047,9 +1048,9 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 1; */
|
z-index: 1; */
|
||||||
height: 0;
|
height: 0;
|
||||||
width: calc(100% - var(--padding-horizontal) * 2);
|
width: 100%;
|
||||||
padding: 0;
|
padding: .5625rem var(--padding-horizontal) 0;
|
||||||
margin-top: .5625rem;//var(--padding-vertical);
|
// margin-top: .5625rem;//var(--padding-vertical);
|
||||||
margin-bottom: -.5625rem;
|
margin-bottom: -.5625rem;
|
||||||
//height: calc(#{$chat-helper-size} + .3125rem);
|
//height: calc(#{$chat-helper-size} + .3125rem);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -1064,7 +1065,7 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@include respond-to(esg-bottom-new) {
|
@include respond-to(esg-bottom-new) {
|
||||||
margin-top: .3125rem;
|
padding-top: .3125rem;
|
||||||
margin-bottom: -.3125rem;
|
margin-bottom: -.3125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1163,29 +1164,78 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
|||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* &:after {
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: .0625rem;
|
||||||
|
background-color: var(--border-color);
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.have-commands {
|
||||||
|
&:after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
.new-message-wrapper {
|
.new-message-wrapper {
|
||||||
--send-as-size: 1.875rem;
|
--send-as-size: 1.875rem;
|
||||||
--send-as-margin-left: .25rem;
|
--send-as-margin-left: .25rem;
|
||||||
--send-as-margin-right: .375rem;
|
--send-as-margin-right: .375rem;
|
||||||
--send-as-total-size: calc(var(--send-as-size) + var(--send-as-margin-left) + var(--send-as-margin-right));
|
--send-as-total-size: calc(var(--send-as-size) + var(--send-as-margin-left) + var(--send-as-margin-right));
|
||||||
|
--commands-size: 2.375rem;
|
||||||
|
--commands-margin-left: .25rem;
|
||||||
|
--commands-margin-right: .375rem;
|
||||||
|
--commands-total-size: calc(var(--commands-size) + var(--commands-margin-left) + var(--commands-margin-right));
|
||||||
|
--offset-translateX: 0px;
|
||||||
//padding: 4.5px 0;
|
//padding: 4.5px 0;
|
||||||
//padding-bottom: 4.5px;
|
//padding-bottom: 4.5px;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
min-height: var(--chat-input-size);
|
min-height: var(--chat-input-size);
|
||||||
|
|
||||||
|
.new-message-bot-commands,
|
||||||
|
.new-message-send-as-container {
|
||||||
|
position: absolute;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
bottom: calc(var(--padding-vertical) + .4375rem);
|
||||||
|
cursor: pointer;
|
||||||
|
transform: scale(0);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-message-bot-commands {
|
||||||
|
width: var(--commands-size);
|
||||||
|
height: 1.875rem;
|
||||||
|
border-radius: 1.875rem;
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: var(--commands-margin-left);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&-icon-scale {
|
||||||
|
transform: scale(.875);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animated-menu-close-icon {
|
||||||
|
--color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.new-message-send-as {
|
.new-message-send-as {
|
||||||
&-container {
|
&-container {
|
||||||
width: var(--send-as-size);
|
width: var(--send-as-size);
|
||||||
height: var(--send-as-size);
|
height: var(--send-as-size);
|
||||||
position: absolute;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
// margin: 0 0.375rem .4375rem var(--send-as-margin-left);
|
// margin: 0 0.375rem .4375rem var(--send-as-margin-left);
|
||||||
margin-left: var(--send-as-margin-left);
|
margin-left: var(--send-as-margin-left);
|
||||||
bottom: calc(var(--padding-vertical) + .4375rem);
|
|
||||||
cursor: pointer;
|
|
||||||
transform: scale(0);
|
|
||||||
background: none !important;
|
background: none !important;
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
.btn-menu {
|
.btn-menu {
|
||||||
max-height: 20rem;
|
max-height: 20rem;
|
||||||
@ -1253,7 +1303,15 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.has-send-as {
|
&.has-offset {
|
||||||
|
&[data-offset="as"] {
|
||||||
|
--offset-translateX: var(--send-as-total-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-offset="commands"] {
|
||||||
|
--offset-translateX: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
.toggle-emoticons,
|
.toggle-emoticons,
|
||||||
.input-message-container {
|
.input-message-container {
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
@ -1261,16 +1319,17 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
|||||||
|
|
||||||
&:not(.backwards) {
|
&:not(.backwards) {
|
||||||
.toggle-emoticons {
|
.toggle-emoticons {
|
||||||
transform: translateX(var(--send-as-total-size));
|
transform: translateX(var(--offset-translateX));
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-message-container {
|
.input-message-container {
|
||||||
--translateX: calc(var(--send-as-total-size));
|
--translateX: calc(var(--offset-translateX));
|
||||||
padding-right: var(--translateX);
|
padding-right: var(--translateX);
|
||||||
transform: translate(var(--translateX));
|
transform: translate(var(--translateX));
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-message-send-as-container {
|
.new-message-send-as-container,
|
||||||
|
.new-message-bot-commands {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1278,7 +1337,8 @@ $background-transition-total-time: #{$input-transition-time - $background-transi
|
|||||||
&.animating {
|
&.animating {
|
||||||
.toggle-emoticons,
|
.toggle-emoticons,
|
||||||
.input-message-container,
|
.input-message-container,
|
||||||
.new-message-send-as-container {
|
.new-message-send-as-container,
|
||||||
|
.new-message-bot-commands {
|
||||||
transition: transform var(--transition-standard-in);
|
transition: transform var(--transition-standard-in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
85
src/scss/partials/_chatBotCommands.scss
Normal file
85
src/scss/partials/_chatBotCommands.scss
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
.bot-commands {
|
||||||
|
--border-radius-padding: #{$border-radius-big * 2};
|
||||||
|
--offset: .5rem;
|
||||||
|
position: absolute !important;
|
||||||
|
// bottom: 100%;
|
||||||
|
bottom: calc(100% - var(--border-radius-padding));
|
||||||
|
right: calc(var(--offset) * -1);
|
||||||
|
left: calc(var(--offset) * -1);
|
||||||
|
width: auto !important;
|
||||||
|
max-height: 20rem;
|
||||||
|
max-width: none;
|
||||||
|
border-radius: $border-radius-big $border-radius-big 0 0 !important;
|
||||||
|
background-color: transparent !important;
|
||||||
|
pointer-events: none;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: var(--offset) var(--offset) 0 !important;
|
||||||
|
box-shadow: none;
|
||||||
|
animation: none !important;
|
||||||
|
visibility: visible !important;
|
||||||
|
transition: none !important;
|
||||||
|
display: flex !important;
|
||||||
|
|
||||||
|
.scrollable {
|
||||||
|
background-color: var(--surface-color);
|
||||||
|
box-shadow: $chat-input-box-shadow;
|
||||||
|
border-radius: inherit;
|
||||||
|
height: auto;
|
||||||
|
pointer-events: all;
|
||||||
|
// max-height: 20rem;
|
||||||
|
|
||||||
|
@include animation-level(2) {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(var(--height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-visible {
|
||||||
|
&.animating {
|
||||||
|
.scrollable {
|
||||||
|
transition: transform var(--transition-standard-in), opacity var(--transition-standard-in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.backwards) {
|
||||||
|
.scrollable {
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-list {
|
||||||
|
border-radius: inherit;
|
||||||
|
width: 100%;
|
||||||
|
height: var(--height);
|
||||||
|
// padding-bottom: var(--border-radius-padding);
|
||||||
|
padding-bottom: 0;
|
||||||
|
|
||||||
|
&-element {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
padding-left: 3.375rem;
|
||||||
|
|
||||||
|
&-avatar {
|
||||||
|
position: absolute;
|
||||||
|
left: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-name,
|
||||||
|
&-description {
|
||||||
|
margin-left: 0;
|
||||||
|
font-size: .875rem;
|
||||||
|
line-height: var(--line-height-14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -307,6 +307,7 @@ $chat-input-inner-padding-handhelds: .25rem;
|
|||||||
@import "partials/chatInlineHelper";
|
@import "partials/chatInlineHelper";
|
||||||
@import "partials/chatSearch";
|
@import "partials/chatSearch";
|
||||||
@import "partials/chatDrop";
|
@import "partials/chatDrop";
|
||||||
|
@import "partials/chatBotCommands";
|
||||||
@import "partials/crop";
|
@import "partials/crop";
|
||||||
@import "partials/sidebar";
|
@import "partials/sidebar";
|
||||||
@import "partials/profile";
|
@import "partials/profile";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user