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
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(); |
|
} |
|
}
|
|
|