mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +00:00
Merge commit '811f6981ca2f744e8521903b71cbf62a81983910'
This commit is contained in:
commit
470ea8f692
@ -265,6 +265,7 @@ public protocol PresentationGroupCall: class {
|
|||||||
var members: Signal<PresentationGroupCallMembers?, NoError> { get }
|
var members: Signal<PresentationGroupCallMembers?, NoError> { get }
|
||||||
var audioLevels: Signal<[(PeerId, Float)], NoError> { get }
|
var audioLevels: Signal<[(PeerId, Float)], NoError> { get }
|
||||||
var myAudioLevel: Signal<Float, NoError> { get }
|
var myAudioLevel: Signal<Float, NoError> { get }
|
||||||
|
var speakingAudioLevels: Signal<[(PeerId, Float)], NoError> { get }
|
||||||
var isMuted: Signal<Bool, NoError> { get }
|
var isMuted: Signal<Bool, NoError> { get }
|
||||||
|
|
||||||
func leave(terminateIfPossible: Bool) -> Signal<Bool, NoError>
|
func leave(terminateIfPossible: Bool) -> Signal<Bool, NoError>
|
||||||
|
|||||||
@ -403,6 +403,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
|||||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
||||||
strongSelf.mediaAccessoryPanel?.0.containerNode.updatePresentationData(presentationData)
|
strongSelf.mediaAccessoryPanel?.0.containerNode.updatePresentationData(presentationData)
|
||||||
strongSelf.locationBroadcastAccessoryPanel?.updatePresentationData(presentationData)
|
strongSelf.locationBroadcastAccessoryPanel?.updatePresentationData(presentationData)
|
||||||
|
strongSelf.groupCallAccessoryPanel?.updatePresentationData(presentationData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -217,7 +217,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePresentationData(_ presentationData: PresentationData) {
|
public func updatePresentationData(_ presentationData: PresentationData) {
|
||||||
self.theme = presentationData.theme
|
self.theme = presentationData.theme
|
||||||
self.strings = presentationData.strings
|
self.strings = presentationData.strings
|
||||||
|
|
||||||
@ -359,24 +359,13 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
strongSelf.micButton.view.insertSubview(audioLevelView, at: 0)
|
strongSelf.micButton.view.insertSubview(audioLevelView, at: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = value
|
|
||||||
if value <= 0.15 {
|
|
||||||
value = 0.0
|
|
||||||
}
|
|
||||||
let level = min(1.0, max(0.0, CGFloat(value)))
|
let level = min(1.0, max(0.0, CGFloat(value)))
|
||||||
let avatarScale: CGFloat
|
|
||||||
|
|
||||||
strongSelf.audioLevelView?.updateLevel(CGFloat(value) * 2.0)
|
strongSelf.audioLevelView?.updateLevel(CGFloat(value) * 2.0)
|
||||||
if value > 0.0 {
|
if value > 0.0 {
|
||||||
strongSelf.audioLevelView?.startAnimating()
|
strongSelf.audioLevelView?.startAnimating()
|
||||||
avatarScale = 1.03 + level * 0.1
|
|
||||||
} else {
|
} else {
|
||||||
strongSelf.audioLevelView?.stopAnimating(duration: 0.5)
|
strongSelf.audioLevelView?.stopAnimating(duration: 0.5)
|
||||||
avatarScale = 1.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .spring)
|
|
||||||
//transition.updateSublayerTransformScale(node: strongSelf.avatarNode, scale: avatarScale, beginWithCurrentState: true)
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
} else if data.groupCall == nil {
|
} else if data.groupCall == nil {
|
||||||
|
|||||||
@ -72,9 +72,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class SpeakingParticipantsContext {
|
private class SpeakingParticipantsContext {
|
||||||
private let speakingLevelThreshold: Float = 0.15
|
private let speakingLevelThreshold: Float = 0.1
|
||||||
private let cutoffTimeout: Int32 = 1
|
private let cutoffTimeout: Int32 = 3
|
||||||
private let silentTimeout: Int32 = 3
|
private let silentTimeout: Int32 = 2
|
||||||
|
|
||||||
struct Participant {
|
struct Participant {
|
||||||
let timestamp: Int32
|
let timestamp: Int32
|
||||||
@ -89,6 +89,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let audioLevelsPromise = Promise<[(PeerId, Float)]>()
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,13 +126,23 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var audioLevels: [(PeerId, Float)] = []
|
||||||
|
for (peerId, speaker) in validSpeakers {
|
||||||
|
audioLevels.append((peerId, speaker.level))
|
||||||
|
}
|
||||||
|
|
||||||
self.participants = validSpeakers
|
self.participants = validSpeakers
|
||||||
self.speakingParticipants = speakingParticipants
|
self.speakingParticipants = speakingParticipants
|
||||||
|
self.audioLevelsPromise.set(.single(audioLevels))
|
||||||
}
|
}
|
||||||
|
|
||||||
func get() -> Signal<Set<PeerId>, NoError> {
|
func get() -> Signal<Set<PeerId>, NoError> {
|
||||||
return self.speakingParticipantsPromise.get() |> distinctUntilChanged
|
return self.speakingParticipantsPromise.get() |> distinctUntilChanged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAudioLevels() -> Signal<[(PeerId, Float)], NoError> {
|
||||||
|
return self.audioLevelsPromise.get()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public let account: Account
|
public let account: Account
|
||||||
@ -189,9 +201,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
private var audioLevelsDisposable = MetaDisposable()
|
private var audioLevelsDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
|
||||||
private let speakingParticipantsContext = SpeakingParticipantsContext()
|
private let speakingParticipantsContext = SpeakingParticipantsContext()
|
||||||
private var speakingParticipantsReportTimestamp: [PeerId: Double] = [:]
|
private var speakingParticipantsReportTimestamp: [PeerId: Double] = [:]
|
||||||
|
public var speakingAudioLevels: Signal<[(PeerId, Float)], NoError> {
|
||||||
|
return self.speakingParticipantsContext.getAudioLevels()
|
||||||
|
}
|
||||||
|
|
||||||
private var participantsContextStateDisposable = MetaDisposable()
|
private var participantsContextStateDisposable = MetaDisposable()
|
||||||
private var participantsContext: GroupCallParticipantsContext?
|
private var participantsContext: GroupCallParticipantsContext?
|
||||||
|
|||||||
@ -137,21 +137,23 @@ public final class VoiceChatController: ViewController {
|
|||||||
}
|
}
|
||||||
return signal
|
return signal
|
||||||
|> mapToSignal { value in
|
|> mapToSignal { value in
|
||||||
if value > 0.0 {
|
|
||||||
return .single(value)
|
return .single(value)
|
||||||
|> then(.single(0.0) |> delay(1.0, queue: Queue.mainQueue()))
|
|
||||||
} else {
|
|
||||||
return .single(value)
|
|
||||||
}
|
|
||||||
} |> mapToThrottled { next -> Signal<Float, NoError> in
|
|
||||||
return .single(next) |> then(.complete() |> delay(0.1, queue: Queue.mainQueue()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateAudioLevels(_ levels: [(PeerId, Float)]) {
|
func updateAudioLevels(_ levels: [(PeerId, Float)], ignore: Set<PeerId> = Set()) {
|
||||||
|
var updated = Set<PeerId>()
|
||||||
for (peerId, level) in levels {
|
for (peerId, level) in levels {
|
||||||
if let pipe = self.audioLevels[peerId] {
|
if let pipe = self.audioLevels[peerId] {
|
||||||
pipe.putNext(level)
|
pipe.putNext(max(0.001, level))
|
||||||
|
updated.insert(peerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ignore.isEmpty {
|
||||||
|
for (peerId, pipe) in self.audioLevels {
|
||||||
|
if !updated.contains(peerId) && !ignore.contains(peerId) {
|
||||||
|
pipe.putNext(0.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,12 +597,12 @@ public final class VoiceChatController: ViewController {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
self.audioLevelsDisposable = (call.audioLevels
|
self.audioLevelsDisposable = (call.speakingAudioLevels
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] levels in
|
|> deliverOnMainQueue).start(next: { [weak self] levels in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.itemInteraction?.updateAudioLevels(levels)
|
strongSelf.itemInteraction?.updateAudioLevels(levels, ignore: Set([strongSelf.context.account.peerId]))
|
||||||
})
|
})
|
||||||
|
|
||||||
self.myAudioLevelDisposable = (call.myAudioLevel
|
self.myAudioLevelDisposable = (call.myAudioLevel
|
||||||
|
|||||||
@ -555,7 +555,7 @@ public class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if strongSelf.audioLevelView == nil {
|
if strongSelf.audioLevelView == nil, value > 0.0 {
|
||||||
let audioLevelView = VoiceBlobView(
|
let audioLevelView = VoiceBlobView(
|
||||||
frame: blobFrame,
|
frame: blobFrame,
|
||||||
maxLevel: 0.3,
|
maxLevel: 0.3,
|
||||||
@ -574,29 +574,27 @@ public class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||||||
playbackMaskLayer.path = maskPath.cgPath
|
playbackMaskLayer.path = maskPath.cgPath
|
||||||
audioLevelView.layer.mask = playbackMaskLayer
|
audioLevelView.layer.mask = playbackMaskLayer
|
||||||
|
|
||||||
audioLevelView.setColor(.green)
|
audioLevelView.setColor(UIColor(rgb: 0x34c759))
|
||||||
strongSelf.audioLevelView = audioLevelView
|
strongSelf.audioLevelView = audioLevelView
|
||||||
strongSelf.offsetContainerNode.view.insertSubview(audioLevelView, at: 0)
|
strongSelf.offsetContainerNode.view.insertSubview(audioLevelView, at: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = value
|
|
||||||
if value <= 0.15 {
|
|
||||||
value = 0.0
|
|
||||||
}
|
|
||||||
let level = min(1.0, max(0.0, CGFloat(value)))
|
let level = min(1.0, max(0.0, CGFloat(value)))
|
||||||
let avatarScale: CGFloat
|
if let audioLevelView = strongSelf.audioLevelView {
|
||||||
|
audioLevelView.updateLevel(CGFloat(value) * 2.0)
|
||||||
|
|
||||||
strongSelf.audioLevelView?.updateLevel(CGFloat(value) * 2.0)
|
let avatarScale: CGFloat
|
||||||
if value > 0.0 {
|
if value > 0.0 {
|
||||||
strongSelf.audioLevelView?.startAnimating()
|
audioLevelView.startAnimating()
|
||||||
avatarScale = 1.03 + level * 0.1
|
avatarScale = 1.03 + level * 0.1
|
||||||
} else {
|
} else {
|
||||||
strongSelf.audioLevelView?.stopAnimating(duration: 0.5)
|
audioLevelView.stopAnimating(duration: 0.5)
|
||||||
avatarScale = 1.0
|
avatarScale = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .spring)
|
let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .spring)
|
||||||
transition.updateTransformScale(node: strongSelf.avatarNode, scale: avatarScale, beginWithCurrentState: true)
|
transition.updateTransformScale(node: strongSelf.avatarNode, scale: avatarScale, beginWithCurrentState: true)
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
} else if let audioLevelView = strongSelf.audioLevelView {
|
} else if let audioLevelView = strongSelf.audioLevelView {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user