Video call improvements

This commit is contained in:
Ali 2020-08-04 23:08:27 +04:00
parent abb6e4a6bf
commit 8134159629
43 changed files with 3722 additions and 3585 deletions

View File

@ -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";

View File

@ -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?

View File

@ -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
}

View File

@ -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
}
}
}

View File

@ -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))

View File

@ -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))
}
})

View File

@ -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)
}
})

View File

@ -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)
}
})

View File

@ -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)"))

View File

@ -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)
}
}

View File

@ -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:

View File

@ -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 {

View File

@ -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 {

View File

@ -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>) {

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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))

View File

@ -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):

View File

@ -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))
})
}
}*/
}
}
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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)

View File

@ -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)
}))
}

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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))
}
})

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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")
}

View File

@ -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 {

View File

@ -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;

View File

@ -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