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

View File

@ -21,7 +21,8 @@ private extension PresentationGroupCallState {
networkState: .connecting,
canManageCall: false,
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 {
strongSelf._canBeRemoved.set(.single(true))
}
@ -579,6 +580,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.summaryInfoState.set(.single(SummaryInfoState(info: callInfo)))
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()
var ssrcs: [UInt32] = []
@ -640,6 +644,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
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(
participantCount: state.totalCount,
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] = []
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
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
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)
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
}
})
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, _, _):
updatedGroupCallParticipants.append((
callId,
.call(isTerminated: true)
.call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false))
))
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in

View File

@ -244,6 +244,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
nextParticipantsFetchOffset: nextParticipantsFetchOffset,
adminIds: Set(),
isCreator: false,
defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false),
totalCount: totalCount,
version: version
)
@ -322,6 +323,16 @@ public func joinGroupCall(account: Account, peerId: PeerId, callId: Int64, acces
switch update {
case let .updateGroupCall(_, 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
default:
break
@ -525,10 +536,16 @@ public final class GroupCallParticipantsContext {
}
public struct State: Equatable {
public struct DefaultParticipantsAreMuted: Equatable {
public var isMuted: Bool
public var canChange: Bool
}
public var participants: [Participant]
public var nextParticipantsFetchOffset: String?
public var adminIds: Set<PeerId>
public var isCreator: Bool
public var defaultParticipantsAreMuted: DefaultParticipantsAreMuted
public var totalCount: Int
public var version: Int32
}
@ -582,7 +599,7 @@ public final class GroupCallParticipantsContext {
}
case state(update: StateUpdate)
case call(isTerminated: Bool)
case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted)
}
private let account: Account
@ -631,6 +648,8 @@ public final class GroupCallParticipantsContext {
private let updatesDisposable = MetaDisposable()
private var activitiesDisposable: Disposable?
private let updateDefaultMuteDisposable = MetaDisposable()
public init(account: Account, peerId: PeerId, id: Int64, accessHash: Int64, state: State) {
self.account = account
self.id = id
@ -703,6 +722,7 @@ public final class GroupCallParticipantsContext {
nextParticipantsFetchOffset: strongSelf.stateValue.state.nextParticipantsFetchOffset,
adminIds: strongSelf.stateValue.state.adminIds,
isCreator: strongSelf.stateValue.state.isCreator,
defaultParticipantsAreMuted: strongSelf.stateValue.state.defaultParticipantsAreMuted,
totalCount: strongSelf.stateValue.state.totalCount,
version: strongSelf.stateValue.state.version
),
@ -716,6 +736,7 @@ public final class GroupCallParticipantsContext {
self.disposable.dispose()
self.updatesDisposable.dispose()
self.activitiesDisposable?.dispose()
self.updateDefaultMuteDisposable.dispose()
}
public func addUpdates(updates: [Update]) {
@ -723,6 +744,8 @@ public final class GroupCallParticipantsContext {
for update in updates {
if case let .state(update) = 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 adminIds = strongSelf.stateValue.state.adminIds
let isCreator = strongSelf.stateValue.state.isCreator
let defaultParticipantsAreMuted = strongSelf.stateValue.state.defaultParticipantsAreMuted
updatedParticipants.sort()
for i in 0 ..< updatedParticipants.count {
@ -852,6 +876,7 @@ public final class GroupCallParticipantsContext {
nextParticipantsFetchOffset: nextParticipantsFetchOffset,
adminIds: adminIds,
isCreator: isCreator,
defaultParticipantsAreMuted: defaultParticipantsAreMuted,
totalCount: updatedTotalCount,
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 {