Browse Source

Handle peer title and bio change

master
Eduard Kuzmenko 4 years ago
parent
commit
76a9abc678
  1. 9
      src/components/avatar.ts
  2. 16
      src/components/chat/bubbles.ts
  3. 10
      src/components/chat/topbar.ts
  4. 59
      src/components/peerTitle.ts
  5. 4
      src/components/sidebarLeft/tabs/editProfile.ts
  6. 27
      src/components/sidebarRight/tabs/editGroup.ts
  7. 75
      src/components/sidebarRight/tabs/sharedMedia.ts
  8. 100
      src/lib/appManagers/appChatsManager.ts
  9. 42
      src/lib/appManagers/appDialogsManager.ts
  10. 4
      src/lib/appManagers/appImManager.ts
  11. 31
      src/lib/appManagers/appUsersManager.ts
  12. 8
      src/lib/mtproto/networker.ts
  13. 3
      src/lib/rootScope.ts
  14. 26
      src/scss/partials/_button.scss
  15. 6
      src/scss/partials/_rightSidebar.scss

9
src/components/avatar.ts

@ -7,15 +7,16 @@ import { Photo } from "../layer";
import appPeersManager from "../lib/appManagers/appPeersManager"; import appPeersManager from "../lib/appManagers/appPeersManager";
//import type { LazyLoadQueueIntersector } from "./lazyLoadQueue"; //import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
rootScope.on('avatar_update', (e) => { const onAvatarUpdate = (peerId: number) => {
let peerId = e;
appProfileManager.removeFromAvatarsCache(peerId); appProfileManager.removeFromAvatarsCache(peerId);
(Array.from(document.querySelectorAll('avatar-element[peer="' + peerId + '"]')) as AvatarElement[]).forEach(elem => { (Array.from(document.querySelectorAll('avatar-element[peer="' + peerId + '"]')) as AvatarElement[]).forEach(elem => {
//console.log('updating avatar:', elem); //console.log('updating avatar:', elem);
elem.update(); elem.update();
}); });
}); };
rootScope.on('avatar_update', onAvatarUpdate);
rootScope.on('peer_title_edit', onAvatarUpdate);
export default class AvatarElement extends HTMLElement { export default class AvatarElement extends HTMLElement {
private peerId: number; private peerId: number;

16
src/components/chat/bubbles.ts

@ -47,6 +47,7 @@ import RepliesElement from "./replies";
import DEBUG from "../../config/debug"; import DEBUG from "../../config/debug";
import { SliceEnd } from "../../helpers/slicedArray"; import { SliceEnd } from "../../helpers/slicedArray";
import serverTimeManager from "../../lib/mtproto/serverTimeManager"; import serverTimeManager from "../../lib/mtproto/serverTimeManager";
import PeerTitle from "../peerTitle";
const USE_MEDIA_TAILS = false; const USE_MEDIA_TAILS = false;
const IGNORE_ACTIONS = ['messageActionHistoryClear']; const IGNORE_ACTIONS = ['messageActionHistoryClear'];
@ -155,7 +156,7 @@ export default class ChatBubbles {
const message = this.chat.getMessage(mid); const message = this.chat.getMessage(mid);
if(+bubble.dataset.timestamp >= (message.date - serverTimeManager.serverTimeOffset - 1)) { if(+bubble.dataset.timestamp >= (message.date + serverTimeManager.serverTimeOffset - 1)) {
return; return;
} }
@ -2353,16 +2354,19 @@ export default class ChatBubbles {
const needName = (peerId < 0 && (peerId !== message.fromId || our)) && message.fromId !== rootScope.myId; const needName = (peerId < 0 && (peerId !== message.fromId || our)) && message.fromId !== rootScope.myId;
if(needName || message.fwd_from || message.reply_to_mid) { // chat if(needName || message.fwd_from || message.reply_to_mid) { // chat
let title = this.appPeersManager.getPeerTitle(message.fwdFromId || message.fromId); let title: HTMLSpanElement;
const isForwardFromChannel = message.from_id && message.from_id._ === 'peerChannel' && message.fromId === message.fwdFromId; const isForwardFromChannel = message.from_id && message.from_id._ === 'peerChannel' && message.fromId === message.fwdFromId;
let isHidden = message.fwd_from && !message.fwd_from.from_id && !message.fwd_from.channel_id; let isHidden = message.fwd_from && !message.fwd_from.from_id && !message.fwd_from.channel_id;
if(isHidden) { if(isHidden) {
///////this.log('message to render hidden', message); ///////this.log('message to render hidden', message);
title = RichTextProcessor.wrapEmojiText(message.fwd_from.from_name); title = document.createElement('span');
title.innerHTML = RichTextProcessor.wrapEmojiText(message.fwd_from.from_name);
//title = message.fwd_from.from_name; //title = message.fwd_from.from_name;
bubble.classList.add('hidden-profile'); bubble.classList.add('hidden-profile');
} else {
title = new PeerTitle({peerId: message.fwdFromId || message.fromId}).element;
} }
//this.log(title); //this.log(title);
@ -2383,11 +2387,11 @@ export default class ChatBubbles {
if(this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || isForwardFromChannel) { if(this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || isForwardFromChannel) {
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fwdFromId, false); nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fwdFromId, false);
nameDiv.innerHTML = title; nameDiv.append(title);
} else { } else {
/* const fromTitle = message.fromId === this.myID || appPeersManager.isBroadcast(message.fwdFromId || message.fromId) ? '' : `<div class="name" data-peer-id="${message.fromId}" style="color: ${appPeersManager.getPeerColorByID(message.fromId, false)};">${appPeersManager.getPeerTitle(message.fromId)}</div>`; /* const fromTitle = message.fromId === this.myID || appPeersManager.isBroadcast(message.fwdFromId || message.fromId) ? '' : `<div class="name" data-peer-id="${message.fromId}" style="color: ${appPeersManager.getPeerColorByID(message.fromId, false)};">${appPeersManager.getPeerTitle(message.fromId)}</div>`;
nameDiv.innerHTML = fromTitle + 'Forwarded from ' + title; */ nameDiv.innerHTML = fromTitle + 'Forwarded from ' + title; */
nameDiv.innerHTML = 'Forwarded from ' + title; nameDiv.append('Forwarded from ', title);
if(savedFrom) { if(savedFrom) {
nameDiv.dataset.savedFrom = savedFrom; nameDiv.dataset.savedFrom = savedFrom;
@ -2400,7 +2404,7 @@ export default class ChatBubbles {
if(!bubble.classList.contains('sticker') && needName) { if(!bubble.classList.contains('sticker') && needName) {
let nameDiv = document.createElement('div'); let nameDiv = document.createElement('div');
nameDiv.classList.add('name'); nameDiv.classList.add('name');
nameDiv.innerHTML = title; nameDiv.append(title);
if(!our) { if(!our) {
nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fromId, false); nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fromId, false);

10
src/components/chat/topbar.ts

@ -22,7 +22,7 @@ import PopupDeleteDialog from "../popups/deleteDialog";
import appNavigationController from "../appNavigationController"; import appNavigationController from "../appNavigationController";
import { LEFT_COLUMN_ACTIVE_CLASSNAME } from "../sidebarLeft"; import { LEFT_COLUMN_ACTIVE_CLASSNAME } from "../sidebarLeft";
import AppPrivateSearchTab from "../sidebarRight/tabs/search"; import AppPrivateSearchTab from "../sidebarRight/tabs/search";
import { SliderSuperTab } from "../slider"; import PeerTitle from "../peerTitle";
export default class ChatTopbar { export default class ChatTopbar {
container: HTMLDivElement; container: HTMLDivElement;
@ -482,8 +482,12 @@ export default class ChatTopbar {
}); });
} }
} else if(this.chat.type === 'chat') { } else if(this.chat.type === 'chat') {
if(this.peerId === rootScope.myId) title = 'Saved Messages'; this.title.innerHTML = '';
else title = this.appPeersManager.getPeerTitle(this.peerId); this.title.append(new PeerTitle({
peerId: this.peerId,
dialog: true,
}).element);
return;
} }
this.title.innerHTML = title; this.title.innerHTML = title;

59
src/components/peerTitle.ts

@ -0,0 +1,59 @@
import { MOUNT_CLASS_TO } from "../config/debug";
import appPeersManager from "../lib/appManagers/appPeersManager";
import rootScope from "../lib/rootScope";
export type PeerTitleOptions = {
peerId: number,
plainText?: boolean,
onlyFirstName?: boolean,
dialog?: boolean
};
const weakMap: WeakMap<HTMLElement, PeerTitle> = new WeakMap();
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.peerTitleWeakMap = weakMap);
rootScope.on('peer_title_edit', (peerId) => {
const elements = Array.from(document.querySelectorAll(`.peer-title[data-peer-id="${peerId}"]`)) as HTMLElement[];
elements.forEach(element => {
const peerTitle = weakMap.get(element);
//console.log('in the summer silence i was doing nothing', peerTitle, peerId);
if(peerTitle) {
peerTitle.update();
}
});
});
export default class PeerTitle {
public element: HTMLElement;
public peerId: number;
public plainText = false;
public onlyFirstName = false;
public dialog = false;
constructor(options: PeerTitleOptions) {
this.element = document.createElement('span');
this.element.classList.add('peer-title');
this.update(options);
weakMap.set(this.element, this);
}
public update(options?: PeerTitleOptions) {
if(options) {
for(let i in options) {
// @ts-ignore
this.element.dataset[i] = options[i] ? '' + (typeof(options[i]) === 'boolean' ? +options[i] : options[i]) : '0';
// @ts-ignore
this[i] = options[i];
}
}
if(this.peerId !== rootScope.myId || !this.dialog) {
this.element.innerHTML = appPeersManager.getPeerTitle(this.peerId, this.plainText, this.onlyFirstName);
} else {
this.element.innerHTML = this.onlyFirstName ? 'Saved' : 'Saved Messages';
}
}
}

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

@ -158,14 +158,14 @@ export default class AppEditProfileTab extends SliderSuperTab {
let promises: Promise<any>[] = []; let promises: Promise<any>[] = [];
promises.push(appProfileManager.updateProfile(this.firstNameInputField.value, this.lastNameInputField.value, this.bioInputField.value).then(() => { promises.push(appProfileManager.updateProfile(this.firstNameInputField.value, this.lastNameInputField.value, this.bioInputField.value).then(() => {
this.slider.selectTab(0); this.close();
}, (err) => { }, (err) => {
console.error('updateProfile error:', err); console.error('updateProfile error:', err);
})); }));
if(this.editPeer.uploadAvatar) { if(this.editPeer.uploadAvatar) {
promises.push(this.editPeer.uploadAvatar().then(inputFile => { promises.push(this.editPeer.uploadAvatar().then(inputFile => {
appProfileManager.uploadProfilePhoto(inputFile); return appProfileManager.uploadProfilePhoto(inputFile);
})); }));
} }

27
src/components/sidebarRight/tabs/editGroup.ts

@ -7,6 +7,7 @@ import CheckboxField from "../../checkboxField";
import Button from "../../button"; import Button from "../../button";
import appChatsManager from "../../../lib/appManagers/appChatsManager"; import appChatsManager from "../../../lib/appManagers/appChatsManager";
import appProfileManager from "../../../lib/appManagers/appProfileManager"; import appProfileManager from "../../../lib/appManagers/appProfileManager";
import { attachClickEvent } from "../../../helpers/dom";
export default class AppEditGroupTab extends SliderSuperTab { export default class AppEditGroupTab extends SliderSuperTab {
private groupNameInputField: InputField; private groupNameInputField: InputField;
@ -77,6 +78,32 @@ export default class AppEditGroupTab extends SliderSuperTab {
section.content.append(this.editPeer.avatarEdit.container, inputWrapper, groupTypeRow.container, permissionsRow.container, administratorsRow.container); section.content.append(this.editPeer.avatarEdit.container, inputWrapper, groupTypeRow.container, permissionsRow.container, administratorsRow.container);
this.scrollable.append(section.container); this.scrollable.append(section.container);
attachClickEvent(this.editPeer.nextBtn, () => {
this.editPeer.nextBtn.disabled = true;
let promises: Promise<any>[] = [];
const id = -this.peerId;
if(this.groupNameInputField.isValid()) {
promises.push(appChatsManager.editTitle(id, this.groupNameInputField.value));
}
if(this.descriptionInputField.isValid()) {
promises.push(appChatsManager.editAbout(id, this.descriptionInputField.value));
}
if(this.editPeer.uploadAvatar) {
promises.push(this.editPeer.uploadAvatar().then(inputFile => {
return appChatsManager.editPhoto(id, inputFile);
}));
}
Promise.race(promises).finally(() => {
this.editPeer.nextBtn.removeAttribute('disabled');
this.close();
});
}, {listenerSetter: this.listenerSetter});
} }
{ {

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

@ -11,11 +11,12 @@ import AvatarElement from "../../avatar";
import Scrollable from "../../scrollable"; import Scrollable from "../../scrollable";
import { SliderTab } from "../../slider"; import { SliderTab } from "../../slider";
import CheckboxField from "../../checkboxField"; import CheckboxField from "../../checkboxField";
import { attachClickEvent, cancelEvent } from "../../../helpers/dom"; import { attachClickEvent } from "../../../helpers/dom";
import appSidebarRight from ".."; import appSidebarRight from "..";
import { TransitionSlider } from "../../transition"; import { TransitionSlider } from "../../transition";
import appNotificationsManager from "../../../lib/appManagers/appNotificationsManager"; import appNotificationsManager from "../../../lib/appManagers/appNotificationsManager";
import AppEditGroupTab from "./editGroup"; import AppEditGroupTab from "./editGroup";
import PeerTitle from "../../peerTitle";
let setText = (text: string, el: HTMLDivElement) => { let setText = (text: string, el: HTMLDivElement) => {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
@ -66,6 +67,8 @@ export default class AppSharedMediaTab implements SliderTab {
cleaned: boolean; cleaned: boolean;
searchSuper: AppSearchSuper; searchSuper: AppSearchSuper;
private setBioTimeout: number;
public init() { public init() {
this.container = document.getElementById('shared-media-container'); this.container = document.getElementById('shared-media-container');
this.closeBtn = this.container.querySelector('.sidebar-header .btn-icon'); this.closeBtn = this.container.querySelector('.sidebar-header .btn-icon');
@ -164,6 +167,12 @@ export default class AppSharedMediaTab implements SliderTab {
} }
}); });
rootScope.on('peer_bio_edit', (peerId) => {
if(peerId === this.peerId) {
this.setBio(true);
}
});
rootScope.on('user_update', (e) => { rootScope.on('user_update', (e) => {
const userId = e; const userId = e;
@ -276,6 +285,10 @@ export default class AppSharedMediaTab implements SliderTab {
this.profileElements.notificationsCheckbox.checked = true; this.profileElements.notificationsCheckbox.checked = true;
this.profileElements.notificationsStatus.innerText = 'Enabled'; this.profileElements.notificationsStatus.innerText = 'Enabled';
this.editBtn.style.display = 'none'; this.editBtn.style.display = 'none';
if(this.setBioTimeout) {
window.clearTimeout(this.setBioTimeout);
this.setBioTimeout = 0;
}
this.searchSuper.cleanupHTML(); this.searchSuper.cleanupHTML();
this.searchSuper.selectTab(0, false); this.searchSuper.selectTab(0, false);
@ -312,7 +325,6 @@ export default class AppSharedMediaTab implements SliderTab {
this.cleaned = false; this.cleaned = false;
const peerId = this.peerId; const peerId = this.peerId;
const threadId = this.threadId;
this.cleanupHTML(); this.cleanupHTML();
@ -342,11 +354,42 @@ export default class AppSharedMediaTab implements SliderTab {
if(user.phone && peerId !== rootScope.myId) { if(user.phone && peerId !== rootScope.myId) {
setText(user.rPhone, this.profileElements.phone); setText(user.rPhone, this.profileElements.phone);
} }
}/* else {
appProfileManager.getProfile(peerId).then(userFull => { //membersLi.style.display = appPeersManager.isBroadcast(peerId) ? 'none' : '';
} */
this.setBio();
this.profileElements.name.innerHTML = '';
this.profileElements.name.append(new PeerTitle({
peerId,
dialog: true
}).element);
this.editBtn.style.display = '';
this.setPeerStatus(true);
}
public setBio(override?: true) {
if(this.setBioTimeout) {
window.clearTimeout(this.setBioTimeout);
this.setBioTimeout = 0;
}
const peerId = this.peerId;
const threadId = this.threadId;
if(!peerId) {
return;
}
let promise: Promise<boolean>;
if(peerId > 0) {
promise = appProfileManager.getProfile(peerId, override).then(userFull => {
if(this.peerId !== peerId || this.threadId !== threadId) { if(this.peerId !== peerId || this.threadId !== threadId) {
this.log.warn('peer changed'); this.log.warn('peer changed');
return; return false;
} }
if(userFull.rAbout && peerId !== rootScope.myId) { if(userFull.rAbout && peerId !== rootScope.myId) {
@ -354,15 +397,13 @@ export default class AppSharedMediaTab implements SliderTab {
} }
//this.log('userFull', userFull); //this.log('userFull', userFull);
return true;
}); });
} else { } else {
//membersLi.style.display = appPeersManager.isBroadcast(peerId) ? 'none' : ''; promise = appProfileManager.getChatFull(-peerId, override).then((chatFull) => {
let chat = appPeersManager.getPeer(peerId);
appProfileManager.getChatFull(chat.id).then((chatFull) => {
if(this.peerId !== peerId || this.threadId !== threadId) { if(this.peerId !== peerId || this.threadId !== threadId) {
this.log.warn('peer changed'); this.log.warn('peer changed');
return; return false;
} }
//this.log('chatInfo res 2:', chatFull); //this.log('chatInfo res 2:', chatFull);
@ -370,16 +411,16 @@ export default class AppSharedMediaTab implements SliderTab {
if(chatFull.about) { if(chatFull.about) {
setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio); setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio);
} }
return true;
}); });
} }
let title: string; promise.then((canSetNext) => {
if(peerId === rootScope.myId) title = 'Saved Messages'; if(canSetNext) {
else title = appPeersManager.getPeerTitle(peerId); this.setBioTimeout = window.setTimeout(() => this.setBio(true), 60e3);
this.profileElements.name.innerHTML = title; }
this.editBtn.style.display = ''; });
this.setPeerStatus(true);
} }
onOpenAfterTimeout() { onOpenAfterTimeout() {

100
src/lib/appManagers/appChatsManager.ts

@ -7,6 +7,7 @@ import { RichTextProcessor } from "../richtextprocessor";
import rootScope from "../rootScope"; import rootScope from "../rootScope";
import apiUpdatesManager from "./apiUpdatesManager"; import apiUpdatesManager from "./apiUpdatesManager";
import appMessagesManager from "./appMessagesManager"; import appMessagesManager from "./appMessagesManager";
import appPeersManager from "./appPeersManager";
import appProfileManager from "./appProfileManager"; import appProfileManager from "./appProfileManager";
import appStateManager from "./appStateManager"; import appStateManager from "./appStateManager";
import appUsersManager from "./appUsersManager"; import appUsersManager from "./appUsersManager";
@ -137,7 +138,7 @@ export class AppChatsManager {
this.usernames[searchUsername] = chat.id; this.usernames[searchUsername] = chat.id;
} */ } */
let changedPhoto = false; let changedPhoto = false, changedTitle = false;
if(oldChat === undefined) { if(oldChat === undefined) {
this.chats[chat.id] = chat; this.chats[chat.id] = chat;
} else { } else {
@ -147,6 +148,10 @@ export class AppChatsManager {
changedPhoto = true; changedPhoto = true;
} }
if(oldChat.title !== chat.title) {
changedTitle = true;
}
safeReplaceObject(oldChat, chat); safeReplaceObject(oldChat, chat);
rootScope.broadcast('chat_update', chat.id); rootScope.broadcast('chat_update', chat.id);
} }
@ -159,6 +164,10 @@ export class AppChatsManager {
if(changedPhoto) { if(changedPhoto) {
rootScope.broadcast('avatar_update', -chat.id); rootScope.broadcast('avatar_update', -chat.id);
} }
if(changedTitle) {
rootScope.broadcast('peer_title_edit', -chat.id);
}
} }
public getChat(id: number) { public getChat(id: number) {
@ -413,7 +422,10 @@ export class AppChatsManager {
}).then((updates: any) => { }).then((updates: any) => {
apiUpdatesManager.processUpdateMessage(updates); apiUpdatesManager.processUpdateMessage(updates);
return updates.chats[0].id; const channelId = updates.chats[0].id;
rootScope.broadcast('history_focus', -channelId);
return channelId;
}); });
} }
@ -436,33 +448,11 @@ export class AppChatsManager {
}).then(updates => { }).then(updates => {
apiUpdatesManager.processUpdateMessage(updates); apiUpdatesManager.processUpdateMessage(updates);
return (updates as any as Updates.updates).chats[0].id; const chatId = (updates as any as Updates.updates).chats[0].id;
}); rootScope.broadcast('history_focus', -chatId);
}
public editPhoto(id: number, inputFile: InputFile) {
const isChannel = this.isChannel(id);
const inputChatPhoto: InputChatPhoto.inputChatUploadedPhoto = { return chatId;
_: 'inputChatUploadedPhoto', });
file: inputFile
};
if(isChannel) {
return apiManager.invokeApi('channels.editPhoto', {
channel: this.getChannelInput(id),
photo: inputChatPhoto
}).then(updates => {
apiUpdatesManager.processUpdateMessage(updates);
});
} else {
return apiManager.invokeApi('messages.editChatPhoto', {
chat_id: id,
photo: inputChatPhoto
}).then(updates => {
apiUpdatesManager.processUpdateMessage(updates);
});
}
} }
public async getOnlines(id: number): Promise<number> { public async getOnlines(id: number): Promise<number> {
@ -544,6 +534,60 @@ export class AppChatsManager {
public leave(id: number) { public leave(id: number) {
return this.isChannel(id) ? this.leaveChannel(id) : this.leaveChat(id); return this.isChannel(id) ? this.leaveChannel(id) : this.leaveChat(id);
} }
public editPhoto(id: number, inputFile: InputFile) {
const inputChatPhoto: InputChatPhoto = {
_: 'inputChatUploadedPhoto',
file: inputFile
};
let promise: any;
if(this.isChannel(id)) {
promise = apiManager.invokeApi('channels.editPhoto', {
channel: this.getChannelInput(id),
photo: inputChatPhoto
});
} else {
promise = apiManager.invokeApi('messages.editChatPhoto', {
chat_id: id,
photo: inputChatPhoto
});
}
return promise.then((updates: any) => {
apiUpdatesManager.processUpdateMessage(updates);
});
}
public editTitle(id: number, title: string) {
let promise: any;
if(this.isChannel(id)) {
promise = apiManager.invokeApi('channels.editTitle', {
channel: this.getChannelInput(id),
title
});
} else {
promise = apiManager.invokeApi('messages.editChatTitle', {
chat_id: id,
title
});
}
return promise.then((updates: any) => {
apiUpdatesManager.processUpdateMessage(updates);
});
}
public editAbout(id: number, about: string) {
return apiManager.invokeApi('messages.editChatAbout', {
peer: appPeersManager.getInputPeerById(-id),
about
}).then(bool => {
//apiUpdatesManager.processUpdateMessage(updates);
rootScope.broadcast('peer_bio_edit', -id);
});
}
} }
const appChatsManager = new AppChatsManager(); const appChatsManager = new AppChatsManager();

42
src/lib/appManagers/appDialogsManager.ts

@ -28,6 +28,7 @@ import App from "../../config/app";
import DEBUG, { MOUNT_CLASS_TO } from "../../config/debug"; import DEBUG, { MOUNT_CLASS_TO } from "../../config/debug";
import appNotificationsManager from "./appNotificationsManager"; import appNotificationsManager from "./appNotificationsManager";
import { InputNotifyPeer } from "../../layer"; import { InputNotifyPeer } from "../../layer";
import PeerTitle from "../../components/peerTitle";
type DialogDom = { type DialogDom = {
avatarEl: AvatarElement, avatarEl: AvatarElement,
@ -43,8 +44,8 @@ type DialogDom = {
muteAnimationTimeout?: number muteAnimationTimeout?: number
}; };
const testScroll = false; //const testScroll = false;
let testTopSlice = 1; //let testTopSlice = 1;
class ConnectionStatusComponent { class ConnectionStatusComponent {
public static CHANGE_STATE_DELAY = 1000; public static CHANGE_STATE_DELAY = 1000;
@ -270,7 +271,7 @@ export class AppDialogsManager {
this.setListClickListener(this.chatList, null, true); this.setListClickListener(this.chatList, null, true);
if(testScroll) { /* if(testScroll) {
let i = 0; let i = 0;
let add = () => { let add = () => {
let li = document.createElement('li'); let li = document.createElement('li');
@ -284,7 +285,7 @@ export class AppDialogsManager {
add(); add();
} }
(window as any).addElement = add; (window as any).addElement = add;
} } */
rootScope.on('user_update', (e) => { rootScope.on('user_update', (e) => {
const userId = e; const userId = e;
@ -712,9 +713,9 @@ export class AppDialogsManager {
} }
private loadDialogs(side: SliceSides = 'bottom') { private loadDialogs(side: SliceSides = 'bottom') {
if(testScroll) { /* if(testScroll) {
return; return;
} } */
if(this.loadDialogsPromise/* || 1 === 1 */) return this.loadDialogsPromise; if(this.loadDialogsPromise/* || 1 === 1 */) return this.loadDialogsPromise;
@ -1081,16 +1082,17 @@ export class AppDialogsManager {
if(sender && sender.id) { if(sender && sender.id) {
const senderBold = document.createElement('b'); const senderBold = document.createElement('b');
let str = '';
if(sender.id === rootScope.myId) { if(sender.id === rootScope.myId) {
str = 'You'; senderBold.innerHTML = 'You';
} else { } else {
//str = sender.first_name || sender.last_name || sender.username; //str = sender.first_name || sender.last_name || sender.username;
str = appPeersManager.getPeerTitle(lastMessage.fromId, true, true); senderBold.append(new PeerTitle({
peerId: lastMessage.fromId,
onlyFirstName: true,
}).element);
} }
//senderBold.innerText = str + ': '; senderBold.append(': ');
senderBold.innerHTML = RichTextProcessor.wrapRichText(str, {noLinebreaks: true, noLinks: true}) + ': ';
//console.log(sender, senderBold.innerText); //console.log(sender, senderBold.innerText);
dom.lastMessageSpan.prepend(senderBold); dom.lastMessageSpan.prepend(senderBold);
} //////// else console.log('no sender', lastMessage, peerId); } //////// else console.log('no sender', lastMessage, peerId);
@ -1229,8 +1231,6 @@ export class AppDialogsManager {
} }
} }
let title = appPeersManager.getPeerTitle(peerId, false, onlyFirstName);
const avatarEl = new AvatarElement(); const avatarEl = new AvatarElement();
avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0'); avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0');
avatarEl.setAttribute('peer', '' + peerId); avatarEl.setAttribute('peer', '' + peerId);
@ -1260,14 +1260,14 @@ export class AppDialogsManager {
const titleSpanContainer = document.createElement('span'); const titleSpanContainer = document.createElement('span');
titleSpanContainer.classList.add('user-title'); titleSpanContainer.classList.add('user-title');
const titleSpan = document.createElement('span'); const peerTitle = new PeerTitle({
peerId,
if(peerId === rootScope.myId && meAsSaved) { dialog: meAsSaved,
title = onlyFirstName ? 'Saved' : 'Saved Messages'; onlyFirstName,
} plainText: false
});
titleSpan.innerHTML = title; titleSpanContainer.append(peerTitle.element);
titleSpanContainer.append(titleSpan);
//p.classList.add('') //p.classList.add('')
// в других случаях иконка верификации не нужна (а первый - это главные чатлисты) // в других случаях иконка верификации не нужна (а первый - это главные чатлисты)
@ -1329,7 +1329,7 @@ export class AppDialogsManager {
const dom: DialogDom = { const dom: DialogDom = {
avatarEl, avatarEl,
captionDiv, captionDiv,
titleSpan, titleSpan: peerTitle.element,
titleSpanContainer, titleSpanContainer,
statusSpan, statusSpan,
lastTimeSpan, lastTimeSpan,

4
src/lib/appManagers/appImManager.ts

@ -192,6 +192,10 @@ export class AppImManager {
} }
}); });
rootScope.on('history_focus', (peerId) => {
this.setInnerPeer(peerId);
});
/* rootScope.on('peer_changing', (chat) => { /* rootScope.on('peer_changing', (chat) => {
this.saveChatPosition(chat); this.saveChatPosition(chat);
}); });

31
src/lib/appManagers/appUsersManager.ts

@ -40,7 +40,7 @@ export class AppUsersManager {
const update = e as Update; const update = e as Update;
//console.log('on apiUpdate', update); //console.log('on apiUpdate', update);
switch(update._) { switch(update._) {
case 'updateUserStatus': case 'updateUserStatus': {
const userId = update.user_id; const userId = update.user_id;
const user = this.users[userId]; const user = this.users[userId];
if(user) { if(user) {
@ -58,7 +58,9 @@ export class AppUsersManager {
user.sortStatus = this.getUserStatusForSort(user.status); user.sortStatus = this.getUserStatusForSort(user.status);
rootScope.broadcast('user_update', userId); rootScope.broadcast('user_update', userId);
} //////else console.warn('No user by id:', userId); } //////else console.warn('No user by id:', userId);
break; break;
}
case 'updateUserPhoto': { case 'updateUserPhoto': {
const userId = update.user_id; const userId = update.user_id;
@ -84,6 +86,22 @@ export class AppUsersManager {
break; break;
} }
case 'updateUserName': {
const userId = update.user_id;
const user = this.users[userId];
if(user) {
this.forceUserOnline(userId);
this.saveApiUser(Object.assign({}, user, {
first_name: update.first_name,
last_name: update.last_name,
username: update.username
}));
}
break;
}
/* case 'updateContactLink': /* case 'updateContactLink':
this.onContactUpdated(update.user_id, update.my_link._ === 'contactLinkContact'); this.onContactUpdated(update.user_id, update.my_link._ === 'contactLinkContact');
break; */ break; */
@ -305,10 +323,17 @@ export class AppUsersManager {
user.sortStatus = this.getUserStatusForSort(user.status); user.sortStatus = this.getUserStatusForSort(user.status);
} }
let changedTitle = false;
const oldUser = this.users[userId]; const oldUser = this.users[userId];
if(oldUser === undefined) { if(oldUser === undefined) {
this.users[userId] = user; this.users[userId] = user;
} else { } else {
if(user.first_name !== oldUser.first_name
|| user.last_name !== oldUser.last_name
|| user.username !== oldUser.username) {
changedTitle = true;
}
safeReplaceObject(oldUser, user); safeReplaceObject(oldUser, user);
} }
@ -318,6 +343,10 @@ export class AppUsersManager {
safeReplaceObject(this.cachedPhotoLocations[userId], user && safeReplaceObject(this.cachedPhotoLocations[userId], user &&
user.photo ? user.photo : {empty: true}); user.photo ? user.photo : {empty: true});
} }
if(changedTitle) {
rootScope.broadcast('peer_title_edit', user.id);
}
} }
/* public saveUserAccess(id: number, accessHash: string) { /* public saveUserAccess(id: number, accessHash: string) {

8
src/lib/mtproto/networker.ts

@ -1249,23 +1249,23 @@ export default class MTPNetworker {
const nextReq = Date.now() + (delay || 0); const nextReq = Date.now() + (delay || 0);
if(this.nextReq && (delay === undefined || this.nextReq <= nextReq)) { if(this.nextReq && (delay === undefined || this.nextReq <= nextReq)) {
this.debug && this.log('scheduleRequest: nextReq', this.nextReq, nextReq); //this.debug && this.log('scheduleRequest: nextReq', this.nextReq, nextReq);
return; return;
} }
this.debug && this.log('scheduleRequest: delay', delay); //this.debug && this.log('scheduleRequest: delay', delay);
/* if(this.nextReqTimeout) { /* if(this.nextReqTimeout) {
return; return;
} */ } */
const perf = performance.now(); //const perf = performance.now();
if(this.nextReqTimeout) { if(this.nextReqTimeout) {
clearTimeout(this.nextReqTimeout); clearTimeout(this.nextReqTimeout);
} }
const cb = () => { const cb = () => {
this.debug && this.log('scheduleRequest: timeout delay was:', performance.now() - perf); //this.debug && this.log('scheduleRequest: timeout delay was:', performance.now() - perf);
this.nextReqTimeout = 0; this.nextReqTimeout = 0;
this.nextReq = 0; this.nextReq = 0;

3
src/lib/rootScope.ts

@ -21,6 +21,8 @@ export type BroadcastEvents = {
'peer_pinned_hidden': {peerId: number, maxId: number}, 'peer_pinned_hidden': {peerId: number, maxId: number},
'peer_typings': {peerId: number, typings: UserTyping[]}, 'peer_typings': {peerId: number, typings: UserTyping[]},
'peer_block': {peerId: number, blocked: boolean}, 'peer_block': {peerId: number, blocked: boolean},
'peer_title_edit': number,
'peer_bio_edit': number,
'filter_delete': MyDialogFilter, 'filter_delete': MyDialogFilter,
'filter_update': MyDialogFilter, 'filter_update': MyDialogFilter,
@ -43,6 +45,7 @@ export type BroadcastEvents = {
'history_delete': {peerId: number, msgs: {[mid: number]: true}}, 'history_delete': {peerId: number, msgs: {[mid: number]: true}},
'history_forbidden': number, 'history_forbidden': number,
'history_reload': number, 'history_reload': number,
'history_focus': number,
//'history_request': void, //'history_request': void,
'message_edit': {storage: MessagesStorage, peerId: number, mid: number}, 'message_edit': {storage: MessagesStorage, peerId: number, mid: number},

26
src/scss/partials/_button.scss

@ -1,3 +1,16 @@
.btn, .btn-icon {
background: none;
outline: none;
border: none;
cursor: pointer;
body.animation-level-0 & {
transition: none;
}
@include btn-hoverable();
}
.btn-icon { .btn-icon {
text-align: center; text-align: center;
font-size: 1.5rem; font-size: 1.5rem;
@ -339,19 +352,6 @@
} }
} }
.btn, .btn-icon {
background: none;
outline: none;
border: none;
cursor: pointer;
body.animation-level-0 & {
transition: none;
}
@include btn-hoverable();
}
.btn-color-primary { .btn-color-primary {
background: $color-blue; background: $color-blue;
color: #fff; color: #fff;

6
src/scss/partials/_rightSidebar.scss

@ -776,11 +776,13 @@
} }
.sidebar-left-section { .sidebar-left-section {
padding-bottom: 0;
&:first-child { &:first-child {
padding-top: 0; padding-top: 0;
} }
&:not(:last-child) {
padding-bottom: 0;
}
} }
.checkbox-field { .checkbox-field {

Loading…
Cancel
Save