mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Video call improvements
This commit is contained in:
parent
abb6e4a6bf
commit
8134159629
@ -4788,6 +4788,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"ContactList.Context.SendMessage" = "Send Message";
|
||||
"ContactList.Context.StartSecretChat" = "Start Secret Chat";
|
||||
"ContactList.Context.Call" = "Call";
|
||||
"ContactList.Context.VideoCall" = "Video Call";
|
||||
|
||||
"Theme.Context.Apply" = "Apply";
|
||||
|
||||
@ -5332,7 +5333,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"PeerInfo.ButtonMessage" = "Message";
|
||||
"PeerInfo.ButtonDiscuss" = "Discuss";
|
||||
"PeerInfo.ButtonCall" = "Call";
|
||||
"PeerInfo.ButtonVideoCall" = "Video Call";
|
||||
"PeerInfo.ButtonVideoCall" = "Video";
|
||||
"PeerInfo.ButtonMute" = "Mute";
|
||||
"PeerInfo.ButtonUnmute" = "Unmute";
|
||||
"PeerInfo.ButtonMore" = "More";
|
||||
|
@ -647,6 +647,7 @@ public protocol AccountContext: class {
|
||||
|
||||
var currentLimitsConfiguration: Atomic<LimitsConfiguration> { get }
|
||||
var currentContentSettings: Atomic<ContentSettings> { get }
|
||||
var currentAppConfiguration: Atomic<AppConfiguration> { get }
|
||||
|
||||
func storeSecureIdPassword(password: String)
|
||||
func getStoredSecureIdPassword() -> String?
|
||||
|
@ -81,17 +81,20 @@ public final class PresentationCallVideoView {
|
||||
|
||||
public let getOrientation: () -> Orientation
|
||||
public let setOnOrientationUpdated: (((Orientation) -> Void)?) -> Void
|
||||
public let setOnIsMirroredUpdated: (((Bool) -> Void)?) -> Void
|
||||
|
||||
public init(
|
||||
view: UIView,
|
||||
setOnFirstFrameReceived: @escaping ((() -> Void)?) -> Void,
|
||||
getOrientation: @escaping () -> Orientation,
|
||||
setOnOrientationUpdated: @escaping (((Orientation) -> Void)?) -> Void
|
||||
setOnOrientationUpdated: @escaping (((Orientation) -> Void)?) -> Void,
|
||||
setOnIsMirroredUpdated: @escaping (((Bool) -> Void)?) -> Void
|
||||
) {
|
||||
self.view = view
|
||||
self.setOnFirstFrameReceived = setOnFirstFrameReceived
|
||||
self.getOrientation = getOrientation
|
||||
self.setOnOrientationUpdated = setOnOrientationUpdated
|
||||
self.setOnIsMirroredUpdated = setOnIsMirroredUpdated
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,5 +136,5 @@ public protocol PresentationCall: class {
|
||||
public protocol PresentationCallManager: class {
|
||||
var currentCallSignal: Signal<PresentationCall?, NoError> { get }
|
||||
|
||||
func requestCall(account: Account, peerId: PeerId, isVideo: Bool, endCurrentIfAny: Bool) -> RequestCallResult
|
||||
func requestCall(context: AccountContext, peerId: PeerId, isVideo: Bool, endCurrentIfAny: Bool) -> RequestCallResult
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
import SyncCore
|
||||
|
||||
public struct VideoCallsConfiguration: Equatable {
|
||||
public enum VideoCallsSupport {
|
||||
case disabled
|
||||
case full
|
||||
case onlyVideo
|
||||
}
|
||||
|
||||
public var videoCallsSupport: VideoCallsSupport
|
||||
|
||||
public init(appConfiguration: AppConfiguration) {
|
||||
var videoCallsSupport: VideoCallsSupport = .full
|
||||
if let data = appConfiguration.data, let value = data["video_calls_support"] as? String {
|
||||
switch value {
|
||||
case "disabled":
|
||||
videoCallsSupport = .disabled
|
||||
case "full":
|
||||
videoCallsSupport = .full
|
||||
case "only_video":
|
||||
videoCallsSupport = .onlyVideo
|
||||
default:
|
||||
videoCallsSupport = .full
|
||||
}
|
||||
}
|
||||
self.videoCallsSupport = videoCallsSupport
|
||||
}
|
||||
}
|
||||
|
||||
public extension VideoCallsConfiguration {
|
||||
var areVideoCallsEnabled: Bool {
|
||||
switch self.videoCallsSupport {
|
||||
case .disabled:
|
||||
return false
|
||||
case .full, .onlyVideo:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
@ -277,7 +277,7 @@ public final class CallListController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
let callResult = strongSelf.context.sharedContext.callManager?.requestCall(account: strongSelf.context.account, peerId: peerId, isVideo: isVideo, endCurrentIfAny: false)
|
||||
let callResult = strongSelf.context.sharedContext.callManager?.requestCall(context: strongSelf.context, peerId: peerId, isVideo: isVideo, endCurrentIfAny: false)
|
||||
if let callResult = callResult {
|
||||
if case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peerId {
|
||||
@ -291,7 +291,7 @@ public final class CallListController: ViewController {
|
||||
if let strongSelf = self, let peer = peer, let current = current {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
if let strongSelf = self {
|
||||
let _ = strongSelf.context.sharedContext.callManager?.requestCall(account: strongSelf.context.account, peerId: peerId, isVideo: isVideo, endCurrentIfAny: true)
|
||||
let _ = strongSelf.context.sharedContext.callManager?.requestCall(context: strongSelf.context, peerId: peerId, isVideo: isVideo, endCurrentIfAny: true)
|
||||
began?()
|
||||
}
|
||||
})]), in: .window(.root))
|
||||
|
@ -113,15 +113,17 @@ func contactContextMenuItems(context: AccountContext, peerId: PeerId, contactsCo
|
||||
}
|
||||
var canVideoCall = false
|
||||
if canCall {
|
||||
if context.sharedContext.immediateExperimentalUISettings.videoCalls {
|
||||
canVideoCall = true
|
||||
if let cachedUserData = transaction.getPeerCachedData(peerId: peerId) as? CachedUserData {
|
||||
if cachedUserData.videoCallsAvailable {
|
||||
canVideoCall = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if canCall {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ContactList_Context_Call, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Call"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
if let contactsController = contactsController {
|
||||
let callResult = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peerId, isVideo: false, endCurrentIfAny: false)
|
||||
let callResult = context.sharedContext.callManager?.requestCall(context: context, peerId: peerId, isVideo: false, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peerId {
|
||||
context.sharedContext.navigateToCurrentCall()
|
||||
@ -133,7 +135,7 @@ func contactContextMenuItems(context: AccountContext, peerId: PeerId, contactsCo
|
||||
|> deliverOnMainQueue).start(next: { [weak contactsController] peer, current in
|
||||
if let contactsController = contactsController, let peer = peer, let current = current {
|
||||
contactsController.present(textAlertController(context: context, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
let _ = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peerId, isVideo: false, endCurrentIfAny: true)
|
||||
let _ = context.sharedContext.callManager?.requestCall(context: context, peerId: peerId, isVideo: false, endCurrentIfAny: true)
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
@ -144,10 +146,9 @@ func contactContextMenuItems(context: AccountContext, peerId: PeerId, contactsCo
|
||||
})))
|
||||
}
|
||||
if canVideoCall {
|
||||
//TODO:localize
|
||||
items.append(.action(ContextMenuActionItem(text: "Video Call", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Call"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ContactList_Context_VideoCall, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Call"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
if let contactsController = contactsController {
|
||||
let callResult = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peerId, isVideo: true, endCurrentIfAny: false)
|
||||
let callResult = context.sharedContext.callManager?.requestCall(context: context, peerId: peerId, isVideo: true, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peerId {
|
||||
context.sharedContext.navigateToCurrentCall()
|
||||
@ -159,7 +160,7 @@ func contactContextMenuItems(context: AccountContext, peerId: PeerId, contactsCo
|
||||
|> deliverOnMainQueue).start(next: { [weak contactsController] peer, current in
|
||||
if let contactsController = contactsController, let peer = peer, let current = current {
|
||||
contactsController.present(textAlertController(context: context, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
let _ = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peerId, isVideo: true, endCurrentIfAny: true)
|
||||
let _ = context.sharedContext.callManager?.requestCall(context: context, peerId: peerId, isVideo: true, endCurrentIfAny: true)
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
|
@ -877,7 +877,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
|
||||
ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: presentationData.strings.UserInfo_TelegramCall, action: {
|
||||
dismissAction()
|
||||
let callResult = context.sharedContext.callManager?.requestCall(account: context.account, peerId: user.id, isVideo: false, endCurrentIfAny: false)
|
||||
let callResult = context.sharedContext.callManager?.requestCall(context: context, peerId: user.id, isVideo: false, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == user.id {
|
||||
context.sharedContext.navigateToCurrentCall()
|
||||
@ -888,7 +888,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
|
||||
} |> deliverOnMainQueue).start(next: { peer, current in
|
||||
if let peer = peer, let current = current {
|
||||
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
let _ = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peer.id, isVideo: false, endCurrentIfAny: true)
|
||||
let _ = context.sharedContext.callManager?.requestCall(context: context, peerId: peer.id, isVideo: false, endCurrentIfAny: true)
|
||||
})]), nil)
|
||||
}
|
||||
})
|
||||
|
@ -597,7 +597,7 @@ private func userInfoEntries(account: Account, presentationData: PresentationDat
|
||||
|
||||
var callsAvailable = true
|
||||
if let cachedUserData = cachedPeerData as? CachedUserData {
|
||||
callsAvailable = cachedUserData.callsAvailable
|
||||
callsAvailable = cachedUserData.voiceCallsAvailable
|
||||
}
|
||||
|
||||
entries.append(UserInfoEntry.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: user, presence: view.peerPresences[user.id], cachedData: cachedPeerData, state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), displayCall: user.botInfo == nil && callsAvailable))
|
||||
@ -873,7 +873,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
return
|
||||
}
|
||||
|
||||
let callResult = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: false)
|
||||
let callResult = context.sharedContext.callManager?.requestCall(context: context, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peer.id {
|
||||
context.sharedContext.navigateToCurrentCall()
|
||||
@ -884,7 +884,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
} |> deliverOnMainQueue).start(next: { peer, current in
|
||||
if let peer = peer, let current = current {
|
||||
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
let _ = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: true)
|
||||
let _ = context.sharedContext.callManager?.requestCall(context: context, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: true)
|
||||
})]), nil)
|
||||
}
|
||||
})
|
||||
|
@ -72,9 +72,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
case alternativeFolderTabs(Bool)
|
||||
case playerEmbedding(Bool)
|
||||
case playlistPlayback(Bool)
|
||||
case videoCalls(Bool)
|
||||
case videoCallsReference(Bool)
|
||||
case videoCallsInfo(PresentationTheme, String)
|
||||
case enableHighBitrateVideoCalls(Bool)
|
||||
case hostInfo(PresentationTheme, String)
|
||||
case versionInfo(PresentationTheme)
|
||||
|
||||
@ -90,7 +88,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
return DebugControllerSection.experiments.rawValue
|
||||
case .clearTips, .reimport, .resetData, .resetDatabase, .resetHoles, .reindexUnread, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .alternativeFolderTabs, .playerEmbedding, .playlistPlayback:
|
||||
return DebugControllerSection.experiments.rawValue
|
||||
case .videoCalls, .videoCallsReference, .videoCallsInfo:
|
||||
case .enableHighBitrateVideoCalls:
|
||||
return DebugControllerSection.videoExperiments.rawValue
|
||||
case .hostInfo, .versionInfo:
|
||||
return DebugControllerSection.info.rawValue
|
||||
@ -149,12 +147,8 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
return 24
|
||||
case .playlistPlayback:
|
||||
return 25
|
||||
case .videoCalls:
|
||||
case .enableHighBitrateVideoCalls:
|
||||
return 26
|
||||
case .videoCallsReference:
|
||||
return 27
|
||||
case .videoCallsInfo:
|
||||
return 28
|
||||
case .hostInfo:
|
||||
return 29
|
||||
case .versionInfo:
|
||||
@ -576,28 +570,16 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
}).start()
|
||||
})
|
||||
case let .videoCalls(value):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Experimental Feature", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
case let .enableHighBitrateVideoCalls(value):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "HD Video Calls", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
|
||||
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
|
||||
var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
|
||||
settings.videoCalls = value
|
||||
settings.enableHighBitrateVideoCalls = value
|
||||
return settings
|
||||
})
|
||||
}).start()
|
||||
})
|
||||
case let .videoCallsReference(value):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Reference Implementation", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
|
||||
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
|
||||
var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
|
||||
settings.videoCallsReference = value
|
||||
return settings
|
||||
})
|
||||
}).start()
|
||||
})
|
||||
case let .videoCallsInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .hostInfo(theme, string):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(string), sectionId: self.section)
|
||||
case let .versionInfo(theme):
|
||||
@ -643,11 +625,7 @@ private func debugControllerEntries(presentationData: PresentationData, loggingS
|
||||
entries.append(.alternativeFolderTabs(experimentalSettings.foldersTabAtBottom))
|
||||
entries.append(.playerEmbedding(experimentalSettings.playerEmbedding))
|
||||
entries.append(.playlistPlayback(experimentalSettings.playlistPlayback))
|
||||
entries.append(.videoCalls(experimentalSettings.videoCalls))
|
||||
if experimentalSettings.videoCalls {
|
||||
entries.append(.videoCallsReference(experimentalSettings.videoCallsReference))
|
||||
}
|
||||
entries.append(.videoCallsInfo(presentationData.theme, "Enables experimental transmission of electromagnetic radiation synchronized with pressure waves. Needs to be enabled on both sides."))
|
||||
entries.append(.enableHighBitrateVideoCalls(experimentalSettings.enableHighBitrateVideoCalls))
|
||||
|
||||
if let backupHostOverride = networkSettings?.backupHostOverride {
|
||||
entries.append(.hostInfo(presentationData.theme, "Host: \(backupHostOverride)"))
|
||||
|
@ -8,7 +8,8 @@ public final class CachedUserData: CachedPeerData {
|
||||
public let pinnedMessageId: MessageId?
|
||||
public let isBlocked: Bool
|
||||
public let commonGroupCount: Int32
|
||||
public let callsAvailable: Bool
|
||||
public let voiceCallsAvailable: Bool
|
||||
public let videoCallsAvailable: Bool
|
||||
public let callsPrivate: Bool
|
||||
public let canPinMessages: Bool
|
||||
public let hasScheduledMessages: Bool
|
||||
@ -24,21 +25,23 @@ public final class CachedUserData: CachedPeerData {
|
||||
self.pinnedMessageId = nil
|
||||
self.isBlocked = false
|
||||
self.commonGroupCount = 0
|
||||
self.callsAvailable = false
|
||||
self.voiceCallsAvailable = false
|
||||
self.videoCallsAvailable = false
|
||||
self.callsPrivate = false
|
||||
self.canPinMessages = false
|
||||
self.hasScheduledMessages = false
|
||||
self.messageIds = Set()
|
||||
}
|
||||
|
||||
public init(about: String?, botInfo: BotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, callsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool) {
|
||||
public init(about: String?, botInfo: BotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool) {
|
||||
self.about = about
|
||||
self.botInfo = botInfo
|
||||
self.peerStatusSettings = peerStatusSettings
|
||||
self.pinnedMessageId = pinnedMessageId
|
||||
self.isBlocked = isBlocked
|
||||
self.commonGroupCount = commonGroupCount
|
||||
self.callsAvailable = callsAvailable
|
||||
self.voiceCallsAvailable = voiceCallsAvailable
|
||||
self.videoCallsAvailable = videoCallsAvailable
|
||||
self.callsPrivate = callsPrivate
|
||||
self.canPinMessages = canPinMessages
|
||||
self.hasScheduledMessages = hasScheduledMessages
|
||||
@ -66,7 +69,8 @@ public final class CachedUserData: CachedPeerData {
|
||||
}
|
||||
self.isBlocked = decoder.decodeInt32ForKey("b", orElse: 0) != 0
|
||||
self.commonGroupCount = decoder.decodeInt32ForKey("cg", orElse: 0)
|
||||
self.callsAvailable = decoder.decodeInt32ForKey("ca", orElse: 0) != 0
|
||||
self.voiceCallsAvailable = decoder.decodeInt32ForKey("ca", orElse: 0) != 0
|
||||
self.videoCallsAvailable = decoder.decodeInt32ForKey("vca", orElse: 0) != 0
|
||||
self.callsPrivate = decoder.decodeInt32ForKey("cp", orElse: 0) != 0
|
||||
self.canPinMessages = decoder.decodeInt32ForKey("cpm", orElse: 0) != 0
|
||||
self.hasScheduledMessages = decoder.decodeBoolForKey("hsm", orElse: false)
|
||||
@ -105,7 +109,8 @@ public final class CachedUserData: CachedPeerData {
|
||||
}
|
||||
encoder.encodeInt32(self.isBlocked ? 1 : 0, forKey: "b")
|
||||
encoder.encodeInt32(self.commonGroupCount, forKey: "cg")
|
||||
encoder.encodeInt32(self.callsAvailable ? 1 : 0, forKey: "ca")
|
||||
encoder.encodeInt32(self.voiceCallsAvailable ? 1 : 0, forKey: "ca")
|
||||
encoder.encodeInt32(self.videoCallsAvailable ? 1 : 0, forKey: "vca")
|
||||
encoder.encodeInt32(self.callsPrivate ? 1 : 0, forKey: "cp")
|
||||
encoder.encodeInt32(self.canPinMessages ? 1 : 0, forKey: "cpm")
|
||||
encoder.encodeBool(self.hasScheduledMessages, forKey: "hsm")
|
||||
@ -123,46 +128,50 @@ public final class CachedUserData: CachedPeerData {
|
||||
return false
|
||||
}
|
||||
|
||||
return other.about == self.about && other.botInfo == self.botInfo && self.peerStatusSettings == other.peerStatusSettings && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount && self.callsAvailable == other.callsAvailable && self.callsPrivate == other.callsPrivate && self.hasScheduledMessages == other.hasScheduledMessages
|
||||
return other.about == self.about && other.botInfo == self.botInfo && self.peerStatusSettings == other.peerStatusSettings && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount && self.voiceCallsAvailable == other.voiceCallsAvailable && self.videoCallsAvailable == other.videoCallsAvailable && self.callsPrivate == other.callsPrivate && self.hasScheduledMessages == other.hasScheduledMessages
|
||||
}
|
||||
|
||||
public func withUpdatedAbout(_ about: String?) -> CachedUserData {
|
||||
return CachedUserData(about: about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedBotInfo(_ botInfo: BotInfo?) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedIsBlocked(_ isBlocked: Bool) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedCommonGroupCount(_ commonGroupCount: Int32) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedCallsAvailable(_ callsAvailable: Bool) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
public func withUpdatedVoiceCallsAvailable(_ voiceCallsAvailable: Bool) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedVideoCallsAvailable(_ videoCallsAvailable: Bool) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedCallsPrivate(_ callsPrivate: Bool) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedCanPinMessages(_ canPinMessages: Bool) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages)
|
||||
}
|
||||
|
||||
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedUserData {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages)
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +255,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[889491791] = { return Api.Update.parse_updateDialogFilters($0) }
|
||||
dict[643940105] = { return Api.Update.parse_updatePhoneCallSignalingData($0) }
|
||||
dict[1708307556] = { return Api.Update.parse_updateChannelParticipant($0) }
|
||||
dict[1854571743] = { return Api.Update.parse_updateChannelMessageForwards($0) }
|
||||
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
||||
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
||||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||
@ -388,7 +387,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1694474197] = { return Api.messages.Chats.parse_chats($0) }
|
||||
dict[-1663561404] = { return Api.messages.Chats.parse_chatsSlice($0) }
|
||||
dict[482797855] = { return Api.InputSingleMedia.parse_inputSingleMedia($0) }
|
||||
dict[1831138451] = { return Api.MessageViews.parse_messageViews($0) }
|
||||
dict[218751099] = { return Api.InputPrivacyRule.parse_inputPrivacyValueAllowContacts($0) }
|
||||
dict[407582158] = { return Api.InputPrivacyRule.parse_inputPrivacyValueAllowAll($0) }
|
||||
dict[320652927] = { return Api.InputPrivacyRule.parse_inputPrivacyValueAllowUsers($0) }
|
||||
@ -600,7 +598,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1820043071] = { return Api.User.parse_user($0) }
|
||||
dict[-2082087340] = { return Api.Message.parse_messageEmpty($0) }
|
||||
dict[-1642487306] = { return Api.Message.parse_messageService($0) }
|
||||
dict[-181507201] = { return Api.Message.parse_message($0) }
|
||||
dict[1160515173] = { return Api.Message.parse_message($0) }
|
||||
dict[831924812] = { return Api.StatsGroupTopInviter.parse_statsGroupTopInviter($0) }
|
||||
dict[186120336] = { return Api.messages.RecentStickers.parse_recentStickersNotModified($0) }
|
||||
dict[586395571] = { return Api.messages.RecentStickers.parse_recentStickers($0) }
|
||||
@ -685,7 +683,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[364538944] = { return Api.messages.Dialogs.parse_dialogs($0) }
|
||||
dict[1910543603] = { return Api.messages.Dialogs.parse_dialogsSlice($0) }
|
||||
dict[-253500010] = { return Api.messages.Dialogs.parse_dialogsNotModified($0) }
|
||||
dict[-1986399595] = { return Api.stats.MessageStats.parse_messageStats($0) }
|
||||
dict[-709641735] = { return Api.EmojiKeyword.parse_emojiKeyword($0) }
|
||||
dict[594408994] = { return Api.EmojiKeyword.parse_emojiKeywordDeleted($0) }
|
||||
dict[-290921362] = { return Api.upload.CdnFile.parse_cdnFileReuploadNeeded($0) }
|
||||
@ -708,6 +705,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-395967805] = { return Api.messages.AllStickers.parse_allStickersNotModified($0) }
|
||||
dict[-302170017] = { return Api.messages.AllStickers.parse_allStickers($0) }
|
||||
dict[-1655957568] = { return Api.PhoneConnection.parse_phoneConnection($0) }
|
||||
dict[1667228533] = { return Api.PhoneConnection.parse_phoneConnectionWebrtc($0) }
|
||||
dict[-206688531] = { return Api.help.UserInfo.parse_userInfoEmpty($0) }
|
||||
dict[32192344] = { return Api.help.UserInfo.parse_userInfo($0) }
|
||||
dict[-1194283041] = { return Api.AccountDaysTTL.parse_accountDaysTTL($0) }
|
||||
@ -1108,8 +1106,6 @@ public struct Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputSingleMedia:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.MessageViews:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputPrivacyRule:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.DhConfig:
|
||||
@ -1370,8 +1366,6 @@ public struct Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.Dialogs:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.stats.MessageStats:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.EmojiKeyword:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.upload.CdnFile:
|
||||
|
@ -6038,7 +6038,6 @@ public extension Api {
|
||||
case updateDialogFilters
|
||||
case updatePhoneCallSignalingData(phoneCallId: Int64, data: Buffer)
|
||||
case updateChannelParticipant(flags: Int32, channelId: Int32, date: Int32, userId: Int32, prevParticipant: Api.ChannelParticipant?, newParticipant: Api.ChannelParticipant?, qts: Int32)
|
||||
case updateChannelMessageForwards(channelId: Int32, id: Int32, forwards: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -6731,14 +6730,6 @@ public extension Api {
|
||||
if Int(flags) & Int(1 << 1) != 0 {newParticipant!.serialize(buffer, true)}
|
||||
serializeInt32(qts, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .updateChannelMessageForwards(let channelId, let id, let forwards):
|
||||
if boxed {
|
||||
buffer.appendInt32(1854571743)
|
||||
}
|
||||
serializeInt32(channelId, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
serializeInt32(forwards, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -6908,8 +6899,6 @@ public extension Api {
|
||||
return ("updatePhoneCallSignalingData", [("phoneCallId", phoneCallId), ("data", data)])
|
||||
case .updateChannelParticipant(let flags, let channelId, let date, let userId, let prevParticipant, let newParticipant, let qts):
|
||||
return ("updateChannelParticipant", [("flags", flags), ("channelId", channelId), ("date", date), ("userId", userId), ("prevParticipant", prevParticipant), ("newParticipant", newParticipant), ("qts", qts)])
|
||||
case .updateChannelMessageForwards(let channelId, let id, let forwards):
|
||||
return ("updateChannelMessageForwards", [("channelId", channelId), ("id", id), ("forwards", forwards)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -8288,23 +8277,6 @@ public extension Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_updateChannelMessageForwards(_ reader: BufferReader) -> Update? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.Update.updateChannelMessageForwards(channelId: _1!, id: _2!, forwards: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum PopularContact: TypeConstructorDescription {
|
||||
@ -11746,44 +11718,6 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum MessageViews: TypeConstructorDescription {
|
||||
case messageViews(views: Int32, forwards: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageViews(let views, let forwards):
|
||||
if boxed {
|
||||
buffer.appendInt32(1831138451)
|
||||
}
|
||||
serializeInt32(views, buffer: buffer, boxed: false)
|
||||
serializeInt32(forwards, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageViews(let views, let forwards):
|
||||
return ("messageViews", [("views", views), ("forwards", forwards)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageViews(_ reader: BufferReader) -> MessageViews? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.MessageViews.messageViews(views: _1!, forwards: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum InputPrivacyRule: TypeConstructorDescription {
|
||||
case inputPrivacyValueAllowContacts
|
||||
@ -17158,7 +17092,7 @@ public extension Api {
|
||||
public enum Message: TypeConstructorDescription {
|
||||
case messageEmpty(id: Int32)
|
||||
case messageService(flags: Int32, id: Int32, fromId: Int32?, toId: Api.Peer, replyToMsgId: Int32?, date: Int32, action: Api.MessageAction)
|
||||
case message(flags: Int32, id: Int32, fromId: Int32?, toId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int32?, replyToMsgId: Int32?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, restrictionReason: [Api.RestrictionReason]?)
|
||||
case message(flags: Int32, id: Int32, fromId: Int32?, toId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int32?, replyToMsgId: Int32?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, restrictionReason: [Api.RestrictionReason]?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -17180,9 +17114,9 @@ public extension Api {
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
action.serialize(buffer, true)
|
||||
break
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let editDate, let postAuthor, let groupedId, let restrictionReason):
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let editDate, let postAuthor, let groupedId, let restrictionReason):
|
||||
if boxed {
|
||||
buffer.appendInt32(-181507201)
|
||||
buffer.appendInt32(1160515173)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
@ -17201,7 +17135,6 @@ public extension Api {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(forwards!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 15) != 0 {serializeInt32(editDate!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 16) != 0 {serializeString(postAuthor!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 17) != 0 {serializeInt64(groupedId!, buffer: buffer, boxed: false)}
|
||||
@ -17220,8 +17153,8 @@ public extension Api {
|
||||
return ("messageEmpty", [("id", id)])
|
||||
case .messageService(let flags, let id, let fromId, let toId, let replyToMsgId, let date, let action):
|
||||
return ("messageService", [("flags", flags), ("id", id), ("fromId", fromId), ("toId", toId), ("replyToMsgId", replyToMsgId), ("date", date), ("action", action)])
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let editDate, let postAuthor, let groupedId, let restrictionReason):
|
||||
return ("message", [("flags", flags), ("id", id), ("fromId", fromId), ("toId", toId), ("fwdFrom", fwdFrom), ("viaBotId", viaBotId), ("replyToMsgId", replyToMsgId), ("date", date), ("message", message), ("media", media), ("replyMarkup", replyMarkup), ("entities", entities), ("views", views), ("forwards", forwards), ("editDate", editDate), ("postAuthor", postAuthor), ("groupedId", groupedId), ("restrictionReason", restrictionReason)])
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let editDate, let postAuthor, let groupedId, let restrictionReason):
|
||||
return ("message", [("flags", flags), ("id", id), ("fromId", fromId), ("toId", toId), ("fwdFrom", fwdFrom), ("viaBotId", viaBotId), ("replyToMsgId", replyToMsgId), ("date", date), ("message", message), ("media", media), ("replyMarkup", replyMarkup), ("entities", entities), ("views", views), ("editDate", editDate), ("postAuthor", postAuthor), ("groupedId", groupedId), ("restrictionReason", restrictionReason)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -17307,16 +17240,14 @@ public extension Api {
|
||||
var _13: Int32?
|
||||
if Int(_1!) & Int(1 << 10) != 0 {_13 = reader.readInt32() }
|
||||
var _14: Int32?
|
||||
if Int(_1!) & Int(1 << 10) != 0 {_14 = reader.readInt32() }
|
||||
var _15: Int32?
|
||||
if Int(_1!) & Int(1 << 15) != 0 {_15 = reader.readInt32() }
|
||||
var _16: String?
|
||||
if Int(_1!) & Int(1 << 16) != 0 {_16 = parseString(reader) }
|
||||
var _17: Int64?
|
||||
if Int(_1!) & Int(1 << 17) != 0 {_17 = reader.readInt64() }
|
||||
var _18: [Api.RestrictionReason]?
|
||||
if Int(_1!) & Int(1 << 15) != 0 {_14 = reader.readInt32() }
|
||||
var _15: String?
|
||||
if Int(_1!) & Int(1 << 16) != 0 {_15 = parseString(reader) }
|
||||
var _16: Int64?
|
||||
if Int(_1!) & Int(1 << 17) != 0 {_16 = reader.readInt64() }
|
||||
var _17: [Api.RestrictionReason]?
|
||||
if Int(_1!) & Int(1 << 22) != 0 {if let _ = reader.readInt32() {
|
||||
_18 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self)
|
||||
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self)
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
@ -17331,13 +17262,12 @@ public extension Api {
|
||||
let _c11 = (Int(_1!) & Int(1 << 6) == 0) || _11 != nil
|
||||
let _c12 = (Int(_1!) & Int(1 << 7) == 0) || _12 != nil
|
||||
let _c13 = (Int(_1!) & Int(1 << 10) == 0) || _13 != nil
|
||||
let _c14 = (Int(_1!) & Int(1 << 10) == 0) || _14 != nil
|
||||
let _c15 = (Int(_1!) & Int(1 << 15) == 0) || _15 != nil
|
||||
let _c16 = (Int(_1!) & Int(1 << 16) == 0) || _16 != nil
|
||||
let _c17 = (Int(_1!) & Int(1 << 17) == 0) || _17 != nil
|
||||
let _c18 = (Int(_1!) & Int(1 << 22) == 0) || _18 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 {
|
||||
return Api.Message.message(flags: _1!, id: _2!, fromId: _3, toId: _4!, fwdFrom: _5, viaBotId: _6, replyToMsgId: _7, date: _8!, message: _9!, media: _10, replyMarkup: _11, entities: _12, views: _13, forwards: _14, editDate: _15, postAuthor: _16, groupedId: _17, restrictionReason: _18)
|
||||
let _c14 = (Int(_1!) & Int(1 << 15) == 0) || _14 != nil
|
||||
let _c15 = (Int(_1!) & Int(1 << 16) == 0) || _15 != nil
|
||||
let _c16 = (Int(_1!) & Int(1 << 17) == 0) || _16 != nil
|
||||
let _c17 = (Int(_1!) & Int(1 << 22) == 0) || _17 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
|
||||
return Api.Message.message(flags: _1!, id: _2!, fromId: _3, toId: _4!, fwdFrom: _5, viaBotId: _6, replyToMsgId: _7, date: _8!, message: _9!, media: _10, replyMarkup: _11, entities: _12, views: _13, editDate: _14, postAuthor: _15, groupedId: _16, restrictionReason: _17)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -19911,6 +19841,7 @@ public extension Api {
|
||||
}
|
||||
public enum PhoneConnection: TypeConstructorDescription {
|
||||
case phoneConnection(id: Int64, ip: String, ipv6: String, port: Int32, peerTag: Buffer)
|
||||
case phoneConnectionWebrtc(flags: Int32, id: Int64, ip: String, ipv6: String, port: Int32, username: String, password: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -19924,6 +19855,18 @@ public extension Api {
|
||||
serializeInt32(port, buffer: buffer, boxed: false)
|
||||
serializeBytes(peerTag, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .phoneConnectionWebrtc(let flags, let id, let ip, let ipv6, let port, let username, let password):
|
||||
if boxed {
|
||||
buffer.appendInt32(1667228533)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeString(ip, buffer: buffer, boxed: false)
|
||||
serializeString(ipv6, buffer: buffer, boxed: false)
|
||||
serializeInt32(port, buffer: buffer, boxed: false)
|
||||
serializeString(username, buffer: buffer, boxed: false)
|
||||
serializeString(password, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -19931,6 +19874,8 @@ public extension Api {
|
||||
switch self {
|
||||
case .phoneConnection(let id, let ip, let ipv6, let port, let peerTag):
|
||||
return ("phoneConnection", [("id", id), ("ip", ip), ("ipv6", ipv6), ("port", port), ("peerTag", peerTag)])
|
||||
case .phoneConnectionWebrtc(let flags, let id, let ip, let ipv6, let port, let username, let password):
|
||||
return ("phoneConnectionWebrtc", [("flags", flags), ("id", id), ("ip", ip), ("ipv6", ipv6), ("port", port), ("username", username), ("password", password)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -19957,6 +19902,35 @@ public extension Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_phoneConnectionWebrtc(_ reader: BufferReader) -> PhoneConnection? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: String?
|
||||
_4 = parseString(reader)
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: String?
|
||||
_6 = parseString(reader)
|
||||
var _7: String?
|
||||
_7 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.PhoneConnection.phoneConnectionWebrtc(flags: _1!, id: _2!, ip: _3!, ipv6: _4!, port: _5!, username: _6!, password: _7!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum AccountDaysTTL: TypeConstructorDescription {
|
||||
|
@ -810,42 +810,6 @@ public struct stats {
|
||||
}
|
||||
|
||||
}
|
||||
public enum MessageStats: TypeConstructorDescription {
|
||||
case messageStats(viewsGraph: Api.StatsGraph)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageStats(let viewsGraph):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1986399595)
|
||||
}
|
||||
viewsGraph.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageStats(let viewsGraph):
|
||||
return ("messageStats", [("viewsGraph", viewsGraph)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? {
|
||||
var _1: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.stats.MessageStats.messageStats(viewsGraph: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
|
@ -2243,6 +2243,26 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func getMessagesViews(peer: Api.InputPeer, id: [Int32], increment: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-993483427)
|
||||
peer.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(id.count))
|
||||
for item in id {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
increment.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "messages.getMessagesViews", parameters: [("peer", peer), ("id", id), ("increment", increment)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: [Int32]?
|
||||
if let _ = reader.readInt32() {
|
||||
result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func editChatAdmin(chatId: Int32, userId: Api.InputUser, isAdmin: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1444503762)
|
||||
@ -3698,26 +3718,6 @@ public extension Api {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getMessagesViews(peer: Api.InputPeer, id: [Int32], increment: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.MessageViews]>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-39035462)
|
||||
peer.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(id.count))
|
||||
for item in id {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
increment.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "messages.getMessagesViews", parameters: [("peer", peer), ("id", id), ("increment", increment)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.MessageViews]? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: [Api.MessageViews]?
|
||||
if let _ = reader.readInt32() {
|
||||
result = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageViews.self)
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public struct channels {
|
||||
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
@ -4450,41 +4450,6 @@ public extension Api {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getMessagePublicForwards(channel: Api.InputChannel, msgId: Int32, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1445996571)
|
||||
channel.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
serializeInt32(offsetRate, buffer: buffer, boxed: false)
|
||||
offsetPeer.serialize(buffer, true)
|
||||
serializeInt32(offsetId, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "stats.getMessagePublicForwards", parameters: [("channel", channel), ("msgId", msgId), ("offsetRate", offsetRate), ("offsetPeer", offsetPeer), ("offsetId", offsetId), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.Messages?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.messages.Messages
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getMessageStats(flags: Int32, channel: Api.InputChannel, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stats.MessageStats>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1226791947)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
channel.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "stats.getMessageStats", parameters: [("flags", flags), ("channel", channel), ("msgId", msgId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.MessageStats? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.stats.MessageStats?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.stats.MessageStats
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public struct auth {
|
||||
public static func checkPhone(phoneNumber: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.auth.CheckedPhone>) {
|
||||
|
@ -34,11 +34,11 @@ private final class CallVideoNode: ASDisplayNode {
|
||||
private(set) var isReady: Bool = false
|
||||
private var isReadyTimer: SwiftSignalKit.Timer?
|
||||
|
||||
private let isFlippedUpdated: () -> Void
|
||||
private let isFlippedUpdated: (CallVideoNode) -> Void
|
||||
|
||||
private(set) var currentOrientation: PresentationCallVideoView.Orientation
|
||||
|
||||
init(videoView: PresentationCallVideoView, isReadyUpdated: @escaping () -> Void, orientationUpdated: @escaping () -> Void, isFlippedUpdated: @escaping () -> Void) {
|
||||
init(videoView: PresentationCallVideoView, assumeReadyAfterTimeout: Bool, isReadyUpdated: @escaping () -> Void, orientationUpdated: @escaping () -> Void, isFlippedUpdated: @escaping (CallVideoNode) -> Void) {
|
||||
self.isReadyUpdated = isReadyUpdated
|
||||
self.isFlippedUpdated = isFlippedUpdated
|
||||
|
||||
@ -46,46 +46,60 @@ private final class CallVideoNode: ASDisplayNode {
|
||||
self.videoTransformContainer.clipsToBounds = true
|
||||
self.videoView = videoView
|
||||
videoView.view.clipsToBounds = true
|
||||
videoView.view.backgroundColor = .black
|
||||
|
||||
self.currentOrientation = videoView.getOrientation()
|
||||
|
||||
super.init()
|
||||
|
||||
self.backgroundColor = .black
|
||||
|
||||
self.videoTransformContainer.view.addSubview(self.videoView.view)
|
||||
self.addSubnode(self.videoTransformContainer)
|
||||
|
||||
self.videoView.setOnFirstFrameReceived { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if !strongSelf.isReady {
|
||||
strongSelf.isReady = true
|
||||
strongSelf.isReadyTimer?.invalidate()
|
||||
strongSelf.isReadyUpdated()
|
||||
Queue.mainQueue().async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if !strongSelf.isReady {
|
||||
strongSelf.isReady = true
|
||||
strongSelf.isReadyTimer?.invalidate()
|
||||
strongSelf.isReadyUpdated()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.videoView.setOnOrientationUpdated { [weak self] orientation in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.currentOrientation != orientation {
|
||||
strongSelf.currentOrientation = orientation
|
||||
orientationUpdated()
|
||||
Queue.mainQueue().async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.currentOrientation != orientation {
|
||||
strongSelf.currentOrientation = orientation
|
||||
orientationUpdated()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.isReadyTimer = SwiftSignalKit.Timer(timeout: 3.0, repeat: false, completion: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
self.videoView.setOnIsMirroredUpdated { [weak self] _ in
|
||||
Queue.mainQueue().async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.isFlippedUpdated(strongSelf)
|
||||
}
|
||||
if !strongSelf.isReady {
|
||||
strongSelf.isReady = true
|
||||
strongSelf.isReadyUpdated()
|
||||
}
|
||||
}, queue: .mainQueue())
|
||||
}
|
||||
|
||||
if assumeReadyAfterTimeout {
|
||||
self.isReadyTimer = SwiftSignalKit.Timer(timeout: 3.0, repeat: false, completion: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if !strongSelf.isReady {
|
||||
strongSelf.isReady = true
|
||||
strongSelf.isReadyUpdated()
|
||||
}
|
||||
}, queue: .mainQueue())
|
||||
}
|
||||
self.isReadyTimer?.start()
|
||||
}
|
||||
|
||||
@ -201,8 +215,6 @@ private final class CallVideoNode: ASDisplayNode {
|
||||
if let effectView = self.effectView {
|
||||
transition.updateCornerRadius(layer: effectView.layer, cornerRadius: self.currentCornerRadius)
|
||||
}
|
||||
|
||||
transition.updateCornerRadius(layer: self.layer, cornerRadius: self.currentCornerRadius)
|
||||
}
|
||||
|
||||
func updateIsBlurred(isBlurred: Bool) {
|
||||
@ -567,7 +579,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
||||
return
|
||||
}
|
||||
if let incomingVideoView = incomingVideoView {
|
||||
let incomingVideoNode = CallVideoNode(videoView: incomingVideoView, isReadyUpdated: {
|
||||
let incomingVideoNode = CallVideoNode(videoView: incomingVideoView, assumeReadyAfterTimeout: false, isReadyUpdated: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -581,13 +593,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
||||
if let (layout, navigationBarHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
}
|
||||
}, isFlippedUpdated: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let (layout, navigationBarHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
}
|
||||
}, isFlippedUpdated: { _ in
|
||||
})
|
||||
strongSelf.incomingVideoNodeValue = incomingVideoNode
|
||||
strongSelf.expandedVideoNode = incomingVideoNode
|
||||
@ -637,7 +643,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
||||
strongSelf.updateButtonsMode(transition: .animated(duration: 0.4, curve: .spring))
|
||||
}
|
||||
|
||||
let outgoingVideoNode = CallVideoNode(videoView: outgoingVideoView, isReadyUpdated: {
|
||||
let outgoingVideoNode = CallVideoNode(videoView: outgoingVideoView, assumeReadyAfterTimeout: true, isReadyUpdated: {
|
||||
if delayUntilInitialized {
|
||||
Queue.mainQueue().after(0.4, {
|
||||
applyNode()
|
||||
@ -650,13 +656,26 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
||||
if let (layout, navigationBarHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
}
|
||||
}, isFlippedUpdated: {
|
||||
guard let strongSelf = self else {
|
||||
}, isFlippedUpdated: { videoNode in
|
||||
guard let _ = self else {
|
||||
return
|
||||
}
|
||||
if let (layout, navigationBarHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
}
|
||||
/*if videoNode === strongSelf.minimizedVideoNode, let tempView = videoNode.view.snapshotView(afterScreenUpdates: true) {
|
||||
videoNode.view.superview?.insertSubview(tempView, aboveSubview: videoNode.view)
|
||||
videoNode.view.frame = videoNode.frame
|
||||
let transitionOptions: UIView.AnimationOptions = [.transitionFlipFromRight, .showHideTransitionViews]
|
||||
|
||||
UIView.transition(with: tempView, duration: 1.0, options: transitionOptions, animations: {
|
||||
tempView.isHidden = true
|
||||
}, completion: { [weak tempView] _ in
|
||||
tempView?.removeFromSuperview()
|
||||
})
|
||||
|
||||
videoNode.view.isHidden = true
|
||||
UIView.transition(with: videoNode.view, duration: 1.0, options: transitionOptions, animations: {
|
||||
videoNode.view.isHidden = false
|
||||
})
|
||||
}*/
|
||||
})
|
||||
|
||||
strongSelf.candidateOutgoingVideoNodeValue = outgoingVideoNode
|
||||
|
@ -29,7 +29,7 @@ public final class CallKitIntegration {
|
||||
return self.audioSessionActivePromise.get()
|
||||
}
|
||||
|
||||
init?(enableVideoCalls: Bool, startCall: @escaping (Account, UUID, String, Bool) -> Signal<Bool, NoError>, answerCall: @escaping (UUID) -> Void, endCall: @escaping (UUID) -> Signal<Bool, NoError>, setCallMuted: @escaping (UUID, Bool) -> Void, audioSessionActivationChanged: @escaping (Bool) -> Void) {
|
||||
init?(startCall: @escaping (Account, UUID, String, Bool) -> Signal<Bool, NoError>, answerCall: @escaping (UUID) -> Void, endCall: @escaping (UUID) -> Signal<Bool, NoError>, setCallMuted: @escaping (UUID, Bool) -> Void, audioSessionActivationChanged: @escaping (Bool) -> Void) {
|
||||
if !CallKitIntegration.isAvailable {
|
||||
return nil
|
||||
}
|
||||
@ -40,7 +40,7 @@ public final class CallKitIntegration {
|
||||
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
if sharedProviderDelegate == nil {
|
||||
sharedProviderDelegate = CallKitProviderDelegate(enableVideoCalls: enableVideoCalls)
|
||||
sharedProviderDelegate = CallKitProviderDelegate()
|
||||
}
|
||||
(sharedProviderDelegate as? CallKitProviderDelegate)?.setup(audioSessionActivePromise: self.audioSessionActivePromise, startCall: startCall, answerCall: answerCall, endCall: endCall, setCallMuted: setCallMuted, audioSessionActivationChanged: audioSessionActivationChanged)
|
||||
} else {
|
||||
@ -112,8 +112,8 @@ class CallKitProviderDelegate: NSObject, CXProviderDelegate {
|
||||
|
||||
fileprivate var audioSessionActivePromise: ValuePromise<Bool>?
|
||||
|
||||
init(enableVideoCalls: Bool) {
|
||||
self.provider = CXProvider(configuration: CallKitProviderDelegate.providerConfiguration(enableVideoCalls: enableVideoCalls))
|
||||
override init() {
|
||||
self.provider = CXProvider(configuration: CallKitProviderDelegate.providerConfiguration())
|
||||
|
||||
super.init()
|
||||
|
||||
@ -129,7 +129,7 @@ class CallKitProviderDelegate: NSObject, CXProviderDelegate {
|
||||
self.audioSessionActivationChanged = audioSessionActivationChanged
|
||||
}
|
||||
|
||||
private static func providerConfiguration(enableVideoCalls: Bool) -> CXProviderConfiguration {
|
||||
private static func providerConfiguration() -> CXProviderConfiguration {
|
||||
let providerConfiguration = CXProviderConfiguration(localizedName: "Telegram")
|
||||
|
||||
providerConfiguration.supportsVideo = false
|
||||
|
@ -169,6 +169,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
public let isOutgoing: Bool
|
||||
public var isVideo: Bool
|
||||
public var isVideoPossible: Bool
|
||||
public let enableHighBitrateVideoCalls: Bool
|
||||
public let peer: Peer?
|
||||
|
||||
private let serializedData: String?
|
||||
@ -257,7 +258,8 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
currentNetworkType: NetworkType,
|
||||
updatedNetworkType: Signal<NetworkType, NoError>,
|
||||
startWithVideo: Bool,
|
||||
isVideoPossible: Bool
|
||||
isVideoPossible: Bool,
|
||||
enableHighBitrateVideoCalls: Bool
|
||||
) {
|
||||
self.account = account
|
||||
self.audioSession = audioSession
|
||||
@ -286,6 +288,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
self.isVideoPossible = isVideoPossible
|
||||
self.peer = peer
|
||||
self.isVideo = startWithVideo
|
||||
self.enableHighBitrateVideoCalls = enableHighBitrateVideoCalls
|
||||
if self.isVideo {
|
||||
self.videoCapturer = OngoingCallVideoCapturer()
|
||||
self.statePromise.set(PresentationCallState(state: isOutgoing ? .waiting : .ringing, videoState: .outgoingRequested, remoteVideoState: .active))
|
||||
@ -569,7 +572,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
if let _ = audioSessionControl, !wasActive || previousControl == nil {
|
||||
let logName = "\(id.id)_\(id.accessHash)"
|
||||
|
||||
let ongoingContext = OngoingCallContext(account: account, callSessionManager: self.callSessionManager, internalId: self.internalId, proxyServer: proxyServer, auxiliaryServers: auxiliaryServers, initialNetworkType: self.currentNetworkType, updatedNetworkType: self.updatedNetworkType, serializedData: self.serializedData, dataSaving: dataSaving, derivedState: self.derivedState, key: key, isOutgoing: sessionState.isOutgoing, video: self.videoCapturer, connections: connections, maxLayer: maxLayer, version: version, allowP2P: allowsP2P, audioSessionActive: self.audioSessionActive.get(), logName: logName)
|
||||
let ongoingContext = OngoingCallContext(account: account, callSessionManager: self.callSessionManager, internalId: self.internalId, proxyServer: proxyServer, initialNetworkType: self.currentNetworkType, updatedNetworkType: self.updatedNetworkType, serializedData: self.serializedData, dataSaving: dataSaving, derivedState: self.derivedState, key: key, isOutgoing: sessionState.isOutgoing, video: self.videoCapturer, connections: connections, maxLayer: maxLayer, version: version, allowP2P: allowsP2P, enableHighBitrateVideoCalls: self.enableHighBitrateVideoCalls, audioSessionActive: self.audioSessionActive.get(), logName: logName)
|
||||
self.ongoingContext = ongoingContext
|
||||
ongoingContext.setIsMuted(self.isMutedValue)
|
||||
|
||||
@ -811,6 +814,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
if let view = view {
|
||||
let setOnFirstFrameReceived = view.setOnFirstFrameReceived
|
||||
let setOnOrientationUpdated = view.setOnOrientationUpdated
|
||||
let setOnIsMirroredUpdated = view.setOnIsMirroredUpdated
|
||||
completion(PresentationCallVideoView(
|
||||
view: view.view,
|
||||
setOnFirstFrameReceived: { f in
|
||||
@ -849,6 +853,11 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
}
|
||||
f?(mappedValue)
|
||||
}
|
||||
},
|
||||
setOnIsMirroredUpdated: { f in
|
||||
setOnIsMirroredUpdated { value in
|
||||
f?(value)
|
||||
}
|
||||
}
|
||||
))
|
||||
} else {
|
||||
@ -867,6 +876,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
if let view = view {
|
||||
let setOnFirstFrameReceived = view.setOnFirstFrameReceived
|
||||
let setOnOrientationUpdated = view.setOnOrientationUpdated
|
||||
let setOnIsMirroredUpdated = view.setOnIsMirroredUpdated
|
||||
completion(PresentationCallVideoView(
|
||||
view: view.view,
|
||||
setOnFirstFrameReceived: { f in
|
||||
@ -905,8 +915,12 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
}
|
||||
f?(mappedValue)
|
||||
}
|
||||
},
|
||||
setOnIsMirroredUpdated: { f in
|
||||
setOnIsMirroredUpdated { value in
|
||||
f?(value)
|
||||
}
|
||||
}
|
||||
|
||||
))
|
||||
} else {
|
||||
completion(nil)
|
||||
|
@ -82,7 +82,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
private let accountManager: AccountManager
|
||||
private let audioSession: ManagedAudioSession
|
||||
private let callKitIntegration: CallKitIntegration?
|
||||
private var isVideoPossible: Bool
|
||||
|
||||
private var currentCallValue: PresentationCallImpl?
|
||||
private var currentCall: PresentationCallImpl? {
|
||||
@ -117,15 +116,14 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
return OngoingCallContext.maxLayer
|
||||
}
|
||||
|
||||
public static func voipVersions(includeExperimental: Bool, includeReference: Bool) -> [String] {
|
||||
public static func voipVersions(includeExperimental: Bool, includeReference: Bool) -> [(version: String, supportsVideo: Bool)] {
|
||||
return OngoingCallContext.versions(includeExperimental: includeExperimental, includeReference: includeReference)
|
||||
}
|
||||
|
||||
public init(accountManager: AccountManager, enableVideoCalls: Bool, getDeviceAccessData: @escaping () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void), isMediaPlaying: @escaping () -> Bool, resumeMediaPlayback: @escaping () -> Void, audioSession: ManagedAudioSession, activeAccounts: Signal<[Account], NoError>) {
|
||||
public init(accountManager: AccountManager, getDeviceAccessData: @escaping () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void), isMediaPlaying: @escaping () -> Bool, resumeMediaPlayback: @escaping () -> Void, audioSession: ManagedAudioSession, activeAccounts: Signal<[Account], NoError>) {
|
||||
self.getDeviceAccessData = getDeviceAccessData
|
||||
self.accountManager = accountManager
|
||||
self.audioSession = audioSession
|
||||
self.isVideoPossible = enableVideoCalls
|
||||
|
||||
self.isMediaPlaying = isMediaPlaying
|
||||
self.resumeMediaPlayback = resumeMediaPlayback
|
||||
@ -136,7 +134,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
var setCallMutedImpl: ((UUID, Bool) -> Void)?
|
||||
var audioSessionActivationChangedImpl: ((Bool) -> Void)?
|
||||
|
||||
self.callKitIntegration = CallKitIntegration(enableVideoCalls: enableVideoCalls, startCall: { account, uuid, handle, isVideo in
|
||||
self.callKitIntegration = CallKitIntegration(startCall: { account, uuid, handle, isVideo in
|
||||
if let startCallImpl = startCallImpl {
|
||||
return startCallImpl(account, uuid, handle, isVideo)
|
||||
} else {
|
||||
@ -214,7 +212,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
|
||||
startCallImpl = { [weak self] account, uuid, handle, isVideo in
|
||||
if let strongSelf = self, let userId = Int32(handle) {
|
||||
return strongSelf.startCall(account: account, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), isVideo: isVideo, isVideoPossible: strongSelf.isVideoPossible, internalId: uuid)
|
||||
return strongSelf.startCall(account: account, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), isVideo: isVideo, internalId: uuid)
|
||||
|> take(1)
|
||||
|> map { result -> Bool in
|
||||
return result
|
||||
@ -283,7 +281,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
private func ringingStatesUpdated(_ ringingStates: [(Account, Peer, CallSessionRingingState, Bool, NetworkType)], enableCallKit: Bool) {
|
||||
if let firstState = ringingStates.first {
|
||||
if self.currentCall == nil {
|
||||
self.currentCallDisposable.set((combineLatest(firstState.0.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings]) |> take(1))
|
||||
self.currentCallDisposable.set((combineLatest(firstState.0.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] preferences, sharedData in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -292,6 +290,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
let configuration = preferences.values[PreferencesKeys.voipConfiguration] as? VoipConfiguration ?? .defaultValue
|
||||
let derivedState = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState] as? VoipDerivedState ?? .default
|
||||
let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings ?? .defaultSettings
|
||||
let experimentalSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings] as? ExperimentalUISettings ?? .defaultSettings
|
||||
let appConfiguration = preferences.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? AppConfiguration.defaultValue
|
||||
|
||||
let call = PresentationCallImpl(
|
||||
@ -313,7 +312,8 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
currentNetworkType: firstState.4,
|
||||
updatedNetworkType: firstState.0.networkType,
|
||||
startWithVideo: firstState.2.isVideo,
|
||||
isVideoPossible: strongSelf.isVideoPossible
|
||||
isVideoPossible: firstState.2.isVideoPossible,
|
||||
enableHighBitrateVideoCalls: experimentalSettings.enableHighBitrateVideoCalls
|
||||
)
|
||||
strongSelf.updateCurrentCall(call)
|
||||
strongSelf.currentCallPromise.set(.single(call))
|
||||
@ -339,8 +339,9 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func requestCall(account: Account, peerId: PeerId, isVideo: Bool, endCurrentIfAny: Bool) -> RequestCallResult {
|
||||
let isVideoPossible = self.isVideoPossible
|
||||
public func requestCall(context: AccountContext, peerId: PeerId, isVideo: Bool, endCurrentIfAny: Bool) -> RequestCallResult {
|
||||
let account = context.account
|
||||
|
||||
if let call = self.currentCall, !endCurrentIfAny {
|
||||
return .alreadyInProgress(call.peerId)
|
||||
}
|
||||
@ -405,7 +406,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.startCall(account: account, peerId: peerId, isVideo: isVideo, isVideoPossible: isVideoPossible).start()
|
||||
let _ = strongSelf.startCall(account: account, peerId: peerId, isVideo: isVideo).start()
|
||||
}
|
||||
if let currentCall = self.currentCall {
|
||||
self.startCallDisposable.set((currentCall.hangUp()
|
||||
@ -423,7 +424,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
account: Account,
|
||||
peerId: PeerId,
|
||||
isVideo: Bool,
|
||||
isVideoPossible: Bool,
|
||||
internalId: CallSessionInternalId = CallSessionInternalId()
|
||||
) -> Signal<Bool, NoError> {
|
||||
let (presentationData, present, openSettings) = self.getDeviceAccessData()
|
||||
@ -459,9 +459,28 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
if !accessEnabled {
|
||||
return .single(false)
|
||||
}
|
||||
return (combineLatest(queue: .mainQueue(), account.callSessionManager.request(peerId: peerId, isVideo: isVideo, internalId: internalId), networkType |> take(1), account.postbox.peerView(id: peerId) |> map { peerView -> Bool in
|
||||
|
||||
let request = account.postbox.transaction { transaction -> VideoCallsConfiguration in
|
||||
let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration) as? AppConfiguration ?? AppConfiguration.defaultValue
|
||||
return VideoCallsConfiguration(appConfiguration: appConfiguration)
|
||||
}
|
||||
|> mapToSignal { callsConfiguration -> Signal<CallSessionInternalId, NoError> in
|
||||
let isVideoPossible: Bool
|
||||
switch callsConfiguration.videoCallsSupport {
|
||||
case .disabled:
|
||||
isVideoPossible = isVideo
|
||||
case .full:
|
||||
isVideoPossible = true
|
||||
case .onlyVideo:
|
||||
isVideoPossible = isVideo
|
||||
}
|
||||
|
||||
return account.callSessionManager.request(peerId: peerId, isVideo: isVideo, enableVideo: isVideoPossible, internalId: internalId)
|
||||
}
|
||||
|
||||
return (combineLatest(queue: .mainQueue(), request, networkType |> take(1), account.postbox.peerView(id: peerId) |> map { peerView -> Bool in
|
||||
return peerView.peerIsContact
|
||||
} |> take(1), account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings]) |> take(1))
|
||||
} |> take(1), account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1))
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext { internalId, currentNetworkType, isContact, preferences, sharedData in
|
||||
if let strongSelf = self, accessEnabled {
|
||||
@ -474,6 +493,19 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings] as? AutodownloadSettings ?? .defaultSettings
|
||||
let appConfiguration = preferences.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? AppConfiguration.defaultValue
|
||||
|
||||
let callsConfiguration = VideoCallsConfiguration(appConfiguration: appConfiguration)
|
||||
let isVideoPossible: Bool
|
||||
switch callsConfiguration.videoCallsSupport {
|
||||
case .disabled:
|
||||
isVideoPossible = isVideo
|
||||
case .full:
|
||||
isVideoPossible = true
|
||||
case .onlyVideo:
|
||||
isVideoPossible = isVideo
|
||||
}
|
||||
|
||||
let experimentalSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings] as? ExperimentalUISettings ?? .defaultSettings
|
||||
|
||||
let call = PresentationCallImpl(
|
||||
account: account,
|
||||
audioSession: strongSelf.audioSession,
|
||||
@ -496,7 +528,8 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
currentNetworkType: currentNetworkType,
|
||||
updatedNetworkType: account.networkType,
|
||||
startWithVideo: isVideo,
|
||||
isVideoPossible: isVideoPossible
|
||||
isVideoPossible: isVideoPossible,
|
||||
enableHighBitrateVideoCalls: experimentalSettings.enableHighBitrateVideoCalls
|
||||
)
|
||||
strongSelf.updateCurrentCall(call)
|
||||
strongSelf.currentCallPromise.set(.single(call))
|
||||
|
@ -1253,8 +1253,8 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
updatedState.addReadMessagesContents((PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), messages))
|
||||
case let .updateChannelMessageViews(channelId, id, views):
|
||||
updatedState.addUpdateMessageImpressionCount(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: id), count: views)
|
||||
case let .updateChannelMessageForwards(channelId, id, forwards):
|
||||
updatedState.addUpdateMessageForwardsCount(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: id), count: forwards)
|
||||
/*case let .updateChannelMessageForwards(channelId, id, forwards):
|
||||
updatedState.addUpdateMessageForwardsCount(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: id), count: forwards)*/
|
||||
case let .updateNewStickerSet(stickerset):
|
||||
updatedState.addUpdateInstalledStickerPacks(.add(stickerset))
|
||||
case let .updateStickerSetsOrder(flags, order):
|
||||
@ -1898,8 +1898,8 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
||||
updatedState.addReadMessagesContents((peer.id, messages))
|
||||
case let .updateChannelMessageViews(_, id, views):
|
||||
updatedState.addUpdateMessageImpressionCount(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id), count: views)
|
||||
case let .updateChannelMessageForwards(_, id, views):
|
||||
updatedState.addUpdateMessageForwardsCount(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id), count: views)
|
||||
/*case let .updateChannelMessageForwards(_, id, views):
|
||||
updatedState.addUpdateMessageForwardsCount(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id), count: views)*/
|
||||
case let .updateChannelWebPage(_, apiWebpage, _, _):
|
||||
switch apiWebpage {
|
||||
case let .webPageEmpty(id):
|
||||
|
@ -591,7 +591,7 @@ public final class AccountViewTracker {
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
return account.network.request(Api.functions.messages.getMessagesViews(peer: inputPeer, id: messageIds.map { $0.id }, increment: .boolTrue))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<[Api.MessageViews]?, NoError> in
|
||||
|> `catch` { _ -> Signal<[Int32]?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { viewCounts -> Signal<Void, NoError> in
|
||||
@ -599,7 +599,20 @@ public final class AccountViewTracker {
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
for i in 0 ..< messageIds.count {
|
||||
if i < viewCounts.count {
|
||||
if case let .messageViews(views, forwards) = viewCounts[i] {
|
||||
let views = viewCounts[i]
|
||||
do {
|
||||
transaction.updateMessage(messageIds[i], update: { currentMessage in
|
||||
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
|
||||
var attributes = currentMessage.attributes
|
||||
loop: for j in 0 ..< attributes.count {
|
||||
if let attribute = attributes[j] as? ViewCountMessageAttribute {
|
||||
attributes[j] = ViewCountMessageAttribute(count: max(attribute.count, Int(views)))
|
||||
}
|
||||
}
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
|
||||
})
|
||||
}
|
||||
/*if case let .messageViews(views, forwards) = viewCounts[i] {
|
||||
transaction.updateMessage(messageIds[i], update: { currentMessage in
|
||||
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
|
||||
var attributes = currentMessage.attributes
|
||||
@ -613,7 +626,7 @@ public final class AccountViewTracker {
|
||||
}
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
|
||||
})
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,10 +108,7 @@ public struct CallSessionRingingState: Equatable {
|
||||
public let id: CallSessionInternalId
|
||||
public let peerId: PeerId
|
||||
public let isVideo: Bool
|
||||
|
||||
public static func ==(lhs: CallSessionRingingState, rhs: CallSessionRingingState) -> Bool {
|
||||
return lhs.id == rhs.id && lhs.peerId == rhs.peerId && lhs.isVideo == rhs.isVideo
|
||||
}
|
||||
public let isVideoPossible: Bool
|
||||
}
|
||||
|
||||
public enum DropCallReason {
|
||||
@ -191,18 +188,79 @@ public struct CallSession {
|
||||
public let state: CallSessionState
|
||||
}
|
||||
|
||||
public struct CallSessionConnection {
|
||||
public let id: Int64
|
||||
public let ip: String
|
||||
public let ipv6: String
|
||||
public let port: Int32
|
||||
public let peerTag: Data
|
||||
public enum CallSessionConnection: Equatable {
|
||||
public struct Reflector: Equatable {
|
||||
public let id: Int64
|
||||
public let ip: String
|
||||
public let ipv6: String
|
||||
public let port: Int32
|
||||
public let peerTag: Data
|
||||
|
||||
public init(
|
||||
id: Int64,
|
||||
ip: String,
|
||||
ipv6: String,
|
||||
port: Int32,
|
||||
peerTag: Data
|
||||
) {
|
||||
self.id = id
|
||||
self.ip = ip
|
||||
self.ipv6 = ipv6
|
||||
self.port = port
|
||||
self.peerTag = peerTag
|
||||
}
|
||||
}
|
||||
|
||||
public struct WebRtcReflector: Equatable {
|
||||
public let id: Int64
|
||||
public let hasStun: Bool
|
||||
public let hasTurn: Bool
|
||||
public let ip: String
|
||||
public let ipv6: String
|
||||
public let port: Int32
|
||||
public let username: String
|
||||
public let password: String
|
||||
|
||||
public init(
|
||||
id: Int64,
|
||||
hasStun: Bool,
|
||||
hasTurn: Bool,
|
||||
ip: String,
|
||||
ipv6: String,
|
||||
port: Int32,
|
||||
username: String,
|
||||
password: String
|
||||
) {
|
||||
self.id = id
|
||||
self.hasStun = hasStun
|
||||
self.hasTurn = hasTurn
|
||||
self.ip = ip
|
||||
self.ipv6 = ipv6
|
||||
self.port = port
|
||||
self.username = username
|
||||
self.password = password
|
||||
}
|
||||
}
|
||||
|
||||
case reflector(Reflector)
|
||||
case webRtcReflector(WebRtcReflector)
|
||||
}
|
||||
|
||||
private func parseConnection(_ apiConnection: Api.PhoneConnection) -> CallSessionConnection {
|
||||
switch apiConnection {
|
||||
case let .phoneConnection(id, ip, ipv6, port, peerTag):
|
||||
return CallSessionConnection(id: id, ip: ip, ipv6: ipv6, port: port, peerTag: peerTag.makeData())
|
||||
return .reflector(CallSessionConnection.Reflector(id: id, ip: ip, ipv6: ipv6, port: port, peerTag: peerTag.makeData()))
|
||||
case let .phoneConnectionWebrtc(flags, id, ip, ipv6, port, username, password):
|
||||
return .webRtcReflector(CallSessionConnection.WebRtcReflector(
|
||||
id: id,
|
||||
hasStun: (flags & (1 << 1)) != 0,
|
||||
hasTurn: (flags & (1 << 0)) != 0,
|
||||
ip: ip,
|
||||
ipv6: ipv6,
|
||||
port: port,
|
||||
username: username,
|
||||
password: password
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,6 +277,7 @@ private final class CallSessionContext {
|
||||
let peerId: PeerId
|
||||
let isOutgoing: Bool
|
||||
var type: CallSession.CallType
|
||||
let isVideoPossible: Bool
|
||||
var state: CallSessionInternalState
|
||||
let subscribers = Bag<(CallSession) -> Void>()
|
||||
let signalingSubscribers = Bag<(Data) -> Void>()
|
||||
@ -235,10 +294,11 @@ private final class CallSessionContext {
|
||||
}
|
||||
}
|
||||
|
||||
init(peerId: PeerId, isOutgoing: Bool, type: CallSession.CallType, state: CallSessionInternalState) {
|
||||
init(peerId: PeerId, isOutgoing: Bool, type: CallSession.CallType, isVideoPossible: Bool, state: CallSessionInternalState) {
|
||||
self.peerId = peerId
|
||||
self.isOutgoing = isOutgoing
|
||||
self.type = type
|
||||
self.isVideoPossible = isVideoPossible
|
||||
self.state = state
|
||||
}
|
||||
|
||||
@ -247,8 +307,8 @@ private final class CallSessionContext {
|
||||
}
|
||||
}
|
||||
|
||||
private func selectVersionOnAccept(localVersions: [String], remoteVersions: [String]) -> [String]? {
|
||||
let filteredVersions = localVersions.filter(remoteVersions.contains)
|
||||
private func selectVersionOnAccept(localVersions: [CallSessionManagerImplementationVersion], remoteVersions: [String]) -> [String]? {
|
||||
let filteredVersions = localVersions.map(\.version).filter(remoteVersions.contains)
|
||||
if filteredVersions.isEmpty {
|
||||
return nil
|
||||
} else {
|
||||
@ -256,12 +316,22 @@ private func selectVersionOnAccept(localVersions: [String], remoteVersions: [Str
|
||||
}
|
||||
}
|
||||
|
||||
public struct CallSessionManagerImplementationVersion: Hashable {
|
||||
public var version: String
|
||||
public var supportsVideo: Bool
|
||||
|
||||
public init(version: String, supportsVideo: Bool) {
|
||||
self.version = version
|
||||
self.supportsVideo = supportsVideo
|
||||
}
|
||||
}
|
||||
|
||||
private final class CallSessionManagerContext {
|
||||
private let queue: Queue
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let maxLayer: Int32
|
||||
private var versions: [String]
|
||||
private var versions: [CallSessionManagerImplementationVersion]
|
||||
private let addUpdates: (Api.Updates) -> Void
|
||||
|
||||
private let ringingSubscribers = Bag<([CallSessionRingingState]) -> Void>()
|
||||
@ -270,7 +340,7 @@ private final class CallSessionManagerContext {
|
||||
|
||||
private let disposables = DisposableSet()
|
||||
|
||||
init(queue: Queue, postbox: Postbox, network: Network, maxLayer: Int32, versions: [String], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
init(queue: Queue, postbox: Postbox, network: Network, maxLayer: Int32, versions: [CallSessionManagerImplementationVersion], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
self.queue = queue
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
@ -284,10 +354,32 @@ private final class CallSessionManagerContext {
|
||||
self.disposables.dispose()
|
||||
}
|
||||
|
||||
func updateVersions(versions: [String]) {
|
||||
func updateVersions(versions: [CallSessionManagerImplementationVersion]) {
|
||||
self.versions = versions.reversed()
|
||||
}
|
||||
|
||||
func filteredVersions(enableVideo: Bool) -> [String] {
|
||||
return self.versions.compactMap { version -> String? in
|
||||
if enableVideo {
|
||||
return version.version
|
||||
} else if !version.supportsVideo {
|
||||
return version.version
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func videoVersions() -> [String] {
|
||||
return self.versions.compactMap { version -> String? in
|
||||
if version.supportsVideo {
|
||||
return version.version
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ringingStates() -> Signal<[CallSessionRingingState], NoError> {
|
||||
let queue = self.queue
|
||||
return Signal { [weak self] subscriber in
|
||||
@ -366,7 +458,7 @@ private final class CallSessionManagerContext {
|
||||
var ringingContexts: [CallSessionRingingState] = []
|
||||
for (id, context) in self.contexts {
|
||||
if case .ringing = context.state {
|
||||
ringingContexts.append(CallSessionRingingState(id: id, peerId: context.peerId, isVideo: context.type == .video))
|
||||
ringingContexts.append(CallSessionRingingState(id: id, peerId: context.peerId, isVideo: context.type == .video, isVideoPossible: context.isVideoPossible))
|
||||
}
|
||||
}
|
||||
return ringingContexts
|
||||
@ -398,8 +490,13 @@ private final class CallSessionManagerContext {
|
||||
let b = Data(bytesNoCopy: bBytes, count: 256, deallocator: .free)
|
||||
|
||||
if randomStatus == 0 {
|
||||
var isVideoPossible = self.videoVersions().contains(where: { versions.contains($0) })
|
||||
#if DEBUG
|
||||
isVideoPossible = true
|
||||
#endif
|
||||
|
||||
let internalId = CallSessionInternalId()
|
||||
let context = CallSessionContext(peerId: peerId, isOutgoing: false, type: isVideo ? .video : .audio, state: .ringing(id: stableId, accessHash: accessHash, gAHash: gAHash, b: b, versions: versions))
|
||||
let context = CallSessionContext(peerId: peerId, isOutgoing: false, type: isVideo ? .video : .audio, isVideoPossible: isVideoPossible, state: .ringing(id: stableId, accessHash: accessHash, gAHash: gAHash, b: b, versions: versions))
|
||||
self.contexts[internalId] = context
|
||||
let queue = self.queue
|
||||
context.acknowledgeIncomingCallDisposable.set(self.network.request(Api.functions.phone.receivedCall(peer: .inputPhoneCall(id: stableId, accessHash: accessHash))).start(error: { [weak self] _ in
|
||||
@ -529,11 +626,7 @@ private final class CallSessionManagerContext {
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .ringing(id, accessHash, gAHash, b, remoteVersions):
|
||||
guard var acceptVersions = selectVersionOnAccept(localVersions: self.versions, remoteVersions: remoteVersions) else {
|
||||
self.drop(internalId: internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
return
|
||||
}
|
||||
acceptVersions = self.versions
|
||||
let acceptVersions = self.versions.map(\.version)
|
||||
context.state = .accepting(id: id, accessHash: accessHash, gAHash: gAHash, b: b, disposable: (acceptCallSession(postbox: self.postbox, network: self.network, stableId: id, accessHash: accessHash, b: b, maxLayer: self.maxLayer, versions: acceptVersions) |> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
if case .accepting = context.state {
|
||||
@ -819,12 +912,12 @@ private final class CallSessionManagerContext {
|
||||
return (key, keyId, keyVisualHash)
|
||||
}
|
||||
|
||||
func request(peerId: PeerId, internalId: CallSessionInternalId, isVideo: Bool) -> CallSessionInternalId? {
|
||||
func request(peerId: PeerId, internalId: CallSessionInternalId, isVideo: Bool, enableVideo: Bool) -> CallSessionInternalId? {
|
||||
let aBytes = malloc(256)!
|
||||
let randomStatus = SecRandomCopyBytes(nil, 256, aBytes.assumingMemoryBound(to: UInt8.self))
|
||||
let a = Data(bytesNoCopy: aBytes, count: 256, deallocator: .free)
|
||||
if randomStatus == 0 {
|
||||
self.contexts[internalId] = CallSessionContext(peerId: peerId, isOutgoing: true, type: isVideo ? .video : .audio, state: .requesting(a: a, disposable: (requestCallSession(postbox: self.postbox, network: self.network, peerId: peerId, a: a, maxLayer: self.maxLayer, versions: self.versions, isVideo: isVideo) |> deliverOn(queue)).start(next: { [weak self] result in
|
||||
self.contexts[internalId] = CallSessionContext(peerId: peerId, isOutgoing: true, type: isVideo ? .video : .audio, isVideoPossible: enableVideo || isVideo, state: .requesting(a: a, disposable: (requestCallSession(postbox: self.postbox, network: self.network, peerId: peerId, a: a, maxLayer: self.maxLayer, versions: self.filteredVersions(enableVideo: enableVideo), isVideo: isVideo) |> deliverOn(queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
if case .requesting = context.state {
|
||||
switch result {
|
||||
@ -858,7 +951,7 @@ public final class CallSessionManager {
|
||||
private let queue = Queue()
|
||||
private var contextRef: Unmanaged<CallSessionManagerContext>?
|
||||
|
||||
init(postbox: Postbox, network: Network, maxLayer: Int32, versions: [String], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
init(postbox: Postbox, network: Network, maxLayer: Int32, versions: [CallSessionManagerImplementationVersion], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
self.queue.async {
|
||||
let context = CallSessionManagerContext(queue: self.queue, postbox: postbox, network: network, maxLayer: maxLayer, versions: versions, addUpdates: addUpdates)
|
||||
self.contextRef = Unmanaged.passRetained(context)
|
||||
@ -917,12 +1010,12 @@ public final class CallSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func request(peerId: PeerId, isVideo: Bool, internalId: CallSessionInternalId = CallSessionInternalId()) -> Signal<CallSessionInternalId, NoError> {
|
||||
public func request(peerId: PeerId, isVideo: Bool, enableVideo: Bool, internalId: CallSessionInternalId = CallSessionInternalId()) -> Signal<CallSessionInternalId, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self?.withContext { context in
|
||||
if let internalId = context.request(peerId: peerId, internalId: internalId, isVideo: isVideo) {
|
||||
if let internalId = context.request(peerId: peerId, internalId: internalId, isVideo: isVideo, enableVideo: enableVideo) {
|
||||
subscriber.putNext(internalId)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
@ -944,7 +1037,7 @@ public final class CallSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func updateVersions(versions: [String]) {
|
||||
public func updateVersions(versions: [CallSessionManagerImplementationVersion]) {
|
||||
self.withContext { context in
|
||||
context.updateVersions(versions: versions)
|
||||
}
|
||||
|
@ -39,7 +39,8 @@ public struct MessageStatsContextState: Equatable {
|
||||
}
|
||||
|
||||
private func requestMessageStats(postbox: Postbox, network: Network, datacenterId: Int32, messageId: MessageId, dark: Bool = false) -> Signal<MessageStats?, NoError> {
|
||||
return postbox.transaction { transaction -> (Peer, Message)? in
|
||||
return .single(nil)
|
||||
/*return postbox.transaction { transaction -> (Peer, Message)? in
|
||||
if let peer = transaction.getPeer(messageId.peerId), let message = transaction.getMessage(messageId) {
|
||||
return (peer, message)
|
||||
} else {
|
||||
@ -86,7 +87,7 @@ private func requestMessageStats(postbox: Postbox, network: Network, datacenterI
|
||||
}
|
||||
}
|
||||
|> retryRequest
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private final class MessageStatsContextImpl {
|
||||
|
@ -403,12 +403,12 @@ public struct NetworkInitializationArguments {
|
||||
public let languagesCategory: String
|
||||
public let appVersion: String
|
||||
public let voipMaxLayer: Int32
|
||||
public let voipVersions: [String]
|
||||
public let voipVersions: [CallSessionManagerImplementationVersion]
|
||||
public let appData: Signal<Data?, NoError>
|
||||
public let autolockDeadine: Signal<Int32?, NoError>
|
||||
public let encryptionProvider: EncryptionProvider
|
||||
|
||||
public init(apiId: Int32, apiHash: String, languagesCategory: String, appVersion: String, voipMaxLayer: Int32, voipVersions: [String], appData: Signal<Data?, NoError>, autolockDeadine: Signal<Int32?, NoError>, encryptionProvider: EncryptionProvider) {
|
||||
public init(apiId: Int32, apiHash: String, languagesCategory: String, appVersion: String, voipMaxLayer: Int32, voipVersions: [CallSessionManagerImplementationVersion], appData: Signal<Data?, NoError>, autolockDeadine: Signal<Int32?, NoError>, encryptionProvider: EncryptionProvider) {
|
||||
self.apiId = apiId
|
||||
self.apiHash = apiHash
|
||||
self.languagesCategory = languagesCategory
|
||||
|
@ -292,7 +292,8 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
|
||||
}
|
||||
}
|
||||
case let .publicForwards(messageId, datacenterId):
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> (Api.InputChannel?, Int32, MessageIndex?, Api.InputPeer) in
|
||||
remoteSearchResult = .single((nil, nil))
|
||||
/*remoteSearchResult = account.postbox.transaction { transaction -> (Api.InputChannel?, Int32, MessageIndex?, Api.InputPeer) in
|
||||
let sourcePeer = transaction.getPeer(messageId.peerId)
|
||||
let inputChannel = sourcePeer.flatMap { apiInputChannel($0) }
|
||||
|
||||
@ -329,7 +330,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
|
||||
|> `catch` { _ -> Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> in
|
||||
return .single((nil, nil))
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
return remoteSearchResult
|
||||
|
@ -136,7 +136,7 @@ func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
|
||||
|
||||
func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
switch message {
|
||||
case let .message(flags, _, fromId, toId, fwdHeader, viaBotId, _, _, _, media, _, entities, _, _, _, _, _, _):
|
||||
case let .message(flags, _, fromId, toId, fwdHeader, viaBotId, _, _, _, media, _, entities, _, _, _, _, _):
|
||||
let peerId: PeerId
|
||||
switch toId {
|
||||
case let .peerUser(userId):
|
||||
@ -240,7 +240,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
|
||||
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> [MessageId]? {
|
||||
switch message {
|
||||
case let .message(flags, _, fromId, toId, _, _, replyToMsgId, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(flags, _, fromId, toId, _, _, replyToMsgId, _, _, _, _, _, _, _, _, _, _):
|
||||
if let replyToMsgId = replyToMsgId {
|
||||
let peerId: PeerId
|
||||
switch toId {
|
||||
@ -398,7 +398,7 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
|
||||
extension StoreMessage {
|
||||
convenience init?(apiMessage: Api.Message, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
|
||||
switch apiMessage {
|
||||
case let .message(flags, id, fromId, toId, fwdFrom, viaBotId, replyToMsgId, date, message, media, replyMarkup, entities, views, forwards, editDate, postAuthor, groupingId, restrictionReason):
|
||||
case let .message(flags, id, fromId, toId, fwdFrom, viaBotId, replyToMsgId, date, message, media, replyMarkup, entities, views, editDate, postAuthor, groupingId, restrictionReason):
|
||||
let peerId: PeerId
|
||||
var authorId: PeerId?
|
||||
switch toId {
|
||||
@ -521,9 +521,9 @@ extension StoreMessage {
|
||||
attributes.append(ViewCountMessageAttribute(count: Int(views)))
|
||||
}
|
||||
|
||||
if let forwards = forwards, namespace != Namespaces.Message.ScheduledCloud {
|
||||
/*if let forwards = forwards, namespace != Namespaces.Message.ScheduledCloud {
|
||||
attributes.append(ForwardCountMessageAttribute(count: Int(forwards)))
|
||||
}
|
||||
}*/
|
||||
|
||||
if let editDate = editDate {
|
||||
attributes.append(EditedMessageAttribute(date: editDate, isHidden: (flags & (1 << 21)) != 0))
|
||||
|
@ -193,7 +193,11 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
case let .userFull(userFull):
|
||||
let botInfo = userFull.botInfo.flatMap(BotInfo.init(apiBotInfo:))
|
||||
let isBlocked = (userFull.flags & (1 << 0)) != 0
|
||||
let callsAvailable = (userFull.flags & (1 << 4)) != 0
|
||||
let voiceCallsAvailable = (userFull.flags & (1 << 4)) != 0
|
||||
var videoCallsAvailable = (userFull.flags & (1 << 13)) != 0
|
||||
#if DEBUG
|
||||
videoCallsAvailable = true
|
||||
#endif
|
||||
let callsPrivate = (userFull.flags & (1 << 5)) != 0
|
||||
let canPinMessages = (userFull.flags & (1 << 7)) != 0
|
||||
let pinnedMessageId = userFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
|
||||
@ -205,7 +209,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
hasScheduledMessages = true
|
||||
}
|
||||
|
||||
return previous.withUpdatedAbout(userFull.about).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(userFull.commonChatsCount).withUpdatedIsBlocked(isBlocked).withUpdatedCallsAvailable(callsAvailable).withUpdatedCallsPrivate(callsPrivate).withUpdatedCanPinMessages(canPinMessages).withUpdatedPeerStatusSettings(peerStatusSettings).withUpdatedPinnedMessageId(pinnedMessageId).withUpdatedHasScheduledMessages(hasScheduledMessages)
|
||||
return previous.withUpdatedAbout(userFull.about).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(userFull.commonChatsCount).withUpdatedIsBlocked(isBlocked).withUpdatedVoiceCallsAvailable(voiceCallsAvailable).withUpdatedVideoCallsAvailable(videoCallsAvailable).withUpdatedCallsPrivate(callsPrivate).withUpdatedCanPinMessages(canPinMessages).withUpdatedPeerStatusSettings(peerStatusSettings).withUpdatedPinnedMessageId(pinnedMessageId).withUpdatedHasScheduledMessages(hasScheduledMessages)
|
||||
}
|
||||
})
|
||||
return true
|
||||
|
@ -58,7 +58,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
||||
self.putNext(groups)
|
||||
}
|
||||
case let .updateShortChatMessage(flags, id, fromId, chatId, message, pts, ptsCount, date, fwdFrom, viaBotId, replyToMsgId, entities):
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: fromId, toId: Api.Peer.peerChat(chatId: chatId), fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, editDate: nil, postAuthor: nil, groupedId: nil, restrictionReason: nil)
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: fromId, toId: Api.Peer.peerChat(chatId: chatId), fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, editDate: nil, postAuthor: nil, groupedId: nil, restrictionReason: nil)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
@ -75,7 +75,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
||||
generatedToId = Api.Peer.peerUser(userId: self.peerId.id)
|
||||
}
|
||||
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: generatedFromId, toId: generatedToId, fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, editDate: nil, postAuthor: nil, groupedId: nil, restrictionReason: nil)
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: generatedFromId, toId: generatedToId, fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, editDate: nil, postAuthor: nil, groupedId: nil, restrictionReason: nil)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -141,11 +141,18 @@ public final class AccountContextImpl: AccountContext {
|
||||
return self._contentSettings.get()
|
||||
}
|
||||
|
||||
public var currentAppConfiguration: Atomic<AppConfiguration>
|
||||
private let _appConfiguration = Promise<AppConfiguration>()
|
||||
public var appConfiguration: Signal<AppConfiguration, NoError> {
|
||||
return self._appConfiguration.get()
|
||||
}
|
||||
|
||||
public var watchManager: WatchManager?
|
||||
|
||||
private var storedPassword: (String, CFAbsoluteTime, SwiftSignalKit.Timer)?
|
||||
private var limitsConfigurationDisposable: Disposable?
|
||||
private var contentSettingsDisposable: Disposable?
|
||||
private var appConfigurationDisposable: Disposable?
|
||||
|
||||
private let deviceSpecificContactImportContexts: QueueLocalObject<DeviceSpecificContactImportContexts>
|
||||
private var managedAppSpecificContactsDisposable: Disposable?
|
||||
@ -177,7 +184,7 @@ public final class AccountContextImpl: AccountContext {
|
||||
}
|
||||
#endif
|
||||
|
||||
public init(sharedContext: SharedAccountContextImpl, account: Account, /*tonContext: StoredTonContext?, */limitsConfiguration: LimitsConfiguration, contentSettings: ContentSettings, temp: Bool = false)
|
||||
public init(sharedContext: SharedAccountContextImpl, account: Account, /*tonContext: StoredTonContext?, */limitsConfiguration: LimitsConfiguration, contentSettings: ContentSettings, appConfiguration: AppConfiguration, temp: Bool = false)
|
||||
{
|
||||
self.sharedContextImpl = sharedContext
|
||||
self.account = account
|
||||
@ -233,6 +240,16 @@ public final class AccountContextImpl: AccountContext {
|
||||
let _ = currentContentSettings.swap(value)
|
||||
})
|
||||
|
||||
let updatedAppConfiguration = getAppConfiguration(postbox: account.postbox)
|
||||
self.currentAppConfiguration = Atomic(value: appConfiguration)
|
||||
self._appConfiguration.set(.single(appConfiguration) |> then(updatedAppConfiguration))
|
||||
|
||||
let currentAppConfiguration = self.currentAppConfiguration
|
||||
self.appConfigurationDisposable = (self._appConfiguration.get()
|
||||
|> deliverOnMainQueue).start(next: { value in
|
||||
let _ = currentAppConfiguration.swap(value)
|
||||
})
|
||||
|
||||
let queue = Queue()
|
||||
self.deviceSpecificContactImportContexts = QueueLocalObject(queue: queue, generate: {
|
||||
return DeviceSpecificContactImportContexts(queue: queue)
|
||||
@ -248,11 +265,8 @@ public final class AccountContextImpl: AccountContext {
|
||||
})
|
||||
}
|
||||
|
||||
self.experimentalUISettingsDisposable = (sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.experimentalUISettings])
|
||||
|> deliverOnMainQueue).start(next: { sharedData in
|
||||
if let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings] as? ExperimentalUISettings {
|
||||
account.callSessionManager.updateVersions(versions: PresentationCallManagerImpl.voipVersions(includeExperimental: settings.videoCalls, includeReference: settings.videoCallsReference))
|
||||
}
|
||||
account.callSessionManager.updateVersions(versions: PresentationCallManagerImpl.voipVersions(includeExperimental: true, includeReference: false).map { version, supportsVideo -> CallSessionManagerImplementationVersion in
|
||||
CallSessionManagerImplementationVersion(version: version, supportsVideo: supportsVideo)
|
||||
})
|
||||
}
|
||||
|
||||
@ -260,6 +274,7 @@ public final class AccountContextImpl: AccountContext {
|
||||
self.limitsConfigurationDisposable?.dispose()
|
||||
self.managedAppSpecificContactsDisposable?.dispose()
|
||||
self.contentSettingsDisposable?.dispose()
|
||||
self.appConfigurationDisposable?.dispose()
|
||||
self.experimentalUISettingsDisposable?.dispose()
|
||||
}
|
||||
|
||||
@ -284,3 +299,17 @@ public final class AccountContextImpl: AccountContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getAppConfiguration(transaction: Transaction) -> AppConfiguration {
|
||||
let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration) as? AppConfiguration ?? AppConfiguration.defaultValue
|
||||
return appConfiguration
|
||||
}
|
||||
|
||||
func getAppConfiguration(postbox: Postbox) -> Signal<AppConfiguration, NoError> {
|
||||
return postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
||||
|> map { view -> AppConfiguration in
|
||||
let appConfiguration: AppConfiguration = view.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? AppConfiguration.defaultValue
|
||||
return appConfiguration
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
}
|
||||
|
@ -401,7 +401,9 @@ final class SharedApplicationContext {
|
||||
}
|
||||
}
|
||||
|
||||
let networkArguments = NetworkInitializationArguments(apiId: apiId, apiHash: apiHash, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: PresentationCallManagerImpl.voipMaxLayer, voipVersions: PresentationCallManagerImpl.voipVersions(includeExperimental: false, includeReference: false), appData: self.deviceToken.get()
|
||||
let networkArguments = NetworkInitializationArguments(apiId: apiId, apiHash: apiHash, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: PresentationCallManagerImpl.voipMaxLayer, voipVersions: PresentationCallManagerImpl.voipVersions(includeExperimental: true, includeReference: false).map { version, supportsVideo -> CallSessionManagerImplementationVersion in
|
||||
CallSessionManagerImplementationVersion(version: version, supportsVideo: supportsVideo)
|
||||
}, appData: self.deviceToken.get()
|
||||
|> map { token in
|
||||
let data = buildConfig.bundleData(withAppToken: token, signatureDict: signatureDict)
|
||||
if let data = data, let jsonString = String(data: data, encoding: .utf8) {
|
||||
@ -990,7 +992,7 @@ final class SharedApplicationContext {
|
||||
}
|
||||
return true
|
||||
})
|
||||
|> mapToSignal { account -> Signal<(Account, LimitsConfiguration, CallListSettings, ContentSettings)?, NoError> in
|
||||
|> mapToSignal { account -> Signal<(Account, LimitsConfiguration, CallListSettings, ContentSettings, AppConfiguration)?, NoError> in
|
||||
return sharedApplicationContext.sharedContext.accountManager.transaction { transaction -> CallListSettings? in
|
||||
return transaction.getSharedData(ApplicationSpecificSharedDataKeys.callListSettings) as? CallListSettings
|
||||
}
|
||||
@ -1003,12 +1005,13 @@ final class SharedApplicationContext {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|> mapToSignal { callListSettings -> Signal<(Account, LimitsConfiguration, CallListSettings, ContentSettings)?, NoError> in
|
||||
|> mapToSignal { callListSettings -> Signal<(Account, LimitsConfiguration, CallListSettings, ContentSettings, AppConfiguration)?, NoError> in
|
||||
if let account = account {
|
||||
return account.postbox.transaction { transaction -> (Account, LimitsConfiguration, CallListSettings, ContentSettings)? in
|
||||
return account.postbox.transaction { transaction -> (Account, LimitsConfiguration, CallListSettings, ContentSettings, AppConfiguration)? in
|
||||
let limitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration) as? LimitsConfiguration ?? LimitsConfiguration.defaultValue
|
||||
let contentSettings = getContentSettings(transaction: transaction)
|
||||
return (account, limitsConfiguration, callListSettings ?? CallListSettings.defaultSettings, contentSettings)
|
||||
let appConfiguration = getAppConfiguration(transaction: transaction)
|
||||
return (account, limitsConfiguration, callListSettings ?? CallListSettings.defaultSettings, contentSettings, appConfiguration)
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
@ -1017,11 +1020,8 @@ final class SharedApplicationContext {
|
||||
}
|
||||
|> deliverOnMainQueue
|
||||
|> map { accountAndSettings -> AuthorizedApplicationContext? in
|
||||
return accountAndSettings.flatMap { account, limitsConfiguration, callListSettings, contentSettings in
|
||||
#if ENABLE_WALLET
|
||||
let tonContext = StoredTonContext(basePath: account.basePath, postbox: account.postbox, network: account.network, keychain: tonKeychain)
|
||||
#endif
|
||||
let context = AccountContextImpl(sharedContext: sharedApplicationContext.sharedContext, account: account/*, tonContext: tonContext*/, limitsConfiguration: limitsConfiguration, contentSettings: contentSettings)
|
||||
return accountAndSettings.flatMap { account, limitsConfiguration, callListSettings, contentSettings, appConfiguration in
|
||||
let context = AccountContextImpl(sharedContext: sharedApplicationContext.sharedContext, account: account, limitsConfiguration: limitsConfiguration, contentSettings: contentSettings, appConfiguration: appConfiguration)
|
||||
return AuthorizedApplicationContext(sharedApplicationContext: sharedApplicationContext, mainWindow: self.mainWindow, watchManagerArguments: watchManagerArgumentsPromise.get(), context: context, accountManager: sharedApplicationContext.sharedContext.accountManager, showCallsTab: callListSettings.showTab, reinitializedNotificationSettings: {
|
||||
let _ = (self.context.get()
|
||||
|> take(1)
|
||||
|
@ -763,7 +763,7 @@ final class AuthorizedApplicationContext {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.context.sharedContext.callManager?.requestCall(account: strongSelf.context.account, peerId: peerId, isVideo: isVideo, endCurrentIfAny: false)
|
||||
let _ = strongSelf.context.sharedContext.callManager?.requestCall(context: strongSelf.context, peerId: peerId, isVideo: isVideo, endCurrentIfAny: false)
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -1219,7 +1219,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
|
||||
let callResult = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: false)
|
||||
let callResult = context.sharedContext.callManager?.requestCall(context: context, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peer.id {
|
||||
context.sharedContext.navigateToCurrentCall()
|
||||
@ -1231,7 +1231,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|> deliverOnMainQueue).start(next: { peer, current in
|
||||
if let peer = peer, let current = current {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
let _ = context.sharedContext.callManager?.requestCall(account: context.account, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: true)
|
||||
let _ = context.sharedContext.callManager?.requestCall(context: context, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: true)
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
@ -2922,7 +2922,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
} else if let cachedData = combinedInitialData.cachedData as? CachedUserData {
|
||||
peerIsBlocked = cachedData.isBlocked
|
||||
callsAvailable = cachedData.callsAvailable
|
||||
callsAvailable = cachedData.voiceCallsAvailable
|
||||
callsPrivate = cachedData.callsPrivate
|
||||
pinnedMessageId = cachedData.pinnedMessageId
|
||||
} else if let cachedData = combinedInitialData.cachedData as? CachedGroupData {
|
||||
@ -3063,7 +3063,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
} else if let cachedData = cachedData as? CachedUserData {
|
||||
peerIsBlocked = cachedData.isBlocked
|
||||
callsAvailable = cachedData.callsAvailable
|
||||
callsAvailable = cachedData.voiceCallsAvailable
|
||||
callsPrivate = cachedData.callsPrivate
|
||||
pinnedMessageId = cachedData.pinnedMessageId
|
||||
} else if let cachedData = cachedData as? CachedGroupData {
|
||||
|
@ -911,15 +911,17 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
||||
result.append(.message)
|
||||
}
|
||||
var callsAvailable = false
|
||||
var videoCallsAvailable = false
|
||||
if !user.isDeleted, user.botInfo == nil, !user.flags.contains(.isSupport) {
|
||||
if let cachedUserData = cachedData as? CachedUserData {
|
||||
callsAvailable = cachedUserData.callsAvailable
|
||||
callsAvailable = cachedUserData.voiceCallsAvailable
|
||||
videoCallsAvailable = cachedUserData.videoCallsAvailable
|
||||
}
|
||||
callsAvailable = true
|
||||
}
|
||||
if callsAvailable {
|
||||
result.append(.call)
|
||||
if videoCallsEnabled {
|
||||
if videoCallsEnabled && videoCallsAvailable {
|
||||
result.append(.videoCall)
|
||||
}
|
||||
}
|
||||
|
@ -2565,7 +2565,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
self.isAvatarExpanded = avatarInitiallyExpanded
|
||||
self.isOpenedFromChat = isOpenedFromChat
|
||||
self.isSettings = isSettings
|
||||
self.videoCallsEnabled = context.sharedContext.immediateExperimentalUISettings.videoCalls
|
||||
self.videoCallsEnabled = VideoCallsConfiguration(appConfiguration: context.currentAppConfiguration.with { $0 }).areVideoCallsEnabled
|
||||
|
||||
self.avatarListNode = PeerInfoAvatarListNode(context: context, readyWhenGalleryLoads: avatarInitiallyExpanded)
|
||||
|
||||
|
@ -1422,7 +1422,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.isOpenedFromChat = isOpenedFromChat
|
||||
self.videoCallsEnabled = context.sharedContext.immediateExperimentalUISettings.videoCalls
|
||||
self.videoCallsEnabled = VideoCallsConfiguration(appConfiguration: context.currentAppConfiguration.with { $0 }).areVideoCallsEnabled
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.nearbyPeerDistance = nearbyPeerDistance
|
||||
self.callMessages = callMessages
|
||||
@ -3153,7 +3153,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
return
|
||||
}
|
||||
|
||||
let callResult = self.context.sharedContext.callManager?.requestCall(account: self.context.account, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: false)
|
||||
let callResult = self.context.sharedContext.callManager?.requestCall(context: self.context, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peer.id {
|
||||
self.context.sharedContext.navigateToCurrentCall()
|
||||
@ -3170,7 +3170,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.context.sharedContext.callManager?.requestCall(account: strongSelf.context.account, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: true)
|
||||
let _ = strongSelf.context.sharedContext.callManager?.requestCall(context: strongSelf.context, peerId: peer.id, isVideo: isVideo, endCurrentIfAny: true)
|
||||
})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
|
@ -260,10 +260,11 @@ public class ShareRootControllerImpl {
|
||||
|
||||
let applicationInterface = account
|
||||
|> mapToSignal { sharedContext, account, otherAccounts -> Signal<(AccountContext, PostboxAccessChallengeData, [AccountWithInfo]), ShareAuthorizationError> in
|
||||
let limitsConfigurationAndContentSettings = account.postbox.transaction { transaction -> (LimitsConfiguration, ContentSettings) in
|
||||
let limitsConfigurationAndContentSettings = account.postbox.transaction { transaction -> (LimitsConfiguration, ContentSettings, AppConfiguration) in
|
||||
return (
|
||||
transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration) as? LimitsConfiguration ?? LimitsConfiguration.defaultValue,
|
||||
getContentSettings(transaction: transaction)
|
||||
getContentSettings(transaction: transaction),
|
||||
getAppConfiguration(transaction: transaction)
|
||||
)
|
||||
}
|
||||
return combineLatest(sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationPasscodeSettings]), limitsConfigurationAndContentSettings, sharedContext.accountManager.accessChallengeData())
|
||||
@ -272,7 +273,7 @@ public class ShareRootControllerImpl {
|
||||
|> castError(ShareAuthorizationError.self)
|
||||
|> map { sharedData, limitsConfigurationAndContentSettings, data -> (AccountContext, PostboxAccessChallengeData, [AccountWithInfo]) in
|
||||
updateLegacyLocalization(strings: sharedContext.currentPresentationData.with({ $0 }).strings)
|
||||
let context = AccountContextImpl(sharedContext: sharedContext, account: account/*, tonContext: nil*/, limitsConfiguration: limitsConfigurationAndContentSettings.0, contentSettings: limitsConfigurationAndContentSettings.1)
|
||||
let context = AccountContextImpl(sharedContext: sharedContext, account: account, limitsConfiguration: limitsConfigurationAndContentSettings.0, contentSettings: limitsConfigurationAndContentSettings.1, appConfiguration: limitsConfigurationAndContentSettings.2)
|
||||
return (context, data.data, otherAccounts)
|
||||
}
|
||||
}
|
||||
|
@ -574,7 +574,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
})
|
||||
|
||||
if let mainWindow = mainWindow, applicationBindings.isMainApp {
|
||||
let callManager = PresentationCallManagerImpl(accountManager: self.accountManager, enableVideoCalls: self.immediateExperimentalUISettings.videoCalls, getDeviceAccessData: {
|
||||
let callManager = PresentationCallManagerImpl(accountManager: self.accountManager, getDeviceAccessData: {
|
||||
return (self.currentPresentationData.with { $0 }, { [weak self] c, a in
|
||||
self?.presentGlobalController(c, a)
|
||||
}, {
|
||||
@ -937,7 +937,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
}
|
||||
|
||||
public func makeTempAccountContext(account: Account) -> AccountContext {
|
||||
return AccountContextImpl(sharedContext: self, account: account/*, tonContext: nil*/, limitsConfiguration: .defaultValue, contentSettings: .default, temp: true)
|
||||
return AccountContextImpl(sharedContext: self, account: account, limitsConfiguration: .defaultValue, contentSettings: .default, appConfiguration: .defaultValue, temp: true)
|
||||
}
|
||||
|
||||
public func openChatMessage(_ params: OpenChatMessageParams) -> Bool {
|
||||
|
@ -9,8 +9,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
|
||||
public var chatListPhotos: Bool
|
||||
public var knockoutWallpaper: Bool
|
||||
public var foldersTabAtBottom: Bool
|
||||
public var videoCalls: Bool
|
||||
public var videoCallsReference: Bool
|
||||
public var enableHighBitrateVideoCalls: Bool
|
||||
public var playerEmbedding: Bool
|
||||
public var playlistPlayback: Bool
|
||||
|
||||
@ -22,8 +21,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
|
||||
chatListPhotos: false,
|
||||
knockoutWallpaper: false,
|
||||
foldersTabAtBottom: false,
|
||||
videoCalls: false,
|
||||
videoCallsReference: true,
|
||||
enableHighBitrateVideoCalls: false,
|
||||
playerEmbedding: false,
|
||||
playlistPlayback: false
|
||||
)
|
||||
@ -36,8 +34,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
|
||||
chatListPhotos: Bool,
|
||||
knockoutWallpaper: Bool,
|
||||
foldersTabAtBottom: Bool,
|
||||
videoCalls: Bool,
|
||||
videoCallsReference: Bool,
|
||||
enableHighBitrateVideoCalls: Bool,
|
||||
playerEmbedding: Bool,
|
||||
playlistPlayback: Bool
|
||||
) {
|
||||
@ -47,8 +44,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
|
||||
self.chatListPhotos = chatListPhotos
|
||||
self.knockoutWallpaper = knockoutWallpaper
|
||||
self.foldersTabAtBottom = foldersTabAtBottom
|
||||
self.videoCalls = videoCalls
|
||||
self.videoCallsReference = videoCallsReference
|
||||
self.enableHighBitrateVideoCalls = enableHighBitrateVideoCalls
|
||||
self.playerEmbedding = playerEmbedding
|
||||
self.playlistPlayback = playlistPlayback
|
||||
}
|
||||
@ -60,8 +56,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
|
||||
self.chatListPhotos = decoder.decodeInt32ForKey("chatListPhotos", orElse: 0) != 0
|
||||
self.knockoutWallpaper = decoder.decodeInt32ForKey("knockoutWallpaper", orElse: 0) != 0
|
||||
self.foldersTabAtBottom = decoder.decodeInt32ForKey("foldersTabAtBottom", orElse: 0) != 0
|
||||
self.videoCalls = decoder.decodeInt32ForKey("videoCalls", orElse: 0) != 0
|
||||
self.videoCallsReference = decoder.decodeInt32ForKey("videoCallsReference", orElse: 1) != 0
|
||||
self.enableHighBitrateVideoCalls = decoder.decodeInt32ForKey("enableHighBitrateVideoCalls", orElse: 0) != 0
|
||||
self.playerEmbedding = decoder.decodeInt32ForKey("playerEmbedding", orElse: 0) != 0
|
||||
self.playlistPlayback = decoder.decodeInt32ForKey("playlistPlayback", orElse: 0) != 0
|
||||
}
|
||||
@ -73,8 +68,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
|
||||
encoder.encodeInt32(self.chatListPhotos ? 1 : 0, forKey: "chatListPhotos")
|
||||
encoder.encodeInt32(self.knockoutWallpaper ? 1 : 0, forKey: "knockoutWallpaper")
|
||||
encoder.encodeInt32(self.foldersTabAtBottom ? 1 : 0, forKey: "foldersTabAtBottom")
|
||||
encoder.encodeInt32(self.videoCalls ? 1 : 0, forKey: "videoCalls")
|
||||
encoder.encodeInt32(self.videoCallsReference ? 1 : 0, forKey: "videoCallsReference")
|
||||
encoder.encodeInt32(self.enableHighBitrateVideoCalls ? 1 : 0, forKey: "enableHighBitrateVideoCalls")
|
||||
encoder.encodeInt32(self.playerEmbedding ? 1 : 0, forKey: "playerEmbedding")
|
||||
encoder.encodeInt32(self.playlistPlayback ? 1 : 0, forKey: "playlistPlayback")
|
||||
}
|
||||
|
@ -8,20 +8,25 @@ import TelegramUIPreferences
|
||||
|
||||
import TgVoip
|
||||
import TgVoipWebrtc
|
||||
//import TgVoipWebrtcCustom
|
||||
|
||||
private func callConnectionDescription(_ connection: CallSessionConnection) -> OngoingCallConnectionDescription {
|
||||
return OngoingCallConnectionDescription(connectionId: connection.id, ip: connection.ip, ipv6: connection.ipv6, port: connection.port, peerTag: connection.peerTag)
|
||||
private func callConnectionDescription(_ connection: CallSessionConnection) -> OngoingCallConnectionDescription? {
|
||||
switch connection {
|
||||
case let .reflector(reflector):
|
||||
return OngoingCallConnectionDescription(connectionId: reflector.id, ip: reflector.ip, ipv6: reflector.ipv6, port: reflector.port, peerTag: reflector.peerTag)
|
||||
case .webRtcReflector:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func callConnectionDescriptionWebrtc(_ connection: CallSessionConnection) -> OngoingCallConnectionDescriptionWebrtc {
|
||||
return OngoingCallConnectionDescriptionWebrtc(connectionId: connection.id, ip: connection.ip, ipv6: connection.ipv6, port: connection.port, peerTag: connection.peerTag)
|
||||
private func callConnectionDescriptionWebrtc(_ connection: CallSessionConnection) -> OngoingCallConnectionDescriptionWebrtc? {
|
||||
switch connection {
|
||||
case .reflector:
|
||||
return nil
|
||||
case let .webRtcReflector(reflector):
|
||||
return OngoingCallConnectionDescriptionWebrtc(connectionId: reflector.id, hasStun: reflector.hasStun, hasTurn: reflector.hasTurn, ip: reflector.ip.isEmpty ? reflector.ipv6 : reflector.ip, port: reflector.port, username: reflector.username, password: reflector.password)
|
||||
}
|
||||
}
|
||||
|
||||
/*private func callConnectionDescriptionWebrtcCustom(_ connection: CallSessionConnection) -> OngoingCallConnectionDescriptionWebrtcCustom {
|
||||
return OngoingCallConnectionDescriptionWebrtcCustom(connectionId: connection.id, ip: connection.ip, ipv6: connection.ipv6, port: connection.port, peerTag: connection.peerTag)
|
||||
}*/
|
||||
|
||||
private let callLogsLimit = 20
|
||||
|
||||
public func callLogNameForId(id: Int64, account: Account) -> String? {
|
||||
@ -323,6 +328,9 @@ public final class OngoingCallVideoCapturer {
|
||||
return .rotation0
|
||||
},
|
||||
setOnOrientationUpdated: { _ in
|
||||
},
|
||||
setOnIsMirroredUpdated: { [weak view] f in
|
||||
view?.setOnIsMirroredUpdated(f)
|
||||
}
|
||||
))
|
||||
} else {
|
||||
@ -437,17 +445,20 @@ public final class OngoingCallContextPresentationCallVideoView {
|
||||
public let setOnFirstFrameReceived: ((() -> Void)?) -> Void
|
||||
public let getOrientation: () -> OngoingCallVideoOrientation
|
||||
public let setOnOrientationUpdated: (((OngoingCallVideoOrientation) -> Void)?) -> Void
|
||||
public let setOnIsMirroredUpdated: (((Bool) -> Void)?) -> Void
|
||||
|
||||
public init(
|
||||
view: UIView,
|
||||
setOnFirstFrameReceived: @escaping ((() -> Void)?) -> Void,
|
||||
getOrientation: @escaping () -> OngoingCallVideoOrientation,
|
||||
setOnOrientationUpdated: @escaping (((OngoingCallVideoOrientation) -> Void)?) -> Void
|
||||
setOnOrientationUpdated: @escaping (((OngoingCallVideoOrientation) -> Void)?) -> Void,
|
||||
setOnIsMirroredUpdated: @escaping (((Bool) -> Void)?) -> Void
|
||||
) {
|
||||
self.view = view
|
||||
self.setOnFirstFrameReceived = setOnFirstFrameReceived
|
||||
self.getOrientation = getOrientation
|
||||
self.setOnOrientationUpdated = setOnOrientationUpdated
|
||||
self.setOnIsMirroredUpdated = setOnIsMirroredUpdated
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,15 +514,17 @@ public final class OngoingCallContext {
|
||||
return OngoingCallThreadLocalContext.maxLayer()
|
||||
}
|
||||
|
||||
public static func versions(includeExperimental: Bool, includeReference: Bool) -> [String] {
|
||||
var result: [String] = [OngoingCallThreadLocalContext.version()]
|
||||
public static func versions(includeExperimental: Bool, includeReference: Bool) -> [(version: String, supportsVideo: Bool)] {
|
||||
var result: [(version: String, supportsVideo: Bool)] = [(OngoingCallThreadLocalContext.version(), false)]
|
||||
if includeExperimental {
|
||||
result.append(contentsOf: OngoingCallThreadLocalContextWebrtc.versions(withIncludeReference: includeReference))
|
||||
result.append(contentsOf: OngoingCallThreadLocalContextWebrtc.versions(withIncludeReference: includeReference).map { version -> (version: String, supportsVideo: Bool) in
|
||||
return (version, true)
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public init(account: Account, callSessionManager: CallSessionManager, internalId: CallSessionInternalId, proxyServer: ProxyServerSettings?, auxiliaryServers: [AuxiliaryServer], initialNetworkType: NetworkType, updatedNetworkType: Signal<NetworkType, NoError>, serializedData: String?, dataSaving: VoiceCallDataSaving, derivedState: VoipDerivedState, key: Data, isOutgoing: Bool, video: OngoingCallVideoCapturer?, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, allowP2P: Bool, audioSessionActive: Signal<Bool, NoError>, logName: String) {
|
||||
public init(account: Account, callSessionManager: CallSessionManager, internalId: CallSessionInternalId, proxyServer: ProxyServerSettings?, initialNetworkType: NetworkType, updatedNetworkType: Signal<NetworkType, NoError>, serializedData: String?, dataSaving: VoiceCallDataSaving, derivedState: VoipDerivedState, key: Data, isOutgoing: Bool, video: OngoingCallVideoCapturer?, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, allowP2P: Bool, enableHighBitrateVideoCalls: Bool, audioSessionActive: Signal<Bool, NoError>, logName: String) {
|
||||
let _ = setupLogs
|
||||
OngoingCallThreadLocalContext.applyServerConfig(serializedData)
|
||||
|
||||
@ -540,35 +553,33 @@ public final class OngoingCallContext {
|
||||
break
|
||||
}
|
||||
}
|
||||
var rtcServers: [VoipRtcServerWebrtc] = []
|
||||
for server in auxiliaryServers {
|
||||
switch server.connection {
|
||||
case .stun:
|
||||
rtcServers.append(VoipRtcServerWebrtc(
|
||||
host: server.host,
|
||||
port: Int32(clamping: server.port),
|
||||
username: "",
|
||||
password: "",
|
||||
isTurn: false
|
||||
))
|
||||
case let .turn(username, password):
|
||||
rtcServers.append(VoipRtcServerWebrtc(
|
||||
host: server.host,
|
||||
port: Int32(clamping: server.port),
|
||||
username: username,
|
||||
password: password,
|
||||
isTurn: true
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
let screenSize = UIScreen.main.bounds.size
|
||||
let portraitSize = CGSize(width: min(screenSize.width, screenSize.height), height: max(screenSize.width, screenSize.height))
|
||||
let preferredAspectRatio = portraitSize.width / portraitSize.height
|
||||
|
||||
let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, rtcServers: rtcServers, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescriptionWebrtc(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescriptionWebrtc), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath, sendSignalingData: { [weak callSessionManager] data in
|
||||
|
||||
let unfilteredConnections = [connections.primary] + connections.alternatives
|
||||
var processedConnections: [CallSessionConnection] = []
|
||||
var filteredConnections: [OngoingCallConnectionDescriptionWebrtc] = []
|
||||
for connection in unfilteredConnections {
|
||||
if processedConnections.contains(connection) {
|
||||
continue
|
||||
}
|
||||
processedConnections.append(connection)
|
||||
if let mapped = callConnectionDescriptionWebrtc(connection) {
|
||||
if mapped.ip.isEmpty {
|
||||
continue
|
||||
}
|
||||
filteredConnections.append(mapped)
|
||||
}
|
||||
}
|
||||
let primaryConnection = filteredConnections.first!
|
||||
let restConnections = Array(filteredConnections[1...])
|
||||
|
||||
let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: primaryConnection, alternativeConnections: restConnections, maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath, sendSignalingData: { [weak callSessionManager] data in
|
||||
callSessionManager?.sendSignalingData(internalId: internalId, data: data)
|
||||
}, videoCapturer: video?.impl, preferredAspectRatio: Float(preferredAspectRatio))
|
||||
}, videoCapturer: video?.impl, preferredAspectRatio: Float(preferredAspectRatio), enableHighBitrateVideoCalls: enableHighBitrateVideoCalls)
|
||||
|
||||
strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context))
|
||||
context.stateChanged = { [weak callSessionManager] state, videoState, remoteVideoState in
|
||||
@ -628,7 +639,7 @@ public final class OngoingCallContext {
|
||||
break
|
||||
}
|
||||
}
|
||||
let context = OngoingCallThreadLocalContext(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForType(initialNetworkType), dataSaving: ongoingDataSavingForType(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescription(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescription), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath)
|
||||
let context = OngoingCallThreadLocalContext(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForType(initialNetworkType), dataSaving: ongoingDataSavingForType(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescription(connections.primary)!, alternativeConnections: connections.alternatives.compactMap(callConnectionDescription), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath)
|
||||
|
||||
strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context))
|
||||
context.stateChanged = { state in
|
||||
@ -775,6 +786,11 @@ public final class OngoingCallContext {
|
||||
view?.setOnOrientationUpdated { value in
|
||||
f?(OngoingCallVideoOrientation(value))
|
||||
}
|
||||
},
|
||||
setOnIsMirroredUpdated: { [weak view] f in
|
||||
view?.setOnIsMirroredUpdated { value in
|
||||
f?(value)
|
||||
}
|
||||
}
|
||||
))
|
||||
} else {
|
||||
|
@ -13,12 +13,14 @@
|
||||
@interface OngoingCallConnectionDescriptionWebrtc : NSObject
|
||||
|
||||
@property (nonatomic, readonly) int64_t connectionId;
|
||||
@property (nonatomic, readonly) bool hasStun;
|
||||
@property (nonatomic, readonly) bool hasTurn;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull ip;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull ipv6;
|
||||
@property (nonatomic, readonly) int32_t port;
|
||||
@property (nonatomic, strong, readonly) NSData * _Nonnull peerTag;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull username;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull password;
|
||||
|
||||
- (instancetype _Nonnull)initWithConnectionId:(int64_t)connectionId ip:(NSString * _Nonnull)ip ipv6:(NSString * _Nonnull)ipv6 port:(int32_t)port peerTag:(NSData * _Nonnull)peerTag;
|
||||
- (instancetype _Nonnull)initWithConnectionId:(int64_t)connectionId hasStun:(bool)hasStun hasTurn:(bool)hasTurn ip:(NSString * _Nonnull)ip port:(int32_t)port username:(NSString * _Nonnull)username password:(NSString * _Nonnull)password;
|
||||
|
||||
@end
|
||||
|
||||
@ -81,24 +83,13 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
||||
|
||||
@end
|
||||
|
||||
@interface VoipRtcServerWebrtc : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString * _Nonnull host;
|
||||
@property (nonatomic, readonly) int32_t port;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nullable username;
|
||||
@property (nonatomic, strong, readonly) NSString * _Nullable password;
|
||||
@property (nonatomic, readonly) bool isTurn;
|
||||
|
||||
- (instancetype _Nonnull)initWithHost:(NSString * _Nonnull)host port:(int32_t)port username:(NSString * _Nullable)username password:(NSString * _Nullable)password isTurn:(bool)isTurn;
|
||||
|
||||
@end
|
||||
|
||||
@protocol OngoingCallThreadLocalContextWebrtcVideoView <NSObject>
|
||||
|
||||
@property (nonatomic, readonly) OngoingCallVideoOrientationWebrtc orientation;
|
||||
|
||||
- (void)setOnFirstFrameReceived:(void (^ _Nullable)())onFirstFrameReceived;
|
||||
- (void)setOnOrientationUpdated:(void (^ _Nullable)(OngoingCallVideoOrientationWebrtc))onOrientationUpdated;
|
||||
- (void)setOnIsMirroredUpdated:(void (^ _Nullable)(bool))onIsMirroredUpdated;
|
||||
|
||||
@end
|
||||
|
||||
@ -123,7 +114,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
||||
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtc, OngoingCallVideoStateWebrtc, OngoingCallRemoteVideoStateWebrtc);
|
||||
@property (nonatomic, copy) void (^ _Nullable signalBarsChanged)(int32_t);
|
||||
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy rtcServers:(NSArray<VoipRtcServerWebrtc *> * _Nonnull)rtcServers networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^ _Nonnull)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredAspectRatio:(float)preferredAspectRatio;
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^ _Nonnull)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredAspectRatio:(float)preferredAspectRatio enableHighBitrateVideoCalls:(bool)enableHighBitrateVideoCalls;
|
||||
|
||||
- (void)beginTermination;
|
||||
- (void)stop:(void (^_Nullable)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile))completion;
|
||||
|
@ -22,14 +22,16 @@
|
||||
|
||||
@implementation OngoingCallConnectionDescriptionWebrtc
|
||||
|
||||
- (instancetype _Nonnull)initWithConnectionId:(int64_t)connectionId ip:(NSString * _Nonnull)ip ipv6:(NSString * _Nonnull)ipv6 port:(int32_t)port peerTag:(NSData * _Nonnull)peerTag {
|
||||
- (instancetype _Nonnull)initWithConnectionId:(int64_t)connectionId hasStun:(bool)hasStun hasTurn:(bool)hasTurn ip:(NSString * _Nonnull)ip port:(int32_t)port username:(NSString * _Nonnull)username password:(NSString * _Nonnull)password {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_connectionId = connectionId;
|
||||
_hasStun = hasStun;
|
||||
_hasTurn = hasTurn;
|
||||
_ip = ip;
|
||||
_ipv6 = ipv6;
|
||||
_port = port;
|
||||
_peerTag = peerTag;
|
||||
_username = username;
|
||||
_password = password;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -74,6 +76,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setOnIsMirroredUpdated:(void (^ _Nullable)(bool))onIsMirroredUpdated {
|
||||
if (onIsMirroredUpdated) {
|
||||
[self internalSetOnIsMirroredUpdated:^(bool value) {
|
||||
onIsMirroredUpdated(value);
|
||||
}];
|
||||
} else {
|
||||
[self internalSetOnIsMirroredUpdated:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface GLVideoView (VideoViewImpl) <OngoingCallThreadLocalContextWebrtcVideoView, OngoingCallThreadLocalContextWebrtcVideoViewImpl>
|
||||
@ -102,6 +114,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setOnIsMirroredUpdated:(void (^ _Nullable)(bool))onIsMirroredUpdated {
|
||||
if (onIsMirroredUpdated) {
|
||||
[self internalSetOnIsMirroredUpdated:^(bool value) {
|
||||
onIsMirroredUpdated(value);
|
||||
}];
|
||||
} else {
|
||||
[self internalSetOnIsMirroredUpdated:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation OngoingCallThreadLocalContextVideoCapturer
|
||||
@ -219,22 +241,6 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation VoipRtcServerWebrtc
|
||||
|
||||
- (instancetype _Nonnull)initWithHost:(NSString * _Nonnull)host port:(int32_t)port username:(NSString * _Nullable)username password:(NSString * _Nullable)password isTurn:(bool)isTurn {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_host = host;
|
||||
_port = port;
|
||||
_username = username;
|
||||
_password = password;
|
||||
_isTurn = isTurn;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static tgcalls::NetworkType callControllerNetworkTypeForType(OngoingCallNetworkTypeWebrtc type) {
|
||||
switch (type) {
|
||||
case OngoingCallNetworkTypeWifi:
|
||||
@ -294,7 +300,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy rtcServers:(NSArray<VoipRtcServerWebrtc *> * _Nonnull)rtcServers networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredAspectRatio:(float)preferredAspectRatio {
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredAspectRatio:(float)preferredAspectRatio enableHighBitrateVideoCalls:(bool)enableHighBitrateVideoCalls {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_version = version;
|
||||
@ -334,42 +340,31 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
proxyValue = std::unique_ptr<tgcalls::Proxy>(proxyObject);
|
||||
}
|
||||
|
||||
std::vector<tgcalls::RtcServer> parsedRtcServers;
|
||||
for (VoipRtcServerWebrtc *server in rtcServers) {
|
||||
parsedRtcServers.push_back((tgcalls::RtcServer){
|
||||
.host = server.host.UTF8String,
|
||||
.port = (uint16_t)server.port,
|
||||
.login = server.username.UTF8String,
|
||||
.password = server.password.UTF8String,
|
||||
.isTurn = server.isTurn
|
||||
});
|
||||
}
|
||||
NSArray<OngoingCallConnectionDescriptionWebrtc *> *connections = [@[primaryConnection] arrayByAddingObjectsFromArray:alternativeConnections];
|
||||
|
||||
/*TgVoipCrypto crypto;
|
||||
crypto.sha1 = &TGCallSha1;
|
||||
crypto.sha256 = &TGCallSha256;
|
||||
crypto.rand_bytes = &TGCallRandomBytes;
|
||||
crypto.aes_ige_encrypt = &TGCallAesIgeEncrypt;
|
||||
crypto.aes_ige_decrypt = &TGCallAesIgeDecrypt;
|
||||
crypto.aes_ctr_encrypt = &TGCallAesCtrEncrypt;*/
|
||||
std::vector<tgcalls::RtcServer> parsedRtcServers;
|
||||
for (OngoingCallConnectionDescriptionWebrtc *connection in connections) {
|
||||
if (connection.hasStun) {
|
||||
parsedRtcServers.push_back((tgcalls::RtcServer){
|
||||
.host = connection.ip.UTF8String,
|
||||
.port = (uint16_t)connection.port,
|
||||
.login = "",
|
||||
.password = "",
|
||||
.isTurn = false
|
||||
});
|
||||
}
|
||||
if (connection.hasTurn) {
|
||||
parsedRtcServers.push_back((tgcalls::RtcServer){
|
||||
.host = connection.ip.UTF8String,
|
||||
.port = (uint16_t)connection.port,
|
||||
.login = connection.username.UTF8String,
|
||||
.password = connection.password.UTF8String,
|
||||
.isTurn = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<tgcalls::Endpoint> endpoints;
|
||||
NSArray<OngoingCallConnectionDescriptionWebrtc *> *connections = [@[primaryConnection] arrayByAddingObjectsFromArray:alternativeConnections];
|
||||
for (OngoingCallConnectionDescriptionWebrtc *connection in connections) {
|
||||
unsigned char peerTag[16];
|
||||
[connection.peerTag getBytes:peerTag length:16];
|
||||
|
||||
tgcalls::Endpoint endpoint;
|
||||
endpoint.endpointId = connection.connectionId;
|
||||
endpoint.host = {
|
||||
.ipv4 = std::string(connection.ip.UTF8String),
|
||||
.ipv6 = std::string(connection.ipv6.UTF8String)
|
||||
};
|
||||
endpoint.port = (uint16_t)connection.port;
|
||||
endpoint.type = tgcalls::EndpointType::UdpRelay;
|
||||
memcpy(endpoint.peerTag, peerTag, 16);
|
||||
endpoints.push_back(endpoint);
|
||||
}
|
||||
|
||||
tgcalls::Config config = {
|
||||
.initializationTimeout = _callConnectTimeout,
|
||||
@ -382,7 +377,8 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
.enableCallUpgrade = false,
|
||||
.logPath = logPath.length == 0 ? "" : std::string(logPath.UTF8String),
|
||||
.maxApiLayer = [OngoingCallThreadLocalContextWebrtc maxLayer],
|
||||
.preferredAspectRatio = preferredAspectRatio
|
||||
.preferredAspectRatio = preferredAspectRatio,
|
||||
.enableHighBitrateVideo = enableHighBitrateVideoCalls
|
||||
};
|
||||
|
||||
auto encryptionKeyValue = std::make_shared<std::array<uint8_t, 256>>();
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit ebe663f05867d81a84f02d10d6bb4dae737162a2
|
||||
Subproject commit 0806eae4d11e1fdc2f82402f2f49a3a2ff053077
|
Loading…
x
Reference in New Issue
Block a user