From c4a46fb33496bd513a3d5c96bcb507aa2e6e39e3 Mon Sep 17 00:00:00 2001 From: morethanwords Date: Tue, 25 May 2021 22:00:33 +0300 Subject: [PATCH] Wait for key when no colon in input --- src/components/chat/autocompleteHelper.ts | 6 +- src/components/chat/commandsHelper.ts | 69 ++++++++++++++++++++++ src/components/chat/emojiHelper.ts | 3 +- src/components/chat/input.ts | 51 ++++++++-------- src/lib/appManagers/appProfileManager.ts | 10 ++-- src/scss/partials/_chatCommandsHelper.scss | 33 +++++++++++ src/scss/partials/_chatEmojiHelper.scss | 18 ++++-- src/scss/style.scss | 18 +++--- 8 files changed, 161 insertions(+), 47 deletions(-) create mode 100644 src/components/chat/commandsHelper.ts create mode 100644 src/scss/partials/_chatCommandsHelper.scss diff --git a/src/components/chat/autocompleteHelper.ts b/src/components/chat/autocompleteHelper.ts index e1018e3f..bf6478d7 100644 --- a/src/components/chat/autocompleteHelper.ts +++ b/src/components/chat/autocompleteHelper.ts @@ -21,9 +21,9 @@ export default class AutocompleteHelper extends EventListenerBase<{ protected resetTarget: () => void; constructor(appendTo: HTMLElement, - private listType: 'xy' | 'x' | 'y', - private onSelect: (target: Element) => boolean | void, - private waitForKey?: string + protected listType: 'xy' | 'x' | 'y', + protected onSelect: (target: Element) => boolean | void, + protected waitForKey?: string ) { super(false); diff --git a/src/components/chat/commandsHelper.ts b/src/components/chat/commandsHelper.ts new file mode 100644 index 00000000..cac6e852 --- /dev/null +++ b/src/components/chat/commandsHelper.ts @@ -0,0 +1,69 @@ +import { BotCommand } from "../../layer"; +import RichTextProcessor from "../../lib/richtextprocessor"; +import AvatarElement from "../avatar"; +import Scrollable from "../scrollable"; +import AutocompleteHelper from "./autocompleteHelper"; + +export default class CommandsHelper extends AutocompleteHelper { + private scrollable: Scrollable; + + constructor(appendTo: HTMLElement) { + super(appendTo, 'y', (target) => { + + }); + + this.container.classList.add('commands-helper'); + } + + private init() { + this.list = document.createElement('div'); + this.list.classList.add('commands-helper-commands'); + + this.container.append(this.list); + + this.scrollable = new Scrollable(this.container); + + this.addEventListener('visible', () => { + setTimeout(() => { // it is not rendered yet + this.scrollable.container.scrollTop = 0; + }, 0); + }); + } + + public renderCommands(commands: {userId: number, command: BotCommand}[]) { + if(this.init) { + if(!commands.length) { + return; + } + + this.init(); + this.init = null; + } + + if(commands.length) { + this.list.innerHTML = ''; + commands.forEach(command => { + const div = document.createElement('div'); + div.classList.add('commands-helper-command'); + + const avatar = new AvatarElement(); + avatar.classList.add('avatar-30'); + avatar.setAttribute('dialog', '0'); + avatar.setAttribute('peer', '' + command.userId); + + const name = document.createElement('div'); + name.classList.add('commands-helper-command-name'); + name.innerText = '/' + command.command.command; + + const description = document.createElement('div'); + description.classList.add('commands-helper-command-description'); + description.innerHTML = RichTextProcessor.wrapEmojiText(command.command.description); + + div.append(avatar, name, description); + this.list.append(div); + }); + } + + this.toggle(!commands.length); + } +} diff --git a/src/components/chat/emojiHelper.ts b/src/components/chat/emojiHelper.ts index 3f26b84b..25e251fb 100644 --- a/src/components/chat/emojiHelper.ts +++ b/src/components/chat/emojiHelper.ts @@ -29,7 +29,7 @@ export default class EmojiHelper extends AutocompleteHelper { }); } - public renderEmojis(emojis: string[]) { + public renderEmojis(emojis: string[], waitForKey: boolean) { if(this.init) { if(!emojis.length) { return; @@ -46,6 +46,7 @@ export default class EmojiHelper extends AutocompleteHelper { }); } + this.waitForKey = waitForKey ? 'ArrowUp' : undefined; this.toggle(!emojis.length); } } diff --git a/src/components/chat/input.ts b/src/components/chat/input.ts index cf89c429..a5017c82 100644 --- a/src/components/chat/input.ts +++ b/src/components/chat/input.ts @@ -29,7 +29,7 @@ import PopupNewMedia from '../popups/newMedia'; import { toast } from "../toast"; import { wrapReply } from "../wrappers"; import InputField from '../inputField'; -import { MessageEntity, DraftMessage } from '../../layer'; +import { MessageEntity, DraftMessage, BotInfo, BotCommand } from '../../layer'; import StickersHelper from './stickersHelper'; import ButtonIcon from '../buttonIcon'; import DivAndCaption from '../divAndCaption'; @@ -60,6 +60,8 @@ import { MarkdownType, markdownTags } from '../../helpers/dom/getRichElementValu import getRichValueWithCaret from '../../helpers/dom/getRichValueWithCaret'; import EmojiHelper from './emojiHelper'; import setRichFocus from '../../helpers/dom/setRichFocus'; +import SearchIndex from '../../lib/searchIndex'; +import CommandsHelper from './commandsHelper'; const RECORD_MIN_TIME = 500; const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.'; @@ -130,6 +132,7 @@ export default class ChatInput { readonly executedHistory: string[] = []; private canUndoFromHTML = ''; + private commandsHelper: CommandsHelper; private emojiHelper: EmojiHelper; private stickersHelper: StickersHelper; private listenerSetter: ListenerSetter; @@ -363,6 +366,7 @@ export default class ChatInput { this.newMessageWrapper.append(...[this.btnToggleEmoticons, this.inputMessageContainer, this.btnScheduled, this.attachMenu, this.recordTimeEl, this.fileInput].filter(Boolean)); this.rowsWrapper.append(this.replyElements.container); + this.commandsHelper = new CommandsHelper(this.rowsWrapper); this.emojiHelper = new EmojiHelper(this.rowsWrapper, this); this.stickersHelper = new StickersHelper(this.rowsWrapper); this.rowsWrapper.append(this.newMessageWrapper); @@ -1267,30 +1271,27 @@ export default class ChatInput { } else { this.hideSuggestions() } - } else if (!matches[1] && matches[2] == '/') { // commands - if (this.commands && this.commands.index) { - if (query.length) { - var foundObject = SearchIndexManager.search(query, this.commands.index) - var foundCommands = [] - var command - for (var i = 0, length = this.commands.list.length; i < length; i++) { - command = this.commands.list[i] - if (foundObject[command.value]) { - foundCommands.push(command) - } - } - } else { - var foundCommands = this.commands.list - } - if (foundCommands.length) { - this.showCommandsSuggestions(foundCommands) - } else { - this.hideSuggestions() - } - } else { - this.hideSuggestions() + } else */ /* if(!matches[1] && matches[2][0] === '/') { // commands + if(this.chat.peerId > 0) { + this.chat.appProfileManager.getProfileByPeerId(this.chat.peerId).then(full => { + const botInfos: BotInfo.botInfo[] = [].concat(full.bot_info); + const index = new SearchIndex(false, false); + + const commands: Map = new Map(); + botInfos.forEach(botInfo => { + botInfo.commands.forEach(botCommand => { + commands.set(botCommand.command, {userId: botInfo.user_id, command: botCommand}); + index.indexObject(botCommand.command, '/' + botCommand.command); + }); + }); + + const found = index.search(matches[2]); + const filtered = Array.from(found).map(command => commands.get(command)); + this.commandsHelper.renderCommands(filtered); + console.log('found commands', found, filtered); + }); } - } else *//* if(firstChar === ':') */ { // emoji + } else */ { // emoji if(value.match(/^\s*:(.+):\s*$/)) { this.emojiHelper.toggle(true); return; @@ -1299,7 +1300,7 @@ export default class ChatInput { this.appEmojiManager.getBothEmojiKeywords().then(() => { const q = matches[2].replace(/^:/, ''); const emojis = this.appEmojiManager.searchEmojis(q); - this.emojiHelper.renderEmojis(emojis); + this.emojiHelper.renderEmojis(emojis, matches[2][0] !== ':'); //console.log(emojis); }); } diff --git a/src/lib/appManagers/appProfileManager.ts b/src/lib/appManagers/appProfileManager.ts index 408fc036..7adf2cfe 100644 --- a/src/lib/appManagers/appProfileManager.ts +++ b/src/lib/appManagers/appProfileManager.ts @@ -30,7 +30,7 @@ import appUsersManager, { User } from "./appUsersManager"; type PeerPhotoSize = 'photo_small' | 'photo_big'; export class AppProfileManager { - private botInfos: any = {}; + //private botInfos: any = {}; private usersFull: {[id: string]: UserFull.userFull} = {}; public chatsFull: {[id: string]: ChatFull} = {}; private fullPromises: {[peerId: string]: Promise} = {}; @@ -122,7 +122,7 @@ export class AppProfileManager { }); } - public saveBotInfo(botInfo: any) { + /* public saveBotInfo(botInfo: any) { const botId = botInfo && botInfo.user_id; if(!botId) { return null; @@ -140,7 +140,7 @@ export class AppProfileManager { description: botInfo.description, commands: commands }; - } + } */ public getProfile(id: number, override?: true): Promise { if(this.usersFull[id] && !override) { @@ -167,9 +167,9 @@ export class AppProfileManager { appNotificationsManager.savePeerSettings(id, userFull.notify_settings); - if(userFull.bot_info) { + /* if(userFull.bot_info) { userFull.bot_info = this.saveBotInfo(userFull.bot_info) as any; - } + } */ //appMessagesManager.savePinnedMessage(id, userFull.pinned_msg_id); diff --git a/src/scss/partials/_chatCommandsHelper.scss b/src/scss/partials/_chatCommandsHelper.scss new file mode 100644 index 00000000..889f23e2 --- /dev/null +++ b/src/scss/partials/_chatCommandsHelper.scss @@ -0,0 +1,33 @@ +.commands-helper { + left: 0; + //width: 320px !important; + + .scrollable { + position: relative; + max-height: 232px; + } + + &-commands { + padding: .5rem 0; + } + + &-command { + height: 3.125rem; + display: flex; + padding: 0 .75rem; + align-items: center; + cursor: pointer; + + @include hover(); + + &-name { + margin-left: .875rem; + font-weight: 500; + } + + &-description { + margin-left: .5625rem; + color: var(--secondary-text-color); + } + } +} diff --git a/src/scss/partials/_chatEmojiHelper.scss b/src/scss/partials/_chatEmojiHelper.scss index 497a8b11..a6fc6d27 100644 --- a/src/scss/partials/_chatEmojiHelper.scss +++ b/src/scss/partials/_chatEmojiHelper.scss @@ -1,21 +1,29 @@ .emoji-helper { height: 50px; - padding: .25rem !important; + padding: .25rem 0 !important; > .scrollable { position: relative; } .super-emojis { - display: flex; + display: block; white-space: nowrap; + /* display: flex; align-items: center; - justify-content: flex-start; + justify-content: flex-start; */ + + &:before, &:after { + display: inline-block; + content: " "; + //flex: 0 0 auto; + width: .1875rem; + } } - .super-emoji { + /* .super-emoji { flex: 0 0 auto; - } + } */ .super-emoji:not(.active) { @include hover() { diff --git a/src/scss/style.scss b/src/scss/style.scss index 91cf267a..0afeb011 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -236,6 +236,7 @@ html.night { @import "partials/chatMarkupTooltip"; @import "partials/chatStickersHelper"; @import "partials/chatEmojiHelper"; +@import "partials/chatCommandsHelper"; @import "partials/chatSearch"; @import "partials/chatDrop"; @import "partials/crop"; @@ -1266,23 +1267,24 @@ middle-ellipsis-element { // ! No chrome 56 support display: grid; grid-column-gap: 2.44px; - grid-template-columns: repeat(auto-fill, 42px); + grid-template-columns: repeat(auto-fill, 2.625rem); justify-content: space-between; - font-size: 2.25rem; - line-height: 2.25rem; + font-size: 2.125rem; + line-height: 2.125rem; .super-emoji { display: inline-block; - margin: 0 1.44px; // ! magic number - padding: 4px 4px; + margin: 0 .0625rem; + padding: .25rem; line-height: inherit; - border-radius: 8px; + border-radius: $border-radius; cursor: pointer; user-select: none; + vertical-align: middle; - width: 42px; - height: 42px; + width: 2.625rem; + height: 2.625rem; html:not(.emoji-supported) & { position: relative;