Browse Source

Fix sending textUrl entity

Fix fetching webpage by textUrl entity
master
Eduard Kuzmenko 4 years ago
parent
commit
2c5a301484
  1. 5
      src/components/chat/bubbles.ts
  2. 69
      src/components/chat/input.ts
  3. 25
      src/components/misc.ts
  4. 2
      src/components/sidebarRight/tabs/sharedMedia.ts
  5. 4
      src/lib/rlottie/rlottie.worker.ts
  6. 5
      src/scss/partials/_button.scss

5
src/components/chat/bubbles.ts

@ -235,9 +235,10 @@ export default class ChatBubbles {
this.bubbleGroups.removeBubble(bubble, tempId); */ this.bubbleGroups.removeBubble(bubble, tempId); */
if(message.media?.webpage && !bubble.querySelector('.web')) { if(message.media?.webpage && !bubble.querySelector('.web')) {
const mounted = this.getMountedBubble(mid); this.renderMessage(message, true, false, bubble, false);
/* const mounted = this.getMountedBubble(mid);
if(!mounted) return; if(!mounted) return;
this.renderMessage(mounted.message, true, false, mounted.bubble, false); this.renderMessage(mounted.message, true, false, mounted.bubble, false); */
} }
//delete this.bubbles[tempId]; //delete this.bubbles[tempId];

69
src/components/chat/input.ts

@ -12,7 +12,7 @@ import apiManager from "../../lib/mtproto/mtprotoworker";
import opusDecodeController from "../../lib/opusDecodeController"; import opusDecodeController from "../../lib/opusDecodeController";
import RichTextProcessor from "../../lib/richtextprocessor"; import RichTextProcessor from "../../lib/richtextprocessor";
import { attachClickEvent, blurActiveElement, cancelEvent, cancelSelection, findUpClassName, getRichValue, getSelectedNodes, isInputEmpty, markdownTags, MarkdownType, placeCaretAtEnd, serializeNodes } from "../../helpers/dom"; import { attachClickEvent, blurActiveElement, cancelEvent, cancelSelection, findUpClassName, getRichValue, getSelectedNodes, isInputEmpty, markdownTags, MarkdownType, placeCaretAtEnd, serializeNodes } from "../../helpers/dom";
import { ButtonMenuItemOptions } from '../buttonMenu'; import ButtonMenu, { ButtonMenuItemOptions } from '../buttonMenu';
import emoticonsDropdown from "../emoticonsDropdown"; import emoticonsDropdown from "../emoticonsDropdown";
import PopupCreatePoll from "../popupCreatePoll"; import PopupCreatePoll from "../popupCreatePoll";
import PopupForward from '../popupForward'; import PopupForward from '../popupForward';
@ -28,6 +28,7 @@ import DivAndCaption from '../divAndCaption';
import ButtonMenuToggle from '../buttonMenuToggle'; import ButtonMenuToggle from '../buttonMenuToggle';
import ListenerSetter from '../../helpers/listenerSetter'; import ListenerSetter from '../../helpers/listenerSetter';
import Button from '../button'; import Button from '../button';
import { attachContextMenuListener, openBtnMenu } from '../misc';
const RECORD_MIN_TIME = 500; const RECORD_MIN_TIME = 500;
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.'; const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
@ -55,6 +56,9 @@ export default class ChatInput {
public attachMenu: HTMLButtonElement; public attachMenu: HTMLButtonElement;
private attachMenuButtons: (ButtonMenuItemOptions & {verify: (peerId: number) => boolean})[]; private attachMenuButtons: (ButtonMenuItemOptions & {verify: (peerId: number) => boolean})[];
public sendMenu: HTMLDivElement;
private sendMenuButtons: (ButtonMenuItemOptions & {verify: (peerId: number) => boolean})[];
public replyElements: { public replyElements: {
container?: HTMLElement, container?: HTMLElement,
cancelBtn?: HTMLButtonElement, cancelBtn?: HTMLButtonElement,
@ -187,6 +191,26 @@ export default class ChatInput {
this.attachMenu.classList.add('attach-file', 'tgico-attach'); this.attachMenu.classList.add('attach-file', 'tgico-attach');
this.attachMenu.classList.remove('tgico-more'); this.attachMenu.classList.remove('tgico-more');
this.sendMenuButtons = [{
icon: 'mute',
text: 'Send Without Sound',
onClick: () => {
},
verify: (peerId: number) => true
}, {
icon: 'schedule',
text: 'Schedule Message',
onClick: () => {
},
verify: (peerId: number) => true
}];
this.sendMenu = ButtonMenu(this.sendMenuButtons, this.listenerSetter);
this.sendMenu.classList.add('menu-send', 'top-left');
//this.inputContainer.append(this.sendMenu);
this.recordTimeEl = document.createElement('div'); this.recordTimeEl = document.createElement('div');
this.recordTimeEl.classList.add('record-time'); this.recordTimeEl.classList.add('record-time');
@ -213,7 +237,16 @@ export default class ChatInput {
<span class="tgico tgico-microphone2"></span> <span class="tgico tgico-microphone2"></span>
`); `);
this.btnSendContainer.append(this.recordRippleEl, this.btnSend); attachContextMenuListener(this.btnSend, (e: any) => {
if(this.isInputEmpty()) {
return;
}
cancelEvent(e);
openBtnMenu(this.sendMenu);
}, this.listenerSetter);
this.btnSendContainer.append(this.recordRippleEl, this.btnSend, this.sendMenu);
this.inputContainer.append(this.btnCancelRecord, this.btnSendContainer); this.inputContainer.append(this.btnCancelRecord, this.btnSendContainer);
@ -691,17 +724,21 @@ export default class ChatInput {
//console.log('messageInput input', this.messageInput.innerText, this.serializeNodes(Array.from(this.messageInput.childNodes))); //console.log('messageInput input', this.messageInput.innerText, this.serializeNodes(Array.from(this.messageInput.childNodes)));
//const value = this.messageInput.innerText; //const value = this.messageInput.innerText;
const value = getRichValue(this.messageInput); const richValue = getRichValue(this.messageInput);
//const entities = RichTextProcessor.parseEntities(value);
const markdownEntities: MessageEntity[] = [];
const value = RichTextProcessor.parseMarkdown(richValue, markdownEntities);
const entities = RichTextProcessor.mergeEntities(markdownEntities, RichTextProcessor.parseEntities(value));
const entities = RichTextProcessor.parseEntities(value); //this.chat.log('messageInput entities', richValue, value, markdownEntities);
//console.log('messageInput entities', entities);
if(this.stickersHelper) { if(this.stickersHelper) {
let emoticon = ''; let emoticon = '';
if(entities.length && entities[0]._ == 'messageEntityEmoji') { if(entities.length && entities[0]._ == 'messageEntityEmoji') {
const entity = entities[0]; const entity = entities[0];
if(entity.length == value.length && !entity.offset) { if(entity.length == richValue.length && !entity.offset) {
emoticon = value; emoticon = richValue;
} }
} }
@ -714,17 +751,19 @@ export default class ChatInput {
this.undoHistory.length = 0; this.undoHistory.length = 0;
} }
const urlEntities = entities.filter(e => e._ == 'messageEntityUrl'); const urlEntities: Array<MessageEntity.messageEntityUrl | MessageEntity.messageEntityTextUrl> = entities.filter(e => e._ == 'messageEntityUrl' || e._ == 'messageEntityTextUrl') as any;
if(urlEntities.length) { if(urlEntities.length) {
const richEntities: MessageEntity[] = [];
const richValue = RichTextProcessor.parseMarkdown(getRichValue(this.messageInput), richEntities);
//console.log('messageInput url', entities, richEntities);
for(const entity of urlEntities) { for(const entity of urlEntities) {
const url = value.slice(entity.offset, entity.offset + entity.length); let url: string;
if(entity._ === 'messageEntityTextUrl') {
url = entity.url;
} else {
url = richValue.slice(entity.offset, entity.offset + entity.length);
if(!(url.includes('http://') || url.includes('https://')) && !richEntities.find(e => e._ == 'messageEntityTextUrl')) { if(!(url.includes('http://') || url.includes('https://'))) {
continue; continue;
} }
}
//console.log('messageInput url:', url); //console.log('messageInput url:', url);
@ -732,7 +771,7 @@ export default class ChatInput {
this.lastUrl = url; this.lastUrl = url;
this.willSendWebPage = null; this.willSendWebPage = null;
apiManager.invokeApi('messages.getWebPage', { apiManager.invokeApi('messages.getWebPage', {
url: url, url,
hash: 0 hash: 0
}).then((webpage) => { }).then((webpage) => {
webpage = this.appWebPagesManager.saveWebPage(webpage); webpage = this.appWebPagesManager.saveWebPage(webpage);
@ -762,7 +801,7 @@ export default class ChatInput {
} }
} }
if(!value.trim() && !serializeNodes(Array.from(this.messageInput.childNodes)).trim()) { if(!richValue.trim() && !serializeNodes(Array.from(this.messageInput.childNodes)).trim()) {
this.messageInput.innerHTML = ''; this.messageInput.innerHTML = '';
this.appMessagesManager.setTyping(this.chat.peerId, 'sendMessageCancelAction'); this.appMessagesManager.setTyping(this.chat.peerId, 'sendMessageCancelAction');

25
src/components/misc.ts

@ -134,7 +134,8 @@ export const closeBtnMenu = () => {
if(openedMenu) { if(openedMenu) {
openedMenu.classList.remove('active'); openedMenu.classList.remove('active');
openedMenu.parentElement.classList.remove('menu-open'); openedMenu.parentElement.classList.remove('menu-open');
openedMenu.previousElementSibling.remove(); // remove overlay //openedMenu.previousElementSibling.remove(); // remove overlay
if(menuOverlay) menuOverlay.remove();
openedMenu = null; openedMenu = null;
} }
@ -165,7 +166,7 @@ window.addEventListener('resize', () => {
} */ } */
}); });
let openedMenu: HTMLElement = null, openedMenuOnClose: () => void = null; let openedMenu: HTMLElement = null, openedMenuOnClose: () => void = null, menuOverlay: HTMLElement = null;
export function openBtnMenu(menuElement: HTMLElement, onClose?: () => void) { export function openBtnMenu(menuElement: HTMLElement, onClose?: () => void) {
closeBtnMenu(); closeBtnMenu();
@ -173,9 +174,19 @@ export function openBtnMenu(menuElement: HTMLElement, onClose?: () => void) {
openedMenu.classList.add('active'); openedMenu.classList.add('active');
openedMenu.parentElement.classList.add('menu-open'); openedMenu.parentElement.classList.add('menu-open');
const overlay = document.createElement('div'); if(!menuOverlay) {
overlay.classList.add('btn-menu-overlay'); menuOverlay = document.createElement('div');
openedMenu.parentElement.insertBefore(overlay, openedMenu); menuOverlay.classList.add('btn-menu-overlay');
// ! because this event must be canceled, and can't cancel on menu click (below)
menuOverlay.addEventListener(CLICK_EVENT_NAME, (e) => {
cancelEvent(e);
onClick(e);
});
}
openedMenu.parentElement.insertBefore(menuOverlay, openedMenu);
//document.body.classList.add('disable-hover'); //document.body.classList.add('disable-hover');
openedMenuOnClose = onClose; openedMenuOnClose = onClose;
@ -186,11 +197,11 @@ export function openBtnMenu(menuElement: HTMLElement, onClose?: () => void) {
window.addEventListener('contextmenu', onClick, {once: true}); window.addEventListener('contextmenu', onClick, {once: true});
} }
// ! because this event must be canceled, and can't cancel on menu click (below) /* // ! because this event must be canceled, and can't cancel on menu click (below)
overlay.addEventListener(CLICK_EVENT_NAME, (e) => { overlay.addEventListener(CLICK_EVENT_NAME, (e) => {
cancelEvent(e); cancelEvent(e);
onClick(e); onClick(e);
}); }); */
// ! safari iOS doesn't handle window click event on overlay, idk why // ! safari iOS doesn't handle window click event on overlay, idk why
document.addEventListener(CLICK_EVENT_NAME, onClick); document.addEventListener(CLICK_EVENT_NAME, onClick);

2
src/components/sidebarRight/tabs/sharedMedia.ts

@ -690,7 +690,7 @@ export default class AppSharedMediaTab implements SliderTab {
const peerId = this.peerId; const peerId = this.peerId;
let typesToLoad = single ? [this.sharedMediaType] : this.sharedMediaTypes.filter(t => t !== this.sharedMediaType); let typesToLoad = single ? [this.sharedMediaType] : this.sharedMediaTypes.filter(t => t !== this.sharedMediaType && t !== 'inputMessagesFilterEmpty');
typesToLoad = typesToLoad.filter(type => !this.loadedAllMedia[type] typesToLoad = typesToLoad.filter(type => !this.loadedAllMedia[type]
|| this.usedFromHistory[type] < this.historiesStorage[peerId][type].length); || this.usedFromHistory[type] < this.historiesStorage[peerId][type].length);

4
src/lib/rlottie/rlottie.worker.ts

@ -119,6 +119,10 @@ const queryableFunctions = {
throw new Error('Invalid file'); throw new Error('Invalid file');
} */ } */
/* let perf = performance.now();
let json = JSON.parse(jsString);
console.log('sticker decode:', performance.now() - perf); */
const match = jsString.match(/"fr":\s*?(\d+?),/); const match = jsString.match(/"fr":\s*?(\d+?),/);
const frameRate = +match?.[1] || DEFAULT_FPS; const frameRate = +match?.[1] || DEFAULT_FPS;

5
src/scss/partials/_button.scss

@ -192,11 +192,14 @@
//background-color: rgba(0, 0, 0, .2); //background-color: rgba(0, 0, 0, .2);
} }
&-toggle &-overlay { /* &-toggle */&-overlay {
left: -100vw; left: -100vw;
right: -100vw; right: -100vw;
top: -100vh; top: -100vh;
bottom: -100vh; bottom: -100vh;
width: auto !important;
max-width: none !important;
} }
} }

Loading…
Cancel
Save