Voice Chat UI fixes

This commit is contained in:
Ali 2020-11-30 19:02:16 +04:00
parent c42525c87c
commit 131d80a1d9
5 changed files with 103 additions and 8 deletions

View File

@ -163,21 +163,29 @@ public struct PresentationGroupCallState: Equatable {
case connected case connected
} }
public enum DefaultParticipantMuteState {
case unmuted
case muted
}
public var networkState: NetworkState public var networkState: NetworkState
public var canManageCall: Bool public var canManageCall: Bool
public var adminIds: Set<PeerId> public var adminIds: Set<PeerId>
public var muteState: GroupCallParticipantsContext.Participant.MuteState? public var muteState: GroupCallParticipantsContext.Participant.MuteState?
public var defaultParticipantMuteState: DefaultParticipantMuteState?
public init( public init(
networkState: NetworkState, networkState: NetworkState,
canManageCall: Bool, canManageCall: Bool,
adminIds: Set<PeerId>, adminIds: Set<PeerId>,
muteState: GroupCallParticipantsContext.Participant.MuteState? muteState: GroupCallParticipantsContext.Participant.MuteState?,
defaultParticipantMuteState: DefaultParticipantMuteState?
) { ) {
self.networkState = networkState self.networkState = networkState
self.canManageCall = canManageCall self.canManageCall = canManageCall
self.adminIds = adminIds self.adminIds = adminIds
self.muteState = muteState self.muteState = muteState
self.defaultParticipantMuteState = defaultParticipantMuteState
} }
} }
@ -263,6 +271,7 @@ public protocol PresentationGroupCall: class {
func toggleIsMuted() func toggleIsMuted()
func setIsMuted(action: PresentationGroupCallMuteAction) func setIsMuted(action: PresentationGroupCallMuteAction)
func updateDefaultParticipantsAreMuted(isMuted: Bool)
func setCurrentAudioOutput(_ output: AudioSessionOutput) func setCurrentAudioOutput(_ output: AudioSessionOutput)
func updateMuteState(peerId: PeerId, isMuted: Bool) func updateMuteState(peerId: PeerId, isMuted: Bool)

View File

@ -21,7 +21,8 @@ private extension PresentationGroupCallState {
networkState: .connecting, networkState: .connecting,
canManageCall: false, canManageCall: false,
adminIds: Set(), adminIds: Set(),
muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true) muteState: GroupCallParticipantsContext.Participant.MuteState(canUnmute: true),
defaultParticipantMuteState: nil
) )
} }
} }
@ -389,7 +390,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
} }
} }
} }
case let .call(isTerminated): case let .call(isTerminated, _):
if isTerminated { if isTerminated {
strongSelf._canBeRemoved.set(.single(true)) strongSelf._canBeRemoved.set(.single(true))
} }
@ -579,6 +580,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.summaryInfoState.set(.single(SummaryInfoState(info: callInfo))) self.summaryInfoState.set(.single(SummaryInfoState(info: callInfo)))
self.stateValue.canManageCall = initialState.isCreator || initialState.adminIds.contains(self.accountContext.account.peerId) self.stateValue.canManageCall = initialState.isCreator || initialState.adminIds.contains(self.accountContext.account.peerId)
if self.stateValue.canManageCall && initialState.defaultParticipantsAreMuted.canChange {
self.stateValue.defaultParticipantMuteState = initialState.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
}
self.ssrcMapping.removeAll() self.ssrcMapping.removeAll()
var ssrcs: [UInt32] = [] var ssrcs: [UInt32] = []
@ -640,6 +644,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.stateValue.adminIds = state.adminIds strongSelf.stateValue.adminIds = state.adminIds
if (state.isCreator || state.adminIds.contains(strongSelf.accountContext.account.peerId)) && state.defaultParticipantsAreMuted.canChange {
strongSelf.stateValue.defaultParticipantMuteState = state.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
}
strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState( strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState(
participantCount: state.totalCount, participantCount: state.totalCount,
topParticipants: topParticipants, topParticipants: topParticipants,
@ -921,4 +929,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
} }
} }
} }
public func updateDefaultParticipantsAreMuted(isMuted: Bool) {
self.participantsContext?.updateDefaultParticipantsAreMuted(isMuted: isMuted)
}
} }

View File

@ -614,16 +614,36 @@ public final class VoiceChatController: ViewController {
var items: [ContextMenuItem] = [] var items: [ContextMenuItem] = []
if let callState = strongSelf.callState, callState.canManageCall { if let callState = strongSelf.callState, callState.canManageCall, let defaultParticipantMuteState = callState.defaultParticipantMuteState {
let isMuted = defaultParticipantMuteState == .muted
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_SpeakPermissionEveryone, icon: { theme in items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_SpeakPermissionEveryone, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.actionSheet.primaryTextColor) if isMuted {
return nil
} else {
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.actionSheet.primaryTextColor)
}
}, action: { _, f in }, action: { _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
guard let strongSelf = self else {
return
}
strongSelf.call.updateDefaultParticipantsAreMuted(isMuted: false)
}))) })))
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_SpeakPermissionAdmin, icon: { _ in return nil}, action: { _, f in items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_SpeakPermissionAdmin, icon: { theme in
if !isMuted {
return nil
} else {
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.actionSheet.primaryTextColor)
}
}, action: { _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
guard let strongSelf = self else {
return
}
strongSelf.call.updateDefaultParticipantsAreMuted(isMuted: true)
}))) })))
} }

View File

@ -2970,11 +2970,24 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
return current return current
} }
}) })
switch call {
case let .groupCall(flags, _, _, _, _, _):
let isMuted = (flags & (1 << 1)) != 0
let canChange = (flags & (1 << 2)) != 0
let defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: isMuted)
updatedGroupCallParticipants.append((
info.id,
.call(isTerminated: false, defaultParticipantsAreMuted: defaultParticipantsAreMuted)
))
default:
break
}
} }
case let .groupCallDiscarded(callId, _, _): case let .groupCallDiscarded(callId, _, _):
updatedGroupCallParticipants.append(( updatedGroupCallParticipants.append((
callId, callId,
.call(isTerminated: true) .call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false))
)) ))
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in

View File

@ -244,6 +244,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
nextParticipantsFetchOffset: nextParticipantsFetchOffset, nextParticipantsFetchOffset: nextParticipantsFetchOffset,
adminIds: Set(), adminIds: Set(),
isCreator: false, isCreator: false,
defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false),
totalCount: totalCount, totalCount: totalCount,
version: version version: version
) )
@ -322,6 +323,16 @@ public func joinGroupCall(account: Account, peerId: PeerId, callId: Int64, acces
switch update { switch update {
case let .updateGroupCall(_, call): case let .updateGroupCall(_, call):
maybeParsedCall = GroupCallInfo(call) maybeParsedCall = GroupCallInfo(call)
switch call {
case let .groupCall(flags, _, _, _, _, _):
let isMuted = (flags & (1 << 1)) != 0
let canChange = (flags & (1 << 2)) != 0
state.defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange)
default:
break
}
break loop break loop
default: default:
break break
@ -525,10 +536,16 @@ public final class GroupCallParticipantsContext {
} }
public struct State: Equatable { public struct State: Equatable {
public struct DefaultParticipantsAreMuted: Equatable {
public var isMuted: Bool
public var canChange: Bool
}
public var participants: [Participant] public var participants: [Participant]
public var nextParticipantsFetchOffset: String? public var nextParticipantsFetchOffset: String?
public var adminIds: Set<PeerId> public var adminIds: Set<PeerId>
public var isCreator: Bool public var isCreator: Bool
public var defaultParticipantsAreMuted: DefaultParticipantsAreMuted
public var totalCount: Int public var totalCount: Int
public var version: Int32 public var version: Int32
} }
@ -582,7 +599,7 @@ public final class GroupCallParticipantsContext {
} }
case state(update: StateUpdate) case state(update: StateUpdate)
case call(isTerminated: Bool) case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted)
} }
private let account: Account private let account: Account
@ -631,6 +648,8 @@ public final class GroupCallParticipantsContext {
private let updatesDisposable = MetaDisposable() private let updatesDisposable = MetaDisposable()
private var activitiesDisposable: Disposable? private var activitiesDisposable: Disposable?
private let updateDefaultMuteDisposable = MetaDisposable()
public init(account: Account, peerId: PeerId, id: Int64, accessHash: Int64, state: State) { public init(account: Account, peerId: PeerId, id: Int64, accessHash: Int64, state: State) {
self.account = account self.account = account
self.id = id self.id = id
@ -703,6 +722,7 @@ public final class GroupCallParticipantsContext {
nextParticipantsFetchOffset: strongSelf.stateValue.state.nextParticipantsFetchOffset, nextParticipantsFetchOffset: strongSelf.stateValue.state.nextParticipantsFetchOffset,
adminIds: strongSelf.stateValue.state.adminIds, adminIds: strongSelf.stateValue.state.adminIds,
isCreator: strongSelf.stateValue.state.isCreator, isCreator: strongSelf.stateValue.state.isCreator,
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
totalCount: strongSelf.stateValue.state.totalCount, totalCount: strongSelf.stateValue.state.totalCount,
version: strongSelf.stateValue.state.version version: strongSelf.stateValue.state.version
), ),
@ -716,6 +736,7 @@ public final class GroupCallParticipantsContext {
self.disposable.dispose() self.disposable.dispose()
self.updatesDisposable.dispose() self.updatesDisposable.dispose()
self.activitiesDisposable?.dispose() self.activitiesDisposable?.dispose()
self.updateDefaultMuteDisposable.dispose()
} }
public func addUpdates(updates: [Update]) { public func addUpdates(updates: [Update]) {
@ -723,6 +744,8 @@ public final class GroupCallParticipantsContext {
for update in updates { for update in updates {
if case let .state(update) = update { if case let .state(update) = update {
stateUpdates.append(update) stateUpdates.append(update)
} else if case let .call(_, defaultParticipantsAreMuted) = update {
self.stateValue.state.defaultParticipantsAreMuted = defaultParticipantsAreMuted
} }
} }
@ -835,6 +858,7 @@ public final class GroupCallParticipantsContext {
let nextParticipantsFetchOffset = strongSelf.stateValue.state.nextParticipantsFetchOffset let nextParticipantsFetchOffset = strongSelf.stateValue.state.nextParticipantsFetchOffset
let adminIds = strongSelf.stateValue.state.adminIds let adminIds = strongSelf.stateValue.state.adminIds
let isCreator = strongSelf.stateValue.state.isCreator let isCreator = strongSelf.stateValue.state.isCreator
let defaultParticipantsAreMuted = strongSelf.stateValue.state.defaultParticipantsAreMuted
updatedParticipants.sort() updatedParticipants.sort()
for i in 0 ..< updatedParticipants.count { for i in 0 ..< updatedParticipants.count {
@ -852,6 +876,7 @@ public final class GroupCallParticipantsContext {
nextParticipantsFetchOffset: nextParticipantsFetchOffset, nextParticipantsFetchOffset: nextParticipantsFetchOffset,
adminIds: adminIds, adminIds: adminIds,
isCreator: isCreator, isCreator: isCreator,
defaultParticipantsAreMuted: defaultParticipantsAreMuted,
totalCount: updatedTotalCount, totalCount: updatedTotalCount,
version: update.version version: update.version
), ),
@ -953,6 +978,22 @@ public final class GroupCallParticipantsContext {
} }
})) }))
} }
public func updateDefaultParticipantsAreMuted(isMuted: Bool) {
if isMuted == self.stateValue.state.defaultParticipantsAreMuted.isMuted {
return
}
self.stateValue.state.defaultParticipantsAreMuted.isMuted = isMuted
self.updateDefaultMuteDisposable.set((self.account.network.request(Api.functions.phone.toggleGroupCallSettings(flags: 1 << 0, call: .inputGroupCall(id: self.id, accessHash: self.accessHash), joinMuted: isMuted ? .boolTrue : .boolFalse))
|> deliverOnMainQueue).start(next: { [weak self] updates in
guard let strongSelf = self else {
return
}
strongSelf.account.stateManager.addUpdates(updates)
}))
}
} }
extension GroupCallParticipantsContext.Update.StateUpdate { extension GroupCallParticipantsContext.Update.StateUpdate {