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