Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
overtake 2021-04-08 11:19:51 +04:00
commit a7d322999a
27 changed files with 133 additions and 70 deletions

Binary file not shown.

View File

@ -187,6 +187,7 @@ public struct PresentationGroupCallState: Equatable {
public var title: String?
public var raisedHand: Bool
public var scheduleTimestamp: Int32?
public var subscribedToScheduled: Bool
public init(
myPeerId: PeerId,
@ -198,7 +199,8 @@ public struct PresentationGroupCallState: Equatable {
recordingStartTimestamp: Int32?,
title: String?,
raisedHand: Bool,
scheduleTimestamp: Int32?
scheduleTimestamp: Int32?,
subscribedToScheduled: Bool
) {
self.myPeerId = myPeerId
self.networkState = networkState
@ -210,6 +212,7 @@ public struct PresentationGroupCallState: Equatable {
self.title = title
self.raisedHand = raisedHand
self.scheduleTimestamp = scheduleTimestamp
self.subscribedToScheduled = subscribedToScheduled
}
}
@ -323,6 +326,7 @@ public protocol PresentationGroupCall: class {
var memberEvents: Signal<PresentationGroupCallMemberEvent, NoError> { get }
var reconnectedAsEvents: Signal<Peer, NoError> { get }
func toggleScheduledSubscription(_ subscribe: Bool)
func schedule(timestamp: Int32)
func startScheduled()

View File

@ -160,20 +160,20 @@ public final class CachedChannelData: CachedPeerData {
public var accessHash: Int64
public var title: String?
public var scheduleTimestamp: Int32?
public var subscribed: Bool
public var subscribedToScheduled: Bool
public init(
id: Int64,
accessHash: Int64,
title: String?,
scheduleTimestamp: Int32?,
subscribed: Bool
subscribedToScheduled: Bool
) {
self.id = id
self.accessHash = accessHash
self.title = title
self.scheduleTimestamp = scheduleTimestamp
self.subscribed = subscribed
self.subscribedToScheduled = subscribedToScheduled
}
public init(decoder: PostboxDecoder) {
@ -181,7 +181,7 @@ public final class CachedChannelData: CachedPeerData {
self.accessHash = decoder.decodeInt64ForKey("accessHash", orElse: 0)
self.title = decoder.decodeOptionalStringForKey("title")
self.scheduleTimestamp = decoder.decodeOptionalInt32ForKey("scheduleTimestamp")
self.subscribed = decoder.decodeBoolForKey("subscribed", orElse: false)
self.subscribedToScheduled = decoder.decodeBoolForKey("subscribed", orElse: false)
}
public func encode(_ encoder: PostboxEncoder) {
@ -197,7 +197,7 @@ public final class CachedChannelData: CachedPeerData {
} else {
encoder.encodeNil(forKey: "scheduleTimestamp")
}
encoder.encodeBool(self.subscribed, forKey: "subscribed")
encoder.encodeBool(self.subscribedToScheduled, forKey: "subscribed")
}
}

View File

@ -406,7 +406,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
strongSelf.joinGroupCall(
peerId: groupCallPanelData.peerId,
invite: nil,
activeCall: CachedChannelData.ActiveCall(id: groupCallPanelData.info.id, accessHash: groupCallPanelData.info.accessHash, title: groupCallPanelData.info.title, scheduleTimestamp: groupCallPanelData.info.scheduleTimestamp, subscribed: false)
activeCall: CachedChannelData.ActiveCall(id: groupCallPanelData.info.id, accessHash: groupCallPanelData.info.accessHash, title: groupCallPanelData.info.title, scheduleTimestamp: groupCallPanelData.info.scheduleTimestamp, subscribedToScheduled: groupCallPanelData.info.subscribedToScheduled)
)
})
if let navigationBar = self.navigationBar {

View File

@ -505,7 +505,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
transition.updateFrame(node: self.avatarsNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - avatarsSize.width) / 2.0), y: floor((size.height - avatarsSize.height) / 2.0)), size: avatarsSize))
}
var joinText = self.strings.VoiceChat_PanelJoin.uppercased()
var joinText = self.strings.VoiceChat_PanelJoin
var title = self.strings.VoiceChat_Title
var text = self.currentText
var isScheduled = false
@ -554,7 +554,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
self.updateJoinButton()
}
self.joinButtonTitleNode.attributedText = NSAttributedString(string: joinText, font: Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.theme.chat.inputPanel.actionControlForegroundColor)
self.joinButtonTitleNode.attributedText = NSAttributedString(string: joinText.uppercased(), font: Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.theme.chat.inputPanel.actionControlForegroundColor)
let joinButtonTitleSize = self.joinButtonTitleNode.updateLayout(CGSize(width: 150.0, height: .greatestFiniteMagnitude))
let joinButtonSize = CGSize(width: joinButtonTitleSize.width + 20.0, height: 28.0)

View File

@ -78,6 +78,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
streamDcId: nil,
title: call.title,
scheduleTimestamp: call.scheduleTimestamp,
subscribedToScheduled: call.subscribedToScheduled,
recordingStartTimestamp: nil,
sortAscending: true
),
@ -121,7 +122,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
}
return GroupCallPanelData(
peerId: peerId,
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: state.title, scheduleTimestamp: state.scheduleTimestamp, recordingStartTimestamp: nil, sortAscending: state.sortAscending),
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: state.title, scheduleTimestamp: state.scheduleTimestamp, subscribedToScheduled: state.subscribedToScheduled, recordingStartTimestamp: nil, sortAscending: state.sortAscending),
topParticipants: topParticipants,
participantCount: state.totalCount,
activeSpeakers: activeSpeakers,
@ -206,7 +207,7 @@ public final class AccountGroupCallContextCacheImpl: AccountGroupCallContextCach
}
private extension PresentationGroupCallState {
static func initialValue(myPeerId: PeerId, title: String?, scheduleTimestamp: Int32?) -> PresentationGroupCallState {
static func initialValue(myPeerId: PeerId, title: String?, scheduleTimestamp: Int32?, subscribedToScheduled: Bool) -> PresentationGroupCallState {
return PresentationGroupCallState(
myPeerId: myPeerId,
networkState: .connecting,
@ -217,7 +218,8 @@ private extension PresentationGroupCallState {
recordingStartTimestamp: nil,
title: title,
raisedHand: false,
scheduleTimestamp: scheduleTimestamp
scheduleTimestamp: scheduleTimestamp,
subscribedToScheduled: subscribedToScheduled
)
}
}
@ -511,6 +513,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
private let joinDisposable = MetaDisposable()
private let requestDisposable = MetaDisposable()
private let startDisposable = MetaDisposable()
private let subscribeDisposable = MetaDisposable()
private var groupCallParticipantUpdatesDisposable: Disposable?
private let networkStateDisposable = MetaDisposable()
@ -579,7 +582,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.joinAsPeerId = joinAsPeerId ?? accountContext.account.peerId
self.schedulePending = initialCall == nil
self.stateValue = PresentationGroupCallState.initialValue(myPeerId: self.joinAsPeerId, title: initialCall?.title, scheduleTimestamp: initialCall?.scheduleTimestamp)
self.stateValue = PresentationGroupCallState.initialValue(myPeerId: self.joinAsPeerId, title: initialCall?.title, scheduleTimestamp: initialCall?.scheduleTimestamp, subscribedToScheduled: initialCall?.subscribedToScheduled ?? false)
self.statePromise = ValuePromise(self.stateValue)
self.temporaryJoinTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
@ -734,7 +737,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
addedParticipants.append((ssrc, participantUpdate.jsonParams))
}
}
case let .call(isTerminated, _, _, _):
case let .call(isTerminated, _, _, _, _):
if isTerminated {
strongSelf.markAsCanBeRemoved()
}
@ -767,7 +770,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
})
if let initialCall = initialCall, let temporaryParticipantsContext = (self.accountContext.cachedGroupCallContexts as? AccountGroupCallContextCacheImpl)?.impl.syncWith({ impl in
impl.get(account: accountContext.account, peerId: peerId, call: CachedChannelData.ActiveCall(id: initialCall.id, accessHash: initialCall.accessHash, title: initialCall.title, scheduleTimestamp: initialCall.scheduleTimestamp, subscribed: initialCall.subscribed))
impl.get(account: accountContext.account, peerId: peerId, call: CachedChannelData.ActiveCall(id: initialCall.id, accessHash: initialCall.accessHash, title: initialCall.title, scheduleTimestamp: initialCall.scheduleTimestamp, subscribedToScheduled: initialCall.subscribedToScheduled))
}) {
self.switchToTemporaryParticipantsContext(sourceContext: temporaryParticipantsContext.context.participantsContext, oldMyPeerId: self.joinAsPeerId)
} else {
@ -824,6 +827,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.joinDisposable.dispose()
self.requestDisposable.dispose()
self.startDisposable.dispose()
self.subscribeDisposable.dispose()
self.groupCallParticipantUpdatesDisposable?.dispose()
self.leaveDisposable.dispose()
self.isMutedDisposable.dispose()
@ -1666,6 +1670,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
streamDcId: nil,
title: state.title,
scheduleTimestamp: state.scheduleTimestamp,
subscribedToScheduled: false,
recordingStartTimestamp: state.recordingStartTimestamp,
sortAscending: state.sortAscending
))))
@ -1987,6 +1992,17 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.callContext?.setIsNoiseSuppressionEnabled(isNoiseSuppressionEnabled)
}
public func toggleScheduledSubscription(_ subscribe: Bool) {
guard case let .active(callInfo) = self.internalState, callInfo.scheduleTimestamp != nil else {
return
}
self.stateValue.subscribedToScheduled = subscribe
self.subscribeDisposable.set((toggleScheduledGroupCallSubscription(account: self.account, peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash, subscribe: subscribe)
|> deliverOnMainQueue).start())
}
public func schedule(timestamp: Int32) {
guard self.schedulePending else {
return
@ -2270,7 +2286,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
if let value = value {
strongSelf.initialCall = CachedChannelData.ActiveCall(id: value.id, accessHash: value.accessHash, title: value.title, scheduleTimestamp: nil, subscribed: false)
strongSelf.initialCall = CachedChannelData.ActiveCall(id: value.id, accessHash: value.accessHash, title: value.title, scheduleTimestamp: nil, subscribedToScheduled: false)
strongSelf.updateSessionState(internalState: .active(value), audioSessionControl: strongSelf.audioSessionControl)
} else {

View File

@ -607,11 +607,11 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
self.maskProgressLayer.lineCap = .round
self.maskProgressLayer.path = path
let circleFrame = CGRect(origin: CGPoint(x: (358 - buttonSize.width) / 2.0, y: (358 - buttonSize.height) / 2.0), size: buttonSize).insetBy(dx: -progressLineWidth / 2.0, dy: -progressLineWidth / 2.0)
let circleFrame = CGRect(origin: CGPoint(x: (areaSize.width - buttonSize.width) / 2.0, y: (areaSize.height - buttonSize.height) / 2.0), size: buttonSize).insetBy(dx: -progressLineWidth / 2.0, dy: -progressLineWidth / 2.0)
let largerCirclePath = UIBezierPath(roundedRect: CGRect(x: circleFrame.minX, y: circleFrame.minY, width: circleFrame.width, height: circleFrame.height), cornerRadius: circleFrame.width / 2.0).cgPath
self.maskCircleLayer.fillColor = white.cgColor
self.maskCircleLayer.path = largerCirclePath
self.maskCircleLayer.fillColor = white.cgColor
self.maskCircleLayer.isHidden = true
updateInHierarchy = { [weak self] value in
@ -971,6 +971,7 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
CATransaction.commit()
}
private var maskIsCircle = true
private func setupButtonAnimation() {
CATransaction.begin()
CATransaction.setDisableActions(true)
@ -982,6 +983,7 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
let path = UIBezierPath(roundedRect: CGRect(x: 0.0, y: floor((self.bounds.height - buttonHeight) / 2.0), width: self.bounds.width, height: buttonHeight), cornerRadius: 10.0).cgPath
self.maskCircleLayer.path = path
self.maskIsCircle = false
CATransaction.commit()
@ -1001,6 +1003,7 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
let previousPath = self.maskCircleLayer.path
self.maskCircleLayer.path = largerCirclePath
self.maskIsCircle = true
self.maskCircleLayer.animateSpring(from: previousPath as AnyObject, to: largerCirclePath as AnyObject, keyPath: "path", duration: 0.42, initialVelocity: 0.0, damping: 104.0)
@ -1144,9 +1147,13 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
self.updateAnimations()
}
var previousSize: CGSize?
override func layout() {
super.layout()
let sizeUpdated = self.previousSize != self.bounds.size
self.previousSize = self.bounds.size
let bounds = CGRect(x: (self.bounds.width - areaSize.width) / 2.0, y: (self.bounds.height - areaSize.height) / 2.0, width: areaSize.width, height: areaSize.height)
let center = bounds.center
@ -1159,7 +1166,17 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
self.growingForegroundCircleLayer.position = center
self.growingForegroundCircleLayer.bounds = self.foregroundCircleLayer.bounds
self.maskCircleLayer.frame = self.bounds
// circleFrame.insetBy(dx: -progressLineWidth / 2.0, dy: -progressLineWidth / 2.0)
if sizeUpdated && self.maskIsCircle {
CATransaction.begin()
CATransaction.setDisableActions(true)
let circleFrame = CGRect(origin: CGPoint(x: (self.bounds.width - buttonSize.width) / 2.0, y: (self.bounds.height - buttonSize.height) / 2.0), size: buttonSize).insetBy(dx: -progressLineWidth / 2.0, dy: -progressLineWidth / 2.0)
let largerCirclePath = UIBezierPath(roundedRect: CGRect(x: circleFrame.minX, y: circleFrame.minY, width: circleFrame.width, height: circleFrame.height), cornerRadius: circleFrame.width / 2.0).cgPath
self.maskCircleLayer.path = largerCirclePath
CATransaction.commit()
}
self.maskProgressLayer.frame = circleFrame.insetBy(dx: -3.0, dy: -3.0)
self.foregroundView.frame = self.bounds
self.foregroundGradientLayer.frame = self.bounds
@ -1543,22 +1560,22 @@ final class VoiceChatActionButtonIconNode: ManagedAnimationNode {
case .subscribe:
switch state {
case .unsubscribe:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceStart")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceCancelReminder")))
case .mute:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceStart")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceSetReminderToMute")))
case .hand:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceStart")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceSetReminderToRaiseHand")))
default:
break
}
case .unsubscribe:
switch state {
case .subscribe:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceStart")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceSetReminder")))
case .mute:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceStart")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceCancelReminderToMute")))
case .hand:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceStart")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceCancelReminderToRaiseHand")))
default:
break
}
@ -1574,7 +1591,7 @@ final class VoiceChatActionButtonIconNode: ManagedAnimationNode {
case .mute:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceMute")))
case .hand:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceHandOff2")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceUnmuteToRaiseHand")))
default:
break
}
@ -1585,7 +1602,11 @@ final class VoiceChatActionButtonIconNode: ManagedAnimationNode {
case .unmute:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceUnmute")))
case .hand:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceHandOff")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceMuteToRaiseHand")))
case .subscribe:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceSetReminderToRaiseHand"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.001))
case .unsubscribe:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceCancelReminderToRaiseHand"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.001))
case .empty:
self.alpha = 0.0
default:
@ -1594,7 +1615,7 @@ final class VoiceChatActionButtonIconNode: ManagedAnimationNode {
case .hand:
switch state {
case .mute, .unmute:
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceHandOn")))
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceRaiseHandToMute")))
default:
break
}

View File

@ -2438,10 +2438,14 @@ public final class VoiceChatController: ViewController {
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
if self.isScheduling {
self.dismissScheduled()
} else {
self.controller?.dismiss(closing: false)
self.controller?.dismissAllTooltips()
}
}
}
private func presentUndoOverlay(content: UndoOverlayContent, action: @escaping (UndoOverlayAction) -> Bool) {
var animateInAsReplacement = false
@ -2594,7 +2598,7 @@ public final class VoiceChatController: ViewController {
self.call.startScheduled()
self.transitionToCall()
} else {
self.call.toggleScheduledSubscription(!callState.subscribedToScheduled)
}
}
default:
@ -2670,8 +2674,6 @@ public final class VoiceChatController: ViewController {
|> deliverOnMainQueue).start(next: { [weak self] inviteLinks in
if let inviteLinks = inviteLinks {
self?.presentShare(inviteLinks)
} else {
self?.presentShare(GroupCallInviteLinks(listenerLink: "a", speakerLink: nil))
}
})
return
@ -3199,16 +3201,20 @@ public final class VoiceChatController: ViewController {
let actionButtonSubtitle: String
var actionButtonEnabled = true
if let callState = self.callState, !self.isScheduling {
var isScheduled = callState.scheduleTimestamp != nil
if isScheduled {
if callState.scheduleTimestamp != nil {
self.ignoreNextConnecting = true
if callState.canManageCall {
actionButtonState = .scheduled(state: .start)
actionButtonTitle = self.presentationData.strings.VoiceChat_StartNow
actionButtonSubtitle = ""
} else {
if callState.subscribedToScheduled {
actionButtonState = .scheduled(state: .unsubscribe)
actionButtonTitle = self.presentationData.strings.VoiceChat_CancelReminder
} else {
actionButtonState = .scheduled(state: .subscribe)
actionButtonTitle = self.presentationData.strings.VoiceChat_SetReminder
}
actionButtonSubtitle = ""
}
} else {
@ -3681,6 +3687,7 @@ public final class VoiceChatController: ViewController {
@objc func panGesture(_ recognizer: UIPanGestureRecognizer) {
let contentOffset = self.listNode.visibleContentOffset()
let isScheduling = self.isScheduling || self.callState?.scheduleTimestamp != nil
switch recognizer.state {
case .began:
let topInset: CGFloat
@ -3696,7 +3703,7 @@ public final class VoiceChatController: ViewController {
self.controller?.dismissAllTooltips()
case .changed:
var translation = recognizer.translation(in: self.contentContainer.view).y
if (self.isScheduling || self.callState?.scheduleTimestamp != nil) && translation < 0.0 {
if isScheduling && translation < 0.0 {
return
}
var topInset: CGFloat = 0.0
@ -3802,7 +3809,7 @@ public final class VoiceChatController: ViewController {
self.controller?.dismiss(closing: false, manual: true)
}
dismissing = true
} else if !self.isScheduling && (velocity.y < -300.0 || offset < topInset / 2.0) {
} else if !isScheduling && (velocity.y < -300.0 || offset < topInset / 2.0) {
if velocity.y > -1500.0 && !self.isFullscreen {
DispatchQueue.main.async {
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
@ -3819,7 +3826,7 @@ public final class VoiceChatController: ViewController {
self.updateFloatingHeaderOffset(offset: self.currentContentOffset ?? 0.0, transition: .animated(duration: 0.3, curve: .easeInOut), completion: {
self.animatingExpansion = false
})
} else if !self.isScheduling {
} else if !isScheduling {
self.updateIsFullscreen(false)
self.animatingExpansion = true
self.listNode.scroller.setContentOffset(CGPoint(), animated: false)

View File

@ -145,7 +145,7 @@ public final class VoiceChatJoinScreen: ViewController {
defaultJoinAsPeerId = cachedData.callJoinPeerId
}
let activeCall = CachedChannelData.ActiveCall(id: call.info.id, accessHash: call.info.accessHash, title: call.info.title, scheduleTimestamp: call.info.scheduleTimestamp, subscribed: false)
let activeCall = CachedChannelData.ActiveCall(id: call.info.id, accessHash: call.info.accessHash, title: call.info.title, scheduleTimestamp: call.info.scheduleTimestamp, subscribedToScheduled: call.info.subscribedToScheduled)
if availablePeers.count > 0 && defaultJoinAsPeerId == nil {
strongSelf.dismiss()
strongSelf.join(activeCall)

View File

@ -136,7 +136,7 @@ final class VoiceChatTimerNode: ASDisplayNode {
self.subtitleNode.attributedText = NSAttributedString(string: subtitle, font: Font.with(size: 21.0, design: .round, weight: .semibold, traits: []), textColor: .white)
let subtitleSize = self.subtitleNode.updateLayout(size)
self.subtitleNode.frame = CGRect(x: floor((size.width - subtitleSize.width) / 2.0), y: 164.0, width: timerSize.width, height: subtitleSize.height)
self.subtitleNode.frame = CGRect(x: floor((size.width - subtitleSize.width) / 2.0), y: 164.0, width: subtitleSize.width, height: subtitleSize.height)
self.foregroundView.frame = CGRect(origin: CGPoint(), size: size)
}

View File

@ -12,6 +12,7 @@ public struct GroupCallInfo: Equatable {
public var streamDcId: Int32?
public var title: String?
public var scheduleTimestamp: Int32?
public var subscribedToScheduled: Bool
public var recordingStartTimestamp: Int32?
public var sortAscending: Bool
@ -23,6 +24,7 @@ public struct GroupCallInfo: Equatable {
streamDcId: Int32?,
title: String?,
scheduleTimestamp: Int32?,
subscribedToScheduled: Bool,
recordingStartTimestamp: Int32?,
sortAscending: Bool
) {
@ -33,6 +35,7 @@ public struct GroupCallInfo: Equatable {
self.streamDcId = streamDcId
self.title = title
self.scheduleTimestamp = scheduleTimestamp
self.subscribedToScheduled = subscribedToScheduled
self.recordingStartTimestamp = recordingStartTimestamp
self.sortAscending = sortAscending
}
@ -62,6 +65,7 @@ extension GroupCallInfo {
streamDcId: streamDcId,
title: title,
scheduleTimestamp: scheduleDate,
subscribedToScheduled: (flags & (1 << 8)) != 0,
recordingStartTimestamp: recordStartDate,
sortAscending: (flags & (1 << 6)) != 0
)
@ -226,9 +230,9 @@ public func createGroupCall(account: Account, peerId: PeerId, title: String?, sc
return account.postbox.transaction { transaction -> GroupCallInfo in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribed: false))
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribedToScheduled: callInfo.subscribedToScheduled))
} else if let cachedData = cachedData as? CachedGroupData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribed: false))
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribedToScheduled: callInfo.subscribedToScheduled))
} else {
return cachedData
}
@ -271,9 +275,9 @@ public func startScheduledGroupCall(account: Account, peerId: PeerId, callId: In
return account.postbox.transaction { transaction -> GroupCallInfo in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: nil, subscribed: false))
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: nil, subscribedToScheduled: false))
} else if let cachedData = cachedData as? CachedGroupData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: nil, subscribed: false))
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: nil, subscribedToScheduled: false))
} else {
return cachedData
}
@ -315,9 +319,9 @@ public func toggleScheduledGroupCallSubscription(account: Account, peerId: PeerI
return account.postbox.transaction { transaction in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribed: subscribe))
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribedToScheduled: callInfo.subscribedToScheduled))
} else if let cachedData = cachedData as? CachedGroupData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribed: subscribe))
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: callInfo.id, accessHash: callInfo.accessHash, title: callInfo.title, scheduleTimestamp: callInfo.scheduleTimestamp, subscribedToScheduled: callInfo.subscribedToScheduled))
} else {
return cachedData
}
@ -373,19 +377,19 @@ public enum GetGroupCallParticipantsError {
}
public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> {
let sortAscendingValue: Signal<(Bool, Int32?), GetGroupCallParticipantsError>
let sortAscendingValue: Signal<(Bool, Int32?, Bool), GetGroupCallParticipantsError>
if let sortAscending = sortAscending {
sortAscendingValue = .single((sortAscending, nil))
sortAscendingValue = .single((sortAscending, nil, false))
} else {
sortAscendingValue = getCurrentGroupCall(account: account, callId: callId, accessHash: accessHash)
|> mapError { _ -> GetGroupCallParticipantsError in
return .generic
}
|> mapToSignal { result -> Signal<(Bool, Int32?), GetGroupCallParticipantsError> in
|> mapToSignal { result -> Signal<(Bool, Int32?, Bool), GetGroupCallParticipantsError> in
guard let result = result else {
return .fail(.generic)
}
return .single((result.info.sortAscending, result.info.scheduleTimestamp))
return .single((result.info.sortAscending, result.info.scheduleTimestamp, result.info.subscribedToScheduled))
}
}
@ -403,7 +407,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
let version: Int32
let nextParticipantsFetchOffset: String?
let (sortAscendingValue, scheduleTimestamp) = sortAscendingAndScheduleTimestamp
let (sortAscendingValue, scheduleTimestamp, subscribedToScheduled) = sortAscendingAndScheduleTimestamp
switch result {
case let .groupParticipants(count, participants, nextOffset, chats, users, apiVersion):
@ -492,6 +496,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
recordingStartTimestamp: nil,
title: nil,
scheduleTimestamp: scheduleTimestamp,
subscribedToScheduled: subscribedToScheduled,
totalCount: totalCount,
version: version
)
@ -668,9 +673,9 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
return account.postbox.transaction { transaction -> JoinGroupCallResult in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
return cachedData.withUpdatedCallJoinPeerId(joinAs).withUpdatedActiveCall(CachedChannelData.ActiveCall(id: parsedCall.id, accessHash: parsedCall.accessHash, title: parsedCall.title, scheduleTimestamp: nil, subscribed: false))
return cachedData.withUpdatedCallJoinPeerId(joinAs).withUpdatedActiveCall(CachedChannelData.ActiveCall(id: parsedCall.id, accessHash: parsedCall.accessHash, title: parsedCall.title, scheduleTimestamp: nil, subscribedToScheduled: false))
} else if let cachedData = cachedData as? CachedGroupData {
return cachedData.withUpdatedCallJoinPeerId(joinAs).withUpdatedActiveCall(CachedChannelData.ActiveCall(id: parsedCall.id, accessHash: parsedCall.accessHash, title: parsedCall.title, scheduleTimestamp: nil, subscribed: false))
return cachedData.withUpdatedCallJoinPeerId(joinAs).withUpdatedActiveCall(CachedChannelData.ActiveCall(id: parsedCall.id, accessHash: parsedCall.accessHash, title: parsedCall.title, scheduleTimestamp: nil, subscribedToScheduled: false))
} else {
return cachedData
}
@ -1011,6 +1016,7 @@ public final class GroupCallParticipantsContext {
public var recordingStartTimestamp: Int32?
public var title: String?
public var scheduleTimestamp: Int32?
public var subscribedToScheduled: Bool
public var totalCount: Int
public var version: Int32
@ -1123,7 +1129,7 @@ public final class GroupCallParticipantsContext {
}
case state(update: StateUpdate)
case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted, title: String?, recordingStartTimestamp: Int32?)
case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted, title: String?, recordingStartTimestamp: Int32?, scheduleTimestamp: Int32?)
}
public final class MemberEvent {
@ -1313,6 +1319,7 @@ public final class GroupCallParticipantsContext {
recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp,
title: strongSelf.stateValue.state.title,
scheduleTimestamp: strongSelf.stateValue.state.scheduleTimestamp,
subscribedToScheduled: strongSelf.stateValue.state.subscribedToScheduled,
totalCount: strongSelf.stateValue.state.totalCount,
version: strongSelf.stateValue.state.version
),
@ -1368,11 +1375,12 @@ public final class GroupCallParticipantsContext {
for update in updates {
if case let .state(update) = update {
stateUpdates.append(update)
} else if case let .call(_, defaultParticipantsAreMuted, title, recordingStartTimestamp) = update {
} else if case let .call(_, defaultParticipantsAreMuted, title, recordingStartTimestamp, scheduleTimestamp) = update {
var state = self.stateValue.state
state.defaultParticipantsAreMuted = defaultParticipantsAreMuted
state.recordingStartTimestamp = recordingStartTimestamp
state.title = title
state.scheduleTimestamp = scheduleTimestamp
self.stateValue.state = state
}
@ -1446,6 +1454,7 @@ public final class GroupCallParticipantsContext {
recordingStartTimestamp: strongSelf.stateValue.state.recordingStartTimestamp,
title: strongSelf.stateValue.state.title,
scheduleTimestamp: strongSelf.stateValue.state.scheduleTimestamp,
subscribedToScheduled: strongSelf.stateValue.state.subscribedToScheduled,
totalCount: strongSelf.stateValue.state.totalCount,
version: strongSelf.stateValue.state.version
),
@ -1662,6 +1671,7 @@ public final class GroupCallParticipantsContext {
let recordingStartTimestamp = strongSelf.stateValue.state.recordingStartTimestamp
let title = strongSelf.stateValue.state.title
let scheduleTimestamp = strongSelf.stateValue.state.scheduleTimestamp
let subscribedToScheduled = strongSelf.stateValue.state.subscribedToScheduled
updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) })
@ -1676,6 +1686,7 @@ public final class GroupCallParticipantsContext {
recordingStartTimestamp: recordingStartTimestamp,
title: title,
scheduleTimestamp: scheduleTimestamp,
subscribedToScheduled: subscribedToScheduled,
totalCount: updatedTotalCount,
version: update.version
),

View File

@ -2982,9 +2982,9 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
if let info = GroupCallInfo(call) {
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedChannelData {
return current.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribed: false))
return current.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: info.subscribedToScheduled))
} else if let current = current as? CachedGroupData {
return current.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribed: false))
return current.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: info.subscribedToScheduled))
} else {
return current
}
@ -2997,7 +2997,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
let defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange)
updatedGroupCallParticipants.append((
info.id,
.call(isTerminated: false, defaultParticipantsAreMuted: defaultParticipantsAreMuted, title: title, recordingStartTimestamp: recordStartDate)
.call(isTerminated: false, defaultParticipantsAreMuted: defaultParticipantsAreMuted, title: title, recordingStartTimestamp: recordStartDate, scheduleTimestamp: scheduleDate)
))
default:
break
@ -3006,7 +3006,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
case let .groupCallDiscarded(callId, _, _):
updatedGroupCallParticipants.append((
callId,
.call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false), title: nil, recordingStartTimestamp: nil)
.call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false), title: nil, recordingStartTimestamp: nil, scheduleTimestamp: nil)
))
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in

View File

@ -306,7 +306,7 @@ public func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId
if let inputCall = chatFull.call {
switch inputCall {
case let .inputGroupCall(id, accessHash):
updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribed: previous.activeCall?.subscribed ?? false)
updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribedToScheduled: previous.activeCall?.subscribedToScheduled ?? false)
}
}
@ -516,7 +516,7 @@ public func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId
if let inputCall = inputCall {
switch inputCall {
case let .inputGroupCall(id, accessHash):
updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribed: previous.activeCall?.subscribed ?? false)
updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribedToScheduled: previous.activeCall?.subscribedToScheduled ?? false)
}
}

View File

@ -535,7 +535,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
case .groupPhoneCall, .inviteToGroupPhoneCall:
if let activeCall = strongSelf.presentationInterfaceState.activeGroupCallInfo?.activeCall {
strongSelf.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: CachedChannelData.ActiveCall(id: activeCall.id, accessHash: activeCall.accessHash, title: activeCall.title, scheduleTimestamp: activeCall.scheduleTimestamp, subscribed: activeCall.subscribed))
strongSelf.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: CachedChannelData.ActiveCall(id: activeCall.id, accessHash: activeCall.accessHash, title: activeCall.title, scheduleTimestamp: activeCall.scheduleTimestamp, subscribedToScheduled: activeCall.subscribedToScheduled))
} else {
var canManageGroupCalls = false
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel {
@ -569,7 +569,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else {
return
}
strongSelf.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribed: false))
strongSelf.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: info.subscribedToScheduled))
}, error: { [weak self] error in
dismissStatus?()

View File

@ -4020,7 +4020,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
}
strongSelf.context.joinGroupCall(peerId: peerId, invite: nil, requestJoinAsPeerId: { result in
result(joinAsPeerId)
}, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: nil, subscribed: false))
}, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: nil, subscribedToScheduled: false))
}, error: { [weak self] error in
guard let strongSelf = self else {
return
@ -4199,7 +4199,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|> deliverOnMainQueue).start(completed: { [weak self] in
if let strongSelf = self, let peer = strongSelf.data?.peer {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .info(text: presentationData.strings.Conversation_DeletedFromContacts(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root))
let controller = UndoOverlayController(presentationData: presentationData, content: .info(text: presentationData.strings.Conversation_DeletedFromContacts(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false })
controller.keepOnParentDismissal = true
strongSelf.controller?.present(controller, in: .window(.root))
strongSelf.controller?.dismiss()
}
@ -6642,12 +6644,12 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
private func dismissAllTooltips() {
self.window?.forEachController({ controller in
if let controller = controller as? UndoOverlayController {
if let controller = controller as? UndoOverlayController, !controller.keepOnParentDismissal {
controller.dismissWithCommitAction()
}
})
self.forEachController({ controller in
if let controller = controller as? UndoOverlayController {
if let controller = controller as? UndoOverlayController, !controller.keepOnParentDismissal {
controller.dismissWithCommitAction()
}
return true

View File

@ -56,6 +56,8 @@ public final class UndoOverlayController: ViewController {
private var didPlayPresentationAnimation = false
private var dismissed = false
public var keepOnParentDismissal = false
public init(presentationData: PresentationData, content: UndoOverlayContent, elevatedLayout: Bool, animateInAsReplacement: Bool = false, action: @escaping (UndoOverlayAction) -> Bool) {
self.presentationData = presentationData
self.content = content