Chat context menu hint
This commit is contained in:
parent
73d030dd69
commit
74cdb179bd
@ -21,6 +21,7 @@ import type { ApiManagerProxy } from "../../lib/mtproto/mtprotoworker";
|
|||||||
import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager";
|
import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager";
|
||||||
import type { AppEmojiManager } from "../../lib/appManagers/appEmojiManager";
|
import type { AppEmojiManager } from "../../lib/appManagers/appEmojiManager";
|
||||||
import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager";
|
import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager";
|
||||||
|
import type { State } from "../../lib/appManagers/appStateManager";
|
||||||
import type stateStorage from '../../lib/stateStorage';
|
import type stateStorage from '../../lib/stateStorage';
|
||||||
import EventListenerBase from "../../helpers/eventListenerBase";
|
import EventListenerBase from "../../helpers/eventListenerBase";
|
||||||
import { logger, LogTypes } from "../../lib/logger";
|
import { logger, LogTypes } from "../../lib/logger";
|
||||||
@ -35,7 +36,6 @@ import { REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
|||||||
import SetTransition from "../singleTransition";
|
import SetTransition from "../singleTransition";
|
||||||
import { fastRaf } from "../../helpers/schedulers";
|
import { fastRaf } from "../../helpers/schedulers";
|
||||||
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
|
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
|
||||||
import type { State } from "../../lib/appManagers/appStateManager";
|
|
||||||
import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl";
|
import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl";
|
||||||
import mediaSizes from "../../helpers/mediaSizes";
|
import mediaSizes from "../../helpers/mediaSizes";
|
||||||
import ChatSearch from "./search";
|
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.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.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.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') {
|
if(this.type === 'chat') {
|
||||||
this.topbar.constructUtils();
|
this.topbar.constructUtils();
|
||||||
|
@ -8,6 +8,8 @@ import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManage
|
|||||||
import type { AppChatsManager } from "../../lib/appManagers/appChatsManager";
|
import type { AppChatsManager } from "../../lib/appManagers/appChatsManager";
|
||||||
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
||||||
import type { AppPollsManager, Poll } from "../../lib/appManagers/appPollsManager";
|
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 type Chat from "./chat";
|
||||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||||
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
|
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
|
||||||
@ -18,13 +20,12 @@ import PopupPinMessage from "../popups/unpinMessage";
|
|||||||
import { copyTextToClipboard } from "../../helpers/clipboard";
|
import { copyTextToClipboard } from "../../helpers/clipboard";
|
||||||
import PopupSendNow from "../popups/sendNow";
|
import PopupSendNow from "../popups/sendNow";
|
||||||
import { toast } from "../toast";
|
import { toast } from "../toast";
|
||||||
import I18n, { LangPackKey } from "../../lib/langPack";
|
import I18n, { i18n, LangPackKey } from "../../lib/langPack";
|
||||||
import findUpClassName from "../../helpers/dom/findUpClassName";
|
import findUpClassName from "../../helpers/dom/findUpClassName";
|
||||||
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
||||||
import cancelSelection from "../../helpers/dom/cancelSelection";
|
import cancelSelection from "../../helpers/dom/cancelSelection";
|
||||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||||
import isSelectionEmpty from "../../helpers/dom/isSelectionEmpty";
|
import isSelectionEmpty from "../../helpers/dom/isSelectionEmpty";
|
||||||
import appDocsManager, { MyDocument } from "../../lib/appManagers/appDocsManager";
|
|
||||||
|
|
||||||
export default class ChatContextMenu {
|
export default class ChatContextMenu {
|
||||||
private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[];
|
private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[];
|
||||||
@ -39,7 +40,13 @@ export default class ChatContextMenu {
|
|||||||
private mid: number;
|
private mid: number;
|
||||||
private message: any;
|
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) => {
|
const onContextMenu = (e: MouseEvent | Touch | TouchEvent) => {
|
||||||
if(this.init) {
|
if(this.init) {
|
||||||
this.init();
|
this.init();
|
||||||
@ -246,7 +253,7 @@ export default class ChatContextMenu {
|
|||||||
icon: 'download',
|
icon: 'download',
|
||||||
text: 'MediaViewer.Context.Download',
|
text: 'MediaViewer.Context.Download',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
appDocsManager.saveDocFile(this.message.media.document);
|
this.appDocsManager.saveDocFile(this.message.media.document);
|
||||||
},
|
},
|
||||||
verify: () => {
|
verify: () => {
|
||||||
if(this.message.pFlags.is_outgoing) {
|
if(this.message.pFlags.is_outgoing) {
|
||||||
|
@ -33,6 +33,7 @@ import blurActiveElement from "../../helpers/dom/blurActiveElement";
|
|||||||
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
import { cancelEvent } from "../../helpers/dom/cancelEvent";
|
||||||
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
||||||
import findUpTag from "../../helpers/dom/findUpTag";
|
import findUpTag from "../../helpers/dom/findUpTag";
|
||||||
|
import { toast } from "../toast";
|
||||||
|
|
||||||
export default class ChatTopbar {
|
export default class ChatTopbar {
|
||||||
public container: HTMLDivElement;
|
public container: HTMLDivElement;
|
||||||
@ -217,7 +218,22 @@ export default class ChatTopbar {
|
|||||||
icon: 'select',
|
icon: 'select',
|
||||||
text: 'Chat.Menu.SelectMessages',
|
text: 'Chat.Menu.SelectMessages',
|
||||||
onClick: () => {
|
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
|
verify: () => !this.chat.selection.isSelecting && !!Object.keys(this.chat.bubbles.bubbles).length
|
||||||
}, {
|
}, {
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import replaceContent from "../helpers/dom/replaceContent";
|
||||||
|
|
||||||
const toastEl = document.createElement('div');
|
const toastEl = document.createElement('div');
|
||||||
toastEl.classList.add('toast');
|
toastEl.classList.add('toast');
|
||||||
export function toast(html: string) {
|
export function toast(content: string | Node) {
|
||||||
toastEl.innerHTML = html;
|
replaceContent(toastEl, content);
|
||||||
document.body.append(toastEl);
|
document.body.append(toastEl);
|
||||||
|
|
||||||
if(toastEl.dataset.timeout) clearTimeout(+toastEl.dataset.timeout);
|
if(toastEl.dataset.timeout) clearTimeout(+toastEl.dataset.timeout);
|
||||||
|
@ -15,7 +15,7 @@ const App = {
|
|||||||
id: 1025907,
|
id: 1025907,
|
||||||
hash: '452b0359b988148995f22ff0f4229750',
|
hash: '452b0359b988148995f22ff0f4229750',
|
||||||
version: '0.5.7',
|
version: '0.5.7',
|
||||||
langPackVersion: '0.2.5',
|
langPackVersion: '0.2.6',
|
||||||
langPack: 'macos',
|
langPack: 'macos',
|
||||||
langPackCode: 'en',
|
langPackCode: 'en',
|
||||||
domains: [] as string[],
|
domains: [] as string[],
|
||||||
|
@ -27,6 +27,7 @@ const lang = {
|
|||||||
"ExceptionModal.Search.Placeholder": "Add exception...",
|
"ExceptionModal.Search.Placeholder": "Add exception...",
|
||||||
"Chat.Menu.SelectMessages": "Select Messages",
|
"Chat.Menu.SelectMessages": "Select Messages",
|
||||||
"Chat.Menu.ClearSelection": "Clear Selection",
|
"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.UnpinAll": "Unpin All Messages",
|
||||||
"Chat.Input.Attach.PhotoOrVideo": "Photo or Video",
|
"Chat.Input.Attach.PhotoOrVideo": "Photo or Video",
|
||||||
"Chat.Input.Attach.Document": "Document",
|
"Chat.Input.Attach.Document": "Document",
|
||||||
|
@ -88,7 +88,8 @@ export type State = {
|
|||||||
},
|
},
|
||||||
nightTheme?: boolean, // ! DEPRECATED
|
nightTheme?: boolean, // ! DEPRECATED
|
||||||
},
|
},
|
||||||
keepSigned: boolean
|
keepSigned: boolean,
|
||||||
|
chatContextMenuHintWasShown: boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
export const STATE_INIT: State = {
|
export const STATE_INIT: State = {
|
||||||
@ -151,7 +152,8 @@ export const STATE_INIT: State = {
|
|||||||
sound: false
|
sound: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
keepSigned: true
|
keepSigned: true,
|
||||||
|
chatContextMenuHintWasShown: false
|
||||||
};
|
};
|
||||||
|
|
||||||
const ALL_KEYS = Object.keys(STATE_INIT) as any as Array<keyof State>;
|
const ALL_KEYS = Object.keys(STATE_INIT) as any as Array<keyof State>;
|
||||||
|
@ -662,6 +662,10 @@ input:-webkit-autofill:active {
|
|||||||
animation: fade-in-opacity-fade-out-opacity 3s linear forwards;
|
animation: fade-in-opacity-fade-out-opacity 3s linear forwards;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
max-width: 22.5rem;
|
max-width: 22.5rem;
|
||||||
|
|
||||||
|
b {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user