Fix pasting text in input
Mobile markup tooltip
This commit is contained in:
parent
b811e1c86f
commit
921bcdbc27
@ -1,9 +1,10 @@
|
|||||||
import type { AppImManager } from "../../lib/appManagers/appImManager";
|
import type { AppImManager } from "../../lib/appManagers/appImManager";
|
||||||
import { MarkdownType, cancelEvent, getSelectedNodes, markdownTags, findUpClassName, attachClickEvent } from "../../helpers/dom";
|
import { MarkdownType, cancelEvent, getSelectedNodes, markdownTags, findUpClassName, attachClickEvent, cancelSelection } 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";
|
||||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||||
|
import { isApple } from "../../helpers/userAgent";
|
||||||
|
|
||||||
export default class MarkupTooltip {
|
export default class MarkupTooltip {
|
||||||
public container: HTMLElement;
|
public container: HTMLElement;
|
||||||
@ -16,6 +17,7 @@ export default class MarkupTooltip {
|
|||||||
private waitingForMouseUp = false;
|
private waitingForMouseUp = false;
|
||||||
private linkInput: HTMLInputElement;
|
private linkInput: HTMLInputElement;
|
||||||
private savedRange: Range;
|
private savedRange: Range;
|
||||||
|
mouseUpCounter: number = 0;
|
||||||
|
|
||||||
constructor(private appImManager: AppImManager) {
|
constructor(private appImManager: AppImManager) {
|
||||||
|
|
||||||
@ -41,6 +43,7 @@ export default class MarkupTooltip {
|
|||||||
if(c !== 'link') {
|
if(c !== 'link') {
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
this.appImManager.chat.input.applyMarkdown(c);
|
this.appImManager.chat.input.applyMarkdown(c);
|
||||||
|
this.hide();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
attachClickEvent(button, (e) => {
|
attachClickEvent(button, (e) => {
|
||||||
@ -58,7 +61,11 @@ export default class MarkupTooltip {
|
|||||||
this.linkInput.value = '';
|
this.linkInput.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.linkInput.focus();
|
this.setTooltipPosition(true);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.linkInput.focus(); // !!! instant focus will break animation
|
||||||
|
}, 200);
|
||||||
this.linkInput.classList.toggle('is-valid', this.isLinkValid());
|
this.linkInput.classList.toggle('is-valid', this.isLinkValid());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -97,6 +104,7 @@ export default class MarkupTooltip {
|
|||||||
this.container.classList.remove('is-link');
|
this.container.classList.remove('is-link');
|
||||||
//input.value = '';
|
//input.value = '';
|
||||||
this.resetSelection();
|
this.resetSelection();
|
||||||
|
this.setTooltipPosition();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.linkApplyButton = ButtonIcon('check markup-tooltip-link-apply', {noRipple: true});
|
this.linkApplyButton = ButtonIcon('check markup-tooltip-link-apply', {noRipple: true});
|
||||||
@ -135,10 +143,10 @@ export default class MarkupTooltip {
|
|||||||
return !this.linkInput.value.length || !!RichTextProcessor.matchUrl(this.linkInput.value);
|
return !this.linkInput.value.length || !!RichTextProcessor.matchUrl(this.linkInput.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetSelection() {
|
private resetSelection(range: Range = this.savedRange) {
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
selection.removeAllRanges();
|
selection.removeAllRanges();
|
||||||
selection.addRange(this.savedRange);
|
selection.addRange(range);
|
||||||
this.appImManager.chat.input.messageInput.focus();
|
this.appImManager.chat.input.messageInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +155,9 @@ export default class MarkupTooltip {
|
|||||||
|
|
||||||
this.container.classList.remove('is-visible');
|
this.container.classList.remove('is-visible');
|
||||||
document.removeEventListener('mouseup', this.onMouseUp);
|
document.removeEventListener('mouseup', this.onMouseUp);
|
||||||
|
document.removeEventListener('mouseup', this.onMouseUpSingle);
|
||||||
|
this.waitingForMouseUp = false;
|
||||||
|
|
||||||
if(this.hideTimeout) clearTimeout(this.hideTimeout);
|
if(this.hideTimeout) clearTimeout(this.hideTimeout);
|
||||||
this.hideTimeout = window.setTimeout(() => {
|
this.hideTimeout = window.setTimeout(() => {
|
||||||
this.hideTimeout = undefined;
|
this.hideTimeout = undefined;
|
||||||
@ -191,6 +202,41 @@ export default class MarkupTooltip {
|
|||||||
return activeButton;
|
return activeButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setTooltipPosition(isLinkToggle = false) {
|
||||||
|
const selection = document.getSelection();
|
||||||
|
const range = selection.getRangeAt(0);
|
||||||
|
|
||||||
|
const bodyRect = document.body.getBoundingClientRect();
|
||||||
|
const selectionRect = range.getBoundingClientRect();
|
||||||
|
const inputRect = this.appImManager.chat.input.rowsWrapper.getBoundingClientRect();
|
||||||
|
|
||||||
|
this.container.style.maxWidth = inputRect.width + 'px';
|
||||||
|
|
||||||
|
const selectionTop = selectionRect.top + (bodyRect.top * -1);
|
||||||
|
|
||||||
|
const currentTools = this.container.classList.contains('is-link') ? this.wrapper.lastElementChild : this.wrapper.firstElementChild;
|
||||||
|
|
||||||
|
const sizesRect = currentTools.getBoundingClientRect();
|
||||||
|
const top = selectionTop - sizesRect.height - 8;
|
||||||
|
|
||||||
|
const minX = inputRect.left;
|
||||||
|
const maxX = (inputRect.left + inputRect.width) - Math.min(inputRect.width, sizesRect.width);
|
||||||
|
let left: number;
|
||||||
|
if(isLinkToggle) {
|
||||||
|
const containerRect = this.container.getBoundingClientRect();
|
||||||
|
left = clamp(containerRect.left, minX, maxX);
|
||||||
|
} else {
|
||||||
|
const x = selectionRect.left + (selectionRect.width - sizesRect.width) / 2;
|
||||||
|
left = clamp(x, minX, maxX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* const isClamped = x !== minX && x !== maxX && (left === minX || left === maxX || this.container.getBoundingClientRect().left >= maxX);
|
||||||
|
|
||||||
|
if(isLinkToggle && this.container.classList.contains('is-link') && !isClamped) return; */
|
||||||
|
|
||||||
|
this.container.style.transform = `translate3d(${left}px, ${top}px, 0)`;
|
||||||
|
}
|
||||||
|
|
||||||
public show() {
|
public show() {
|
||||||
if(this.init) {
|
if(this.init) {
|
||||||
this.init();
|
this.init();
|
||||||
@ -208,7 +254,9 @@ export default class MarkupTooltip {
|
|||||||
clearTimeout(this.hideTimeout);
|
clearTimeout(this.hideTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
const range = /* this.savedRange = */selection.getRangeAt(0);
|
if(this.container.classList.contains('is-visible')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setActiveMarkupButton();
|
this.setActiveMarkupButton();
|
||||||
|
|
||||||
@ -219,18 +267,7 @@ export default class MarkupTooltip {
|
|||||||
this.container.classList.add('no-transition');
|
this.container.classList.add('no-transition');
|
||||||
}
|
}
|
||||||
|
|
||||||
const bodyRect = document.body.getBoundingClientRect();
|
this.setTooltipPosition();
|
||||||
const selectionRect = range.getBoundingClientRect();
|
|
||||||
const inputRect = this.appImManager.chat.input.rowsWrapper.getBoundingClientRect();
|
|
||||||
|
|
||||||
const selectionTop = selectionRect.top + (bodyRect.top * -1);
|
|
||||||
//const containerRect = this.container.getBoundingClientRect();
|
|
||||||
const sizesRect = this.container.firstElementChild.firstElementChild.getBoundingClientRect();
|
|
||||||
const top = selectionTop - sizesRect.height - 8;
|
|
||||||
const left = clamp(selectionRect.left + (selectionRect.width - sizesRect.width) / 2, inputRect.left, inputRect.right - sizesRect.width);
|
|
||||||
//const top = selectionRect.top - 44 - 8;
|
|
||||||
|
|
||||||
this.container.style.transform = `translate3d(${left}px, ${top}px, 0)`;
|
|
||||||
|
|
||||||
if(isFirstShow) {
|
if(isFirstShow) {
|
||||||
void this.container.offsetLeft; // reflow
|
void this.container.offsetLeft; // reflow
|
||||||
@ -244,19 +281,40 @@ export default class MarkupTooltip {
|
|||||||
|
|
||||||
private onMouseUp = (e: Event) => {
|
private onMouseUp = (e: Event) => {
|
||||||
if(findUpClassName(e.target, 'markup-tooltip')) return;
|
if(findUpClassName(e.target, 'markup-tooltip')) return;
|
||||||
|
/* if(isTouchSupported) {
|
||||||
|
this.appImManager.chat.input.messageInput.focus();
|
||||||
|
cancelEvent(e);
|
||||||
|
} */
|
||||||
|
|
||||||
this.hide();
|
this.hide();
|
||||||
document.removeEventListener('mouseup', this.onMouseUp);
|
document.removeEventListener('mouseup', this.onMouseUp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onMouseUpSingle = (e: Event) => {
|
||||||
|
this.waitingForMouseUp = false;
|
||||||
|
|
||||||
|
if(isTouchSupported) {
|
||||||
|
cancelEvent(e);
|
||||||
|
if(this.mouseUpCounter++ == 0) {
|
||||||
|
this.resetSelection(this.savedRange);
|
||||||
|
} else {
|
||||||
|
this.hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.show();
|
||||||
|
|
||||||
|
!isTouchSupported && document.addEventListener('mouseup', this.onMouseUp);
|
||||||
|
};
|
||||||
|
|
||||||
public setMouseUpEvent() {
|
public setMouseUpEvent() {
|
||||||
if(this.waitingForMouseUp) return;
|
if(this.waitingForMouseUp) return;
|
||||||
this.waitingForMouseUp = true;
|
this.waitingForMouseUp = true;
|
||||||
document.addEventListener('mouseup', (e) => {
|
|
||||||
this.waitingForMouseUp = false;
|
|
||||||
this.show();
|
|
||||||
|
|
||||||
document.addEventListener('mouseup', this.onMouseUp);
|
console.log('[MARKUP]: setMouseUpEvent');
|
||||||
}, {once: true});
|
|
||||||
|
document.addEventListener('mouseup', this.onMouseUpSingle, {once: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
public handleSelection() {
|
public handleSelection() {
|
||||||
@ -281,7 +339,23 @@ export default class MarkupTooltip {
|
|||||||
|
|
||||||
console.log('[MARKUP]: selectionchange');
|
console.log('[MARKUP]: selectionchange');
|
||||||
if(isTouchSupported) {
|
if(isTouchSupported) {
|
||||||
this.show();
|
if(isApple) {
|
||||||
|
this.show();
|
||||||
|
this.setTooltipPosition(); // * because can skip this in .show();
|
||||||
|
} else {
|
||||||
|
if(this.mouseUpCounter == 2) {
|
||||||
|
this.mouseUpCounter = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.savedRange = selection.getRangeAt(0);
|
||||||
|
this.setMouseUpEvent();
|
||||||
|
/* document.addEventListener('touchend', (e) => {
|
||||||
|
cancelEvent(e);
|
||||||
|
this.resetSelection(range);
|
||||||
|
this.show();
|
||||||
|
}, {once: true, passive: false}); */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setMouseUpEvent();
|
this.setMouseUpEvent();
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,15 @@ export class AppImManager {
|
|||||||
//console.log('document paste');
|
//console.log('document paste');
|
||||||
//console.log('item', event.clipboardData.getData());
|
//console.log('item', event.clipboardData.getData());
|
||||||
|
|
||||||
cancelEvent(e);
|
if(e instanceof DragEvent) {
|
||||||
|
const _types = e.dataTransfer.types;
|
||||||
|
// @ts-ignore
|
||||||
|
const isFiles = _types.contains ? _types.contains('Files') : _types.indexOf('Files') >= 0;
|
||||||
|
if(isFiles) {
|
||||||
|
cancelEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getFilesFromEvent(e).then((files: File[]) => {
|
getFilesFromEvent(e).then((files: File[]) => {
|
||||||
if(files.length) {
|
if(files.length) {
|
||||||
if(attachType == 'media' && files.find(file => !['image', 'video'].includes(file.type.split('/')[0]))) {
|
if(attachType == 'media' && files.find(file => !['image', 'video'].includes(file.type.split('/')[0]))) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user