Browse Source

Added 'start bot' button

master
morethanwords 3 years ago
parent
commit
a490f29c40
  1. 10
      src/components/chat/bubbles.ts
  2. 24
      src/components/chat/chat.ts
  3. 73
      src/components/chat/input.ts
  4. 4
      src/components/sidebarLeft/index.ts
  5. 2
      src/helpers/dom/toggleDisability.ts
  6. 3
      src/layer.d.ts
  7. 30
      src/lib/appManagers/appImManager.ts
  8. 29
      src/lib/appManagers/appMessagesManager.ts
  9. 1
      src/lib/mtproto/mtproto_config.ts
  10. 3
      src/scripts/in/schema_additional_params.json

10
src/components/chat/bubbles.ts

@ -1953,7 +1953,7 @@ export default class ChatBubbles {
this.isTopPaddingSet = false; 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');
//console.time('appImManager setPeer pre promise'); //console.time('appImManager setPeer pre promise');
////console.time('appImManager: pre render start'); ////console.time('appImManager: pre render start');
@ -2020,6 +2020,10 @@ export default class ChatBubbles {
this.chat.dispatchEvent('setPeer', lastMsgId, true); this.chat.dispatchEvent('setPeer', lastMsgId, true);
} }
if(startParam !== undefined) {
this.chat.input.setStartParam(startParam);
}
return null; return null;
} }
} else { } else {
@ -2095,7 +2099,7 @@ export default class ChatBubbles {
if(!samePeer) { if(!samePeer) {
scrollable.container.textContent = ''; scrollable.container.textContent = '';
//oldChatInner.remove(); //oldChatInner.remove();
this.chat.finishPeerChange(isTarget, isJump, lastMsgId); this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam);
this.preloader.attach(this.bubblesContainer); this.preloader.attach(this.bubblesContainer);
} }
} }
@ -2110,7 +2114,7 @@ export default class ChatBubbles {
if(cached) { if(cached) {
if(!samePeer) { if(!samePeer) {
this.chat.finishPeerChange(isTarget, isJump, lastMsgId); // * костыль this.chat.finishPeerChange(isTarget, isJump, lastMsgId, startParam); // * костыль
} }
} else { } else {
this.preloader.detach(); this.preloader.detach();

24
src/components/chat/chat.ts

@ -34,7 +34,7 @@ import ChatContextMenu from "./contextMenu";
import ChatInput from "./input"; import ChatInput from "./input";
import ChatSelection from "./selection"; import ChatSelection from "./selection";
import ChatTopbar from "./topbar"; 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 SetTransition from "../singleTransition";
import { fastRaf } from "../../helpers/schedulers"; import { fastRaf } from "../../helpers/schedulers";
import AppPrivateSearchTab from "../sidebarRight/tabs/search"; 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 = logger('CHAT', LogTypes.Log | LogTypes.Warn | LogTypes.Debug | LogTypes.Error);
//this.log.error('Chat construction'); //this.log.error('Chat construction');
this.peerId = NULL_PEER_ID;
this.container.append(this.backgroundEl); this.container.append(this.backgroundEl);
this.appImManager.chatsContainer.append(this.container); this.appImManager.chatsContainer.append(this.container);
} }
@ -255,7 +257,7 @@ export default class Chat extends EventListenerBase<{
this.selection.cleanup(); this.selection.cleanup();
} }
public setPeer(peerId: PeerId, lastMsgId?: number) { public setPeer(peerId: PeerId, lastMsgId?: number, startParam?: string) {
if(!peerId) { if(!peerId) {
this.inited = undefined; this.inited = undefined;
} else if(!this.inited) { } else if(!this.inited) {
@ -270,7 +272,7 @@ export default class Chat extends EventListenerBase<{
const samePeer = this.peerId === peerId; const samePeer = this.peerId === peerId;
if(!samePeer) { if(!samePeer) {
rootScope.dispatchEvent('peer_changing', this); rootScope.dispatchEvent('peer_changing', this);
this.peerId = peerId; this.peerId = peerId || NULL_PEER_ID;
} else if(this.setPeerPromise) { } else if(this.setPeerPromise) {
return; return;
} }
@ -306,7 +308,11 @@ export default class Chat extends EventListenerBase<{
this.peerChanged = samePeer; 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) { if(!result) {
return; return;
} }
@ -361,7 +367,7 @@ export default class Chat extends EventListenerBase<{
return this.setPeer(this.peerId, messageId); 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; if(this.peerChanged) return;
let peerId = this.peerId; let peerId = this.peerId;
@ -372,7 +378,7 @@ export default class Chat extends EventListenerBase<{
this.topbar.setPeer(peerId); this.topbar.setPeer(peerId);
this.topbar.finishPeerChange(isTarget, isJump, lastMsgId); this.topbar.finishPeerChange(isTarget, isJump, lastMsgId);
this.bubbles.finishPeerChange(); this.bubbles.finishPeerChange();
this.input.finishPeerChange(); this.input.finishPeerChange(startParam);
appSidebarRight.sharedMediaTab.fillProfileElements(); appSidebarRight.sharedMediaTab.fillProfileElements();
@ -421,4 +427,10 @@ export default class Chat extends EventListenerBase<{
public canSend(action?: ChatRights) { public canSend(action?: ChatRights) {
return this.appMessagesManager.canSendToPeer(this.peerId, this.threadId, action); 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;
}
} }

73
src/components/chat/input.ts

@ -80,12 +80,13 @@ import { copy } from '../../helpers/object';
import PopupPeer from '../popups/peer'; import PopupPeer from '../popups/peer';
import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport'; import MEDIA_MIME_TYPES_SUPPORTED from '../../environment/mediaMimeTypesSupport';
import appMediaPlaybackController from '../appMediaPlaybackController'; 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 setCaretAt from '../../helpers/dom/setCaretAt';
import CheckboxField from '../checkboxField'; import CheckboxField from '../checkboxField';
import DropdownHover from '../../helpers/dropdownHover'; import DropdownHover from '../../helpers/dropdownHover';
import RadioForm from '../radioForm'; import RadioForm from '../radioForm';
import findUpTag from '../../helpers/dom/findUpTag'; import findUpTag from '../../helpers/dom/findUpTag';
import toggleDisability from '../../helpers/dom/toggleDisability';
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.';
@ -205,6 +206,7 @@ export default class ChatInput {
private fakeSelectionWrapper: HTMLDivElement; private fakeSelectionWrapper: HTMLDivElement;
private fakeWrapperTo: HTMLElement; private fakeWrapperTo: HTMLElement;
private toggleBotStartBtnDisability: () => void;
// private activeContainer: HTMLElement; // private activeContainer: HTMLElement;
@ -678,6 +680,20 @@ export default class ChatInput {
if(this.replyToMsgId && msgs.has(this.replyToMsgId)) { if(this.replyToMsgId && msgs.has(this.replyToMsgId)) {
this.clearHelper('reply'); 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 = Button('btn-primary btn-transparent text-bold chat-input-control-button');
this.botStartBtn.append(i18n('BotStart')); 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); this.controlContainer.append(this.botStartBtn);
} }
@ -824,6 +861,10 @@ export default class ChatInput {
return; return;
} }
if(neededFakeContainer === this.fakeWrapperTo) {
return;
}
/* if(neededFakeContainer === this.botStartContainer && this.fakeWrapperTo === this.fakeSelectionWrapper) { /* if(neededFakeContainer === this.botStartContainer && this.fakeWrapperTo === this.fakeSelectionWrapper) {
this.inputContainer.classList.remove('is-centering'); this.inputContainer.classList.remove('is-centering');
void this.rowsWrapper.offsetLeft; // reflow 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() { public getNeededFakeContainer() {
if(this.chat.selection.isSelecting) { if(this.chat.selection.isSelecting) {
return this.fakeSelectionWrapper; 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; return this.controlContainer;
} }
} }
@ -1011,6 +1065,12 @@ export default class ChatInput {
cancelSelection(); cancelSelection();
this.lastTimeType = 0; this.lastTimeType = 0;
this.startParam = undefined;
if(this.toggleBotStartBtnDisability) {
this.toggleBotStartBtnDisability();
this.toggleBotStartBtnDisability = undefined;
}
if(this.messageInput) { if(this.messageInput) {
this.clearInput(); this.clearInput();
@ -1062,7 +1122,7 @@ export default class ChatInput {
return true; return true;
} }
public finishPeerChange() { public finishPeerChange(startParam?: string) {
const peerId = this.chat.peerId; const peerId = this.chat.peerId;
const {forwardElements, btnScheduled, replyKeyboard, sendMenu, goDownBtn, chatInput} = this; 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.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() { public updateMessageInput() {

4
src/components/sidebarLeft/index.ts

@ -159,7 +159,9 @@ export class AppSidebarLeft extends SidebarSlider {
icon: 'help', icon: 'help',
text: 'TelegramFeatures', text: 'TelegramFeatures',
onClick: () => { onClick: () => {
appImManager.openUsername('TelegramTips'); appImManager.openUsername({
userName: 'TelegramTips'
});
} }
}, { }, {
icon: 'bug', icon: 'bug',

2
src/helpers/dom/toggleDisability.ts

@ -4,7 +4,7 @@
* https://github.com/morethanwords/tweb/blob/master/LICENSE * 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) { if(disable) {
elements.forEach(el => el.setAttribute('disabled', 'true')); elements.forEach(el => el.setAttribute('disabled', 'true'));
} else { } else {

3
src/layer.d.ts vendored

@ -885,7 +885,8 @@ export namespace Message {
totalEntities?: MessageEntity[], totalEntities?: MessageEntity[],
reply_to_mid?: number, reply_to_mid?: number,
savedFrom?: string, savedFrom?: string,
sponsoredMessage?: SponsoredMessage.sponsoredMessage sponsoredMessage?: SponsoredMessage.sponsoredMessage,
promise?: CancellablePromise<void>
}; };
export type messageService = { export type messageService = {

30
src/lib/appManagers/appImManager.ts

@ -604,7 +604,12 @@ export class AppImManager {
const postId = link.post ? appMessagesIdsManager.generateMessageId(+link.post) : undefined; const postId = link.post ? appMessagesIdsManager.generateMessageId(+link.post) : undefined;
const commentId = link.comment ? appMessagesIdsManager.generateMessageId(+link.comment) : 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; break;
} }
@ -740,7 +745,10 @@ export class AppImManager {
switch(p[0]) { switch(p[0]) {
case '@': { case '@': {
this.openUsername(p, postId); this.openUsername({
userName: p,
lastMsgId: postId
});
break; break;
} }
@ -759,8 +767,15 @@ export class AppImManager {
//location.hash = ''; //location.hash = '';
}; };
public openUsername(username: string, lastMsgId?: number, threadId?: number, commentId?: number) { public openUsername(options: {
return appUsersManager.resolveUsername(username).then(peer => { 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 isUser = peer._ === 'user';
const peerId = peer.id.toPeerId(!isUser); const peerId = peer.id.toPeerId(!isUser);
@ -772,7 +787,8 @@ export class AppImManager {
return this.setInnerPeer({ return this.setInnerPeer({
peerId, peerId,
lastMsgId lastMsgId,
startParam: startParam
}); });
}, (err) => { }, (err) => {
if(err.type === 'USERNAME_NOT_OCCUPIED') { if(err.type === 'USERNAME_NOT_OCCUPIED') {
@ -1433,6 +1449,8 @@ export class AppImManager {
this.init = null; this.init = null;
} }
options.peerId ??= NULL_PEER_ID;
const {peerId, lastMsgId} = options; const {peerId, lastMsgId} = options;
const chat = this.chat; const chat = this.chat;
@ -1476,7 +1494,7 @@ export class AppImManager {
} }
if(peerId || mediaSizes.activeScreen !== ScreenSize.mobile) { if(peerId || mediaSizes.activeScreen !== ScreenSize.mobile) {
const result = chat.setPeer(peerId, lastMsgId); const result = chat.setPeer(peerId, lastMsgId, options.startParam);
// * wait for cached render // * wait for cached render
const promise = result?.cached ? result.promise : Promise.resolve(); const promise = result?.cached ? result.promise : Promise.resolve();

29
src/lib/appManagers/appMessagesManager.ts

@ -448,7 +448,7 @@ export class AppMessagesManager {
silent: true silent: true
}> = {}) { }> = {}) {
if(!text.trim()) { if(!text.trim()) {
return; return Promise.resolve();
} }
//this.checkSendOptions(options); //this.checkSendOptions(options);
@ -552,7 +552,13 @@ export class AppMessagesManager {
//if(is<Updates.updateShortSentMessage>(updates, updates._ === 'updateShortSentMessage')) { //if(is<Updates.updateShortSentMessage>(updates, updates._ === 'updateShortSentMessage')) {
if(updates._ === 'updateShortSentMessage') { if(updates._ === 'updateShortSentMessage') {
//assumeType<Updates.updateShortSentMessage>(updates); //assumeType<Updates.updateShortSentMessage>(updates);
// * fix copying object with promise
const promise = message.promise;
delete message.promise;
const newMessage = copy(message); const newMessage = copy(message);
message.promise = promise;
newMessage.date = updates.date; newMessage.date = updates.date;
newMessage.id = updates.id; newMessage.id = updates.id;
newMessage.media = updates.media; newMessage.media = updates.media;
@ -596,8 +602,10 @@ export class AppMessagesManager {
// $timeout(function () { // $timeout(function () {
// ApiUpdatesManager.processUpdateMessage(upd) // ApiUpdatesManager.processUpdateMessage(upd)
// }, 5000) // }, 5000)
}, (/* error: any */) => { message.promise.resolve();
}, (error: any) => {
toggleError(true); toggleError(true);
message.promise.reject(error);
}).finally(() => { }).finally(() => {
if(this.pendingAfterMsgs[peerId] === sentRequestOptions) { if(this.pendingAfterMsgs[peerId] === sentRequestOptions) {
delete this.pendingAfterMsgs[peerId]; delete this.pendingAfterMsgs[peerId];
@ -610,6 +618,8 @@ export class AppMessagesManager {
threadId: options.threadId, threadId: options.threadId,
clearDraft: options.clearDraft clearDraft: options.clearDraft
}); });
return message.promise;
} }
public sendFile(peerId: PeerId, file: File | Blob | MyDocument, options: Partial<{ public sendFile(peerId: PeerId, file: File | Blob | MyDocument, options: Partial<{
@ -1027,8 +1037,11 @@ export class AppMessagesManager {
} }
toggleError(true); toggleError(true);
throw error;
}); });
}); });
sentDeferred.then(message.promise.resolve, message.promise.reject);
} }
return {message, promise: sentDeferred}; return {message, promise: sentDeferred};
@ -1120,6 +1133,7 @@ export class AppMessagesManager {
const invoke = (multiMedia: InputSingleMedia[]) => { const invoke = (multiMedia: InputSingleMedia[]) => {
this.setTyping(peerId, {_: 'sendMessageCancelAction'}); this.setTyping(peerId, {_: 'sendMessageCancelAction'});
const deferred = deferredPromise<void>();
this.sendSmthLazyLoadQueue.push({ this.sendSmthLazyLoadQueue.push({
load: () => { load: () => {
return apiManager.invokeApi('messages.sendMultiMedia', { return apiManager.invokeApi('messages.sendMultiMedia', {
@ -1131,11 +1145,15 @@ export class AppMessagesManager {
clear_draft: options.clearDraft clear_draft: options.clearDraft
}).then((updates) => { }).then((updates) => {
apiUpdatesManager.processUpdateMessage(updates); apiUpdatesManager.processUpdateMessage(updates);
deferred.resolve();
}, (error) => { }, (error) => {
messages.forEach(message => toggleError(message, true)); messages.forEach(message => toggleError(message, true));
deferred.reject(error);
}); });
} }
}); });
return deferred;
}; };
const promises: Promise<InputSingleMedia>[] = messages.map((message) => { const promises: Promise<InputSingleMedia>[] = messages.map((message) => {
@ -1181,8 +1199,8 @@ export class AppMessagesManager {
}); });
}); });
Promise.all(promises).then(inputs => { return Promise.all(promises).then(inputs => {
invoke(inputs.filter(Boolean)); return invoke(inputs.filter(Boolean));
}); });
} }
@ -1362,6 +1380,8 @@ export class AppMessagesManager {
threadId: options.threadId, threadId: options.threadId,
clearDraft: options.clearDraft clearDraft: options.clearDraft
}); });
return message.promise;
} }
/* private checkSendOptions(options: Partial<{ /* private checkSendOptions(options: Partial<{
@ -1472,6 +1492,7 @@ export class AppMessagesManager {
replies: this.generateReplies(peerId), replies: this.generateReplies(peerId),
views: isBroadcast && 1, views: isBroadcast && 1,
pending: true, pending: true,
promise: options.groupId === undefined ? deferredPromise() : undefined
}; };
return message; return message;

1
src/lib/mtproto/mtproto_config.ts

@ -14,3 +14,4 @@ export const NULL_PEER_ID: PeerId = 0;
export const REPLIES_PEER_ID: PeerId = 1271266957; export const REPLIES_PEER_ID: PeerId = 1271266957;
export const SERVICE_PEER_ID: PeerId = 777000; export const SERVICE_PEER_ID: PeerId = 777000;
export const MUTE_UNTIL = 0x7FFFFFFF; export const MUTE_UNTIL = 0x7FFFFFFF;
export const BOT_START_PARAM = '';

3
src/scripts/in/schema_additional_params.json

@ -82,7 +82,8 @@
{"name": "savedFrom", "type": "string"}, {"name": "savedFrom", "type": "string"},
{"name": "sponsored", "type": "true"}, {"name": "sponsored", "type": "true"},
{"name": "local", "type": "true"}, {"name": "local", "type": "true"},
{"name": "sponsoredMessage", "type": "SponsoredMessage.sponsoredMessage"} {"name": "sponsoredMessage", "type": "SponsoredMessage.sponsoredMessage"},
{"name": "promise", "type": "CancellablePromise<void>"}
] ]
}, { }, {
"predicate": "messageService", "predicate": "messageService",

Loading…
Cancel
Save