Voice chat UI changes

This commit is contained in:
Ali
2020-12-04 01:34:16 +00:00
parent dc4eed539e
commit b08e5eb0cf
24 changed files with 5097 additions and 4539 deletions

View File

@@ -26,6 +26,155 @@ public enum LocationBroadcastPanelSource {
case peer(PeerId)
}
final class AccountGroupCallContextImpl: AccountGroupCallContext {
final class Proxy {
let context: AccountGroupCallContextImpl
let removed: () -> Void
init(context: AccountGroupCallContextImpl, removed: @escaping () -> Void) {
self.context = context
self.removed = removed
}
deinit {
self.removed()
}
func keep() {
}
}
var disposable: Disposable?
var participantsContext: GroupCallParticipantsContext?
private let panelDataPromise = Promise<GroupCallPanelData>()
var panelData: Signal<GroupCallPanelData, NoError> {
return self.panelDataPromise.get()
}
init(account: Account, peerId: PeerId, call: CachedChannelData.ActiveCall) {
self.panelDataPromise.set(.single(GroupCallPanelData(
peerId: peerId,
info: GroupCallInfo(
id: call.id,
accessHash: call.accessHash,
participantCount: 0,
clientParams: nil
),
topParticipants: [],
participantCount: 0,
activeSpeakers: Set(),
groupCall: nil
)))
self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", limit: 100)
|> map(Optional.init)
|> `catch` { _ -> Signal<GroupCallParticipantsContext.State?, NoError> in
return .single(nil)
}
|> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self, let state = state else {
return
}
let context = GroupCallParticipantsContext(
account: account,
peerId: peerId,
id: call.id,
accessHash: call.accessHash,
state: state
)
strongSelf.participantsContext = context
strongSelf.panelDataPromise.set(combineLatest(queue: .mainQueue(),
context.state,
context.activeSpeakers
)
|> map { state, activeSpeakers -> GroupCallPanelData in
var topParticipants: [GroupCallParticipantsContext.Participant] = []
for participant in state.participants {
if topParticipants.count >= 3 {
break
}
topParticipants.append(participant)
}
return GroupCallPanelData(
peerId: peerId,
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil),
topParticipants: topParticipants,
participantCount: state.totalCount,
activeSpeakers: activeSpeakers,
groupCall: nil
)
})
})
}
deinit {
self.disposable?.dispose()
}
}
public final class AccountGroupCallContextCacheImpl: AccountGroupCallContextCache {
class Impl {
private class Record {
let context: AccountGroupCallContextImpl
let subscribers = Bag<Void>()
var removeTimer: SwiftSignalKit.Timer?
init(context: AccountGroupCallContextImpl) {
self.context = context
}
}
private let queue: Queue
private var contexts: [Int64: Record] = [:]
init(queue: Queue) {
self.queue = queue
}
func get(account: Account, peerId: PeerId, call: CachedChannelData.ActiveCall) -> AccountGroupCallContextImpl.Proxy {
let result: Record
if let current = self.contexts[call.id] {
result = current
} else {
let context = AccountGroupCallContextImpl(account: account, peerId: peerId, call: call)
result = Record(context: context)
self.contexts[call.id] = result
}
let index = result.subscribers.add(Void())
result.removeTimer?.invalidate()
result.removeTimer = nil
return AccountGroupCallContextImpl.Proxy(context: result.context, removed: { [weak self, weak result] in
Queue.mainQueue().async {
if let strongResult = result, let strongSelf = self, strongSelf.contexts[call.id] === strongResult {
strongResult.subscribers.remove(index)
if strongResult.subscribers.isEmpty {
let removeTimer = SwiftSignalKit.Timer(timeout: 30, repeat: false, completion: {
if let result = result, let strongSelf = self, strongSelf.contexts[call.id] === result, result.subscribers.isEmpty {
strongSelf.contexts.removeValue(forKey: call.id)
}
}, queue: .mainQueue())
strongResult.removeTimer = removeTimer
removeTimer.start()
}
}
}
})
}
}
let queue: Queue = .mainQueue()
let impl: QueueLocalObject<Impl>
public init() {
let queue = self.queue
self.impl = QueueLocalObject(queue: queue, generate: {
return Impl(queue: queue)
})
}
}
private func presentLiveLocationController(context: AccountContext, peerId: PeerId, controller: ViewController) {
let presentImpl: (Message?) -> Void = { [weak controller] message in
if let message = message, let strongController = controller {
@@ -265,7 +414,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
case .none, .all:
break
case let .peer(peerId):
let currentGroupCall: Signal<GroupCallPanelData?, NoError> = callManager.currentGroupCallSignal
/*let currentGroupCall: Signal<GroupCallPanelData?, NoError> = callManager.currentGroupCallSignal
|> distinctUntilChanged(isEqual: { lhs, rhs in
return lhs?.internalId == rhs?.internalId
})
@@ -295,7 +444,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
return SignalTakeAction(passthrough: true, complete: false)
}
})
}
}*/
let availableGroupCall: Signal<GroupCallPanelData?, NoError>
if case let .peer(peerId) = groupCallPanelSource {
@@ -311,7 +460,30 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
guard let activeCall = activeCall else {
return .single(nil)
}
return getGroupCallParticipants(account: context.account, callId: activeCall.id, accessHash: activeCall.accessHash, offset: "", limit: 10)
return Signal { [weak context] subscriber in
guard let context = context, let callContextCache = context.cachedGroupCallContexts as? AccountGroupCallContextCacheImpl else {
return EmptyDisposable
}
let disposable = MetaDisposable()
callContextCache.impl.syncWith { impl in
let callContext = impl.get(account: context.account, peerId: peerId, call: activeCall)
disposable.set((callContext.context.panelData
|> deliverOnMainQueue).start(next: { panelData in
callContext.keep()
subscriber.putNext(panelData)
}))
}
return ActionDisposable {
disposable.dispose()
}
}
|> runOn(.mainQueue())
/*let updatedData: Signal<GroupCallPanelData?, NoError> = getGroupCallParticipants(account: context.account, callId: activeCall.id, accessHash: activeCall.accessHash, offset: "", limit: 10)
|> map(Optional.init)
|> `catch` { _ -> Signal<GroupCallParticipantsContext.State?, NoError> in
return .single(nil)
@@ -365,20 +537,35 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
}
|> runOn(.mainQueue())
}
let initialData: Signal<GroupCallPanelData?, NoError> = .single(GroupCallPanelData(
peerId: peerId,
info: GroupCallInfo(
id: activeCall.id,
accessHash: activeCall.accessHash,
participantCount: 0,
clientParams: nil
),
topParticipants: [],
participantCount: 0,
numberOfActiveSpeakers: 0,
groupCall: nil
))
return initialData
|> then(updatedData)*/
}
} else {
availableGroupCall = .single(nil)
}
self.currentGroupCallDisposable = combineLatest(queue: .mainQueue(),
currentGroupCall,
availableGroupCall
).start(next: { [weak self] currentState, availableState in
self.currentGroupCallDisposable = (availableGroupCall
|> deliverOnMainQueue).start(next: { [weak self] availableState in
guard let strongSelf = self else {
return
}
let panelData = currentState != nil ? nil : availableState
let panelData = availableState
let wasEmpty = strongSelf.groupCallPanelData == nil
strongSelf.groupCallPanelData = panelData