Browse Source

Support copying selected text with context menu

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

26
src/components/chat/contextMenu.ts

@ -4,7 +4,7 @@ import type { AppPeersManager } from "../../lib/appManagers/appPeersManager"; @@ -4,7 +4,7 @@ import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
import type { AppPollsManager, Poll } from "../../lib/appManagers/appPollsManager";
import type Chat from "./chat";
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 { attachContextMenuListener, openBtnMenu, positionMenu } from "../misc";
import PopupDeleteMessages from "../popups/deleteMessages";
@ -188,7 +188,12 @@ export default class ChatContextMenu { @@ -188,7 +188,12 @@ export default class ChatContextMenu {
icon: 'copy',
text: 'Copy',
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',
text: 'Copy selected',
@ -297,11 +302,18 @@ export default class ChatContextMenu { @@ -297,11 +302,18 @@ export default class ChatContextMenu {
};
private onCopyClick = () => {
const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid];
const str = mids.reduce((acc, mid) => {
const message = this.chat.getMessage(mid);
return acc + (message?.message ? message.message + '\n' : '');
}, '').trim();
let str: string;
const selection = window.getSelection();
if(isSelectionEmpty(selection)) {
const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid];
str = mids.reduce((acc, mid) => {
const message = this.chat.getMessage(mid);
return acc + (message?.message ? message.message + '\n' : '');
}, '').trim();
} else {
str = selection.toString();
//cancelSelection();
}
copyTextToClipboard(str);
};

19
src/components/chat/markupTooltip.ts

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
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 ButtonIcon from "../buttonIcon";
import { clamp } from "../../helpers/number";
@ -258,26 +258,13 @@ export default class MarkupTooltip { @@ -258,26 +258,13 @@ export default class MarkupTooltip {
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() {
if(this.init) {
this.init();
this.init = null;
}
if(this.isSelectionEmpty()) {
if(isSelectionEmpty()) {
this.hide();
return;
}
@ -375,7 +362,7 @@ export default class MarkupTooltip { @@ -375,7 +362,7 @@ export default class MarkupTooltip {
}
const selection = document.getSelection();
if(this.isSelectionEmpty(selection)) {
if(isSelectionEmpty(selection)) {
this.hide();
return;
}

13
src/helpers/dom.ts

@ -762,3 +762,16 @@ export function reflowScrollableElement(element: HTMLElement) { @@ -762,3 +762,16 @@ export function reflowScrollableElement(element: HTMLElement) {
void element.offsetLeft; // reflow
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