Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
432 lines
12 KiB
432 lines
12 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
*/ |
|
|
|
import IS_PARALLAX_SUPPORTED from "../environment/parallaxSupport"; |
|
import callbackify from "../helpers/callbackify"; |
|
import { copyTextToClipboard } from "../helpers/clipboard"; |
|
import replaceContent from "../helpers/dom/replaceContent"; |
|
import ListenerSetter from "../helpers/listenerSetter"; |
|
import { fastRaf } from "../helpers/schedulers"; |
|
import { Chat, ChatFull, User } from "../layer"; |
|
import appChatsManager, { Channel } from "../lib/appManagers/appChatsManager"; |
|
import appImManager from "../lib/appManagers/appImManager"; |
|
import appMessagesManager from "../lib/appManagers/appMessagesManager"; |
|
import appNotificationsManager from "../lib/appManagers/appNotificationsManager"; |
|
import appPeersManager from "../lib/appManagers/appPeersManager"; |
|
import appProfileManager from "../lib/appManagers/appProfileManager"; |
|
import appUsersManager from "../lib/appManagers/appUsersManager"; |
|
import I18n from "../lib/langPack"; |
|
import RichTextProcessor from "../lib/richtextprocessor"; |
|
import rootScope from "../lib/rootScope"; |
|
import AvatarElement from "./avatar"; |
|
import CheckboxField from "./checkboxField"; |
|
import generateTitleIcons from "./generateTitleIcons"; |
|
import PeerProfileAvatars from "./peerProfileAvatars"; |
|
import PeerTitle from "./peerTitle"; |
|
import Row from "./row"; |
|
import Scrollable from "./scrollable"; |
|
import { SettingSection, generateDelimiter } from "./sidebarLeft"; |
|
import { toast } from "./toast"; |
|
|
|
let setText = (text: string, row: Row) => { |
|
//fastRaf(() => { |
|
row.title.innerHTML = text || ''; |
|
row.container.style.display = text ? '' : 'none'; |
|
//}); |
|
}; |
|
|
|
export default class PeerProfile { |
|
public element: HTMLElement; |
|
private avatars: PeerProfileAvatars; |
|
private avatar: AvatarElement; |
|
private section: SettingSection; |
|
private name: HTMLDivElement; |
|
private subtitle: HTMLDivElement; |
|
private bio: Row; |
|
private username: Row; |
|
private phone: Row; |
|
private notifications: Row; |
|
private location: Row; |
|
private link: Row; |
|
|
|
private cleaned: boolean; |
|
private setMoreDetailsTimeout: number; |
|
private setPeerStatusInterval: number; |
|
|
|
private peerId: PeerId; |
|
private threadId: number; |
|
|
|
constructor( |
|
public scrollable: Scrollable, |
|
private listenerSetter?: ListenerSetter, |
|
private isDialog = true |
|
) { |
|
if(!IS_PARALLAX_SUPPORTED) { |
|
this.scrollable.container.classList.add('no-parallax'); |
|
} |
|
|
|
if(!listenerSetter) { |
|
this.listenerSetter = new ListenerSetter(); |
|
} |
|
} |
|
|
|
public init() { |
|
this.init = null; |
|
|
|
|
|
this.element = document.createElement('div'); |
|
this.element.classList.add('profile-content'); |
|
|
|
this.section = new SettingSection({ |
|
noDelimiter: true |
|
}); |
|
|
|
this.avatar = new AvatarElement(); |
|
this.avatar.classList.add('profile-avatar', 'avatar-120'); |
|
this.avatar.isDialog = this.isDialog; |
|
this.avatar.attachClickEvent(); |
|
|
|
this.name = document.createElement('div'); |
|
this.name.classList.add('profile-name'); |
|
|
|
this.subtitle = document.createElement('div'); |
|
this.subtitle.classList.add('profile-subtitle'); |
|
|
|
this.bio = new Row({ |
|
title: ' ', |
|
subtitleLangKey: 'UserBio', |
|
icon: 'info', |
|
clickable: (e) => { |
|
if((e.target as HTMLElement).tagName === 'A') { |
|
return; |
|
} |
|
|
|
Promise.resolve(appProfileManager.getProfileByPeerId(this.peerId)).then(full => { |
|
copyTextToClipboard(full.about); |
|
toast(I18n.format('BioCopied', true)); |
|
}); |
|
} |
|
}); |
|
|
|
this.bio.title.classList.add('pre-wrap'); |
|
|
|
this.username = new Row({ |
|
title: ' ', |
|
subtitleLangKey: 'Username', |
|
icon: 'username', |
|
clickable: () => { |
|
const peer: Channel | User.user = appPeersManager.getPeer(this.peerId); |
|
copyTextToClipboard('@' + peer.username); |
|
toast(I18n.format('UsernameCopied', true)); |
|
} |
|
}); |
|
|
|
this.phone = new Row({ |
|
title: ' ', |
|
subtitleLangKey: 'Phone', |
|
icon: 'phone', |
|
clickable: () => { |
|
const peer: User = appUsersManager.getUser(this.peerId); |
|
copyTextToClipboard('+' + peer.phone); |
|
toast(I18n.format('PhoneCopied', true)); |
|
} |
|
}); |
|
|
|
this.link = new Row({ |
|
title: ' ', |
|
subtitleLangKey: 'SetUrlPlaceholder', |
|
icon: 'link', |
|
clickable: () => { |
|
copyTextToClipboard(this.link.title.textContent); |
|
// Promise.resolve(appProfileManager.getChatFull(this.peerId.toChatId())).then(chatFull => { |
|
// copyTextToClipboard(chatFull.exported_invite.link); |
|
toast(I18n.format('LinkCopied', true)); |
|
// }); |
|
} |
|
}); |
|
|
|
this.location = new Row({ |
|
title: ' ', |
|
subtitleLangKey: 'ChatLocation', |
|
icon: 'location' |
|
}); |
|
|
|
this.section.content.append( |
|
this.phone.container, |
|
this.username.container, |
|
this.location.container, |
|
this.bio.container, |
|
this.link.container |
|
); |
|
|
|
const {listenerSetter} = this; |
|
if(this.isDialog) { |
|
this.notifications = new Row({ |
|
checkboxField: new CheckboxField({toggle: true}), |
|
titleLangKey: 'Notifications', |
|
icon: 'unmute' |
|
}); |
|
|
|
listenerSetter.add(this.notifications.checkboxField.input)('change', (e) => { |
|
if(!e.isTrusted) { |
|
return; |
|
} |
|
|
|
//let checked = this.notificationsCheckbox.checked; |
|
appMessagesManager.togglePeerMute(this.peerId); |
|
}); |
|
|
|
listenerSetter.add(rootScope)('dialog_notify_settings', (dialog) => { |
|
if(this.peerId === dialog.peerId) { |
|
const muted = appNotificationsManager.isPeerLocalMuted(this.peerId, false); |
|
this.notifications.checkboxField.checked = !muted; |
|
} |
|
}); |
|
|
|
this.section.content.append(this.notifications.container); |
|
} |
|
|
|
this.element.append(this.section.container); |
|
|
|
if(IS_PARALLAX_SUPPORTED) { |
|
this.element.append(generateDelimiter()); |
|
} |
|
|
|
listenerSetter.add(rootScope)('peer_typings', ({peerId}) => { |
|
if(this.peerId === peerId) { |
|
this.setPeerStatus(); |
|
} |
|
}); |
|
|
|
listenerSetter.add(rootScope)('peer_bio_edit', (peerId) => { |
|
if(peerId === this.peerId) { |
|
this.setMoreDetails(true); |
|
} |
|
}); |
|
|
|
listenerSetter.add(rootScope)('peer_title_edit', (peerId) => { |
|
if(peerId === this.peerId) { |
|
this.fillUsername(); |
|
} |
|
}); |
|
|
|
listenerSetter.add(rootScope)('user_update', (userId) => { |
|
if(this.peerId === userId.toPeerId()) { |
|
this.setPeerStatus(); |
|
} |
|
}); |
|
|
|
listenerSetter.add(rootScope)('contacts_update', (userId) => { |
|
if(this.peerId === userId.toPeerId()) { |
|
const user = appUsersManager.getUser(userId); |
|
if(!user.pFlags.self || !this.isDialog) { |
|
this.fillUserPhone(); |
|
} |
|
} |
|
}); |
|
|
|
listenerSetter.add(rootScope)('avatar_update', (peerId) => { |
|
if(this.peerId === peerId) { |
|
// const photo = appPeersManager.getPeerPhoto(peerId); |
|
// if(!photo && this.avatars) { |
|
this.setAvatar(); |
|
// } |
|
} |
|
}); |
|
|
|
this.setPeerStatusInterval = window.setInterval(this.setPeerStatus, 60e3); |
|
} |
|
|
|
public setPeerStatus = (needClear = false) => { |
|
const peerId = this.peerId; |
|
this.element.classList.toggle('is-me', peerId === rootScope.myId); |
|
if(!peerId || (rootScope.myId === peerId && this.isDialog)) return; |
|
|
|
appImManager.setPeerStatus(this.peerId, this.subtitle, needClear, true, () => peerId === this.peerId, !this.isDialog); |
|
}; |
|
|
|
public cleanupHTML() { |
|
[ |
|
this.bio, |
|
this.phone, |
|
this.username, |
|
this.location, |
|
this.link |
|
].forEach(row => { |
|
row.container.style.display = 'none'; |
|
}); |
|
|
|
if(this.notifications) { |
|
this.notifications.container.style.display = ''; |
|
this.notifications.checkboxField.checked = true; |
|
} |
|
|
|
if(this.setMoreDetailsTimeout) { |
|
window.clearTimeout(this.setMoreDetailsTimeout); |
|
this.setMoreDetailsTimeout = 0; |
|
} |
|
} |
|
|
|
private canBeDetailed() { |
|
return this.peerId !== rootScope.myId || !this.isDialog; |
|
} |
|
|
|
public setAvatar() { |
|
if(this.canBeDetailed()) { |
|
const photo = appPeersManager.getPeerPhoto(this.peerId); |
|
|
|
if(photo) { |
|
const oldAvatars = this.avatars; |
|
this.avatars = new PeerProfileAvatars(this.scrollable); |
|
this.avatars.setPeer(this.peerId); |
|
this.avatars.info.append(this.name, this.subtitle); |
|
|
|
this.avatar.remove(); |
|
|
|
if(oldAvatars) oldAvatars.container.replaceWith(this.avatars.container); |
|
else this.element.prepend(this.avatars.container); |
|
|
|
if(IS_PARALLAX_SUPPORTED) { |
|
this.scrollable.container.classList.add('parallax'); |
|
} |
|
|
|
return; |
|
} |
|
} |
|
|
|
if(IS_PARALLAX_SUPPORTED) { |
|
this.scrollable.container.classList.remove('parallax'); |
|
} |
|
|
|
if(this.avatars) { |
|
this.avatars.container.remove(); |
|
this.avatars.cleanup(); |
|
this.avatars = undefined; |
|
} |
|
|
|
this.avatar.updateWithOptions({peerId: this.peerId}); |
|
|
|
this.section.content.prepend(this.avatar, this.name, this.subtitle); |
|
} |
|
|
|
private fillUsername() { |
|
const {peerId} = this; |
|
if(peerId.isUser() && this.canBeDetailed()) { |
|
const username = appPeersManager.getPeerUsername(peerId); |
|
setText(username, this.username); |
|
} |
|
} |
|
|
|
private fillUserPhone() { |
|
const {peerId} = this; |
|
if(peerId.isUser() && this.canBeDetailed()) { |
|
const user = appUsersManager.getUser(peerId); |
|
setText(user.phone ? appUsersManager.formatUserPhone(user.phone) : undefined, this.phone); |
|
} |
|
} |
|
|
|
private fillNotifications() { |
|
const notificationsRow = this.notifications; |
|
if(!notificationsRow) { |
|
return; |
|
} |
|
|
|
if(this.canBeDetailed()) { |
|
const muted = appNotificationsManager.isPeerLocalMuted(this.peerId, false); |
|
notificationsRow.checkboxField.checked = !muted; |
|
} else { |
|
fastRaf(() => { |
|
notificationsRow.container.style.display = 'none'; |
|
}); |
|
} |
|
} |
|
|
|
private fillRows() { |
|
const peerId = this.peerId; |
|
|
|
this.fillUsername(); |
|
this.fillUserPhone(); |
|
this.fillNotifications(); |
|
this.setMoreDetails(); |
|
|
|
replaceContent(this.name, new PeerTitle({ |
|
peerId, |
|
dialog: this.isDialog, |
|
}).element); |
|
|
|
this.name.append(...generateTitleIcons(peerId)); |
|
|
|
this.setPeerStatus(true); |
|
} |
|
|
|
public fillProfileElements() { |
|
if(!this.cleaned) return; |
|
this.cleaned = false; |
|
|
|
this.cleanupHTML(); |
|
this.setAvatar(); |
|
this.fillRows(); |
|
} |
|
|
|
public setMoreDetails(override?: true) { |
|
if(this.setMoreDetailsTimeout) { |
|
window.clearTimeout(this.setMoreDetailsTimeout); |
|
this.setMoreDetailsTimeout = 0; |
|
} |
|
|
|
const peerId = this.peerId; |
|
const threadId = this.threadId; |
|
|
|
if(!peerId || appPeersManager.isRestricted(peerId) || !this.canBeDetailed()) { |
|
return; |
|
} |
|
|
|
callbackify(appProfileManager.getProfileByPeerId(peerId, override), (peerFull) => { |
|
if(this.peerId !== peerId || this.threadId !== threadId || appPeersManager.isRestricted(peerId)) { |
|
//this.log.warn('peer changed'); |
|
return; |
|
} |
|
|
|
//this.log('chatInfo res 2:', chatFull); |
|
|
|
// if(peerFull.about) { |
|
setText(peerFull.about ? RichTextProcessor.wrapRichText(peerFull.about) : undefined, this.bio); |
|
// } |
|
|
|
if(!peerId.isUser()) { |
|
const chat: Chat.channel = appChatsManager.getChat(peerId.toChatId()); |
|
if(chat.username) { |
|
setText('https://t.me/' + chat.username, this.link); |
|
} else { |
|
const exportedInvite = (peerFull as ChatFull.channelFull).exported_invite; |
|
if(exportedInvite) { |
|
setText(exportedInvite.link, this.link); |
|
} |
|
} |
|
} |
|
|
|
const location = (peerFull as ChatFull.channelFull).location; |
|
if(location?._ == 'channelLocation') { |
|
setText(location.address, this.location); |
|
} |
|
|
|
this.setMoreDetailsTimeout = window.setTimeout(() => this.setMoreDetails(true), 60e3); |
|
}); |
|
} |
|
|
|
public setPeer(peerId: PeerId, threadId = 0) { |
|
if(this.peerId === peerId && this.threadId === threadId) return; |
|
|
|
if(this.init) { |
|
this.init(); |
|
} |
|
|
|
this.peerId = peerId; |
|
this.threadId = threadId; |
|
|
|
this.cleaned = true; |
|
} |
|
}
|
|
|