Browse Source

Support copying selected text with context menu

master
Eduard Kuzmenko 4 years ago
parent
commit
1994da3b8d
  1. 18
      src/components/chat/contextMenu.ts
  2. 19
      src/components/chat/markupTooltip.ts
  3. 13
      src/helpers/dom.ts

18
src/components/chat/contextMenu.ts

@ -4,7 +4,7 @@ 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 Chat from "./chat"; import type Chat from "./chat";
import { isTouchSupported } from "../../helpers/touchSupport"; import { isTouchSupported } from "../../helpers/touchSupport";
import { attachClickEvent, cancelEvent, cancelSelection, findUpClassName } from "../../helpers/dom"; import { attachClickEvent, cancelEvent, cancelSelection, findUpClassName, isSelectionEmpty } from "../../helpers/dom";
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu"; import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
import { attachContextMenuListener, openBtnMenu, positionMenu } from "../misc"; import { attachContextMenuListener, openBtnMenu, positionMenu } from "../misc";
import PopupDeleteMessages from "../popups/deleteMessages"; import PopupDeleteMessages from "../popups/deleteMessages";
@ -188,7 +188,12 @@ export default class ChatContextMenu {
icon: 'copy', icon: 'copy',
text: 'Copy', text: 'Copy',
onClick: this.onCopyClick, onClick: this.onCopyClick,
verify: () => !!this.message.message verify: () => !!this.message.message && isSelectionEmpty()
}, {
icon: 'copy',
text: 'Copy Selected Text',
onClick: this.onCopyClick,
verify: () => !!this.message.message && !isSelectionEmpty()
}, { }, {
icon: 'copy', icon: 'copy',
text: 'Copy selected', text: 'Copy selected',
@ -297,11 +302,18 @@ export default class ChatContextMenu {
}; };
private onCopyClick = () => { private onCopyClick = () => {
let str: string;
const selection = window.getSelection();
if(isSelectionEmpty(selection)) {
const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid]; const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid];
const str = mids.reduce((acc, mid) => { str = mids.reduce((acc, mid) => {
const message = this.chat.getMessage(mid); const message = this.chat.getMessage(mid);
return acc + (message?.message ? message.message + '\n' : ''); return acc + (message?.message ? message.message + '\n' : '');
}, '').trim(); }, '').trim();
} else {
str = selection.toString();
//cancelSelection();
}
copyTextToClipboard(str); copyTextToClipboard(str);
}; };

19
src/components/chat/markupTooltip.ts

@ -1,5 +1,5 @@
import type { AppImManager } from "../../lib/appManagers/appImManager"; import type { AppImManager } from "../../lib/appManagers/appImManager";
import { MarkdownType, cancelEvent, getSelectedNodes, markdownTags, findUpClassName, attachClickEvent, cancelSelection } from "../../helpers/dom"; import { MarkdownType, cancelEvent, getSelectedNodes, markdownTags, findUpClassName, attachClickEvent, cancelSelection, isSelectionEmpty } from "../../helpers/dom";
import RichTextProcessor from "../../lib/richtextprocessor"; import RichTextProcessor from "../../lib/richtextprocessor";
import ButtonIcon from "../buttonIcon"; import ButtonIcon from "../buttonIcon";
import { clamp } from "../../helpers/number"; import { clamp } from "../../helpers/number";
@ -258,26 +258,13 @@ export default class MarkupTooltip {
this.container.style.transform = `translate3d(${left}px, ${top}px, 0)`; this.container.style.transform = `translate3d(${left}px, ${top}px, 0)`;
} }
public isSelectionEmpty(selection = window.getSelection()) {
if(!selection || !selection.rangeCount) {
return true;
}
const selectionRange = selection.getRangeAt(0);
if(!selectionRange.toString() || !selectionRange.START_TO_END) {
return true;
}
return false;
}
public show() { public show() {
if(this.init) { if(this.init) {
this.init(); this.init();
this.init = null; this.init = null;
} }
if(this.isSelectionEmpty()) { if(isSelectionEmpty()) {
this.hide(); this.hide();
return; return;
} }
@ -375,7 +362,7 @@ export default class MarkupTooltip {
} }
const selection = document.getSelection(); const selection = document.getSelection();
if(this.isSelectionEmpty(selection)) { if(isSelectionEmpty(selection)) {
this.hide(); this.hide();
return; return;
} }

13
src/helpers/dom.ts

@ -762,3 +762,16 @@ export function reflowScrollableElement(element: HTMLElement) {
void element.offsetLeft; // reflow void element.offsetLeft; // reflow
element.style.display = ''; element.style.display = '';
} }
export function isSelectionEmpty(selection = window.getSelection()) {
if(!selection || !selection.rangeCount) {
return true;
}
const selectionRange = selection.getRangeAt(0);
if(!selectionRange.toString() || !selectionRange.START_TO_END) {
return true;
}
return false;
}

Loading…
Cancel
Save