Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
5.6 KiB
180 lines
5.6 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
*/ |
|
|
|
import type ChatInput from "./input"; |
|
import DropdownHover from "../../helpers/dropdownHover"; |
|
import { KeyboardButton, ReplyMarkup } from "../../layer"; |
|
import rootScope from "../../lib/rootScope"; |
|
import ListenerSetter, { Listener } from "../../helpers/listenerSetter"; |
|
import findUpClassName from "../../helpers/dom/findUpClassName"; |
|
import IS_TOUCH_SUPPORTED from "../../environment/touchSupport"; |
|
import findUpAsChild from "../../helpers/dom/findUpAsChild"; |
|
import cancelEvent from "../../helpers/dom/cancelEvent"; |
|
import { getHeavyAnimationPromise } from "../../hooks/useHeavyAnimationCheck"; |
|
import confirmationPopup from "../confirmationPopup"; |
|
import safeAssign from "../../helpers/object/safeAssign"; |
|
import setInnerHTML from "../../helpers/dom/setInnerHTML"; |
|
import wrapEmojiText from "../../lib/richTextProcessor/wrapEmojiText"; |
|
import { AppManagers } from "../../lib/appManagers/managers"; |
|
|
|
export default class ReplyKeyboard extends DropdownHover { |
|
private static BASE_CLASS = 'reply-keyboard'; |
|
private appendTo: HTMLElement; |
|
private listenerSetter: ListenerSetter; |
|
private managers: AppManagers; |
|
private btnHover: HTMLElement; |
|
private peerId: PeerId; |
|
private touchListener: Listener; |
|
private chatInput: ChatInput; |
|
|
|
constructor(options: { |
|
listenerSetter: ListenerSetter, |
|
managers: AppManagers, |
|
appendTo: HTMLElement, |
|
btnHover: HTMLElement, |
|
chatInput: ChatInput |
|
}) { |
|
super({ |
|
element: document.createElement('div') |
|
}); |
|
|
|
safeAssign(this, options); |
|
|
|
this.element.classList.add(ReplyKeyboard.BASE_CLASS); |
|
this.element.style.display = 'none'; |
|
|
|
this.attachButtonListener(this.btnHover, this.listenerSetter); |
|
this.listenerSetter.add(rootScope)('history_reply_markup', async({peerId}) => { |
|
if(this.peerId === peerId) { |
|
if(this.checkAvailability() && this.isActive()) { |
|
await this.render(); |
|
} |
|
|
|
getHeavyAnimationPromise().then(() => { |
|
this.checkForceReply(); |
|
}); |
|
} |
|
}); |
|
} |
|
|
|
protected init() { |
|
this.appendTo.append(this.element); |
|
|
|
this.listenerSetter.add(this)('open', async() => { |
|
await this.render(); |
|
|
|
if(IS_TOUCH_SUPPORTED) { |
|
this.touchListener = this.listenerSetter.add(document.body)('touchstart', this.onBodyTouchStart, {passive: false, capture: true}) as any as Listener; |
|
this.listenerSetter.add(this)('close', () => { |
|
this.listenerSetter.remove(this.touchListener); |
|
}, {once: true}); |
|
} |
|
}); |
|
|
|
this.listenerSetter.add(this.element)('click', (e) => { |
|
const target = findUpClassName(e.target, 'btn'); |
|
if(!target) { |
|
return; |
|
} |
|
|
|
const type = target.dataset.type as KeyboardButton['_']; |
|
const {peerId} = this; |
|
switch(type) { |
|
case 'keyboardButtonRequestPhone': { |
|
confirmationPopup({ |
|
titleLangKey: 'ShareYouPhoneNumberTitle', |
|
button: { |
|
langKey: 'OK' |
|
}, |
|
descriptionLangKey: 'AreYouSureShareMyContactInfoBot' |
|
}).then(() => { |
|
this.managers.appMessagesManager.sendContact(peerId, rootScope.myId); |
|
}); |
|
break; |
|
} |
|
|
|
default: { |
|
this.managers.appMessagesManager.sendText(peerId, target.dataset.text); |
|
break; |
|
} |
|
} |
|
|
|
this.toggle(false); |
|
}); |
|
|
|
return super.init(); |
|
} |
|
|
|
private onBodyTouchStart = (e: TouchEvent) => { |
|
const target = e.touches[0].target as HTMLElement; |
|
if(!findUpAsChild(target, this.element) && target !== this.btnHover) { |
|
cancelEvent(e); |
|
this.toggle(false); |
|
} |
|
}; |
|
|
|
public async checkForceReply() { |
|
const replyMarkup = await this.getReplyMarkup(); |
|
if(replyMarkup._ === 'replyKeyboardForceReply' && |
|
!replyMarkup.pFlags.hidden && |
|
!replyMarkup.pFlags.used) { |
|
replyMarkup.pFlags.used = true; |
|
this.chatInput.initMessageReply(replyMarkup.mid); |
|
} |
|
} |
|
|
|
private async getReplyMarkup() { |
|
return (await this.managers.appMessagesManager.getHistoryStorageTransferable(this.peerId)).replyMarkup ?? { |
|
_: 'replyKeyboardHide' |
|
}; |
|
} |
|
|
|
public async render(replyMarkup?: ReplyMarkup.replyKeyboardMarkup) { |
|
if(replyMarkup === undefined) { |
|
replyMarkup = await this.getReplyMarkup() as any; |
|
} |
|
|
|
this.element.textContent = ''; |
|
|
|
for(const row of replyMarkup.rows) { |
|
const div = document.createElement('div'); |
|
div.classList.add(ReplyKeyboard.BASE_CLASS + '-row'); |
|
|
|
for(const button of row.buttons) { |
|
const btn = document.createElement('button'); |
|
btn.classList.add(ReplyKeyboard.BASE_CLASS + '-button', 'btn'); |
|
setInnerHTML(btn, wrapEmojiText(button.text)); |
|
btn.dataset.text = button.text; |
|
btn.dataset.type = button._; |
|
div.append(btn); |
|
} |
|
|
|
this.element.append(div); |
|
} |
|
} |
|
|
|
public async checkAvailability(replyMarkup?: ReplyMarkup) { |
|
if(replyMarkup === undefined) { |
|
replyMarkup = await this.getReplyMarkup(); |
|
} |
|
|
|
const hide = replyMarkup._ === 'replyKeyboardHide' || !(replyMarkup as ReplyMarkup.replyInlineMarkup).rows?.length; |
|
this.btnHover.classList.toggle('hide', hide); |
|
|
|
if(hide) { |
|
this.toggle(false); |
|
} |
|
|
|
return !hide; |
|
} |
|
|
|
public setPeer(peerId: PeerId) { |
|
this.peerId = peerId; |
|
|
|
this.checkAvailability(); |
|
this.checkForceReply(); |
|
} |
|
}
|
|
|