From 74cdb179bd347a07562dcbb4e661e878baa0c9e3 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Tue, 22 Jun 2021 05:28:37 +0300 Subject: [PATCH] Chat context menu hint --- src/components/chat/chat.ts | 4 ++-- src/components/chat/contextMenu.ts | 15 +++++++++++---- src/components/chat/topbar.ts | 18 +++++++++++++++++- src/components/toast.ts | 6 ++++-- src/config/app.ts | 2 +- src/lang.ts | 1 + src/lib/appManagers/appStateManager.ts | 6 ++++-- src/scss/style.scss | 4 ++++ 8 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/components/chat/chat.ts b/src/components/chat/chat.ts index a1eb98fd..b2bc3662 100644 --- a/src/components/chat/chat.ts +++ b/src/components/chat/chat.ts @@ -21,6 +21,7 @@ import type { ApiManagerProxy } from "../../lib/mtproto/mtprotoworker"; import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager"; import type { AppEmojiManager } from "../../lib/appManagers/appEmojiManager"; import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager"; +import type { State } from "../../lib/appManagers/appStateManager"; import type stateStorage from '../../lib/stateStorage'; import EventListenerBase from "../../helpers/eventListenerBase"; import { logger, LogTypes } from "../../lib/logger"; @@ -35,7 +36,6 @@ import { REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config"; import SetTransition from "../singleTransition"; import { fastRaf } from "../../helpers/schedulers"; import AppPrivateSearchTab from "../sidebarRight/tabs/search"; -import type { State } from "../../lib/appManagers/appStateManager"; import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl"; import mediaSizes from "../../helpers/mediaSizes"; import ChatSearch from "./search"; @@ -173,7 +173,7 @@ export default class Chat extends EventListenerBase<{ this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appPeersManager); this.input = new ChatInput(this, this.appMessagesManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager, this.appDraftsManager, this.serverTimeManager, this.appNotificationsManager, this.appEmojiManager); this.selection = new ChatSelection(this, this.bubbles, this.input, this.appMessagesManager); - this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appChatsManager, this.appPeersManager, this.appPollsManager); + this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appPeersManager, this.appPollsManager, this.appDocsManager); if(this.type === 'chat') { this.topbar.constructUtils(); diff --git a/src/components/chat/contextMenu.ts b/src/components/chat/contextMenu.ts index d301b395..eb63a5a0 100644 --- a/src/components/chat/contextMenu.ts +++ b/src/components/chat/contextMenu.ts @@ -8,6 +8,8 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage import type { AppChatsManager } from "../../lib/appManagers/appChatsManager"; import type { AppPeersManager } from "../../lib/appManagers/appPeersManager"; import type { AppPollsManager, Poll } from "../../lib/appManagers/appPollsManager"; +import type { AppDocsManager, MyDocument } from "../../lib/appManagers/appDocsManager"; +import type { AppStateManager } from "../../lib/appManagers/appStateManager"; import type Chat from "./chat"; import { isTouchSupported } from "../../helpers/touchSupport"; import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu"; @@ -18,13 +20,12 @@ import PopupPinMessage from "../popups/unpinMessage"; import { copyTextToClipboard } from "../../helpers/clipboard"; import PopupSendNow from "../popups/sendNow"; import { toast } from "../toast"; -import I18n, { LangPackKey } from "../../lib/langPack"; +import I18n, { i18n, LangPackKey } from "../../lib/langPack"; import findUpClassName from "../../helpers/dom/findUpClassName"; import { cancelEvent } from "../../helpers/dom/cancelEvent"; import cancelSelection from "../../helpers/dom/cancelSelection"; import { attachClickEvent } from "../../helpers/dom/clickEvent"; import isSelectionEmpty from "../../helpers/dom/isSelectionEmpty"; -import appDocsManager, { MyDocument } from "../../lib/appManagers/appDocsManager"; export default class ChatContextMenu { private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[]; @@ -39,7 +40,13 @@ export default class ChatContextMenu { private mid: number; private message: any; - constructor(private attachTo: HTMLElement, private chat: Chat, private appMessagesManager: AppMessagesManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appPollsManager: AppPollsManager) { + constructor(private attachTo: HTMLElement, + private chat: Chat, + private appMessagesManager: AppMessagesManager, + private appPeersManager: AppPeersManager, + private appPollsManager: AppPollsManager, + private appDocsManager: AppDocsManager + ) { const onContextMenu = (e: MouseEvent | Touch | TouchEvent) => { if(this.init) { this.init(); @@ -246,7 +253,7 @@ export default class ChatContextMenu { icon: 'download', text: 'MediaViewer.Context.Download', onClick: () => { - appDocsManager.saveDocFile(this.message.media.document); + this.appDocsManager.saveDocFile(this.message.media.document); }, verify: () => { if(this.message.pFlags.is_outgoing) { diff --git a/src/components/chat/topbar.ts b/src/components/chat/topbar.ts index 93c0b21f..820d90c6 100644 --- a/src/components/chat/topbar.ts +++ b/src/components/chat/topbar.ts @@ -33,6 +33,7 @@ import blurActiveElement from "../../helpers/dom/blurActiveElement"; import { cancelEvent } from "../../helpers/dom/cancelEvent"; import { attachClickEvent } from "../../helpers/dom/clickEvent"; import findUpTag from "../../helpers/dom/findUpTag"; +import { toast } from "../toast"; export default class ChatTopbar { public container: HTMLDivElement; @@ -217,7 +218,22 @@ export default class ChatTopbar { icon: 'select', text: 'Chat.Menu.SelectMessages', onClick: () => { - this.chat.selection.toggleSelection(true, true); + const selection = this.chat.selection; + selection.toggleSelection(true, true); + appStateManager.getState().then(state => { + if(state.chatContextMenuHintWasShown) { + return; + } + + const original = selection.toggleByBubble.bind(selection); + selection.toggleByBubble = (bubble) => { + appStateManager.pushToState('chatContextMenuHintWasShown', true); + toast(i18n('Chat.Menu.Hint')); + + selection.toggleByBubble = original; + selection.toggleByBubble(bubble); + }; + }); }, verify: () => !this.chat.selection.isSelecting && !!Object.keys(this.chat.bubbles.bubbles).length }, { diff --git a/src/components/toast.ts b/src/components/toast.ts index d57221b9..9ab6ca36 100644 --- a/src/components/toast.ts +++ b/src/components/toast.ts @@ -4,10 +4,12 @@ * https://github.com/morethanwords/tweb/blob/master/LICENSE */ +import replaceContent from "../helpers/dom/replaceContent"; + const toastEl = document.createElement('div'); toastEl.classList.add('toast'); -export function toast(html: string) { - toastEl.innerHTML = html; +export function toast(content: string | Node) { + replaceContent(toastEl, content); document.body.append(toastEl); if(toastEl.dataset.timeout) clearTimeout(+toastEl.dataset.timeout); diff --git a/src/config/app.ts b/src/config/app.ts index 651695c9..2c1ddcaa 100644 --- a/src/config/app.ts +++ b/src/config/app.ts @@ -15,7 +15,7 @@ const App = { id: 1025907, hash: '452b0359b988148995f22ff0f4229750', version: '0.5.7', - langPackVersion: '0.2.5', + langPackVersion: '0.2.6', langPack: 'macos', langPackCode: 'en', domains: [] as string[], diff --git a/src/lang.ts b/src/lang.ts index b00c0896..3e76356d 100644 --- a/src/lang.ts +++ b/src/lang.ts @@ -27,6 +27,7 @@ const lang = { "ExceptionModal.Search.Placeholder": "Add exception...", "Chat.Menu.SelectMessages": "Select Messages", "Chat.Menu.ClearSelection": "Clear Selection", + "Chat.Menu.Hint": "To **edit** or **reply**, close this menu.\nThen tap next to a message.", "Chat.Input.UnpinAll": "Unpin All Messages", "Chat.Input.Attach.PhotoOrVideo": "Photo or Video", "Chat.Input.Attach.Document": "Document", diff --git a/src/lib/appManagers/appStateManager.ts b/src/lib/appManagers/appStateManager.ts index 16c6d714..75e7bf62 100644 --- a/src/lib/appManagers/appStateManager.ts +++ b/src/lib/appManagers/appStateManager.ts @@ -88,7 +88,8 @@ export type State = { }, nightTheme?: boolean, // ! DEPRECATED }, - keepSigned: boolean + keepSigned: boolean, + chatContextMenuHintWasShown: boolean }; export const STATE_INIT: State = { @@ -151,7 +152,8 @@ export const STATE_INIT: State = { sound: false } }, - keepSigned: true + keepSigned: true, + chatContextMenuHintWasShown: false }; const ALL_KEYS = Object.keys(STATE_INIT) as any as Array; diff --git a/src/scss/style.scss b/src/scss/style.scss index 1e45b3af..12a088fc 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -662,6 +662,10 @@ input:-webkit-autofill:active { animation: fade-in-opacity-fade-out-opacity 3s linear forwards; z-index: 5; max-width: 22.5rem; + + b { + color: inherit; + } } hr {