Browse Source

Chat move up animation

Rolled back reply wrapper to height animation
Preserve topbar with opened keyboard on iOS
Fix stickers size on iOS
Fix inputs size on handhelds
Fix saving scroll on ESG opening
master
Eduard Kuzmenko 3 years ago
parent
commit
cc1ab7ec6a
  1. 103
      src/components/chat/bubbles.ts
  2. 153
      src/components/chat/input.ts
  3. 1
      src/components/chat/pinnedContainer.ts
  4. 5
      src/components/chat/pinnedMessage.ts
  5. 3
      src/components/chat/topbar.ts
  6. 25
      src/components/emoticonsDropdown/index.ts
  7. 6
      src/components/sidebarLeft/tabs/editFolder.ts
  8. 5
      src/components/sidebarLeft/tabs/editProfile.ts
  9. 3
      src/components/sidebarLeft/tabs/includedChats.ts
  10. 8
      src/components/wrappers.ts
  11. 29
      src/helpers/dom.ts
  12. 4
      src/helpers/fastSmoothScroll.ts
  13. 23
      src/helpers/mediaSizes.ts
  14. 3
      src/lib/appManagers/AppInlineBotsManager.ts
  15. 2
      src/lib/appManagers/appDraftsManager.ts
  16. 4
      src/lib/appManagers/appImManager.ts
  17. 55
      src/lib/appManagers/appMessagesManager.ts
  18. 6
      src/lib/appManagers/appPollsManager.ts
  19. 4
      src/lib/richtextprocessor.ts
  20. 5
      src/lib/rootScope.ts
  21. 4
      src/pages/pageIm.ts
  22. 101
      src/scss/partials/_chat.scss
  23. 3
      src/scss/partials/_chatTopbar.scss
  24. 9
      src/scss/partials/_input.scss
  25. 8
      src/scss/partials/_leftSidebar.scss
  26. 1
      src/scss/partials/_slider.scss
  27. 1
      src/scss/partials/pages/_pages.scss

103
src/components/chat/bubbles.ts

@ -89,7 +89,7 @@ export default class ChatBubbles {
private preloader: ProgressivePreloader = null; private preloader: ProgressivePreloader = null;
private scrolledAll: boolean; private scrolledAll: boolean;
private scrolledAllDown: boolean; public scrolledAllDown: boolean;
private loadedTopTimes = 0; private loadedTopTimes = 0;
private loadedBottomTimes = 0; private loadedBottomTimes = 0;
@ -495,6 +495,93 @@ export default class ChatBubbles {
}); });
} }
}); });
if('ResizeObserver' in window) {
let wasHeight = this.scrollable.container.offsetHeight;
let resizing = false;
let skip = false;
let scrolled = 0;
let part = 0;
let rAF = 0;
const onResizeEnd = () => {
//this.log('resize end', scrolled, this.scrollable.scrollTop);
if(part) {
this.scrollable.scrollTop += Math.round(part);
}
wasHeight = this.scrollable.container.offsetHeight;
scrolled = 0;
rAF = 0;
part = 0;
resizing = false;
skip = false;
};
const setEndRAF = (single: boolean) => {
if(rAF) window.cancelAnimationFrame(rAF);
rAF = window.requestAnimationFrame(single ? onResizeEnd : () => {
rAF = window.requestAnimationFrame(onResizeEnd);
//this.log('resize after RAF', part);
});
};
// @ts-ignore
const resizeObserver = new ResizeObserver((entries) => {
if(skip) {
setEndRAF(false);
return;
}
const entry = entries[0];
const height = entry.contentRect.height;/* Math.ceil(entry.contentRect.height); */
if(!wasHeight) {
wasHeight = height;
return;
}
const realDiff = wasHeight - height;
let diff = realDiff + part;
const _part = diff % 1;
diff -= _part;
if(!resizing) {
resizing = true;
//this.log('resize start', realDiff, this.scrollable.isScrolledDown);
if(realDiff < 0 && this.scrollable.isScrolledDown) {
skip = true;
setEndRAF(false);
return;
}
}
scrolled += diff;
//this.log('resize', wasHeight - height, diff, this.scrollable.container.offsetHeight, this.scrollable.isScrolledDown, height, wasHeight/* , entry */);
if(diff) {
const needScrollTop = this.scrollable.scrollTop + diff;
this.scrollable.scrollTop = needScrollTop;
/* if(rAF) window.cancelAnimationFrame(rAF);
rAF = window.requestAnimationFrame(() => {
this.scrollable.scrollTop = needScrollTop;
setEndRAF(true);
//this.log('resize after RAF', part);
}); */
} //else {
setEndRAF(false);
//}
part = _part;
wasHeight = height;
});
resizeObserver.observe(this.bubblesContainer);
}
} }
public constructPinnedHelpers() { public constructPinnedHelpers() {
@ -2429,12 +2516,12 @@ export default class ChatBubbles {
} */ } */
// touchSupport for safari iOS // touchSupport for safari iOS
isTouchSupported && isApple && (this.scrollable.container.style.overflow = 'hidden'); //isTouchSupported && isApple && (this.scrollable.container.style.overflow = 'hidden');
this.scrollable.scrollTop = newScrollTop; this.scrollable.scrollTop = newScrollTop;
//this.scrollable.scrollTop = this.scrollable.scrollHeight; //this.scrollable.scrollTop = this.scrollable.scrollHeight;
isTouchSupported && isApple && (this.scrollable.container.style.overflow = ''); //isTouchSupported && isApple && (this.scrollable.container.style.overflow = '');
if(isSafari && !isAppleMobile) { // * fix blinking and jumping if(isSafari/* && !isAppleMobile */) { // * fix blinking and jumping
this.scrollable.container.style.display = 'none'; this.scrollable.container.style.display = 'none';
void this.scrollable.container.offsetLeft; // reflow void this.scrollable.container.offsetLeft; // reflow
this.scrollable.container.style.display = ''; this.scrollable.container.style.display = '';
@ -2667,8 +2754,8 @@ export default class ChatBubbles {
const bottomIds = isAdditionRender ? [] : sortedMids.slice(0, sortedMids.findIndex(mid => targetMid >= mid)).reverse(); const bottomIds = isAdditionRender ? [] : sortedMids.slice(0, sortedMids.findIndex(mid => targetMid >= mid)).reverse();
this.log('getHistory: targeting mid:', targetMid, maxId, additionMsgId, this.log('getHistory: targeting mid:', targetMid, maxId, additionMsgId,
topIds.map(m => this.appMessagesManager.getLocalMessageId(m)), topIds.map(m => this.appMessagesManager.getServerMessageId(m)),
bottomIds.map(m => this.appMessagesManager.getLocalMessageId(m))); bottomIds.map(m => this.appMessagesManager.getServerMessageId(m)));
const setBubbles: HTMLElement[] = []; const setBubbles: HTMLElement[] = [];
@ -2839,6 +2926,10 @@ export default class ChatBubbles {
} }
public setUnreadDelimiter() { public setUnreadDelimiter() {
if(!(this.chat.type === 'chat' || this.chat.type === 'discussion')) {
return;
}
if(this.attachedUnreadBubble) { if(this.attachedUnreadBubble) {
return; return;
} }

153
src/components/chat/input.ts

@ -13,7 +13,7 @@ import apiManager from "../../lib/mtproto/mtprotoworker";
//import Recorder from '../opus-recorder/dist/recorder.min'; //import Recorder from '../opus-recorder/dist/recorder.min';
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, isSendShortcutPressed } from "../../helpers/dom"; import { attachClickEvent, blurActiveElement, cancelEvent, cancelSelection, findUpClassName, getRichValue, getSelectedNodes, isInputEmpty, markdownTags, MarkdownType, placeCaretAtEnd, isSendShortcutPressed, fixSafariStickyInput } from "../../helpers/dom";
import { ButtonMenuItemOptions } from '../buttonMenu'; import { ButtonMenuItemOptions } from '../buttonMenu';
import emoticonsDropdown from "../emoticonsDropdown"; import emoticonsDropdown from "../emoticonsDropdown";
import PopupCreatePoll from "../popups/createPoll"; import PopupCreatePoll from "../popups/createPoll";
@ -36,6 +36,7 @@ import rootScope from '../../lib/rootScope';
import PopupPinMessage from '../popups/unpinMessage'; import PopupPinMessage from '../popups/unpinMessage';
import { debounce } from '../../helpers/schedulers'; import { debounce } from '../../helpers/schedulers';
import { tsNow } from '../../helpers/date'; import { tsNow } from '../../helpers/date';
import { isSafari } from '../../helpers/userAgent';
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.';
@ -88,9 +89,9 @@ export default class ChatInput {
private recordRippleEl: HTMLElement; private recordRippleEl: HTMLElement;
private recordStartTime = 0; private recordStartTime = 0;
private scrollTop = 0; // private scrollTop = 0;
private scrollOffsetTop = 0; // private scrollOffsetTop = 0;
private scrollDiff = 0; // private scrollDiff = 0;
public helperType: Exclude<ChatInputHelperType, 'webpage'>; public helperType: Exclude<ChatInputHelperType, 'webpage'>;
private helperFunc: () => void; private helperFunc: () => void;
@ -137,7 +138,7 @@ export default class ChatInput {
this.goDownUnreadBadge = document.createElement('span'); this.goDownUnreadBadge = document.createElement('span');
this.goDownUnreadBadge.classList.add('badge', 'badge-24', 'badge-green'); this.goDownUnreadBadge.classList.add('badge', 'badge-24', 'badge-green');
this.goDownBtn.append(this.goDownUnreadBadge); this.goDownBtn.append(this.goDownUnreadBadge);
this.chatInput.append(this.goDownBtn); this.inputContainer.append(this.goDownBtn);
attachClickEvent(this.goDownBtn, (e) => { attachClickEvent(this.goDownBtn, (e) => {
cancelEvent(e); cancelEvent(e);
@ -145,6 +146,71 @@ export default class ChatInput {
}, {listenerSetter: this.listenerSetter}); }, {listenerSetter: this.listenerSetter});
// * constructor end // * constructor end
/* let setScrollTopTimeout: number;
// @ts-ignore
let height = window.visualViewport.height; */
// @ts-ignore
// this.listenerSetter.add(window.visualViewport, 'resize', () => {
// const scrollable = this.chat.bubbles.scrollable;
// const wasScrolledDown = scrollable.isScrolledDown;
// /* if(wasScrolledDown) {
// this.saveScroll();
// } */
// // @ts-ignore
// let newHeight = window.visualViewport.height;
// const diff = height - newHeight;
// const scrollTop = scrollable.scrollTop;
// const needScrollTop = wasScrolledDown ? scrollable.scrollHeight : scrollTop + diff; // * wasScrolledDown это проверка для десктоп хрома, когда пропадает панель загрузок снизу
// console.log('resize before', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, wasScrolledDown, scrollable.lastScrollTop, diff, needScrollTop);
// scrollable.scrollTop = needScrollTop;
// if(setScrollTopTimeout) clearTimeout(setScrollTopTimeout);
// setScrollTopTimeout = window.setTimeout(() => {
// const diff = height - newHeight;
// const isScrolledDown = scrollable.scrollHeight - Math.round(scrollable.scrollTop + scrollable.container.offsetHeight + diff) <= 1;
// height = newHeight;
// scrollable.scrollTop = needScrollTop;
// console.log('resize after', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, scrollable.isScrolledDown, scrollable.lastScrollTop, isScrolledDown);
// /* if(isScrolledDown) {
// scrollable.scrollTop = scrollable.scrollHeight;
// } */
// //scrollable.scrollTop += diff;
// setScrollTopTimeout = 0;
// }, 0);
// });
// ! Can't use it with resizeObserver
/* this.listenerSetter.add(window.visualViewport, 'resize', () => {
const scrollable = this.chat.bubbles.scrollable;
const wasScrolledDown = scrollable.isScrolledDown;
// @ts-ignore
let newHeight = window.visualViewport.height;
const diff = height - newHeight;
const needScrollTop = wasScrolledDown ? scrollable.scrollHeight : scrollable.scrollTop + diff; // * wasScrolledDown это проверка для десктоп хрома, когда пропадает панель загрузок снизу
//console.log('resize before', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, wasScrolledDown, scrollable.lastScrollTop, diff, needScrollTop);
scrollable.scrollTop = needScrollTop;
height = newHeight;
if(setScrollTopTimeout) clearTimeout(setScrollTopTimeout);
setScrollTopTimeout = window.setTimeout(() => { // * try again for scrolled down Android Chrome
scrollable.scrollTop = needScrollTop;
//console.log('resize after', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, scrollable.isScrolledDown, scrollable.lastScrollTop, isScrolledDown);
setScrollTopTimeout = 0;
}, 0);
}); */
} }
public constructPeerHelpers() { public constructPeerHelpers() {
@ -650,13 +716,19 @@ export default class ChatInput {
if(isTouchSupported) { if(isTouchSupported) {
attachClickEvent(this.messageInput, (e) => { attachClickEvent(this.messageInput, (e) => {
this.appImManager.selectTab(1); // * set chat tab for album orientation this.appImManager.selectTab(1); // * set chat tab for album orientation
this.saveScroll(); //this.saveScroll();
emoticonsDropdown.toggle(false); emoticonsDropdown.toggle(false);
}, {listenerSetter: this.listenerSetter}); }, {listenerSetter: this.listenerSetter});
this.listenerSetter.add(window, 'resize', () => { /* this.listenerSetter.add(window, 'resize', () => {
this.restoreScroll(); this.restoreScroll();
}); }); */
/* if(isSafari) {
this.listenerSetter.add(this.messageInput, 'focusin', () => {
fixSafariStickyInput(this.messageInput);
});
} */
} }
/* this.listenerSetter.add(this.messageInput, 'beforeinput', (e: Event) => { /* this.listenerSetter.add(this.messageInput, 'beforeinput', (e: Event) => {
@ -673,6 +745,14 @@ export default class ChatInput {
} }
}); */ }); */
this.listenerSetter.add(this.messageInput, 'input', this.onMessageInput); this.listenerSetter.add(this.messageInput, 'input', this.onMessageInput);
if(this.chat.type === 'chat' || this.chat.type === 'discussion') {
this.listenerSetter.add(this.messageInput, 'focusin', () => {
if(this.chat.bubbles.scrolledAllDown) {
this.appMessagesManager.readAllHistory(this.chat.peerId, this.chat.threadId);
}
});
}
} }
private prepareDocumentExecute = () => { private prepareDocumentExecute = () => {
@ -1170,10 +1250,7 @@ export default class ChatInput {
public onMessageSent(clearInput = true, clearReply?: boolean) { public onMessageSent(clearInput = true, clearReply?: boolean) {
if(this.chat.type !== 'scheduled') { if(this.chat.type !== 'scheduled') {
const historyStorage = this.appMessagesManager.getHistoryStorage(this.chat.peerId, this.chat.threadId); this.appMessagesManager.readAllHistory(this.chat.peerId, this.chat.threadId, true);
if(historyStorage.maxId) {
this.appMessagesManager.readHistory(this.chat.peerId, historyStorage.maxId, this.chat.threadId); // lol
}
} }
this.scheduleDate = undefined; this.scheduleDate = undefined;
@ -1407,30 +1484,30 @@ export default class ChatInput {
}, 0); }, 0);
} }
public saveScroll() { // public saveScroll() {
this.scrollTop = this.chat.bubbles.scrollable.container.scrollTop; // this.scrollTop = this.chat.bubbles.scrollable.container.scrollTop;
this.scrollOffsetTop = this.chatInput.offsetTop; // this.scrollOffsetTop = this.chatInput.offsetTop;
} // }
public restoreScroll() { // public restoreScroll() {
if(this.chatInput.style.display) return; // if(this.chatInput.style.display) return;
//console.log('input resize', offsetTop, this.chatInput.offsetTop); // //console.log('input resize', offsetTop, this.chatInput.offsetTop);
let newOffsetTop = this.chatInput.offsetTop; // let newOffsetTop = this.chatInput.offsetTop;
let container = this.chat.bubbles.scrollable.container; // let container = this.chat.bubbles.scrollable.container;
let scrollTop = container.scrollTop; // let scrollTop = container.scrollTop;
let clientHeight = container.clientHeight; // let clientHeight = container.clientHeight;
let maxScrollTop = container.scrollHeight; // let maxScrollTop = container.scrollHeight;
if(newOffsetTop < this.scrollOffsetTop) { // if(newOffsetTop < this.scrollOffsetTop) {
this.scrollDiff = this.scrollOffsetTop - newOffsetTop; // this.scrollDiff = this.scrollOffsetTop - newOffsetTop;
container.scrollTop += this.scrollDiff; // container.scrollTop += this.scrollDiff;
} else if(scrollTop != this.scrollTop) { // } else if(scrollTop != this.scrollTop) {
let endDiff = maxScrollTop - (scrollTop + clientHeight); // let endDiff = maxScrollTop - (scrollTop + clientHeight);
if(endDiff < this.scrollDiff/* && false */) { // if(endDiff < this.scrollDiff/* && false */) {
//container.scrollTop -= endDiff; // //container.scrollTop -= endDiff;
} else { // } else {
container.scrollTop -= this.scrollDiff; // container.scrollTop -= this.scrollDiff;
} // }
} // }
} // }
} }

1
src/components/chat/pinnedContainer.ts

@ -61,6 +61,7 @@ export default class PinnedContainer {
} }
this.divAndCaption.container.classList.toggle('is-floating', mediaSizes.isMobile); this.divAndCaption.container.classList.toggle('is-floating', mediaSizes.isMobile);
this.topbar.container.classList.toggle('is-pinned-floating', mediaSizes.isMobile);
const scrollable = this.chat.bubbles.scrollable; const scrollable = this.chat.bubbles.scrollable;

5
src/components/chat/pinnedMessage.ts

@ -550,11 +550,6 @@ export default class ChatPinnedMessage {
} }
} }
public onChangeScreen(from: ScreenSize, to: ScreenSize) {
this.pinnedMessageContainer.divAndCaption.container.classList.toggle('is-floating', to == ScreenSize.mobile
/* || (!this.chatAudio.divAndCaption.container.classList.contains('hide') && to == ScreenSize.medium) */);
}
public _setPinnedMessage() { public _setPinnedMessage() {
/////this.log('setting pinned message', message); /////this.log('setting pinned message', message);
//return; //return;

3
src/components/chat/topbar.ts

@ -328,8 +328,9 @@ export default class ChatTopbar {
}; };
private onChangeScreen = (from: ScreenSize, to: ScreenSize) => { private onChangeScreen = (from: ScreenSize, to: ScreenSize) => {
this.container.classList.toggle('is-pinned-floating', mediaSizes.isMobile);
this.chatAudio && this.chatAudio.divAndCaption.container.classList.toggle('is-floating', to == ScreenSize.mobile); this.chatAudio && this.chatAudio.divAndCaption.container.classList.toggle('is-floating', to == ScreenSize.mobile);
this.pinnedMessage && this.pinnedMessage.onChangeScreen(from, to); this.pinnedMessage && this.pinnedMessage.pinnedMessageContainer.divAndCaption.container.classList.toggle('is-floating', to == ScreenSize.mobile);
this.setUtilsWidth(true); this.setUtilsWidth(true);
}; };

25
src/components/emoticonsDropdown/index.ts

@ -3,7 +3,7 @@ import appChatsManager from "../../lib/appManagers/appChatsManager";
import appImManager from "../../lib/appManagers/appImManager"; import appImManager from "../../lib/appManagers/appImManager";
import { MOUNT_CLASS_TO } from "../../lib/mtproto/mtproto_config"; import { MOUNT_CLASS_TO } from "../../lib/mtproto/mtproto_config";
import rootScope from "../../lib/rootScope"; import rootScope from "../../lib/rootScope";
import { findUpClassName, findUpTag, whichChild } from "../../helpers/dom"; import { blurActiveElement, findUpClassName, findUpTag, whichChild } from "../../helpers/dom";
import animationIntersector from "../animationIntersector"; import animationIntersector from "../animationIntersector";
import { horizontalMenu } from "../horizontalMenu"; import { horizontalMenu } from "../horizontalMenu";
import LazyLoadQueue, { LazyLoadQueueIntersector } from "../lazyLoadQueue"; import LazyLoadQueue, { LazyLoadQueueIntersector } from "../lazyLoadQueue";
@ -219,10 +219,10 @@ export class EmoticonsDropdown {
if(isTouchSupported) { if(isTouchSupported) {
if(willBeActive) { if(willBeActive) {
appImManager.chat.input.saveScroll(); //appImManager.chat.input.saveScroll();
// @ts-ignore if(blurActiveElement()) {
document.activeElement.blur(); await pause(100);
await pause(100); }
} }
} }
@ -253,6 +253,13 @@ export class EmoticonsDropdown {
this.events.onOpenAfter.forEach(cb => cb()); this.events.onOpenAfter.forEach(cb => cb());
}, isTouchSupported ? 0 : 200); }, isTouchSupported ? 0 : 200);
// ! can't use together with resizeObserver
/* if(isTouchSupported) {
const height = this.element.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;
console.log('[ESG]: toggle: enable height', height);
appImManager.chat.bubbles.scrollable.scrollTop += height;
} */
/* if(touchSupport) { /* if(touchSupport) {
this.restoreScroll(); this.restoreScroll();
} */ } */
@ -283,6 +290,14 @@ export class EmoticonsDropdown {
this.events.onCloseAfter.forEach(cb => cb()); this.events.onCloseAfter.forEach(cb => cb());
}, isTouchSupported ? 0 : 200); }, isTouchSupported ? 0 : 200);
/* if(isTouchSupported) {
const scrollHeight = this.container.scrollHeight;
if(scrollHeight) {
const height = this.container.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;
appImManager.chat.bubbles.scrollable.scrollTop -= height;
}
} */
/* if(touchSupport) { /* if(touchSupport) {
this.restoreScroll(); this.restoreScroll();
} */ } */

6
src/components/sidebarLeft/tabs/editFolder.ts

@ -24,7 +24,6 @@ export default class AppEditFolderTab extends SliderSuperTab {
private confirmBtn: HTMLElement; private confirmBtn: HTMLElement;
private menuBtn: HTMLElement; private menuBtn: HTMLElement;
private nameInput: HTMLElement;
private nameInputField: InputField; private nameInputField: InputField;
private include_peers: HTMLElement; private include_peers: HTMLElement;
@ -49,7 +48,7 @@ export default class AppEditFolderTab extends SliderSuperTab {
this.stickerContainer = document.createElement('div'); this.stickerContainer = document.createElement('div');
this.stickerContainer.classList.add('sticker-container'); this.stickerContainer.classList.add('sticker-container');
this.confirmBtn = ButtonIcon('check1 btn-confirm hide'); this.confirmBtn = ButtonIcon('check btn-confirm hide blue');
const deleteFolderButton: ButtonMenuItemOptions = { const deleteFolderButton: ButtonMenuItemOptions = {
icon: 'delete danger', icon: 'delete danger',
text: 'Delete Folder', text: 'Delete Folder',
@ -76,7 +75,6 @@ export default class AppEditFolderTab extends SliderSuperTab {
label: 'Folder Name', label: 'Folder Name',
maxLength: MAX_FOLDER_NAME_LENGTH maxLength: MAX_FOLDER_NAME_LENGTH
}); });
this.nameInput = this.nameInputField.input;
inputWrapper.append(this.nameInputField.container); inputWrapper.append(this.nameInputField.container);
@ -220,7 +218,7 @@ export default class AppEditFolderTab extends SliderSuperTab {
}); });
}); });
this.nameInput.addEventListener('input', () => { this.nameInputField.input.addEventListener('input', () => {
this.filter.title = this.nameInputField.value; this.filter.title = this.nameInputField.value;
this.editCheckForChange(); this.editCheckForChange();
}); });

5
src/components/sidebarLeft/tabs/editProfile.ts

@ -6,10 +6,9 @@ import RichTextProcessor from "../../../lib/richtextprocessor";
import rootScope from "../../../lib/rootScope"; import rootScope from "../../../lib/rootScope";
import AvatarElement from "../../avatar"; import AvatarElement from "../../avatar";
import InputField from "../../inputField"; import InputField from "../../inputField";
import Scrollable from "../../scrollable";
import SidebarSlider, { SliderSuperTab } from "../../slider"; import SidebarSlider, { SliderSuperTab } from "../../slider";
import AvatarEdit from "../../avatarEdit"; import AvatarEdit from "../../avatarEdit";
import ButtonIcon from "../../buttonIcon"; import Button from "../../button";
// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист) // TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист)
@ -48,7 +47,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
this.container.classList.add('edit-profile-container'); this.container.classList.add('edit-profile-container');
this.title.innerText = 'Edit Profile'; this.title.innerText = 'Edit Profile';
//this.scrollWrapper = this.container.querySelector('.scroll-wrapper'); //this.scrollWrapper = this.container.querySelector('.scroll-wrapper');
this.nextBtn = ButtonIcon('check btn-circle btn-corner'); this.nextBtn = Button('btn-circle btn-corner tgico-check');
this.content.append(this.nextBtn); this.content.append(this.nextBtn);
this.avatarElem = document.createElement('avatar-element') as AvatarElement; this.avatarElem = document.createElement('avatar-element') as AvatarElement;

3
src/components/sidebarLeft/tabs/includedChats.ts

@ -8,7 +8,6 @@ import { MyDialogFilter as DialogFilter } from "../../../lib/storages/filters";
import rootScope from "../../../lib/rootScope"; import rootScope from "../../../lib/rootScope";
import { copy } from "../../../helpers/object"; import { copy } from "../../../helpers/object";
import ButtonIcon from "../../buttonIcon"; import ButtonIcon from "../../buttonIcon";
import { FocusDirection } from "../../../helpers/fastSmoothScroll";
import { fastRaf } from "../../../helpers/schedulers"; import { fastRaf } from "../../../helpers/schedulers";
import CheckboxField from "../../checkbox"; import CheckboxField from "../../checkbox";
import Button from "../../button"; import Button from "../../button";
@ -28,7 +27,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
init() { init() {
this.content.remove(); this.content.remove();
this.container.classList.add('included-chatlist-container'); this.container.classList.add('included-chatlist-container');
this.confirmBtn = ButtonIcon('check1 btn-confirm', {noRipple: true}); this.confirmBtn = ButtonIcon('check btn-confirm blue', {noRipple: true});
this.confirmBtn.style.display = 'none'; this.confirmBtn.style.display = 'none';
this.header.append(this.confirmBtn); this.header.append(this.confirmBtn);

8
src/components/wrappers.ts

@ -116,6 +116,8 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
//video.muted = true; //video.muted = true;
const globalVideo = appMediaPlaybackController.addMedia(message.peerId, doc, message.mid); const globalVideo = appMediaPlaybackController.addMedia(message.peerId, doc, message.mid);
video.classList.add('z-depth-1');
video.addEventListener('canplay', () => { video.addEventListener('canplay', () => {
if(globalVideo.currentTime > 0) { if(globalVideo.currentTime > 0) {
video.currentTime = globalVideo.currentTime; video.currentTime = globalVideo.currentTime;
@ -350,7 +352,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
const uploading = message.pFlags.is_outgoing; const uploading = message.pFlags.is_outgoing;
const doc = message.media.document || message.media.webpage.document; const doc = (message.media.document || message.media.webpage.document) as MyDocument;
if(doc.type === 'audio' || doc.type === 'voice') { if(doc.type === 'audio' || doc.type === 'voice') {
const audioElement = new AudioElement(); const audioElement = new AudioElement();
audioElement.setAttribute('message-id', '' + message.mid); audioElement.setAttribute('message-id', '' + message.mid);
@ -458,6 +460,10 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
attachClickEvent(docDiv, (e) => { attachClickEvent(docDiv, (e) => {
preloader.onClick(e); preloader.onClick(e);
}); });
/* if(doc.downloaded) {
downloadDiv.classList.add('downloaded');
} */
} else if(message.media?.preloader) { } else if(message.media?.preloader) {
const icoDiv = docDiv.querySelector('.document-ico'); const icoDiv = docDiv.querySelector('.document-ico');
message.media.preloader.attach(icoDiv, false); message.media.preloader.attach(icoDiv, false);

29
src/helpers/dom.ts

@ -3,7 +3,7 @@ import { MOUNT_CLASS_TO } from "../lib/mtproto/mtproto_config";
import RichTextProcessor from "../lib/richtextprocessor"; import RichTextProcessor from "../lib/richtextprocessor";
import ListenerSetter from "./listenerSetter"; import ListenerSetter from "./listenerSetter";
import { isTouchSupported } from "./touchSupport"; import { isTouchSupported } from "./touchSupport";
import { isSafari, isApple } from "./userAgent"; import { isApple } from "./userAgent";
import rootScope from "../lib/rootScope"; import rootScope from "../lib/rootScope";
/* export function isInDOM(element: Element, parentNode?: HTMLElement): boolean { /* export function isInDOM(element: Element, parentNode?: HTMLElement): boolean {
@ -54,6 +54,10 @@ export function cancelEvent(event: Event) {
} }
export function placeCaretAtEnd(el: HTMLElement) { export function placeCaretAtEnd(el: HTMLElement) {
if(isTouchSupported) {
return;
}
el.focus(); el.focus();
if(typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { if(typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
var range = document.createRange(); var range = document.createRange();
@ -486,7 +490,30 @@ export function getSelectedText(): string {
export function blurActiveElement() { export function blurActiveElement() {
if(document.activeElement && (document.activeElement as HTMLInputElement).blur) { if(document.activeElement && (document.activeElement as HTMLInputElement).blur) {
(document.activeElement as HTMLInputElement).blur(); (document.activeElement as HTMLInputElement).blur();
return true;
} }
return false;
}
export function fixSafariStickyInput(input: HTMLElement) {
input.style.transform = 'translateY(-99999px)';
/* input.style.position = 'fixed';
input.style.top = '-99999px';
input.style.left = '0'; */
input.focus();
setTimeout(() => {
//fastSmoothScroll(findUpClassName(input, 'scrollable-y') || window as any, document.activeElement as HTMLElement, 'start', 4, undefined, FocusDirection.Static);
/* input.style.position = '';
input.style.top = ''; */
input.style.transform = '';
//fastSmoothScroll(findUpClassName(input, 'scrollable-y') || window as any, document.activeElement as HTMLElement, 'start', 4, undefined, FocusDirection.Static);
/* setTimeout(() => {
fastSmoothScroll(findUpClassName(input, 'scrollable-y') || window as any, document.activeElement as HTMLElement, 'start', 4);
}, 50); */
}, 0);
} }
export const CLICK_EVENT_NAME: 'mousedown' | 'touchend' | 'click' = (isTouchSupported ? 'mousedown' : 'click') as any; export const CLICK_EVENT_NAME: 'mousedown' | 'touchend' | 'click' = (isTouchSupported ? 'mousedown' : 'click') as any;

4
src/helpers/fastSmoothScroll.ts

@ -43,7 +43,7 @@ export default function fastSmoothScroll(
return Promise.resolve(); */ return Promise.resolve(); */
} }
if(axis === 'y' && isInDOM(element)) { if(axis === 'y' && isInDOM(element) && container.getBoundingClientRect) {
const elementRect = element.getBoundingClientRect(); const elementRect = element.getBoundingClientRect();
const containerRect = container.getBoundingClientRect(); const containerRect = container.getBoundingClientRect();
@ -102,7 +102,7 @@ function scrollWithJs(
//const { offsetTop: elementTop, offsetHeight: elementHeight } = element; //const { offsetTop: elementTop, offsetHeight: elementHeight } = element;
const elementRect = element.getBoundingClientRect(); const elementRect = element.getBoundingClientRect();
const containerRect = container.getBoundingClientRect(); const containerRect = container.getBoundingClientRect ? container.getBoundingClientRect() : document.body.getBoundingClientRect();
//const transformable = container.firstElementChild as HTMLElement; //const transformable = container.firstElementChild as HTMLElement;

23
src/helpers/mediaSizes.ts

@ -42,7 +42,10 @@ class MediaSizes extends EventListenerBase<{
width: 293, width: 293,
height: 0 height: 0
}, },
esgSticker: {} esgSticker: {
width: 68,
height: 68
}
}, },
desktop: { desktop: {
regular: { regular: {
@ -57,18 +60,28 @@ class MediaSizes extends EventListenerBase<{
width: 451, width: 451,
height: 0 height: 0
}, },
esgSticker: {} esgSticker: {
width: 80,
height: 80
}
} }
}; };
public isMobile = false; public isMobile = false;
public active: Sizes; public active: Sizes;
public activeScreen: ScreenSize; public activeScreen: ScreenSize;
public rAF: number;
constructor() { constructor() {
super(); super();
window.addEventListener('resize', this.handleResize); window.addEventListener('resize', () => {
if(this.rAF) window.cancelAnimationFrame(this.rAF);
this.rAF = window.requestAnimationFrame(() => {
this.handleResize();
this.rAF = 0;
});
});
this.handleResize(); this.handleResize();
} }
@ -90,8 +103,8 @@ class MediaSizes extends EventListenerBase<{
this.active = this.isMobile ? this.sizes.handhelds : this.sizes.desktop; this.active = this.isMobile ? this.sizes.handhelds : this.sizes.desktop;
//console.time('esg'); //console.time('esg');
const computedStyle = window.getComputedStyle(document.documentElement); //const computedStyle = window.getComputedStyle(document.documentElement);
this.active.esgSticker.width = parseFloat(computedStyle.getPropertyValue('--esg-sticker-size')); //this.active.esgSticker.width = parseFloat(computedStyle.getPropertyValue('--esg-sticker-size'));
//console.timeEnd('esg'); //console.timeEnd('esg');
if(wasScreen != activeScreen) { if(wasScreen != activeScreen) {

3
src/lib/appManagers/AppInlineBotsManager.ts

@ -6,6 +6,7 @@ import { RichTextProcessor } from "../richtextprocessor";
import appDocsManager from "./appDocsManager"; import appDocsManager from "./appDocsManager";
import appPhotosManager from "./appPhotosManager"; import appPhotosManager from "./appPhotosManager";
import appUsersManager from "./appUsersManager"; import appUsersManager from "./appUsersManager";
import appMessagesManager from "./appMessagesManager";
export class AppInlineBotsManager { export class AppInlineBotsManager {
private inlineResults: {[qId: string]: BotInlineResult} = {}; private inlineResults: {[qId: string]: BotInlineResult} = {};
@ -271,7 +272,7 @@ export class AppInlineBotsManager {
public callbackButtonClick(peerId: number, mid: number, button: any) { public callbackButtonClick(peerId: number, mid: number, button: any) {
return apiManagerProxy.invokeApi('messages.getBotCallbackAnswer', { return apiManagerProxy.invokeApi('messages.getBotCallbackAnswer', {
peer: appPeersManager.getInputPeerById(peerId), peer: appPeersManager.getInputPeerById(peerId),
msg_id: mid, msg_id: appMessagesManager.getServerMessageId(mid),
data: button.data data: button.data
}, {timeout: 1, stopTime: -1, noErrorBox: true}).then((callbackAnswer) => { }, {timeout: 1, stopTime: -1, noErrorBox: true}).then((callbackAnswer) => {
if(typeof callbackAnswer.message === 'string' && callbackAnswer.message.length) { if(typeof callbackAnswer.message === 'string' && callbackAnswer.message.length) {

2
src/lib/appManagers/appDraftsManager.ts

@ -189,7 +189,7 @@ export class AppDraftsManager {
let entities: MessageEntity[] = localDraft.entities; let entities: MessageEntity[] = localDraft.entities;
if(localDraft.reply_to_msg_id) { if(localDraft.reply_to_msg_id) {
params.reply_to_msg_id = appMessagesManager.getLocalMessageId(localDraft.reply_to_msg_id); params.reply_to_msg_id = appMessagesManager.getServerMessageId(localDraft.reply_to_msg_id);
} }
if(entities?.length) { if(entities?.length) {

4
src/lib/appManagers/appImManager.ts

@ -258,7 +258,7 @@ export class AppImManager {
} }
} }
if(chat.input.messageInput && e.target !== chat.input.messageInput && target.tagName !== 'INPUT' && !target.hasAttribute('contenteditable')) { if(chat.input.messageInput && e.target !== chat.input.messageInput && target.tagName !== 'INPUT' && !target.hasAttribute('contenteditable') && !isTouchSupported) {
chat.input.messageInput.focus(); chat.input.messageInput.focus();
placeCaretAtEnd(chat.input.messageInput); placeCaretAtEnd(chat.input.messageInput);
} }
@ -455,6 +455,8 @@ export class AppImManager {
document.body.classList.remove(RIGHT_COLUMN_ACTIVE_CLASSNAME); document.body.classList.remove(RIGHT_COLUMN_ACTIVE_CLASSNAME);
} }
rootScope.broadcast('im_tab_change', id);
//this._selectTab(id, mediaSizes.isMobile); //this._selectTab(id, mediaSizes.isMobile);
//document.body.classList.toggle(RIGHT_COLUMN_ACTIVE_CLASSNAME, id == 2); //document.body.classList.toggle(RIGHT_COLUMN_ACTIVE_CLASSNAME, id == 2);
} }

55
src/lib/appManagers/appMessagesManager.ts

@ -451,7 +451,7 @@ export class AppMessagesManager {
const messageId = this.generateTempMessageId(peerId); const messageId = this.generateTempMessageId(peerId);
const randomIdS = randomLong(); const randomIdS = randomLong();
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined; const replyToMsgId = options.replyToMsgId ? this.getServerMessageId(options.replyToMsgId) : undefined;
const isChannel = appPeersManager.isChannel(peerId); const isChannel = appPeersManager.isChannel(peerId);
const isBroadcast = appPeersManager.isBroadcast(peerId); const isBroadcast = appPeersManager.isBroadcast(peerId);
@ -607,7 +607,7 @@ export class AppMessagesManager {
const messageId = this.generateTempMessageId(peerId); const messageId = this.generateTempMessageId(peerId);
const randomIdS = randomLong(); const randomIdS = randomLong();
const pFlags = this.generateFlags(peerId); const pFlags = this.generateFlags(peerId);
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined; const replyToMsgId = options.replyToMsgId ? this.getServerMessageId(options.replyToMsgId) : undefined;
const isChannel = appPeersManager.isChannel(peerId); const isChannel = appPeersManager.isChannel(peerId);
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId); const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
const asChannel = !!(isChannel && !isMegagroup); const asChannel = !!(isChannel && !isMegagroup);
@ -1004,7 +1004,7 @@ export class AppMessagesManager {
} }
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId; peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined; const replyToMsgId = options.replyToMsgId ? this.getServerMessageId(options.replyToMsgId) : undefined;
let caption = options.caption || ''; let caption = options.caption || '';
let entities = options.entities || []; let entities = options.entities || [];
@ -1155,7 +1155,7 @@ export class AppMessagesManager {
//this.checkSendOptions(options); //this.checkSendOptions(options);
const messageId = this.generateTempMessageId(peerId); const messageId = this.generateTempMessageId(peerId);
const randomIdS = randomLong(); const randomIdS = randomLong();
const replyToMsgId = options.replyToMsgId ? this.getLocalMessageId(options.replyToMsgId) : undefined; const replyToMsgId = options.replyToMsgId ? this.getServerMessageId(options.replyToMsgId) : undefined;
const isChannel = appPeersManager.isChannel(peerId); const isChannel = appPeersManager.isChannel(peerId);
const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId); const isMegagroup = isChannel && appPeersManager.isMegagroup(peerId);
const asChannel = isChannel && !isMegagroup ? true : false; const asChannel = isChannel && !isMegagroup ? true : false;
@ -1639,7 +1639,7 @@ export class AppMessagesManager {
// ! это может случиться, если запрос идёт не по папке 0, а по 1. почему-то read'ов нет // ! это может случиться, если запрос идёт не по папке 0, а по 1. почему-то read'ов нет
// ! в итоге, чтобы получить 1 диалог, делается первый запрос по папке 0, потом запрос для архивных по папке 1, и потом ещё перезагрузка архивного диалога // ! в итоге, чтобы получить 1 диалог, делается первый запрос по папке 0, потом запрос для архивных по папке 1, и потом ещё перезагрузка архивного диалога
if(!this.getLocalMessageId(dialog.read_inbox_max_id) && !this.getLocalMessageId(dialog.read_outbox_max_id)) { if(!this.getServerMessageId(dialog.read_inbox_max_id) && !this.getServerMessageId(dialog.read_outbox_max_id)) {
noIdsDialogs[dialog.peerId] = dialog; noIdsDialogs[dialog.peerId] = dialog;
this.log.error('noIdsDialogs', dialog); this.log.error('noIdsDialogs', dialog);
@ -1692,7 +1692,7 @@ export class AppMessagesManager {
scheduleDate: number scheduleDate: number
}> = {}) { }> = {}) {
peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId; peerId = appPeersManager.getPeerMigratedTo(peerId) || peerId;
msgIds = msgIds.slice().sort((a, b) => a - b).map(mid => this.getLocalMessageId(mid)); msgIds = msgIds.slice().sort((a, b) => a - b).map(mid => this.getServerMessageId(mid));
const randomIds: string[] = msgIds.map(() => randomLong()); const randomIds: string[] = msgIds.map(() => randomLong());
@ -1911,7 +1911,7 @@ export class AppMessagesManager {
unpin, unpin,
silent, silent,
pm_oneside: oneSide, pm_oneside: oneSide,
id: this.getLocalMessageId(mid) id: this.getServerMessageId(mid)
}).then(updates => { }).then(updates => {
//this.log('pinned updates:', updates); //this.log('pinned updates:', updates);
apiUpdatesManager.processUpdateMessage(updates); apiUpdatesManager.processUpdateMessage(updates);
@ -2023,7 +2023,7 @@ export class AppMessagesManager {
/** /**
* * will ignore outgoing offset * * will ignore outgoing offset
*/ */
public getLocalMessageId(messageId: number) { public getServerMessageId(messageId: number) {
const q = AppMessagesManager.MESSAGE_ID_OFFSET; const q = AppMessagesManager.MESSAGE_ID_OFFSET;
if(messageId <= q) { if(messageId <= q) {
return messageId; return messageId;
@ -2039,7 +2039,7 @@ export class AppMessagesManager {
} }
public incrementMessageId(messageId: number, increment: number) { public incrementMessageId(messageId: number, increment: number) {
return this.generateMessageId(this.getLocalMessageId(messageId) + increment); return this.generateMessageId(this.getServerMessageId(messageId) + increment);
} }
public saveMessages(messages: any[], options: Partial<{ public saveMessages(messages: any[], options: Partial<{
@ -3109,12 +3109,12 @@ export class AppMessagesManager {
min_date: minDate, min_date: minDate,
max_date: maxDate, max_date: maxDate,
limit, limit,
offset_id: this.getLocalMessageId(maxId) || 0, offset_id: this.getServerMessageId(maxId) || 0,
add_offset: backLimit ? -backLimit : 0, add_offset: backLimit ? -backLimit : 0,
max_id: 0, max_id: 0,
min_id: 0, min_id: 0,
hash: 0, hash: 0,
top_msg_id: this.getLocalMessageId(threadId) || 0 top_msg_id: this.getServerMessageId(threadId) || 0
}, { }, {
//timeout: APITIMEOUT, //timeout: APITIMEOUT,
noErrorBox: true noErrorBox: true
@ -3223,7 +3223,7 @@ export class AppMessagesManager {
public getDiscussionMessage(peerId: number, mid: number) { public getDiscussionMessage(peerId: number, mid: number) {
return apiManager.invokeApi('messages.getDiscussionMessage', { return apiManager.invokeApi('messages.getDiscussionMessage', {
peer: appPeersManager.getInputPeerById(peerId), peer: appPeersManager.getInputPeerById(peerId),
msg_id: this.getLocalMessageId(mid) msg_id: this.getServerMessageId(mid)
}).then(result => { }).then(result => {
appChatsManager.saveApiChats(result.chats); appChatsManager.saveApiChats(result.chats);
appUsersManager.saveApiUsers(result.users); appUsersManager.saveApiUsers(result.users);
@ -3290,7 +3290,7 @@ export class AppMessagesManager {
public deleteMessages(peerId: number, mids: number[], revoke?: true) { public deleteMessages(peerId: number, mids: number[], revoke?: true) {
let promise: Promise<any>; let promise: Promise<any>;
const localMessageIds = mids.map(mid => this.getLocalMessageId(mid)); const localMessageIds = mids.map(mid => this.getServerMessageId(mid));
if(peerId < 0 && appPeersManager.isChannel(peerId)) { if(peerId < 0 && appPeersManager.isChannel(peerId)) {
const channelId = -peerId; const channelId = -peerId;
@ -3365,8 +3365,8 @@ export class AppMessagesManager {
if(!historyStorage.readPromise) { if(!historyStorage.readPromise) {
apiPromise = apiManager.invokeApi('messages.readDiscussion', { apiPromise = apiManager.invokeApi('messages.readDiscussion', {
peer: appPeersManager.getInputPeerById(peerId), peer: appPeersManager.getInputPeerById(peerId),
msg_id: this.getLocalMessageId(threadId), msg_id: this.getServerMessageId(threadId),
read_max_id: this.getLocalMessageId(maxId) read_max_id: this.getServerMessageId(maxId)
}); });
} }
@ -3383,7 +3383,7 @@ export class AppMessagesManager {
if(!historyStorage.readPromise) { if(!historyStorage.readPromise) {
apiPromise = apiManager.invokeApi('channels.readHistory', { apiPromise = apiManager.invokeApi('channels.readHistory', {
channel: appChatsManager.getChannelInput(-peerId), channel: appChatsManager.getChannelInput(-peerId),
max_id: this.getLocalMessageId(maxId) max_id: this.getServerMessageId(maxId)
}); });
} }
@ -3399,7 +3399,7 @@ export class AppMessagesManager {
if(!historyStorage.readPromise) { if(!historyStorage.readPromise) {
apiPromise = apiManager.invokeApi('messages.readHistory', { apiPromise = apiManager.invokeApi('messages.readHistory', {
peer: appPeersManager.getInputPeerById(peerId), peer: appPeersManager.getInputPeerById(peerId),
max_id: this.getLocalMessageId(maxId) max_id: this.getServerMessageId(maxId)
}).then((affectedMessages) => { }).then((affectedMessages) => {
apiUpdatesManager.processUpdateMessage({ apiUpdatesManager.processUpdateMessage({
_: 'updateShort', _: 'updateShort',
@ -3439,8 +3439,15 @@ export class AppMessagesManager {
return historyStorage.readPromise = apiPromise; return historyStorage.readPromise = apiPromise;
} }
public readAllHistory(peerId: number, threadId?: number, force = false) {
const historyStorage = this.getHistoryStorage(peerId, threadId);
if(historyStorage.maxId) {
this.readHistory(peerId, historyStorage.maxId, threadId, force); // lol
}
}
public readMessages(peerId: number, msgIds: number[]) { public readMessages(peerId: number, msgIds: number[]) {
msgIds = msgIds.map(mid => this.getLocalMessageId(mid)); msgIds = msgIds.map(mid => this.getServerMessageId(mid));
if(peerId < 0 && appPeersManager.isChannel(peerId)) { if(peerId < 0 && appPeersManager.isChannel(peerId)) {
const channelId = -peerId; const channelId = -peerId;
apiManager.invokeApi('channels.readMessageContents', { apiManager.invokeApi('channels.readMessageContents', {
@ -4394,7 +4401,7 @@ export class AppMessagesManager {
sessionStorage.set({max_seen_msg: maxId}); sessionStorage.set({max_seen_msg: maxId});
apiManager.invokeApi('messages.receivedMessages', { apiManager.invokeApi('messages.receivedMessages', {
max_id: this.getLocalMessageId(maxId) max_id: this.getServerMessageId(maxId)
}); });
} }
@ -4430,7 +4437,7 @@ export class AppMessagesManager {
public sendScheduledMessages(peerId: number, mids: number[]) { public sendScheduledMessages(peerId: number, mids: number[]) {
return apiManager.invokeApi('messages.sendScheduledMessages', { return apiManager.invokeApi('messages.sendScheduledMessages', {
peer: appPeersManager.getInputPeerById(peerId), peer: appPeersManager.getInputPeerById(peerId),
id: mids.map(mid => this.getLocalMessageId(mid)) id: mids.map(mid => this.getServerMessageId(mid))
}).then(updates => { }).then(updates => {
apiUpdatesManager.processUpdateMessage(updates); apiUpdatesManager.processUpdateMessage(updates);
}); });
@ -4439,7 +4446,7 @@ export class AppMessagesManager {
public deleteScheduledMessages(peerId: number, mids: number[]) { public deleteScheduledMessages(peerId: number, mids: number[]) {
return apiManager.invokeApi('messages.deleteScheduledMessages', { return apiManager.invokeApi('messages.deleteScheduledMessages', {
peer: appPeersManager.getInputPeerById(peerId), peer: appPeersManager.getInputPeerById(peerId),
id: mids.map(mid => this.getLocalMessageId(mid)) id: mids.map(mid => this.getServerMessageId(mid))
}).then(updates => { }).then(updates => {
apiUpdatesManager.processUpdateMessage(updates); apiUpdatesManager.processUpdateMessage(updates);
}); });
@ -4607,8 +4614,8 @@ export class AppMessagesManager {
const options = { const options = {
peer: appPeersManager.getInputPeerById(peerId), peer: appPeersManager.getInputPeerById(peerId),
msg_id: this.getLocalMessageId(threadId) || 0, msg_id: this.getServerMessageId(threadId) || 0,
offset_id: this.getLocalMessageId(maxId) || 0, offset_id: this.getServerMessageId(maxId) || 0,
offset_date: offsetDate, offset_date: offsetDate,
add_offset: offset, add_offset: offset,
limit, limit,
@ -4690,7 +4697,7 @@ export class AppMessagesManager {
const msgIds: InputMessage[] = mids.map((msgId: number) => { const msgIds: InputMessage[] = mids.map((msgId: number) => {
return { return {
_: 'inputMessageID', _: 'inputMessageID',
id: this.getLocalMessageId(msgId) id: this.getServerMessageId(msgId)
}; };
}); });

6
src/lib/appManagers/appPollsManager.ts

@ -185,7 +185,7 @@ export class AppPollsManager {
return apiManager.invokeApi('messages.sendVote', { return apiManager.invokeApi('messages.sendVote', {
peer: inputPeer, peer: inputPeer,
msg_id: appMessagesManager.getLocalMessageId(message.mid), msg_id: appMessagesManager.getServerMessageId(message.mid),
options options
}).then(updates => { }).then(updates => {
this.log('sendVote updates:', updates); this.log('sendVote updates:', updates);
@ -198,7 +198,7 @@ export class AppPollsManager {
return apiManager.invokeApi('messages.getPollResults', { return apiManager.invokeApi('messages.getPollResults', {
peer: inputPeer, peer: inputPeer,
msg_id: appMessagesManager.getLocalMessageId(message.mid) msg_id: appMessagesManager.getServerMessageId(message.mid)
}).then(updates => { }).then(updates => {
apiUpdatesManager.processUpdateMessage(updates); apiUpdatesManager.processUpdateMessage(updates);
this.log('getResults updates:', updates); this.log('getResults updates:', updates);
@ -208,7 +208,7 @@ export class AppPollsManager {
public getVotes(message: any, option?: Uint8Array, offset?: string, limit = 20) { public getVotes(message: any, option?: Uint8Array, offset?: string, limit = 20) {
return apiManager.invokeApi('messages.getPollVotes', { return apiManager.invokeApi('messages.getPollVotes', {
peer: appPeersManager.getInputPeerById(message.peerId), peer: appPeersManager.getInputPeerById(message.peerId),
id: appMessagesManager.getLocalMessageId(message.mid), id: appMessagesManager.getServerMessageId(message.mid),
option, option,
offset, offset,
limit limit

4
src/lib/richtextprocessor.ts

@ -584,10 +584,8 @@ namespace RichTextProcessor {
return ''; return '';
} }
let entities = (options.entities || []).slice();
return wrapRichText(text, { return wrapRichText(text, {
entities, entities: options.entities,
noLinks: true, noLinks: true,
wrappingDraft: true, wrappingDraft: true,
passEntities: { passEntities: {

5
src/lib/rootScope.ts

@ -82,7 +82,10 @@ type BroadcastEvents = {
'draft_updated': {peerId: number, threadId: number, draft: MyDraftMessage | undefined}, 'draft_updated': {peerId: number, threadId: number, draft: MyDraftMessage | undefined},
'event-heavy-animation-start': void, 'event-heavy-animation-start': void,
'event-heavy-animation-end': void 'event-heavy-animation-end': void,
'im_mount': void,
'im_tab_change': number
}; };
class RootScope extends EventListenerBase<any> { class RootScope extends EventListenerBase<any> {

4
src/pages/pageIm.ts

@ -9,6 +9,10 @@ let onFirstMount = () => {
// ! TOO SLOW // ! TOO SLOW
/* appStateManager.saveState(); */ /* appStateManager.saveState(); */
import('../lib/rootScope').then(m => {
m.default.broadcast('im_mount');
});
const promise = import('../lib/appManagers/appDialogsManager'); const promise = import('../lib/appManagers/appDialogsManager');
promise.finally(async() => { promise.finally(async() => {
//alert('pageIm!'); //alert('pageIm!');

101
src/scss/partials/_chat.scss

@ -11,6 +11,7 @@ $chat-helper-size: 39px;
.chat-input { .chat-input {
--translateY: 0; --translateY: 0;
--bottom: #{$chat-padding-handhelds};
display: flex; display: flex;
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
@ -38,6 +39,14 @@ $chat-helper-size: 39px;
max-width: var(--messages-container-width) !important; max-width: var(--messages-container-width) !important;
} }
@include respond-to(not-handhelds) {
--bottom: 21px;
}
@include respond-to(esg-bottom) {
--bottom: #{$chat-padding-handhelds};
}
@include respond-to(medium-screens) { @include respond-to(medium-screens) {
width: calc(100% - var(--right-column-width)) !important; width: calc(100% - var(--right-column-width)) !important;
//transition: transform var(--layer-transition); //transition: transform var(--layer-transition);
@ -69,19 +78,13 @@ $chat-helper-size: 39px;
padding: 0 var(--padding-horizontal); padding: 0 var(--padding-horizontal);
flex: 0 0 auto; flex: 0 0 auto;
position: relative; position: relative;
padding-bottom: var(--bottom);
@include respond-to(not-handhelds) { @include respond-to(not-handhelds) {
--padding-horizontal: #{$chat-padding}; --padding-horizontal: #{$chat-padding};
padding-bottom: 21px;
}
@include respond-to(handhelds) {
padding-bottom: $chat-padding-handhelds;
} }
@include respond-to(esg-bottom) { @include respond-to(esg-bottom) {
padding-bottom: $chat-padding-handhelds;
.btn-circle { .btn-circle {
height: $chat-input-handhelds-size; height: $chat-input-handhelds-size;
width: $chat-input-handhelds-size; width: $chat-input-handhelds-size;
@ -394,9 +397,13 @@ $chat-helper-size: 39px;
//max-width: 28.75rem; //max-width: 28.75rem;
} }
.reply-wrapper { /* .reply-wrapper {
transform: none !important; transform: none !important;
border-radius: inherit; border-radius: inherit;
} */
.reply-wrapper {
height: 0 !important;
} }
.btn-send { .btn-send {
@ -627,7 +634,7 @@ $chat-helper-size: 39px;
&.is-centering { &.is-centering {
html:not(.is-safari) & { html:not(.is-safari) & {
transition: width .2s, border-bottom-right-radius .1s, transform .2s; transition: width .2s, max-height .2s, border-bottom-right-radius .1s, transform .2s;
&:after { &:after {
transition: transform .1s; transition: transform .1s;
@ -759,21 +766,28 @@ $chat-helper-size: 39px;
.reply-wrapper { .reply-wrapper {
justify-content: flex-start; justify-content: flex-start;
overflow: hidden; overflow: hidden;
transition: transform var(--layer-transition), border-radius var(--layer-transition); /* transition: transform var(--layer-transition), border-radius var(--layer-transition);
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
//height: calc(#{$chat-helper-size} + .3125rem);
height: 100%; height: 100%;
z-index: 1; */
height: 0;
width: calc(100% - var(--padding-horizontal) * 2);
padding: 0;
margin-top: .3125rem;//var(--padding-vertical);
margin-bottom: -.3125rem;
transition: height var(--layer-transition);
//height: calc(#{$chat-helper-size} + .3125rem);
align-items: flex-start; align-items: flex-start;
z-index: 1;
user-select: none; user-select: none;
z-index: 2;
body.animation-level-0 & { body.animation-level-0 & {
transition: none; transition: none;
} }
@include respond-to(handhelds) { /* @include respond-to(handhelds) {
padding-top: .25rem; padding-top: .25rem;
} }
@ -781,6 +795,10 @@ $chat-helper-size: 39px;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
transform: translateY(#{-$chat-helper-size}); transform: translateY(#{-$chat-helper-size});
} */
.chat.is-helper-active & {
height: 39px;
} }
/* &.active { /* &.active {
@ -910,23 +928,14 @@ $chat-helper-size: 39px;
color: $color-blue; color: $color-blue;
} }
} }
img.emoji {
height: 24px;
width: 24px;
}
} }
.bubbles { .bubbles {
--translateY: 0; --translateY: 0;
/* overflow-y: scroll;
scrollbar-width: none;
-ms-overflow-style: none; */
width: 100%; width: 100%;
height: 100%; height: 100%;
max-height: 100%; max-height: 100%;
flex: 1 1 auto; /* Lets middle column shrink/grow to available width */ flex: 1 1 auto;
//overflow: hidden;
position: relative; position: relative;
transform: translateY(var(--translateY)); transform: translateY(var(--translateY));
@ -940,17 +949,20 @@ $chat-helper-size: 39px;
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); // fix safari overflow -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); // fix safari overflow
} */ } */
.chat.is-helper-active & { // .chat.is-helper-active & {
&:not(.is-selecting), &.is-selecting.backwards { // &:not(.is-selecting), &.is-selecting.backwards {
--translateY: -#{$chat-helper-size}; // /* --translateY: -#{$chat-helper-size};
.bubbles-inner { // .bubbles-inner {
transform: translateY(calc(var(--translateY) * -1)); // transform: translateY(calc(var(--translateY) * -1));
//margin-top: $chat-helper-size; // //margin-top: $chat-helper-size;
//transition: none; // //transition: none;
} // } */
} // /* > .scrollable {
} // margin-bottom: $chat-helper-size;
// } */
// }
// }
&.is-chat-input-hidden.is-selecting:not(.backwards) { &.is-chat-input-hidden.is-selecting:not(.backwards) {
--translateY: -79px; --translateY: -79px;
@ -976,23 +988,9 @@ $chat-helper-size: 39px;
> .scrollable { > .scrollable {
height: auto; height: auto;
/* position: absolute;
bottom: 0;
left: 0; */
//position: relative; // неизвестно зачем это было
//display: flex; // for end
//flex-direction: unset;
display: block; display: block;
//transform: none; /* margin-bottom: 0;
transition: margin-bottom var(--layer-transition) */
/* display: flex;
flex-direction: column;
justify-content: flex-end; */
// * scrollbar takes some width, don't need to set padding for iOS
/* html.is-safari:not(.is-ios) & {
padding-left: 6px;
} */
} }
//} //}
@ -1144,7 +1142,8 @@ $chat-helper-size: 39px;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
right: var(--chat-input-padding); right: var(--chat-input-padding);
top: calc((var(--chat-input-size) * -1) - 6px); //top: calc((var(--chat-input-size) * -1) - 6px);
bottom: calc(var(--chat-input-size) + var(--bottom) + 10px);
cursor: default; cursor: default;
opacity: 0; opacity: 0;
z-index: 2; z-index: 2;

3
src/scss/partials/_chatTopbar.scss

@ -8,12 +8,13 @@
max-height: 3.5rem; max-height: 3.5rem;
// border-bottom: 1px solid #DADCE0; // border-bottom: 1px solid #DADCE0;
@include respond-to(handhelds) { &.is-pinned-floating {
&.is-pinned-audio-shown, &.is-pinned-message-shown:not(.hide-pinned) { &.is-pinned-audio-shown, &.is-pinned-message-shown:not(.hide-pinned) {
margin-bottom: 52px; margin-bottom: 52px;
/* & + .bubbles { /* & + .bubbles {
margin-top: 52px; margin-top: 52px;
} */ } */
& ~ .drops-container { & ~ .drops-container {
--pinned-floating-height: 52px; --pinned-floating-height: 52px;
} }

9
src/scss/partials/_input.scss

@ -59,12 +59,13 @@
&-input { &-input {
--padding: 1rem; --padding: 1rem;
--padding-horizontal: 1rem;
--border-width: 1px; --border-width: 1px;
--border-width-top: 2px; --border-width-top: 2px;
border: var(--border-width) solid #DADCE0; border: var(--border-width) solid #DADCE0;
border-radius: $border-radius-medium; border-radius: $border-radius-medium;
//padding: 0 1rem; //padding: 0 1rem;
padding: calc(var(--padding) - var(--border-width-top)) calc(var(--padding) - var(--border-width)); padding: calc(var(--padding) - var(--border-width-top)) calc(var(--padding-horizontal) - var(--border-width));
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
min-height: var(--height); min-height: var(--height);
@ -75,6 +76,10 @@
/* overflow: hidden; /* overflow: hidden;
white-space: nowrap; */ white-space: nowrap; */
@include respond-to(handhelds) {
--padding: .875rem;
}
body.animation-level-0 & { body.animation-level-0 & {
transition: none; transition: none;
} }
@ -136,7 +141,7 @@
} }
&:focus ~ label, &:valid ~ label, &:not(:empty) ~ label, &:disabled ~ label { &:focus ~ label, &:valid ~ label, &:not(:empty) ~ label, &:disabled ~ label {
transform: translate(-.3125rem, calc(var(--height) / -2 + .125rem)) scale(.75); transform: translate(-.25rem, calc(var(--height) / -2 + .125rem)) scale(.75);
padding: 0 6px; padding: 0 6px;
opacity: 1; opacity: 1;
} }

8
src/scss/partials/_leftSidebar.scss

@ -107,6 +107,10 @@
.folders-tabs-scrollable .menu-horizontal-div-item:first-child { .folders-tabs-scrollable .menu-horizontal-div-item:first-child {
margin-left: .6875rem; margin-left: .6875rem;
@include respond-to(handhelds) {
margin-left: .1875rem;
}
} }
.item-main { .item-main {
@ -712,10 +716,6 @@
} }
} }
.sidebar-header .tgico-check1 {
color: #50a2e9;
}
.popup-forward, .included-chatlist-container { .popup-forward, .included-chatlist-container {
.selector { .selector {
ul { ul {

1
src/scss/partials/_slider.scss

@ -84,6 +84,7 @@
display: grid; display: grid;
//grid-template-columns: 1fr; //grid-template-columns: 1fr;
grid-template-columns: 100%; grid-template-columns: 100%;
grid-template-rows: 100%;
/* @include respond-to(not-handhelds) { /* @include respond-to(not-handhelds) {
overflow-x: hidden; overflow-x: hidden;

1
src/scss/partials/pages/_pages.scss

@ -33,6 +33,7 @@
> .scrollable { > .scrollable {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
&:before, &:after { &:before, &:after {
content: " "; content: " ";

Loading…
Cancel
Save