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.
 
 
 
 
 

276 lines
8.7 KiB

/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import { cancelEvent } from "../helpers/dom/cancelEvent";
import { attachClickEvent } from "../helpers/dom/clickEvent";
import ListenerSetter from "../helpers/listenerSetter";
import type { AppGroupCallsManager } from "../lib/appManagers/appGroupCallsManager";
import GROUP_CALL_STATE from "../lib/calls/groupCallState";
import rootScope from "../lib/rootScope";
import ButtonIcon from "./buttonIcon";
import TopbarWeave from "./topbarWeave";
import SetTransition from "./singleTransition";
import PopupGroupCall from "./groupCall";
import type { AppPeersManager } from "../lib/appManagers/appPeersManager";
import type { AppChatsManager } from "../lib/appManagers/appChatsManager";
import GroupCallDescriptionElement from "./groupCall/description";
import GroupCallTitleElement from "./groupCall/title";
import PopupElement from "./popups";
import throttle from "../helpers/schedulers/throttle";
import GroupCallInstance from "../lib/calls/groupCallInstance";
import CALL_STATE from "../lib/calls/callState";
import replaceContent from "../helpers/dom/replaceContent";
import PeerTitle from "./peerTitle";
import CallDescriptionElement from "./call/description";
// import PopupCall from "./call";
import type { AppAvatarsManager } from "../lib/appManagers/appAvatarsManager";
import GroupCallMicrophoneIconMini from "./groupCall/microphoneIconMini";
function convertCallStateToGroupState(state: CALL_STATE, isMuted: boolean) {
switch(state) {
case CALL_STATE.CLOSING:
case CALL_STATE.CLOSED:
return GROUP_CALL_STATE.CLOSED;
case CALL_STATE.CONNECTED:
return isMuted ? GROUP_CALL_STATE.MUTED : GROUP_CALL_STATE.UNMUTED;
default:
return GROUP_CALL_STATE.CONNECTING;
}
}
const CLASS_NAME = 'topbar-call';
export default class TopbarCall {
public container: HTMLElement;
private listenerSetter: ListenerSetter;
private weave: TopbarWeave;
private center: HTMLDivElement;
private groupCallTitle: GroupCallTitleElement;
private groupCallDescription: GroupCallDescriptionElement;
private groupCallMicrophoneIconMini: GroupCallMicrophoneIconMini;
private callDescription: CallDescriptionElement;
private currentDescription: GroupCallDescriptionElement | CallDescriptionElement;
private instance: GroupCallInstance | any/* CallInstance */;
private instanceListenerSetter: ListenerSetter;
constructor(
private appGroupCallsManager: AppGroupCallsManager,
private appPeersManager: AppPeersManager,
private appChatsManager: AppChatsManager,
private appAvatarsManager: AppAvatarsManager,
) {
const listenerSetter = this.listenerSetter = new ListenerSetter();
listenerSetter.add(rootScope)('call_instance', ({instance, hasCurrent}) => {
if(!hasCurrent) {
this.updateInstance(instance);
}
});
listenerSetter.add(rootScope)('group_call_instance', (instance) => {
this.updateInstance(instance);
});
listenerSetter.add(rootScope)('group_call_update', (groupCall) => {
const instance = this.appGroupCallsManager.groupCall;
if(instance?.id === groupCall.id) {
this.updateInstance(instance);
}
});
listenerSetter.add(rootScope)('group_call_amplitude', ({amplitudes, type}) => {
const {weave} = this;
if(!amplitudes.length || !weave/* || type !== 'input' */) return;
let max = 0;
for(let i = 0; i < amplitudes.length; ++i) {
const {type, value} = amplitudes[i];
max = value > max ? value : max;
}
weave.setAmplitude(max);
});
}
private onState = () => {
this.updateInstance(this.instance);
};
private clearCurrentInstance() {
if(!this.instance) return;
this.center.textContent = '';
if(this.currentDescription) {
this.currentDescription.detach();
this.currentDescription = undefined;
}
this.instance = undefined;
this.instanceListenerSetter.removeAll();
}
private updateInstance(instance: TopbarCall['instance']) {
if(this.construct) {
this.construct();
this.construct = undefined;
}
if(this.instance !== instance) {
this.clearCurrentInstance();
this.instance = instance;
this.instanceListenerSetter = new ListenerSetter();
this.instanceListenerSetter.add(instance as GroupCallInstance)('state', this.onState);
if(instance instanceof GroupCallInstance) {
this.currentDescription = this.groupCallDescription;
} else {
this.currentDescription = this.callDescription;
this.instanceListenerSetter.add(instance)('muted', this.onState);
}
}
const isMuted = this.instance.isMuted;
let state = instance instanceof GroupCallInstance ? instance.state : convertCallStateToGroupState(instance.connectionState, isMuted);
const {weave} = this;
weave.componentDidMount();
const isClosed = state === GROUP_CALL_STATE.CLOSED;
if(!document.body.classList.contains('is-calling') || isClosed) {
if(isClosed) {
weave.setAmplitude(0);
}
SetTransition(document.body, 'is-calling', !isClosed, 250, isClosed ? () => {
weave.componentWillUnmount();
this.clearCurrentInstance();
}: undefined);
}
if(isClosed) {
return;
}
weave.setCurrentState(state, true);
// if(state === GROUP_CALL_STATE.CONNECTING) {
// weave.setCurrentState(state, true);
// } else {
// /* var a = 0;
// animate(() => {
// a += 0.1;
// if(a > 1) a = 0;
// weave.setAmplitude(a);
// return true;
// });
// weave.setAmplitude(1); */
// weave.setCurrentState(state, true);
// }
this.setTitle(instance);
this.setDescription(instance);
this.groupCallMicrophoneIconMini.setState(!isMuted);
}
private setDescription(instance: TopbarCall['instance']) {
return this.currentDescription.update(instance as any);
}
private setTitle(instance: TopbarCall['instance']) {
if(instance instanceof GroupCallInstance) {
return this.groupCallTitle.update(instance);
} else {
replaceContent(this.center, new PeerTitle({peerId: instance.interlocutorUserId.toPeerId()}).element);
}
}
private construct() {
const {listenerSetter} = this;
const container = this.container = document.createElement('div');
container.classList.add('sidebar-header', CLASS_NAME + '-container');
const left = document.createElement('div');
left.classList.add(CLASS_NAME + '-left');
const groupCallMicrophoneIconMini = this.groupCallMicrophoneIconMini = new GroupCallMicrophoneIconMini();
const mute = ButtonIcon();
mute.append(groupCallMicrophoneIconMini.container);
left.append(mute);
const throttledMuteClick = throttle(() => {
this.instance.toggleMuted();
}, 600, true);
attachClickEvent(mute, (e) => {
cancelEvent(e);
throttledMuteClick();
}, {listenerSetter});
const center = this.center = document.createElement('div');
center.classList.add(CLASS_NAME + '-center');
this.groupCallTitle = new GroupCallTitleElement(center);
this.groupCallDescription = new GroupCallDescriptionElement(left);
this.callDescription = new CallDescriptionElement(left);
const right = document.createElement('div');
right.classList.add(CLASS_NAME + '-right');
const end = ButtonIcon('endcall_filled');
right.append(end);
attachClickEvent(end, (e) => {
cancelEvent(e);
const {instance} = this;
if(!instance) {
return;
}
if(instance instanceof GroupCallInstance) {
instance.hangUp();
} else {
instance.hangUp('phoneCallDiscardReasonHangup');
}
}, {listenerSetter});
attachClickEvent(container, () => {
if(this.instance instanceof GroupCallInstance) {
if(PopupElement.getPopup(PopupGroupCall)) {
return;
}
new PopupGroupCall({
appGroupCallsManager: this.appGroupCallsManager,
appPeersManager: this.appPeersManager,
appChatsManager: this.appChatsManager
}).show();
}/* else if(this.instance instanceof CallInstance) {
new PopupCall({
appAvatarsManager: this.appAvatarsManager,
appPeersManager: this.appPeersManager,
instance: this.instance
}).show();
} */
}, {listenerSetter});
container.append(left, center, right);
const weave = this.weave = new TopbarWeave();
const weaveContainer = weave.render();
container.prepend(weaveContainer);
document.getElementById('column-center').prepend(container);
weave.componentDidMount();
}
}