Added 'start bot' button
This commit is contained in:
parent
7db608a216
commit
a490f29c40
@ -1953,7 +1953,7 @@ export default class ChatBubbles {
|
||||
this.isTopPaddingSet = false;
|
||||
}
|
||||
|
||||
public setPeer(peerId: PeerId, lastMsgId?: number): {cached?: boolean, promise: Chat['setPeerPromise']} {
|
||||
public setPeer(peerId: PeerId, lastMsgId?: number, startParam?: string): {cached?: boolean, promise: Chat['setPeerPromise']} {
|
||||
//console.time('appImManager setPeer');
|
||||
//console.time('appImManager setPeer pre promise');
|
||||
////console.time('appImManager: pre render start');
|
||||
@ -2019,6 +2019,10 @@ export default class ChatBubbles {
|
||||
scrollable.scrollTop = scrollable.scrollHeight;
|
||||
this.chat.dispatchEvent('setPeer', lastMsgId, true);
|
||||
}
|
||||
|
||||
if(startParam !== undefined) {
|
||||
this.chat.input.setStartParam(startParam);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -2095,7 +2099,7 @@ export default class ChatBubbles {
|
||||
if(!samePeer) {
|
||||
scrollable.container.textContent = '';
|
||||
//oldChatInner.remove();
|
||||
this.chat.finishPeerChange(isTarget, isJump, lastMsgId);
|
||||
this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam);
|
||||
this.preloader.attach(this.bubblesContainer);
|
||||
}
|
||||
}
|
||||
@ -2110,7 +2114,7 @@ export default class ChatBubbles {
|
||||
|
||||
if(cached) {
|
||||
if(!samePeer) {
|
||||
this.chat.finishPeerChange(isTarget, isJump, lastMsgId); // * костыль
|
||||
this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam); // * костыль
|
||||
}
|
||||
} else {
|
||||
this.preloader.detach();
|
||||
|
@ -34,7 +34,7 @@ import ChatContextMenu from "./contextMenu";
|
||||
import ChatInput from "./input";
|
||||
import ChatSelection from "./selection";
|
||||
import ChatTopbar from "./topbar";
|
||||
import { NULL_PEER_ID, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import { BOT_START_PARAM, NULL_PEER_ID, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import SetTransition from "../singleTransition";
|
||||
import { fastRaf } from "../../helpers/schedulers";
|
||||
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
|
||||
@ -109,6 +109,8 @@ export default class Chat extends EventListenerBase<{
|
||||
this.log = logger('CHAT', LogTypes.Log | LogTypes.Warn | LogTypes.Debug | LogTypes.Error);
|
||||
//this.log.error('Chat construction');
|
||||
|
||||
this.peerId = NULL_PEER_ID;
|
||||
|
||||
this.container.append(this.backgroundEl);
|
||||
this.appImManager.chatsContainer.append(this.container);
|
||||
}
|
||||
@ -255,7 +257,7 @@ export default class Chat extends EventListenerBase<{
|
||||
this.selection.cleanup();
|
||||
}
|
||||
|
||||
public setPeer(peerId: PeerId, lastMsgId?: number) {
|
||||
public setPeer(peerId: PeerId, lastMsgId?: number, startParam?: string) {
|
||||
if(!peerId) {
|
||||
this.inited = undefined;
|
||||
} else if(!this.inited) {
|
||||
@ -270,7 +272,7 @@ export default class Chat extends EventListenerBase<{
|
||||
const samePeer = this.peerId === peerId;
|
||||
if(!samePeer) {
|
||||
rootScope.dispatchEvent('peer_changing', this);
|
||||
this.peerId = peerId;
|
||||
this.peerId = peerId || NULL_PEER_ID;
|
||||
} else if(this.setPeerPromise) {
|
||||
return;
|
||||
}
|
||||
@ -306,7 +308,11 @@ export default class Chat extends EventListenerBase<{
|
||||
|
||||
this.peerChanged = samePeer;
|
||||
|
||||
const result = this.bubbles.setPeer(peerId, lastMsgId);
|
||||
if(startParam === undefined && this.isStartButtonNeeded()) {
|
||||
startParam = BOT_START_PARAM;
|
||||
}
|
||||
|
||||
const result = this.bubbles.setPeer(peerId, lastMsgId, startParam);
|
||||
if(!result) {
|
||||
return;
|
||||
}
|
||||
@ -361,7 +367,7 @@ export default class Chat extends EventListenerBase<{
|
||||
return this.setPeer(this.peerId, messageId);
|
||||
}
|
||||
|
||||
public finishPeerChange(isTarget: boolean, isJump: boolean, lastMsgId: number) {
|
||||
public finishPeerChange(isTarget: boolean, isJump: boolean, lastMsgId: number, startParam?: string) {
|
||||
if(this.peerChanged) return;
|
||||
|
||||
let peerId = this.peerId;
|
||||
@ -372,7 +378,7 @@ export default class Chat extends EventListenerBase<{
|
||||
this.topbar.setPeer(peerId);
|
||||
this.topbar.finishPeerChange(isTarget, isJump, lastMsgId);
|
||||
this.bubbles.finishPeerChange();
|
||||
this.input.finishPeerChange();
|
||||
this.input.finishPeerChange(startParam);
|
||||
|
||||
appSidebarRight.sharedMediaTab.fillProfileElements();
|
||||
|
||||
@ -421,4 +427,10 @@ export default class Chat extends EventListenerBase<{
|
||||
public canSend(action?: ChatRights) {
|
||||
return this.appMessagesManager.canSendToPeer(this.peerId, this.threadId, action);
|
||||
}
|
||||
|
||||
public isStartButtonNeeded() {
|
||||
return this.appPeersManager.isBot(this.peerId) &&
|
||||
!this.appMessagesManager.getDialogOnly(this.peerId) &&
|
||||
!this.appMessagesManager.getHistoryStorage(this.peerId).history.length;
|
||||
}
|
||||
}
|
||||
|
@ -80,12 +80,13 @@ import { copy } from '../../helpers/object';
|
||||
import PopupPeer from '../popups/peer';
|
||||
import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport';
|
||||
import appMediaPlaybackController from '../appMediaPlaybackController';
|
||||
import { NULL_PEER_ID } from '../../lib/mtproto/mtproto_config';
|
||||
import { BOT_START_PARAM, NULL_PEER_ID } from '../../lib/mtproto/mtproto_config';
|
||||
import setCaretAt from '../../helpers/dom/setCaretAt';
|
||||
import CheckboxField from '../checkboxField';
|
||||
import DropdownHover from '../../helpers/dropdownHover';
|
||||
import RadioForm from '../radioForm';
|
||||
import findUpTag from '../../helpers/dom/findUpTag';
|
||||
import toggleDisability from '../../helpers/dom/toggleDisability';
|
||||
|
||||
const RECORD_MIN_TIME = 500;
|
||||
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
|
||||
@ -205,6 +206,7 @@ export default class ChatInput {
|
||||
private fakeSelectionWrapper: HTMLDivElement;
|
||||
|
||||
private fakeWrapperTo: HTMLElement;
|
||||
private toggleBotStartBtnDisability: () => void;
|
||||
|
||||
// private activeContainer: HTMLElement;
|
||||
|
||||
@ -678,6 +680,20 @@ export default class ChatInput {
|
||||
if(this.replyToMsgId && msgs.has(this.replyToMsgId)) {
|
||||
this.clearHelper('reply');
|
||||
}
|
||||
|
||||
/* if(this.chat.isStartButtonNeeded()) {
|
||||
this.setStartParam(BOT_START_PARAM);
|
||||
} */
|
||||
}
|
||||
});
|
||||
|
||||
this.listenerSetter.add(rootScope)('dialogs_multiupdate', (dialogs) => {
|
||||
if(dialogs[this.chat.peerId]) {
|
||||
if(this.startParam === BOT_START_PARAM) {
|
||||
this.setStartParam();
|
||||
} else { // updateNewMessage comes earlier than dialog appers
|
||||
this.center(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -794,6 +810,27 @@ export default class ChatInput {
|
||||
this.botStartBtn = Button('btn-primary btn-transparent text-bold chat-input-control-button');
|
||||
this.botStartBtn.append(i18n('BotStart'));
|
||||
|
||||
attachClickEvent(this.botStartBtn, () => {
|
||||
const {startParam} = this;
|
||||
if(startParam === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toggle = this.toggleBotStartBtnDisability = toggleDisability([this.botStartBtn], true);
|
||||
const peerId = this.chat.peerId;
|
||||
const middleware = this.chat.bubbles.getMiddleware(() => {
|
||||
return this.chat.peerId === peerId && this.startParam === startParam && this.toggleBotStartBtnDisability === toggle;
|
||||
});
|
||||
|
||||
this.appMessagesManager.startBot(peerId.toUserId(), undefined, startParam).then(() => {
|
||||
if(middleware()) {
|
||||
toggle();
|
||||
this.toggleBotStartBtnDisability = undefined;
|
||||
this.setStartParam();
|
||||
}
|
||||
});
|
||||
}, {listenerSetter: this.listenerSetter});
|
||||
|
||||
this.controlContainer.append(this.botStartBtn);
|
||||
}
|
||||
|
||||
@ -824,6 +861,10 @@ export default class ChatInput {
|
||||
return;
|
||||
}
|
||||
|
||||
if(neededFakeContainer === this.fakeWrapperTo) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* if(neededFakeContainer === this.botStartContainer && this.fakeWrapperTo === this.fakeSelectionWrapper) {
|
||||
this.inputContainer.classList.remove('is-centering');
|
||||
void this.rowsWrapper.offsetLeft; // reflow
|
||||
@ -882,10 +923,23 @@ export default class ChatInput {
|
||||
};
|
||||
}
|
||||
|
||||
public setStartParam(startParam?: string) {
|
||||
if(this.startParam === startParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.startParam = startParam;
|
||||
this.center(true);
|
||||
}
|
||||
|
||||
public getNeededFakeContainer() {
|
||||
if(this.chat.selection.isSelecting) {
|
||||
return this.fakeSelectionWrapper;
|
||||
} else if(this.startParam || !this.chat.canSend() || this.chat.type === 'pinned') {
|
||||
} else if(this.startParam !== undefined ||
|
||||
!this.chat.canSend() ||
|
||||
this.chat.type === 'pinned' ||
|
||||
this.chat.isStartButtonNeeded()
|
||||
) {
|
||||
return this.controlContainer;
|
||||
}
|
||||
}
|
||||
@ -1011,6 +1065,12 @@ export default class ChatInput {
|
||||
cancelSelection();
|
||||
|
||||
this.lastTimeType = 0;
|
||||
this.startParam = undefined;
|
||||
|
||||
if(this.toggleBotStartBtnDisability) {
|
||||
this.toggleBotStartBtnDisability();
|
||||
this.toggleBotStartBtnDisability = undefined;
|
||||
}
|
||||
|
||||
if(this.messageInput) {
|
||||
this.clearInput();
|
||||
@ -1062,7 +1122,7 @@ export default class ChatInput {
|
||||
return true;
|
||||
}
|
||||
|
||||
public finishPeerChange() {
|
||||
public finishPeerChange(startParam?: string) {
|
||||
const peerId = this.chat.peerId;
|
||||
|
||||
const {forwardElements, btnScheduled, replyKeyboard, sendMenu, goDownBtn, chatInput} = this;
|
||||
@ -1110,7 +1170,12 @@ export default class ChatInput {
|
||||
this.pinnedControlBtn.append(i18n(this.appPeersManager.canPinMessage(this.chat.peerId) ? 'Chat.Input.UnpinAll' : 'Chat.Pinned.DontShow'));
|
||||
}
|
||||
|
||||
this.center();
|
||||
// * testing
|
||||
// this.startParam = this.appPeersManager.isBot(peerId) ? '123' : undefined;
|
||||
|
||||
this.startParam = startParam;
|
||||
|
||||
this.center(false);
|
||||
}
|
||||
|
||||
public updateMessageInput() {
|
||||
|
@ -159,7 +159,9 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||
icon: 'help',
|
||||
text: 'TelegramFeatures',
|
||||
onClick: () => {
|
||||
appImManager.openUsername('TelegramTips');
|
||||
appImManager.openUsername({
|
||||
userName: 'TelegramTips'
|
||||
});
|
||||
}
|
||||
}, {
|
||||
icon: 'bug',
|
||||
|
@ -4,7 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
export default function toggleDisability(elements: HTMLElement[], disable: boolean) {
|
||||
export default function toggleDisability(elements: HTMLElement[], disable: boolean): () => void {
|
||||
if(disable) {
|
||||
elements.forEach(el => el.setAttribute('disabled', 'true'));
|
||||
} else {
|
||||
|
@ -30,7 +30,7 @@ export function copy<T>(obj: T): T {
|
||||
//lastly, handle objects
|
||||
// @ts-ignore
|
||||
let clonedObj = new obj.constructor();
|
||||
for(var prop in obj){
|
||||
for(var prop in obj) {
|
||||
if(obj.hasOwnProperty(prop)) {
|
||||
clonedObj[prop] = copy(obj[prop]);
|
||||
}
|
||||
|
3
src/layer.d.ts
vendored
3
src/layer.d.ts
vendored
@ -885,7 +885,8 @@ export namespace Message {
|
||||
totalEntities?: MessageEntity[],
|
||||
reply_to_mid?: number,
|
||||
savedFrom?: string,
|
||||
sponsoredMessage?: SponsoredMessage.sponsoredMessage
|
||||
sponsoredMessage?: SponsoredMessage.sponsoredMessage,
|
||||
promise?: CancellablePromise<void>
|
||||
};
|
||||
|
||||
export type messageService = {
|
||||
|
@ -604,7 +604,12 @@ export class AppImManager {
|
||||
const postId = link.post ? appMessagesIdsManager.generateMessageId(+link.post) : undefined;
|
||||
const commentId = link.comment ? appMessagesIdsManager.generateMessageId(+link.comment) : undefined;
|
||||
|
||||
this.openUsername(link.domain, postId, undefined, commentId);
|
||||
this.openUsername({
|
||||
userName: link.domain,
|
||||
lastMsgId: postId,
|
||||
commentId,
|
||||
startParam: link.start
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@ -740,7 +745,10 @@ export class AppImManager {
|
||||
|
||||
switch(p[0]) {
|
||||
case '@': {
|
||||
this.openUsername(p, postId);
|
||||
this.openUsername({
|
||||
userName: p,
|
||||
lastMsgId: postId
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@ -759,8 +767,15 @@ export class AppImManager {
|
||||
//location.hash = '';
|
||||
};
|
||||
|
||||
public openUsername(username: string, lastMsgId?: number, threadId?: number, commentId?: number) {
|
||||
return appUsersManager.resolveUsername(username).then(peer => {
|
||||
public openUsername(options: {
|
||||
userName: string,
|
||||
lastMsgId?: number,
|
||||
threadId?: number,
|
||||
commentId?: number,
|
||||
startParam?: string
|
||||
}) {
|
||||
const {userName, lastMsgId, threadId, commentId, startParam} = options;
|
||||
return appUsersManager.resolveUsername(userName).then(peer => {
|
||||
const isUser = peer._ === 'user';
|
||||
const peerId = peer.id.toPeerId(!isUser);
|
||||
|
||||
@ -772,7 +787,8 @@ export class AppImManager {
|
||||
|
||||
return this.setInnerPeer({
|
||||
peerId,
|
||||
lastMsgId
|
||||
lastMsgId,
|
||||
startParam: startParam
|
||||
});
|
||||
}, (err) => {
|
||||
if(err.type === 'USERNAME_NOT_OCCUPIED') {
|
||||
@ -1433,6 +1449,8 @@ export class AppImManager {
|
||||
this.init = null;
|
||||
}
|
||||
|
||||
options.peerId ??= NULL_PEER_ID;
|
||||
|
||||
const {peerId, lastMsgId} = options;
|
||||
|
||||
const chat = this.chat;
|
||||
@ -1476,7 +1494,7 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
if(peerId || mediaSizes.activeScreen !== ScreenSize.mobile) {
|
||||
const result = chat.setPeer(peerId, lastMsgId);
|
||||
const result = chat.setPeer(peerId, lastMsgId, options.startParam);
|
||||
|
||||
// * wait for cached render
|
||||
const promise = result?.cached ? result.promise : Promise.resolve();
|
||||
|
@ -448,7 +448,7 @@ export class AppMessagesManager {
|
||||
silent: true
|
||||
}> = {}) {
|
||||
if(!text.trim()) {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
//this.checkSendOptions(options);
|
||||
@ -552,7 +552,13 @@ export class AppMessagesManager {
|
||||
//if(is<Updates.updateShortSentMessage>(updates, updates._ === 'updateShortSentMessage')) {
|
||||
if(updates._ === 'updateShortSentMessage') {
|
||||
//assumeType<Updates.updateShortSentMessage>(updates);
|
||||
|
||||
// * fix copying object with promise
|
||||
const promise = message.promise;
|
||||
delete message.promise;
|
||||
const newMessage = copy(message);
|
||||
message.promise = promise;
|
||||
|
||||
newMessage.date = updates.date;
|
||||
newMessage.id = updates.id;
|
||||
newMessage.media = updates.media;
|
||||
@ -596,8 +602,10 @@ export class AppMessagesManager {
|
||||
// $timeout(function () {
|
||||
// ApiUpdatesManager.processUpdateMessage(upd)
|
||||
// }, 5000)
|
||||
}, (/* error: any */) => {
|
||||
message.promise.resolve();
|
||||
}, (error: any) => {
|
||||
toggleError(true);
|
||||
message.promise.reject(error);
|
||||
}).finally(() => {
|
||||
if(this.pendingAfterMsgs[peerId] === sentRequestOptions) {
|
||||
delete this.pendingAfterMsgs[peerId];
|
||||
@ -610,6 +618,8 @@ export class AppMessagesManager {
|
||||
threadId: options.threadId,
|
||||
clearDraft: options.clearDraft
|
||||
});
|
||||
|
||||
return message.promise;
|
||||
}
|
||||
|
||||
public sendFile(peerId: PeerId, file: File | Blob | MyDocument, options: Partial<{
|
||||
@ -1027,8 +1037,11 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
toggleError(true);
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
|
||||
sentDeferred.then(message.promise.resolve, message.promise.reject);
|
||||
}
|
||||
|
||||
return {message, promise: sentDeferred};
|
||||
@ -1120,6 +1133,7 @@ export class AppMessagesManager {
|
||||
const invoke = (multiMedia: InputSingleMedia[]) => {
|
||||
this.setTyping(peerId, {_: 'sendMessageCancelAction'});
|
||||
|
||||
const deferred = deferredPromise<void>();
|
||||
this.sendSmthLazyLoadQueue.push({
|
||||
load: () => {
|
||||
return apiManager.invokeApi('messages.sendMultiMedia', {
|
||||
@ -1131,11 +1145,15 @@ export class AppMessagesManager {
|
||||
clear_draft: options.clearDraft
|
||||
}).then((updates) => {
|
||||
apiUpdatesManager.processUpdateMessage(updates);
|
||||
deferred.resolve();
|
||||
}, (error) => {
|
||||
messages.forEach(message => toggleError(message, true));
|
||||
deferred.reject(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return deferred;
|
||||
};
|
||||
|
||||
const promises: Promise<InputSingleMedia>[] = messages.map((message) => {
|
||||
@ -1181,8 +1199,8 @@ export class AppMessagesManager {
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(promises).then(inputs => {
|
||||
invoke(inputs.filter(Boolean));
|
||||
return Promise.all(promises).then(inputs => {
|
||||
return invoke(inputs.filter(Boolean));
|
||||
});
|
||||
}
|
||||
|
||||
@ -1362,6 +1380,8 @@ export class AppMessagesManager {
|
||||
threadId: options.threadId,
|
||||
clearDraft: options.clearDraft
|
||||
});
|
||||
|
||||
return message.promise;
|
||||
}
|
||||
|
||||
/* private checkSendOptions(options: Partial<{
|
||||
@ -1472,6 +1492,7 @@ export class AppMessagesManager {
|
||||
replies: this.generateReplies(peerId),
|
||||
views: isBroadcast && 1,
|
||||
pending: true,
|
||||
promise: options.groupId === undefined ? deferredPromise() : undefined
|
||||
};
|
||||
|
||||
return message;
|
||||
|
@ -14,3 +14,4 @@ export const NULL_PEER_ID: PeerId = 0;
|
||||
export const REPLIES_PEER_ID: PeerId = 1271266957;
|
||||
export const SERVICE_PEER_ID: PeerId = 777000;
|
||||
export const MUTE_UNTIL = 0x7FFFFFFF;
|
||||
export const BOT_START_PARAM = '';
|
||||
|
@ -82,7 +82,8 @@
|
||||
{"name": "savedFrom", "type": "string"},
|
||||
{"name": "sponsored", "type": "true"},
|
||||
{"name": "local", "type": "true"},
|
||||
{"name": "sponsoredMessage", "type": "SponsoredMessage.sponsoredMessage"}
|
||||
{"name": "sponsoredMessage", "type": "SponsoredMessage.sponsoredMessage"},
|
||||
{"name": "promise", "type": "CancellablePromise<void>"}
|
||||
]
|
||||
}, {
|
||||
"predicate": "messageService",
|
||||
|
Loading…
Reference in New Issue
Block a user