mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
[WIP] Conference calls
This commit is contained in:
parent
e18795980e
commit
2b9f5ed541
@ -283,6 +283,9 @@
|
||||
"LOCAL_CHANNEL_MESSAGE_FWDS" = "%1$@ posted %2$d forwarded messages";
|
||||
"LOCAL_CHAT_MESSAGE_FWDS" = "%1$@ forwarded %2$d messages";
|
||||
|
||||
"PUSH_STORY_HIDDEN_AUTHOR" = "New story was posted";
|
||||
"PUSH_MESSAGE_STARGIFT" = "%1$@|sent you a Gift worth of %2$@ stars";
|
||||
|
||||
// Common
|
||||
"Common.OK" = "OK";
|
||||
"Common.Cancel" = "Cancel";
|
||||
|
@ -535,7 +535,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1098720356] = { return Api.MediaArea.parse_mediaAreaVenue($0) }
|
||||
dict[1235637404] = { return Api.MediaArea.parse_mediaAreaWeather($0) }
|
||||
dict[-808853502] = { return Api.MediaAreaCoordinates.parse_mediaAreaCoordinates($0) }
|
||||
dict[-1808510398] = { return Api.Message.parse_message($0) }
|
||||
dict[-1761756183] = { return Api.Message.parse_message($0) }
|
||||
dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) }
|
||||
dict[-741178048] = { return Api.Message.parse_messageService($0) }
|
||||
dict[-872240531] = { return Api.MessageAction.parse_messageActionBoostApply($0) }
|
||||
@ -723,11 +723,12 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1395233698] = { return Api.PeerSettings.parse_peerSettings($0) }
|
||||
dict[-1707742823] = { return Api.PeerStories.parse_peerStories($0) }
|
||||
dict[1000707084] = { return Api.PhoneCall.parse_phoneCall($0) }
|
||||
dict[912311057] = { return Api.PhoneCall.parse_phoneCallAccepted($0) }
|
||||
dict[1355435489] = { return Api.PhoneCall.parse_phoneCallDiscarded($0) }
|
||||
dict[587035009] = { return Api.PhoneCall.parse_phoneCallAccepted($0) }
|
||||
dict[-103656189] = { return Api.PhoneCall.parse_phoneCallDiscarded($0) }
|
||||
dict[1399245077] = { return Api.PhoneCall.parse_phoneCallEmpty($0) }
|
||||
dict[347139340] = { return Api.PhoneCall.parse_phoneCallRequested($0) }
|
||||
dict[-987599081] = { return Api.PhoneCall.parse_phoneCallWaiting($0) }
|
||||
dict[1161174115] = { return Api.PhoneCall.parse_phoneCallRequested($0) }
|
||||
dict[-288085928] = { return Api.PhoneCall.parse_phoneCallWaiting($0) }
|
||||
dict[-1344096199] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonAllowGroupCall($0) }
|
||||
dict[-84416311] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonBusy($0) }
|
||||
dict[-527056480] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonDisconnect($0) }
|
||||
dict[1471006352] = { return Api.PhoneCallDiscardReason.parse_phoneCallDiscardReasonHangup($0) }
|
||||
|
@ -60,15 +60,15 @@ public extension Api {
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum Message: TypeConstructorDescription {
|
||||
case message(flags: Int32, flags2: Int32, id: Int32, fromId: Api.Peer?, fromBoostsApplied: Int32?, peerId: Api.Peer, savedPeerId: Api.Peer?, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, viaBusinessBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?, quickReplyShortcutId: Int32?, effect: Int64?, factcheck: Api.FactCheck?)
|
||||
case message(flags: Int32, flags2: Int32, id: Int32, fromId: Api.Peer?, fromBoostsApplied: Int32?, peerId: Api.Peer, savedPeerId: Api.Peer?, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, viaBusinessBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?, quickReplyShortcutId: Int32?, effect: Int64?, factcheck: Api.FactCheck?, reportDeliveryUntilDate: Int32?)
|
||||
case messageEmpty(flags: Int32, id: Int32, peerId: Api.Peer?)
|
||||
case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, reactions: Api.MessageReactions?, ttlPeriod: Int32?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .message(let flags, let flags2, let id, let fromId, let fromBoostsApplied, let peerId, let savedPeerId, let fwdFrom, let viaBotId, let viaBusinessBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod, let quickReplyShortcutId, let effect, let factcheck):
|
||||
case .message(let flags, let flags2, let id, let fromId, let fromBoostsApplied, let peerId, let savedPeerId, let fwdFrom, let viaBotId, let viaBusinessBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod, let quickReplyShortcutId, let effect, let factcheck, let reportDeliveryUntilDate):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1808510398)
|
||||
buffer.appendInt32(-1761756183)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(flags2, buffer: buffer, boxed: false)
|
||||
@ -106,6 +106,7 @@ public extension Api {
|
||||
if Int(flags) & Int(1 << 30) != 0 {serializeInt32(quickReplyShortcutId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags2) & Int(1 << 2) != 0 {serializeInt64(effect!, buffer: buffer, boxed: false)}
|
||||
if Int(flags2) & Int(1 << 3) != 0 {factcheck!.serialize(buffer, true)}
|
||||
if Int(flags2) & Int(1 << 5) != 0 {serializeInt32(reportDeliveryUntilDate!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .messageEmpty(let flags, let id, let peerId):
|
||||
if boxed {
|
||||
@ -134,8 +135,8 @@ public extension Api {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .message(let flags, let flags2, let id, let fromId, let fromBoostsApplied, let peerId, let savedPeerId, let fwdFrom, let viaBotId, let viaBusinessBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod, let quickReplyShortcutId, let effect, let factcheck):
|
||||
return ("message", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("fromId", fromId as Any), ("fromBoostsApplied", fromBoostsApplied as Any), ("peerId", peerId as Any), ("savedPeerId", savedPeerId as Any), ("fwdFrom", fwdFrom as Any), ("viaBotId", viaBotId as Any), ("viaBusinessBotId", viaBusinessBotId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("message", message as Any), ("media", media as Any), ("replyMarkup", replyMarkup as Any), ("entities", entities as Any), ("views", views as Any), ("forwards", forwards as Any), ("replies", replies as Any), ("editDate", editDate as Any), ("postAuthor", postAuthor as Any), ("groupedId", groupedId as Any), ("reactions", reactions as Any), ("restrictionReason", restrictionReason as Any), ("ttlPeriod", ttlPeriod as Any), ("quickReplyShortcutId", quickReplyShortcutId as Any), ("effect", effect as Any), ("factcheck", factcheck as Any)])
|
||||
case .message(let flags, let flags2, let id, let fromId, let fromBoostsApplied, let peerId, let savedPeerId, let fwdFrom, let viaBotId, let viaBusinessBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod, let quickReplyShortcutId, let effect, let factcheck, let reportDeliveryUntilDate):
|
||||
return ("message", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("fromId", fromId as Any), ("fromBoostsApplied", fromBoostsApplied as Any), ("peerId", peerId as Any), ("savedPeerId", savedPeerId as Any), ("fwdFrom", fwdFrom as Any), ("viaBotId", viaBotId as Any), ("viaBusinessBotId", viaBusinessBotId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("message", message as Any), ("media", media as Any), ("replyMarkup", replyMarkup as Any), ("entities", entities as Any), ("views", views as Any), ("forwards", forwards as Any), ("replies", replies as Any), ("editDate", editDate as Any), ("postAuthor", postAuthor as Any), ("groupedId", groupedId as Any), ("reactions", reactions as Any), ("restrictionReason", restrictionReason as Any), ("ttlPeriod", ttlPeriod as Any), ("quickReplyShortcutId", quickReplyShortcutId as Any), ("effect", effect as Any), ("factcheck", factcheck as Any), ("reportDeliveryUntilDate", reportDeliveryUntilDate as Any)])
|
||||
case .messageEmpty(let flags, let id, let peerId):
|
||||
return ("messageEmpty", [("flags", flags as Any), ("id", id as Any), ("peerId", peerId as Any)])
|
||||
case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let reactions, let ttlPeriod):
|
||||
@ -224,6 +225,8 @@ public extension Api {
|
||||
if Int(_2!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
|
||||
_28 = Api.parse(reader, signature: signature) as? Api.FactCheck
|
||||
} }
|
||||
var _29: Int32?
|
||||
if Int(_2!) & Int(1 << 5) != 0 {_29 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -252,8 +255,9 @@ public extension Api {
|
||||
let _c26 = (Int(_1!) & Int(1 << 30) == 0) || _26 != nil
|
||||
let _c27 = (Int(_2!) & Int(1 << 2) == 0) || _27 != nil
|
||||
let _c28 = (Int(_2!) & Int(1 << 3) == 0) || _28 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 {
|
||||
return Api.Message.message(flags: _1!, flags2: _2!, id: _3!, fromId: _4, fromBoostsApplied: _5, peerId: _6!, savedPeerId: _7, fwdFrom: _8, viaBotId: _9, viaBusinessBotId: _10, replyTo: _11, date: _12!, message: _13!, media: _14, replyMarkup: _15, entities: _16, views: _17, forwards: _18, replies: _19, editDate: _20, postAuthor: _21, groupedId: _22, reactions: _23, restrictionReason: _24, ttlPeriod: _25, quickReplyShortcutId: _26, effect: _27, factcheck: _28)
|
||||
let _c29 = (Int(_2!) & Int(1 << 5) == 0) || _29 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 {
|
||||
return Api.Message.message(flags: _1!, flags2: _2!, id: _3!, fromId: _4, fromBoostsApplied: _5, peerId: _6!, savedPeerId: _7, fwdFrom: _8, viaBotId: _9, viaBusinessBotId: _10, replyTo: _11, date: _12!, message: _13!, media: _14, replyMarkup: _15, entities: _16, views: _17, forwards: _18, replies: _19, editDate: _20, postAuthor: _21, groupedId: _22, reactions: _23, restrictionReason: _24, ttlPeriod: _25, quickReplyShortcutId: _26, effect: _27, factcheck: _28, reportDeliveryUntilDate: _29)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -1011,11 +1011,11 @@ public extension Api {
|
||||
public extension Api {
|
||||
enum PhoneCall: TypeConstructorDescription {
|
||||
case phoneCall(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gAOrB: Buffer, keyFingerprint: Int64, protocol: Api.PhoneCallProtocol, connections: [Api.PhoneConnection], startDate: Int32, customParameters: Api.DataJSON?, conferenceCall: Api.InputGroupCall?)
|
||||
case phoneCallAccepted(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gB: Buffer, protocol: Api.PhoneCallProtocol)
|
||||
case phoneCallDiscarded(flags: Int32, id: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?)
|
||||
case phoneCallAccepted(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gB: Buffer, protocol: Api.PhoneCallProtocol, conferenceCall: Api.InputGroupCall?)
|
||||
case phoneCallDiscarded(flags: Int32, id: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?, conferenceCall: Api.InputGroupCall?)
|
||||
case phoneCallEmpty(id: Int64)
|
||||
case phoneCallRequested(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gAHash: Buffer, protocol: Api.PhoneCallProtocol)
|
||||
case phoneCallWaiting(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, protocol: Api.PhoneCallProtocol, receiveDate: Int32?)
|
||||
case phoneCallRequested(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gAHash: Buffer, protocol: Api.PhoneCallProtocol, conferenceCall: Api.InputGroupCall?)
|
||||
case phoneCallWaiting(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, protocol: Api.PhoneCallProtocol, receiveDate: Int32?, conferenceCall: Api.InputGroupCall?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -1041,9 +1041,9 @@ public extension Api {
|
||||
if Int(flags) & Int(1 << 7) != 0 {customParameters!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 8) != 0 {conferenceCall!.serialize(buffer, true)}
|
||||
break
|
||||
case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`):
|
||||
case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`, let conferenceCall):
|
||||
if boxed {
|
||||
buffer.appendInt32(912311057)
|
||||
buffer.appendInt32(587035009)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
@ -1053,15 +1053,17 @@ public extension Api {
|
||||
serializeInt64(participantId, buffer: buffer, boxed: false)
|
||||
serializeBytes(gB, buffer: buffer, boxed: false)
|
||||
`protocol`.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 8) != 0 {conferenceCall!.serialize(buffer, true)}
|
||||
break
|
||||
case .phoneCallDiscarded(let flags, let id, let reason, let duration):
|
||||
case .phoneCallDiscarded(let flags, let id, let reason, let duration, let conferenceCall):
|
||||
if boxed {
|
||||
buffer.appendInt32(1355435489)
|
||||
buffer.appendInt32(-103656189)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {reason!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 8) != 0 {conferenceCall!.serialize(buffer, true)}
|
||||
break
|
||||
case .phoneCallEmpty(let id):
|
||||
if boxed {
|
||||
@ -1069,9 +1071,9 @@ public extension Api {
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`):
|
||||
case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`, let conferenceCall):
|
||||
if boxed {
|
||||
buffer.appendInt32(347139340)
|
||||
buffer.appendInt32(1161174115)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
@ -1081,10 +1083,11 @@ public extension Api {
|
||||
serializeInt64(participantId, buffer: buffer, boxed: false)
|
||||
serializeBytes(gAHash, buffer: buffer, boxed: false)
|
||||
`protocol`.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 8) != 0 {conferenceCall!.serialize(buffer, true)}
|
||||
break
|
||||
case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate):
|
||||
case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate, let conferenceCall):
|
||||
if boxed {
|
||||
buffer.appendInt32(-987599081)
|
||||
buffer.appendInt32(-288085928)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
@ -1094,6 +1097,7 @@ public extension Api {
|
||||
serializeInt64(participantId, buffer: buffer, boxed: false)
|
||||
`protocol`.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(receiveDate!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 8) != 0 {conferenceCall!.serialize(buffer, true)}
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -1102,16 +1106,16 @@ public extension Api {
|
||||
switch self {
|
||||
case .phoneCall(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAOrB, let keyFingerprint, let `protocol`, let connections, let startDate, let customParameters, let conferenceCall):
|
||||
return ("phoneCall", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("date", date as Any), ("adminId", adminId as Any), ("participantId", participantId as Any), ("gAOrB", gAOrB as Any), ("keyFingerprint", keyFingerprint as Any), ("`protocol`", `protocol` as Any), ("connections", connections as Any), ("startDate", startDate as Any), ("customParameters", customParameters as Any), ("conferenceCall", conferenceCall as Any)])
|
||||
case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`):
|
||||
return ("phoneCallAccepted", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("date", date as Any), ("adminId", adminId as Any), ("participantId", participantId as Any), ("gB", gB as Any), ("`protocol`", `protocol` as Any)])
|
||||
case .phoneCallDiscarded(let flags, let id, let reason, let duration):
|
||||
return ("phoneCallDiscarded", [("flags", flags as Any), ("id", id as Any), ("reason", reason as Any), ("duration", duration as Any)])
|
||||
case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`, let conferenceCall):
|
||||
return ("phoneCallAccepted", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("date", date as Any), ("adminId", adminId as Any), ("participantId", participantId as Any), ("gB", gB as Any), ("`protocol`", `protocol` as Any), ("conferenceCall", conferenceCall as Any)])
|
||||
case .phoneCallDiscarded(let flags, let id, let reason, let duration, let conferenceCall):
|
||||
return ("phoneCallDiscarded", [("flags", flags as Any), ("id", id as Any), ("reason", reason as Any), ("duration", duration as Any), ("conferenceCall", conferenceCall as Any)])
|
||||
case .phoneCallEmpty(let id):
|
||||
return ("phoneCallEmpty", [("id", id as Any)])
|
||||
case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`):
|
||||
return ("phoneCallRequested", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("date", date as Any), ("adminId", adminId as Any), ("participantId", participantId as Any), ("gAHash", gAHash as Any), ("`protocol`", `protocol` as Any)])
|
||||
case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate):
|
||||
return ("phoneCallWaiting", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("date", date as Any), ("adminId", adminId as Any), ("participantId", participantId as Any), ("`protocol`", `protocol` as Any), ("receiveDate", receiveDate as Any)])
|
||||
case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`, let conferenceCall):
|
||||
return ("phoneCallRequested", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("date", date as Any), ("adminId", adminId as Any), ("participantId", participantId as Any), ("gAHash", gAHash as Any), ("`protocol`", `protocol` as Any), ("conferenceCall", conferenceCall as Any)])
|
||||
case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate, let conferenceCall):
|
||||
return ("phoneCallWaiting", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("date", date as Any), ("adminId", adminId as Any), ("participantId", participantId as Any), ("`protocol`", `protocol` as Any), ("receiveDate", receiveDate as Any), ("conferenceCall", conferenceCall as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -1189,6 +1193,10 @@ public extension Api {
|
||||
if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol
|
||||
}
|
||||
var _9: Api.InputGroupCall?
|
||||
if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
|
||||
_9 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -1197,8 +1205,9 @@ public extension Api {
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.PhoneCall.phoneCallAccepted(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gB: _7!, protocol: _8!)
|
||||
let _c9 = (Int(_1!) & Int(1 << 8) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.PhoneCall.phoneCallAccepted(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gB: _7!, protocol: _8!, conferenceCall: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -1215,12 +1224,17 @@ public extension Api {
|
||||
} }
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
|
||||
var _5: Api.InputGroupCall?
|
||||
if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.PhoneCall.phoneCallDiscarded(flags: _1!, id: _2!, reason: _3, duration: _4)
|
||||
let _c5 = (Int(_1!) & Int(1 << 8) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.PhoneCall.phoneCallDiscarded(flags: _1!, id: _2!, reason: _3, duration: _4, conferenceCall: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -1256,6 +1270,10 @@ public extension Api {
|
||||
if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol
|
||||
}
|
||||
var _9: Api.InputGroupCall?
|
||||
if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
|
||||
_9 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -1264,8 +1282,9 @@ public extension Api {
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.PhoneCall.phoneCallRequested(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gAHash: _7!, protocol: _8!)
|
||||
let _c9 = (Int(_1!) & Int(1 << 8) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.PhoneCall.phoneCallRequested(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gAHash: _7!, protocol: _8!, conferenceCall: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -1290,6 +1309,10 @@ public extension Api {
|
||||
}
|
||||
var _8: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_8 = reader.readInt32() }
|
||||
var _9: Api.InputGroupCall?
|
||||
if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
|
||||
_9 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -1298,8 +1321,9 @@ public extension Api {
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 0) == 0) || _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.PhoneCall.phoneCallWaiting(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, protocol: _7!, receiveDate: _8)
|
||||
let _c9 = (Int(_1!) & Int(1 << 8) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.PhoneCall.phoneCallWaiting(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, protocol: _7!, receiveDate: _8, conferenceCall: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -1310,6 +1334,7 @@ public extension Api {
|
||||
}
|
||||
public extension Api {
|
||||
enum PhoneCallDiscardReason: TypeConstructorDescription {
|
||||
case phoneCallDiscardReasonAllowGroupCall(encryptedKey: Buffer)
|
||||
case phoneCallDiscardReasonBusy
|
||||
case phoneCallDiscardReasonDisconnect
|
||||
case phoneCallDiscardReasonHangup
|
||||
@ -1317,6 +1342,12 @@ public extension Api {
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .phoneCallDiscardReasonAllowGroupCall(let encryptedKey):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1344096199)
|
||||
}
|
||||
serializeBytes(encryptedKey, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .phoneCallDiscardReasonBusy:
|
||||
if boxed {
|
||||
buffer.appendInt32(-84416311)
|
||||
@ -1346,6 +1377,8 @@ public extension Api {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .phoneCallDiscardReasonAllowGroupCall(let encryptedKey):
|
||||
return ("phoneCallDiscardReasonAllowGroupCall", [("encryptedKey", encryptedKey as Any)])
|
||||
case .phoneCallDiscardReasonBusy:
|
||||
return ("phoneCallDiscardReasonBusy", [])
|
||||
case .phoneCallDiscardReasonDisconnect:
|
||||
@ -1357,6 +1390,17 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_phoneCallDiscardReasonAllowGroupCall(_ reader: BufferReader) -> PhoneCallDiscardReason? {
|
||||
var _1: Buffer?
|
||||
_1 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.PhoneCallDiscardReason.phoneCallDiscardReasonAllowGroupCall(encryptedKey: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_phoneCallDiscardReasonBusy(_ reader: BufferReader) -> PhoneCallDiscardReason? {
|
||||
return Api.PhoneCallDiscardReason.phoneCallDiscardReasonBusy
|
||||
}
|
||||
|
@ -7483,6 +7483,27 @@ public extension Api.functions.messages {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func reportMessagesDelivery(flags: Int32, peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1517122453)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(id.count))
|
||||
for item in id {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
return (FunctionDescription(name: "messages.reportMessagesDelivery", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func reportReaction(peer: Api.InputPeer, id: Int32, reactionPeer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
@ -9587,11 +9608,12 @@ public extension Api.functions.phone {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.phone {
|
||||
static func createConferenceCall(peer: Api.InputPhoneCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.phone.PhoneCall>) {
|
||||
static func createConferenceCall(peer: Api.InputPhoneCall, keyFingerprint: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.phone.PhoneCall>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1828162221)
|
||||
buffer.appendInt32(-540472917)
|
||||
peer.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "phone.createConferenceCall", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in
|
||||
serializeInt64(keyFingerprint, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "phone.createConferenceCall", parameters: [("peer", String(describing: peer)), ("keyFingerprint", String(describing: keyFingerprint))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.phone.PhoneCall?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -9834,15 +9856,16 @@ public extension Api.functions.phone {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.phone {
|
||||
static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, joinAs: Api.InputPeer, inviteHash: String?, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, joinAs: Api.InputPeer, inviteHash: String?, keyFingerprint: Int64?, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1322057861)
|
||||
buffer.appendInt32(-702669325)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
joinAs.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(inviteHash!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt64(keyFingerprint!, buffer: buffer, boxed: false)}
|
||||
params.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("joinAs", String(describing: joinAs)), ("inviteHash", String(describing: inviteHash)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("joinAs", String(describing: joinAs)), ("inviteHash", String(describing: inviteHash)), ("keyFingerprint", String(describing: keyFingerprint)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -9915,15 +9938,16 @@ public extension Api.functions.phone {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.phone {
|
||||
static func requestCall(flags: Int32, userId: Api.InputUser, randomId: Int32, gAHash: Buffer, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.phone.PhoneCall>) {
|
||||
static func requestCall(flags: Int32, userId: Api.InputUser, conferenceCall: Api.InputGroupCall?, randomId: Int32, gAHash: Buffer, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.phone.PhoneCall>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1124046573)
|
||||
buffer.appendInt32(-1497079796)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
userId.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 1) != 0 {conferenceCall!.serialize(buffer, true)}
|
||||
serializeInt32(randomId, buffer: buffer, boxed: false)
|
||||
serializeBytes(gAHash, buffer: buffer, boxed: false)
|
||||
`protocol`.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "phone.requestCall", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("randomId", String(describing: randomId)), ("gAHash", String(describing: gAHash)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in
|
||||
return (FunctionDescription(name: "phone.requestCall", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("conferenceCall", String(describing: conferenceCall)), ("randomId", String(describing: randomId)), ("gAHash", String(describing: gAHash)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.phone.PhoneCall?
|
||||
if let signature = reader.readInt32() {
|
||||
|
@ -522,6 +522,13 @@ public final class CallController: ViewController {
|
||||
let _ = self?.dismiss()
|
||||
}
|
||||
|
||||
displayNode.conferenceAddParticipant = { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.conferenceAddParticipant()
|
||||
}
|
||||
|
||||
self.controllerNode.presentCallRating = { [weak self] callId, isVideo in
|
||||
if let strongSelf = self, !strongSelf.presentedCallRating {
|
||||
strongSelf.presentedCallRating = true
|
||||
@ -667,6 +674,35 @@ public final class CallController: ViewController {
|
||||
})
|
||||
}
|
||||
|
||||
private func conferenceAddParticipant() {
|
||||
let controller = self.call.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(
|
||||
context: self.call.context,
|
||||
filter: [.onlyWriteable],
|
||||
hasChatListSelector: true,
|
||||
hasContactSelector: true,
|
||||
hasGlobalSearch: true,
|
||||
title: "Add Participant",
|
||||
pretendPresentedInModal: false
|
||||
))
|
||||
controller.peerSelected = { [weak self, weak controller] peer, _ in
|
||||
controller?.dismiss()
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard case let .call(call) = self.call else {
|
||||
return
|
||||
}
|
||||
guard let call = call as? PresentationCallImpl else {
|
||||
return
|
||||
}
|
||||
let _ = call.requestAddToConference(peerId: peer.id)
|
||||
}
|
||||
self.dismiss()
|
||||
|
||||
(self.call.context.sharedContext.mainWindow?.viewController as? NavigationController)?.pushViewController(controller)
|
||||
}
|
||||
|
||||
@objc private func backPressed() {
|
||||
self.dismiss()
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ final class CallControllerNodeV2: ViewControllerTracingNode, CallControllerNodeP
|
||||
var dismissedInteractively: (() -> Void)?
|
||||
var dismissAllTooltips: (() -> Void)?
|
||||
var restoreUIForPictureInPicture: ((@escaping (Bool) -> Void) -> Void)?
|
||||
var conferenceAddParticipant: (() -> Void)?
|
||||
|
||||
private var emojiKey: (data: Data, resolvedKey: [String])?
|
||||
private var validLayout: (layout: ContainerViewLayout, navigationBarHeight: CGFloat)?
|
||||
@ -129,6 +130,14 @@ final class CallControllerNodeV2: ViewControllerTracingNode, CallControllerNodeP
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if self.sharedContext.immediateExperimentalUISettings.conferenceCalls {
|
||||
self.conferenceAddParticipant?()
|
||||
return
|
||||
}
|
||||
#endif
|
||||
|
||||
self.call.toggleIsMuted()
|
||||
}
|
||||
self.callScreen.endCallAction = { [weak self] in
|
||||
@ -157,6 +166,12 @@ final class CallControllerNodeV2: ViewControllerTracingNode, CallControllerNodeP
|
||||
}
|
||||
self.restoreUIForPictureInPicture?(completion)
|
||||
}
|
||||
self.callScreen.conferenceAddParticipant = { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.conferenceAddParticipant?()
|
||||
}
|
||||
|
||||
self.callScreenState = PrivateCallScreen.State(
|
||||
strings: presentationData.strings,
|
||||
|
@ -550,9 +550,9 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
presentationState = PresentationCallState(state: .terminating(reason), videoState: mappedVideoState, remoteVideoState: .inactive, remoteAudioState: mappedRemoteAudioState, remoteBatteryLevel: mappedRemoteBatteryLevel)
|
||||
case let .terminated(id, reason, options):
|
||||
presentationState = PresentationCallState(state: .terminated(id, reason, self.callWasActive && (options.contains(.reportRating) || self.shouldPresentCallRating)), videoState: mappedVideoState, remoteVideoState: .inactive, remoteAudioState: mappedRemoteAudioState, remoteBatteryLevel: mappedRemoteBatteryLevel)
|
||||
case let .requesting(ringing):
|
||||
case let .requesting(ringing, _):
|
||||
presentationState = PresentationCallState(state: .requesting(ringing), videoState: mappedVideoState, remoteVideoState: mappedRemoteVideoState, remoteAudioState: mappedRemoteAudioState, remoteBatteryLevel: mappedRemoteBatteryLevel)
|
||||
case let .active(_, _, keyVisualHash, _, _, _, _, _, _):
|
||||
case let .active(_, _, keyVisualHash, _, _, _, _, _, _), let .switchedToConference(_, keyVisualHash, _):
|
||||
self.callWasActive = true
|
||||
if let callContextState = callContextState {
|
||||
switch callContextState.state {
|
||||
@ -585,216 +585,233 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
}
|
||||
}
|
||||
|
||||
var conferenceCallData: (key: Data, keyVisualHash: Data, conferenceCall: GroupCallReference)?
|
||||
var conferenceFromCallId: CallId?
|
||||
switch sessionState.state {
|
||||
case let .active(id, key, keyVisualHash, _, _, _, _, _, conferenceCall):
|
||||
if let conferenceCall {
|
||||
conferenceFromCallId = id
|
||||
conferenceCallData = (key, keyVisualHash, conferenceCall)
|
||||
}
|
||||
case let .switchedToConference(key, keyVisualHash, conferenceCall):
|
||||
conferenceCallData = (key, keyVisualHash, conferenceCall)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if let (key, keyVisualHash, conferenceCall) = conferenceCallData {
|
||||
if self.conferenceCallDisposable == nil {
|
||||
presentationState = PresentationCallState(state: .connecting(nil), videoState: mappedVideoState, remoteVideoState: mappedRemoteVideoState, remoteAudioState: mappedRemoteAudioState, remoteBatteryLevel: mappedRemoteBatteryLevel)
|
||||
|
||||
self.conferenceCallDisposable = (self.context.engine.calls.getCurrentGroupCall(callId: conferenceCall.id, accessHash: conferenceCall.accessHash)
|
||||
|> delay(sessionState.isOutgoing ? 0.0 : 2.0, queue: .mainQueue())
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let self, let result else {
|
||||
return
|
||||
}
|
||||
|
||||
let conferenceCall = PresentationGroupCallImpl(
|
||||
accountContext: self.context,
|
||||
audioSession: self.audioSession,
|
||||
callKitIntegration: self.callKitIntegration,
|
||||
getDeviceAccessData: self.getDeviceAccessData,
|
||||
initialCall: EngineGroupCallDescription(
|
||||
id: result.info.id,
|
||||
accessHash: result.info.accessHash,
|
||||
title: nil,
|
||||
scheduleTimestamp: nil,
|
||||
subscribedToScheduled: false,
|
||||
isStream: false
|
||||
),
|
||||
internalId: CallSessionInternalId(),
|
||||
peerId: nil,
|
||||
isChannel: false,
|
||||
invite: nil,
|
||||
joinAsPeerId: nil,
|
||||
isStream: false,
|
||||
encryptionKey: (key, 1),
|
||||
conferenceFromCallId: conferenceFromCallId,
|
||||
isConference: true,
|
||||
sharedAudioDevice: self.sharedAudioDevice
|
||||
)
|
||||
self.conferenceCall = conferenceCall
|
||||
|
||||
conferenceCall.setIsMuted(action: .muted(isPushToTalkActive: !self.isMutedValue))
|
||||
|
||||
let accountPeerId = conferenceCall.account.peerId
|
||||
let videoEndpoints: Signal<(local: String?, remote: PresentationGroupCallRequestedVideo?), NoError> = conferenceCall.members
|
||||
|> map { members -> (local: String?, remote: PresentationGroupCallRequestedVideo?) in
|
||||
guard let members else {
|
||||
return (nil, nil)
|
||||
}
|
||||
var local: String?
|
||||
var remote: PresentationGroupCallRequestedVideo?
|
||||
for participant in members.participants {
|
||||
if let video = participant.requestedPresentationVideoChannel(minQuality: .thumbnail, maxQuality: .full) ?? participant.requestedVideoChannel(minQuality: .thumbnail, maxQuality: .full) {
|
||||
if participant.peer.id == accountPeerId {
|
||||
local = video.endpointId
|
||||
} else {
|
||||
if remote == nil {
|
||||
remote = video
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (local, remote)
|
||||
}
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
return lhs == rhs
|
||||
})
|
||||
|
||||
let remoteIsConnectedAggregated = combineLatest(queue: .mainQueue(),
|
||||
self.remoteConferenceIsConnected.get(),
|
||||
conferenceCall.hasActiveIncomingData
|
||||
)
|
||||
|> map { remoteConferenceIsConnected, hasActiveIncomingData -> Bool in
|
||||
//return remoteConferenceIsConnected || hasActiveIncomingData
|
||||
return true
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
var startTimestamp: Double?
|
||||
self.ongoingContextStateDisposable = (combineLatest(queue: .mainQueue(),
|
||||
conferenceCall.state,
|
||||
videoEndpoints,
|
||||
conferenceCall.signalBars,
|
||||
conferenceCall.isFailed,
|
||||
remoteIsConnectedAggregated
|
||||
)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] callState, videoEndpoints, signalBars, isFailed, remoteIsConnectedAggregated in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var mappedLocalVideoState: PresentationCallState.VideoState = .inactive
|
||||
var mappedRemoteVideoState: PresentationCallState.RemoteVideoState = .inactive
|
||||
|
||||
if let local = videoEndpoints.local {
|
||||
mappedLocalVideoState = .active(isScreencast: false, endpointId: local)
|
||||
}
|
||||
if let remote = videoEndpoints.remote {
|
||||
mappedRemoteVideoState = .active(endpointId: remote.endpointId)
|
||||
}
|
||||
|
||||
self.localVideoEndpointId = videoEndpoints.local
|
||||
self.remoteVideoEndpointId = videoEndpoints.remote?.endpointId
|
||||
|
||||
if let conferenceCall = self.conferenceCall {
|
||||
var requestedVideo: [PresentationGroupCallRequestedVideo] = []
|
||||
if let remote = videoEndpoints.remote {
|
||||
requestedVideo.append(remote)
|
||||
}
|
||||
conferenceCall.setRequestedVideoList(items: requestedVideo)
|
||||
}
|
||||
|
||||
var isConnected = false
|
||||
let mappedState: PresentationCallState.State
|
||||
if isFailed {
|
||||
mappedState = .terminating(.error(.disconnected))
|
||||
} else {
|
||||
switch callState.networkState {
|
||||
case .connecting:
|
||||
mappedState = .connecting(keyVisualHash)
|
||||
case .connected:
|
||||
isConnected = true
|
||||
if remoteIsConnectedAggregated {
|
||||
let timestamp = startTimestamp ?? CFAbsoluteTimeGetCurrent()
|
||||
startTimestamp = timestamp
|
||||
mappedState = .active(timestamp, signalBars, keyVisualHash)
|
||||
} else {
|
||||
mappedState = .connecting(keyVisualHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.updateConferenceIsConnected(isConnected: isConnected)
|
||||
|
||||
if !self.didDropCall && !self.droppedCall {
|
||||
let presentationState = PresentationCallState(
|
||||
state: mappedState,
|
||||
videoState: mappedLocalVideoState,
|
||||
remoteVideoState: mappedRemoteVideoState,
|
||||
remoteAudioState: .active,
|
||||
remoteBatteryLevel: .normal
|
||||
)
|
||||
self.statePromise.set(presentationState)
|
||||
self.updateTone(presentationState, callContextState: nil, previous: nil)
|
||||
}
|
||||
})
|
||||
|
||||
self.ongoingContextIsFailedDisposable = (conferenceCall.isFailed
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if !self.didDropCall {
|
||||
self.didDropCall = true
|
||||
self.callSessionManager.drop(internalId: self.internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
}
|
||||
})
|
||||
|
||||
self.ongoingContextIsDroppedDisposable = (conferenceCall.canBeRemoved
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if !self.didDropCall {
|
||||
self.didDropCall = true
|
||||
self.callSessionManager.drop(internalId: self.internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
}
|
||||
})
|
||||
|
||||
var audioLevelId: UInt32?
|
||||
let audioLevel = conferenceCall.audioLevels |> map { audioLevels -> Float in
|
||||
var result: Float = 0
|
||||
for item in audioLevels {
|
||||
if let audioLevelId {
|
||||
if item.1 == audioLevelId {
|
||||
result = item.2
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if item.1 != 0 {
|
||||
audioLevelId = item.1
|
||||
result = item.2
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
self.audioLevelDisposable = (audioLevel
|
||||
|> deliverOnMainQueue).start(next: { [weak self] level in
|
||||
if let strongSelf = self {
|
||||
strongSelf.audioLevelPromise.set(level)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switch sessionState.state {
|
||||
case .requesting:
|
||||
if let _ = audioSessionControl {
|
||||
self.audioSessionShouldBeActive.set(true)
|
||||
}
|
||||
case let .active(id, key, keyVisualHash, connections, maxLayer, version, customParameters, allowsP2P, conferenceCall):
|
||||
if let conferenceCall, self.conferenceCallDisposable == nil {
|
||||
presentationState = PresentationCallState(state: .connecting(nil), videoState: mappedVideoState, remoteVideoState: mappedRemoteVideoState, remoteAudioState: mappedRemoteAudioState, remoteBatteryLevel: mappedRemoteBatteryLevel)
|
||||
|
||||
self.conferenceCallDisposable = (self.context.engine.calls.getCurrentGroupCall(callId: conferenceCall.id, accessHash: conferenceCall.accessHash)
|
||||
|> delay(sessionState.isOutgoing ? 0.0 : 2.0, queue: .mainQueue())
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let self, let result else {
|
||||
return
|
||||
}
|
||||
|
||||
let conferenceCall = PresentationGroupCallImpl(
|
||||
accountContext: self.context,
|
||||
audioSession: self.audioSession,
|
||||
callKitIntegration: self.callKitIntegration,
|
||||
getDeviceAccessData: self.getDeviceAccessData,
|
||||
initialCall: EngineGroupCallDescription(
|
||||
id: result.info.id,
|
||||
accessHash: result.info.accessHash,
|
||||
title: nil,
|
||||
scheduleTimestamp: nil,
|
||||
subscribedToScheduled: false,
|
||||
isStream: false
|
||||
),
|
||||
internalId: CallSessionInternalId(),
|
||||
peerId: nil,
|
||||
isChannel: false,
|
||||
invite: nil,
|
||||
joinAsPeerId: nil,
|
||||
isStream: false,
|
||||
encryptionKey: key,
|
||||
conferenceFromCallId: id,
|
||||
isConference: true,
|
||||
sharedAudioDevice: self.sharedAudioDevice
|
||||
)
|
||||
self.conferenceCall = conferenceCall
|
||||
|
||||
conferenceCall.setIsMuted(action: .muted(isPushToTalkActive: !self.isMutedValue))
|
||||
|
||||
let accountPeerId = conferenceCall.account.peerId
|
||||
let videoEndpoints: Signal<(local: String?, remote: PresentationGroupCallRequestedVideo?), NoError> = conferenceCall.members
|
||||
|> map { members -> (local: String?, remote: PresentationGroupCallRequestedVideo?) in
|
||||
guard let members else {
|
||||
return (nil, nil)
|
||||
}
|
||||
var local: String?
|
||||
var remote: PresentationGroupCallRequestedVideo?
|
||||
for participant in members.participants {
|
||||
if let video = participant.requestedPresentationVideoChannel(minQuality: .thumbnail, maxQuality: .full) ?? participant.requestedVideoChannel(minQuality: .thumbnail, maxQuality: .full) {
|
||||
if participant.peer.id == accountPeerId {
|
||||
local = video.endpointId
|
||||
} else {
|
||||
if remote == nil {
|
||||
remote = video
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (local, remote)
|
||||
}
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
return lhs == rhs
|
||||
})
|
||||
|
||||
let remoteIsConnectedAggregated = combineLatest(queue: .mainQueue(),
|
||||
self.remoteConferenceIsConnected.get(),
|
||||
conferenceCall.hasActiveIncomingData
|
||||
)
|
||||
|> map { remoteConferenceIsConnected, hasActiveIncomingData -> Bool in
|
||||
return remoteConferenceIsConnected || hasActiveIncomingData
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
var startTimestamp: Double?
|
||||
self.ongoingContextStateDisposable = (combineLatest(queue: .mainQueue(),
|
||||
conferenceCall.state,
|
||||
videoEndpoints,
|
||||
conferenceCall.signalBars,
|
||||
conferenceCall.isFailed,
|
||||
remoteIsConnectedAggregated
|
||||
)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] callState, videoEndpoints, signalBars, isFailed, remoteIsConnectedAggregated in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var mappedLocalVideoState: PresentationCallState.VideoState = .inactive
|
||||
var mappedRemoteVideoState: PresentationCallState.RemoteVideoState = .inactive
|
||||
|
||||
if let local = videoEndpoints.local {
|
||||
mappedLocalVideoState = .active(isScreencast: false, endpointId: local)
|
||||
}
|
||||
if let remote = videoEndpoints.remote {
|
||||
mappedRemoteVideoState = .active(endpointId: remote.endpointId)
|
||||
}
|
||||
|
||||
self.localVideoEndpointId = videoEndpoints.local
|
||||
self.remoteVideoEndpointId = videoEndpoints.remote?.endpointId
|
||||
|
||||
if let conferenceCall = self.conferenceCall {
|
||||
var requestedVideo: [PresentationGroupCallRequestedVideo] = []
|
||||
if let remote = videoEndpoints.remote {
|
||||
requestedVideo.append(remote)
|
||||
}
|
||||
conferenceCall.setRequestedVideoList(items: requestedVideo)
|
||||
}
|
||||
|
||||
var isConnected = false
|
||||
let mappedState: PresentationCallState.State
|
||||
if isFailed {
|
||||
mappedState = .terminating(.error(.disconnected))
|
||||
} else {
|
||||
switch callState.networkState {
|
||||
case .connecting:
|
||||
mappedState = .connecting(keyVisualHash)
|
||||
case .connected:
|
||||
isConnected = true
|
||||
if remoteIsConnectedAggregated {
|
||||
let timestamp = startTimestamp ?? CFAbsoluteTimeGetCurrent()
|
||||
startTimestamp = timestamp
|
||||
mappedState = .active(timestamp, signalBars, keyVisualHash)
|
||||
} else {
|
||||
mappedState = .connecting(keyVisualHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.updateConferenceIsConnected(isConnected: isConnected)
|
||||
|
||||
if !self.didDropCall && !self.droppedCall {
|
||||
let presentationState = PresentationCallState(
|
||||
state: mappedState,
|
||||
videoState: mappedLocalVideoState,
|
||||
remoteVideoState: mappedRemoteVideoState,
|
||||
remoteAudioState: .active,
|
||||
remoteBatteryLevel: .normal
|
||||
)
|
||||
self.statePromise.set(presentationState)
|
||||
self.updateTone(presentationState, callContextState: nil, previous: nil)
|
||||
}
|
||||
})
|
||||
|
||||
self.ongoingContextIsFailedDisposable = (conferenceCall.isFailed
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if !self.didDropCall {
|
||||
self.didDropCall = true
|
||||
self.callSessionManager.drop(internalId: self.internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
}
|
||||
})
|
||||
|
||||
self.ongoingContextIsDroppedDisposable = (conferenceCall.canBeRemoved
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if !self.didDropCall {
|
||||
self.didDropCall = true
|
||||
self.callSessionManager.drop(internalId: self.internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
}
|
||||
})
|
||||
|
||||
var audioLevelId: UInt32?
|
||||
let audioLevel = conferenceCall.audioLevels |> map { audioLevels -> Float in
|
||||
var result: Float = 0
|
||||
for item in audioLevels {
|
||||
if let audioLevelId {
|
||||
if item.1 == audioLevelId {
|
||||
result = item.2
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if item.1 != 0 {
|
||||
audioLevelId = item.1
|
||||
result = item.2
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
self.audioLevelDisposable = (audioLevel
|
||||
|> deliverOnMainQueue).start(next: { [weak self] level in
|
||||
if let strongSelf = self {
|
||||
strongSelf.audioLevelPromise.set(level)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
case let .active(id, key, _, connections, maxLayer, version, customParameters, allowsP2P, conferenceCall):
|
||||
if conferenceCall == nil, self.isExpectedToBeConference {
|
||||
self.createConferenceIfPossible()
|
||||
}
|
||||
|
||||
self.audioSessionShouldBeActive.set(true)
|
||||
|
||||
if self.isExpectedToBeConference {
|
||||
if self.isExpectedToBeConference || conferenceCallData != nil {
|
||||
if sessionState.isOutgoing {
|
||||
self.callKitIntegration?.reportOutgoingCallConnected(uuid: sessionState.id, at: Date())
|
||||
}
|
||||
@ -861,6 +878,8 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
})
|
||||
}
|
||||
}
|
||||
case .switchedToConference:
|
||||
self.audioSessionShouldBeActive.set(true)
|
||||
case let .terminated(_, _, options):
|
||||
self.audioSessionShouldBeActive.set(true)
|
||||
if wasActive {
|
||||
@ -1093,9 +1112,9 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
}
|
||||
|
||||
private func sendConferenceSignalingMessage(dict: [String: Any]) {
|
||||
if let data = try? JSONSerialization.data(withJSONObject: dict) {
|
||||
/*if let data = try? JSONSerialization.data(withJSONObject: dict) {
|
||||
self.context.account.callSessionManager.sendSignalingData(internalId: self.internalId, data: data)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private func updateIsAudioSessionActive(_ value: Bool) {
|
||||
@ -1272,6 +1291,32 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
self.videoCapturer?.setIsVideoEnabled(!isPaused)
|
||||
}
|
||||
|
||||
public func requestAddToConference(peerId: EnginePeer.Id) -> Disposable {
|
||||
var conferenceCall: (conference: GroupCallReference, encryptionKey: Data)?
|
||||
if let sessionState = self.sessionState {
|
||||
switch sessionState.state {
|
||||
case let .active(_, key, _, _, _, _, _, _, conferenceCallValue):
|
||||
if let conferenceCallValue {
|
||||
conferenceCall = (conferenceCallValue, key)
|
||||
}
|
||||
case let .switchedToConference(key, _, conferenceCallValue):
|
||||
conferenceCall = (conferenceCallValue, key)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
guard let conferenceCall else {
|
||||
return EmptyDisposable
|
||||
}
|
||||
return (self.callSessionManager.request(peerId: peerId, isVideo: false, enableVideo: true, conferenceCall: conferenceCall)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] requestedInternalId in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = self
|
||||
})
|
||||
}
|
||||
|
||||
public func setCurrentAudioOutput(_ output: AudioSessionOutput) {
|
||||
guard self.currentAudioOutputValue != output else {
|
||||
return
|
||||
|
@ -536,7 +536,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
||||
|> mapToSignal { areVideoCallsAvailable -> Signal<CallSessionInternalId, NoError> in
|
||||
let isVideoPossible: Bool = areVideoCallsAvailable
|
||||
|
||||
return context.account.callSessionManager.request(peerId: peerId, isVideo: isVideo, enableVideo: isVideoPossible, internalId: internalId)
|
||||
return context.account.callSessionManager.request(peerId: peerId, isVideo: isVideo, enableVideo: isVideoPossible, conferenceCall: nil, internalId: internalId)
|
||||
}
|
||||
|
||||
return (combineLatest(queue: .mainQueue(), request, networkType |> take(1), context.account.postbox.peerView(id: peerId) |> map { peerView -> Bool in
|
||||
|
@ -865,7 +865,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
private var screencastStateDisposable: Disposable?
|
||||
|
||||
public let isStream: Bool
|
||||
private let encryptionKey: Data?
|
||||
private let encryptionKey: (key: Data, fingerprint: Int64)?
|
||||
private let sharedAudioDevice: OngoingCallContext.AudioDevice?
|
||||
|
||||
private let conferenceFromCallId: CallId?
|
||||
@ -885,7 +885,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
invite: String?,
|
||||
joinAsPeerId: EnginePeer.Id?,
|
||||
isStream: Bool,
|
||||
encryptionKey: Data?,
|
||||
encryptionKey: (key: Data, fingerprint: Int64)?,
|
||||
conferenceFromCallId: CallId?,
|
||||
isConference: Bool,
|
||||
sharedAudioDevice: OngoingCallContext.AudioDevice?
|
||||
@ -1711,16 +1711,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
|
||||
var encryptionKey: Data?
|
||||
encryptionKey = self.encryptionKey
|
||||
|
||||
#if DEBUG
|
||||
if encryptionKey == nil {
|
||||
encryptionKey = Data(count: 256)
|
||||
}
|
||||
encryptionKey = self.encryptionKey?.key
|
||||
if "".isEmpty {
|
||||
encryptionKey = nil
|
||||
}
|
||||
#endif
|
||||
|
||||
genericCallContext = .call(OngoingGroupCallContext(audioSessionActive: self.audioSessionActive.get(), video: self.videoCapturer, requestMediaChannelDescriptions: { [weak self] ssrcs, completion in
|
||||
let disposable = MetaDisposable()
|
||||
@ -1860,7 +1854,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
preferMuted: true,
|
||||
joinPayload: joinPayload,
|
||||
peerAdminIds: peerAdminIds,
|
||||
inviteHash: strongSelf.invite
|
||||
inviteHash: strongSelf.invite,
|
||||
keyFingerprint: strongSelf.encryptionKey?.fingerprint
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { joinCallResult in
|
||||
guard let strongSelf = self else {
|
||||
|
@ -126,7 +126,7 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
|
||||
|
||||
func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
|
||||
switch messsage {
|
||||
case let .message(_, _, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
let chatPeerId = messagePeerId
|
||||
return chatPeerId.peerId
|
||||
case let .messageEmpty(_, _, peerId):
|
||||
@ -142,7 +142,7 @@ func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
|
||||
|
||||
func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
switch message {
|
||||
case let .message(_, _, _, fromId, _, chatPeerId, savedPeerId, fwdHeader, viaBotId, viaBusinessBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, fromId, _, chatPeerId, savedPeerId, fwdHeader, viaBotId, viaBusinessBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
|
||||
var result = [peerId]
|
||||
@ -270,7 +270,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
|
||||
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? {
|
||||
switch message {
|
||||
case let .message(_, _, id, _, _, chatPeerId, _, _, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, id, _, _, chatPeerId, _, _, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
if let replyTo = replyTo {
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
|
||||
@ -654,7 +654,7 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
|
||||
extension StoreMessage {
|
||||
convenience init?(apiMessage: Api.Message, accountPeerId: PeerId, peerIsForum: Bool, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
|
||||
switch apiMessage {
|
||||
case let .message(flags, flags2, id, fromId, boosts, chatPeerId, savedPeerId, fwdFrom, viaBotId, viaBusinessBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId, messageEffectId, factCheck):
|
||||
case let .message(flags, flags2, id, fromId, boosts, chatPeerId, savedPeerId, fwdFrom, viaBotId, viaBusinessBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId, messageEffectId, factCheck, _):
|
||||
var attributes: [MessageAttribute] = []
|
||||
|
||||
if (flags2 & (1 << 4)) != 0 {
|
||||
|
@ -200,6 +200,8 @@ extension PhoneCallDiscardReason {
|
||||
self = .hangup
|
||||
case .phoneCallDiscardReasonMissed:
|
||||
self = .missed
|
||||
case .phoneCallDiscardReasonAllowGroupCall:
|
||||
self = .hangup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,19 +134,22 @@ public final class AccountStateManager {
|
||||
public let timestamp: Int32
|
||||
public let peer: EnginePeer
|
||||
public let isVideo: Bool
|
||||
public let isConference: Bool
|
||||
|
||||
init(
|
||||
callId: Int64,
|
||||
callAccessHash: Int64,
|
||||
timestamp: Int32,
|
||||
peer: EnginePeer,
|
||||
isVideo: Bool
|
||||
isVideo: Bool,
|
||||
isConference: Bool
|
||||
) {
|
||||
self.callId = callId
|
||||
self.callAccessHash = callAccessHash
|
||||
self.timestamp = timestamp
|
||||
self.peer = peer
|
||||
self.isVideo = isVideo
|
||||
self.isConference = isConference
|
||||
}
|
||||
}
|
||||
|
||||
@ -2160,7 +2163,7 @@ public final class AccountStateManager {
|
||||
switch update {
|
||||
case let .updatePhoneCall(phoneCall):
|
||||
switch phoneCall {
|
||||
case let .phoneCallRequested(flags, id, accessHash, date, adminId, _, _, _):
|
||||
case let .phoneCallRequested(flags, id, accessHash, date, adminId, _, _, _, conferenceCall):
|
||||
guard let peer = peers.first(where: { $0.id == PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)) }) else {
|
||||
return nil
|
||||
}
|
||||
@ -2169,7 +2172,8 @@ public final class AccountStateManager {
|
||||
callAccessHash: accessHash,
|
||||
timestamp: date,
|
||||
peer: EnginePeer(peer),
|
||||
isVideo: (flags & (1 << 6)) != 0
|
||||
isVideo: (flags & (1 << 6)) != 0,
|
||||
isConference: conferenceCall != nil
|
||||
)
|
||||
default:
|
||||
break
|
||||
|
@ -104,7 +104,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
|
||||
var updatedTimestamp: Int32?
|
||||
if let apiMessage = apiMessage {
|
||||
switch apiMessage {
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
updatedTimestamp = date
|
||||
case .messageEmpty:
|
||||
break
|
||||
@ -400,7 +400,7 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage
|
||||
} else if let message = messages.first, let apiMessage = result.messages.first {
|
||||
if message.scheduleTime != nil && message.scheduleTime == apiMessage.timestamp {
|
||||
namespace = Namespaces.Message.ScheduledCloud
|
||||
} else if let apiMessage = result.messages.first, case let .message(_, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = apiMessage, (flags2 & (1 << 4)) != 0 {
|
||||
} else if let apiMessage = result.messages.first, case let .message(_, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = apiMessage, (flags2 & (1 << 4)) != 0 {
|
||||
namespace = Namespaces.Message.ScheduledCloud
|
||||
}
|
||||
}
|
||||
|
@ -73,32 +73,35 @@ extension GroupCallReference {
|
||||
}
|
||||
|
||||
enum CallSessionInternalState {
|
||||
case ringing(id: Int64, accessHash: Int64, gAHash: Data, b: Data, versions: [String])
|
||||
case accepting(id: Int64, accessHash: Int64, gAHash: Data, b: Data, disposable: Disposable)
|
||||
case ringing(id: Int64, accessHash: Int64, gAHash: Data, b: Data, versions: [String], conferenceCall: GroupCallReference?)
|
||||
case accepting(id: Int64, accessHash: Int64, gAHash: Data, b: Data, conferenceCall: GroupCallReference?, disposable: Disposable)
|
||||
case awaitingConfirmation(id: Int64, accessHash: Int64, gAHash: Data, b: Data, config: SecretChatEncryptionConfig)
|
||||
case requesting(a: Data, disposable: Disposable)
|
||||
case requested(id: Int64, accessHash: Int64, a: Data, gA: Data, config: SecretChatEncryptionConfig, remoteConfirmationTimestamp: Int32?)
|
||||
case confirming(id: Int64, accessHash: Int64, key: Data, keyId: Int64, keyVisualHash: Data, disposable: Disposable)
|
||||
case requesting(a: Data, conferenceCall: GroupCallReference?, disposable: Disposable)
|
||||
case requested(id: Int64, accessHash: Int64, a: Data, gA: Data, config: SecretChatEncryptionConfig, remoteConfirmationTimestamp: Int32?, conferenceCall: GroupCallReference?)
|
||||
case confirming(id: Int64, accessHash: Int64, key: Data, keyId: Int64, keyVisualHash: Data, conferenceCall: GroupCallReference?, disposable: Disposable)
|
||||
case active(id: Int64, accessHash: Int64, beginTimestamp: Int32, key: Data, keyId: Int64, keyVisualHash: Data, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, customParameters: String?, allowsP2P: Bool, conferenceCall: GroupCallReference?)
|
||||
case switchedToConference(key: Data, keyVisualHash: Data, conferenceCall: GroupCallReference)
|
||||
case dropping(reason: CallSessionTerminationReason, disposable: Disposable)
|
||||
case terminated(id: Int64?, accessHash: Int64?, reason: CallSessionTerminationReason, reportRating: Bool, sendDebugLogs: Bool)
|
||||
|
||||
var stableId: Int64? {
|
||||
switch self {
|
||||
case let .ringing(id, _, _, _, _):
|
||||
case let .ringing(id, _, _, _, _, _):
|
||||
return id
|
||||
case let .accepting(id, _, _, _, _):
|
||||
case let .accepting(id, _, _, _, _, _):
|
||||
return id
|
||||
case let .awaitingConfirmation(id, _, _, _, _):
|
||||
return id
|
||||
case .requesting:
|
||||
return nil
|
||||
case let .requested(id, _, _, _, _, _):
|
||||
case let .requested(id, _, _, _, _, _, _):
|
||||
return id
|
||||
case let .confirming(id, _, _, _, _, _):
|
||||
case let .confirming(id, _, _, _, _, _, _):
|
||||
return id
|
||||
case let .active(id, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return id
|
||||
case .switchedToConference:
|
||||
return nil
|
||||
case .dropping:
|
||||
return nil
|
||||
case let .terminated(id, _, _, _, _):
|
||||
@ -161,8 +164,9 @@ public struct CallTerminationOptions: OptionSet {
|
||||
public enum CallSessionState {
|
||||
case ringing
|
||||
case accepting
|
||||
case requesting(ringing: Bool)
|
||||
case requesting(ringing: Bool, conferenceCall: GroupCallReference?)
|
||||
case active(id: CallId, key: Data, keyVisualHash: Data, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, customParameters: String?, allowsP2P: Bool, conferenceCall: GroupCallReference?)
|
||||
case switchedToConference(key: Data, keyVisualHash: Data, conferenceCall: GroupCallReference)
|
||||
case dropping(reason: CallSessionTerminationReason)
|
||||
case terminated(id: CallId?, reason: CallSessionTerminationReason, options: CallTerminationOptions)
|
||||
|
||||
@ -172,12 +176,12 @@ public enum CallSessionState {
|
||||
self = .ringing
|
||||
case .accepting, .awaitingConfirmation:
|
||||
self = .accepting
|
||||
case .requesting:
|
||||
self = .requesting(ringing: false)
|
||||
case .confirming:
|
||||
self = .requesting(ringing: true)
|
||||
case let .requested(_, _, _, _, _, remoteConfirmationTimestamp):
|
||||
self = .requesting(ringing: remoteConfirmationTimestamp != nil)
|
||||
case let .requesting(_, conferenceCall, _):
|
||||
self = .requesting(ringing: false, conferenceCall: conferenceCall)
|
||||
case let .confirming(_, _, _, _, _, conferenceCall, _):
|
||||
self = .requesting(ringing: true, conferenceCall: conferenceCall)
|
||||
case let .requested(_, _, _, _, _, remoteConfirmationTimestamp, conferenceCall):
|
||||
self = .requesting(ringing: remoteConfirmationTimestamp != nil, conferenceCall: conferenceCall)
|
||||
case let .active(id, accessHash, _, key, _, keyVisualHash, connections, maxLayer, version, customParameters, allowsP2P, conferenceCall):
|
||||
self = .active(id: CallId(id: id, accessHash: accessHash), key: key, keyVisualHash: keyVisualHash, connections: connections, maxLayer: maxLayer, version: version, customParameters: customParameters, allowsP2P: allowsP2P, conferenceCall: conferenceCall)
|
||||
case let .dropping(reason, _):
|
||||
@ -197,6 +201,8 @@ public enum CallSessionState {
|
||||
callId = nil
|
||||
}
|
||||
self = .terminated(id: callId, reason: reason, options: options)
|
||||
case let .switchedToConference(key, keyVisualHash, conferenceCall):
|
||||
self = .switchedToConference(key: key, keyVisualHash: keyVisualHash, conferenceCall: conferenceCall)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -330,6 +336,7 @@ private final class CallSessionContext {
|
||||
let isOutgoing: Bool
|
||||
var type: CallSession.CallType
|
||||
var isVideoPossible: Bool
|
||||
let pendingConference: (conference: GroupCallReference, encryptionKey: Data)?
|
||||
var state: CallSessionInternalState
|
||||
let subscribers = Bag<(CallSession) -> Void>()
|
||||
var signalingReceiver: (([Data]) -> Void)?
|
||||
@ -346,11 +353,12 @@ private final class CallSessionContext {
|
||||
}
|
||||
}
|
||||
|
||||
init(peerId: PeerId, isOutgoing: Bool, type: CallSession.CallType, isVideoPossible: Bool, state: CallSessionInternalState) {
|
||||
init(peerId: PeerId, isOutgoing: Bool, type: CallSession.CallType, isVideoPossible: Bool, pendingConference: (conference: GroupCallReference, encryptionKey: Data)?, state: CallSessionInternalState) {
|
||||
self.peerId = peerId
|
||||
self.isOutgoing = isOutgoing
|
||||
self.type = type
|
||||
self.isVideoPossible = isVideoPossible
|
||||
self.pendingConference = pendingConference
|
||||
self.state = state
|
||||
}
|
||||
|
||||
@ -566,7 +574,7 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
}
|
||||
|
||||
private func addIncoming(peerId: PeerId, stableId: CallSessionStableId, accessHash: Int64, timestamp: Int32, gAHash: Data, versions: [String], isVideo: Bool) -> CallSessionInternalId? {
|
||||
private func addIncoming(peerId: PeerId, stableId: CallSessionStableId, accessHash: Int64, timestamp: Int32, gAHash: Data, versions: [String], isVideo: Bool, conferenceCall: GroupCallReference?) -> CallSessionInternalId? {
|
||||
if self.contextIdByStableId[stableId] != nil {
|
||||
return nil
|
||||
}
|
||||
@ -582,7 +590,7 @@ private final class CallSessionManagerContext {
|
||||
//#endif
|
||||
|
||||
let internalId = CallSessionManager.getStableIncomingUUID(stableId: stableId)
|
||||
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))
|
||||
let context = CallSessionContext(peerId: peerId, isOutgoing: false, type: isVideo ? .video : .audio, isVideoPossible: isVideoPossible, pendingConference: nil, state: .ringing(id: stableId, accessHash: accessHash, gAHash: gAHash, b: b, versions: versions, conferenceCall: conferenceCall))
|
||||
self.contexts[internalId] = context
|
||||
let queue = self.queue
|
||||
|
||||
@ -619,7 +627,7 @@ private final class CallSessionManagerContext {
|
||||
var wasRinging = false
|
||||
let isVideo = context.type == .video
|
||||
switch context.state {
|
||||
case let .ringing(id, accessHash, _, _, _):
|
||||
case let .ringing(id, accessHash, _, _, _, _):
|
||||
wasRinging = true
|
||||
let internalReason: DropCallSessionReason
|
||||
switch reason {
|
||||
@ -633,7 +641,7 @@ private final class CallSessionManagerContext {
|
||||
internalReason = .missed
|
||||
}
|
||||
dropData = (id, accessHash, internalReason)
|
||||
case let .accepting(id, accessHash, _, _, disposable):
|
||||
case let .accepting(id, accessHash, _, _, _, disposable):
|
||||
dropData = (id, accessHash, .abort)
|
||||
disposable.dispose()
|
||||
case let .active(id, accessHash, beginTimestamp, _, _, _, _, _, _, _, _, _):
|
||||
@ -648,14 +656,16 @@ private final class CallSessionManagerContext {
|
||||
internalReason = .missed
|
||||
}
|
||||
dropData = (id, accessHash, internalReason)
|
||||
case .switchedToConference:
|
||||
break
|
||||
case .dropping, .terminated:
|
||||
break
|
||||
case let .awaitingConfirmation(id, accessHash, _, _, _):
|
||||
dropData = (id, accessHash, .abort)
|
||||
case let .confirming(id, accessHash, _, _, _, disposable):
|
||||
case let .confirming(id, accessHash, _, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
dropData = (id, accessHash, .abort)
|
||||
case let .requested(id, accessHash, _, _, _, _):
|
||||
case let .requested(id, accessHash, _, _, _, _, _):
|
||||
let internalReason: DropCallSessionReason
|
||||
switch reason {
|
||||
case .busy, .hangUp:
|
||||
@ -666,7 +676,7 @@ private final class CallSessionManagerContext {
|
||||
internalReason = .missed
|
||||
}
|
||||
dropData = (id, accessHash, internalReason)
|
||||
case let .requesting(_, disposable):
|
||||
case let .requesting(_, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(id: nil, accessHash: nil, reason: .ended(.hungUp), reportRating: false, sendDebugLogs: false)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
@ -689,6 +699,8 @@ private final class CallSessionManagerContext {
|
||||
mappedReason = .ended(.hungUp)
|
||||
case .missed:
|
||||
mappedReason = .ended(.missed)
|
||||
case .switchToConference:
|
||||
mappedReason = .ended(.hungUp)
|
||||
}
|
||||
context.state = .dropping(reason: mappedReason, disposable: (dropCallSession(network: self.network, addUpdates: self.addUpdates, stableId: id, accessHash: accessHash, isVideo: isVideo, reason: reason)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] reportRating, sendDebugLogs in
|
||||
@ -729,6 +741,38 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
}
|
||||
|
||||
func dropToConference(internalId: CallSessionInternalId, encryptedGroupKey: Data) {
|
||||
if let context = self.contexts[internalId] {
|
||||
var dropData: (CallSessionStableId, Int64)?
|
||||
let isVideo = context.type == .video
|
||||
switch context.state {
|
||||
case let .active(id, accessHash, _, _, _, _, _, _, _, _, _, _):
|
||||
dropData = (id, accessHash)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if let (id, accessHash) = dropData {
|
||||
self.contextIdByStableId.removeValue(forKey: id)
|
||||
context.state = .dropping(reason: .ended(.hungUp), disposable: (dropCallSession(network: self.network, addUpdates: self.addUpdates, stableId: id, accessHash: accessHash, isVideo: isVideo, reason: .switchToConference(encryptedGroupKey: encryptedGroupKey))
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] reportRating, sendDebugLogs in
|
||||
if let strongSelf = self {
|
||||
if let context = strongSelf.contexts[internalId] {
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: .ended(.hungUp), reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
strongSelf.contextUpdated(internalId: internalId)
|
||||
if context.isEmpty {
|
||||
strongSelf.contexts.removeValue(forKey: internalId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
}
|
||||
} else {
|
||||
self.contextUpdated(internalId: internalId)
|
||||
}
|
||||
}
|
||||
|
||||
func dropAll() {
|
||||
let contexts = self.contexts
|
||||
for (internalId, _) in contexts {
|
||||
@ -739,9 +783,9 @@ private final class CallSessionManagerContext {
|
||||
func accept(internalId: CallSessionInternalId) {
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .ringing(id, accessHash, gAHash, b, _):
|
||||
case let .ringing(id, accessHash, gAHash, b, _, conferenceCall):
|
||||
let acceptVersions = self.versions.map({ $0.version })
|
||||
context.state = .accepting(id: id, accessHash: accessHash, gAHash: gAHash, b: b, disposable: (acceptCallSession(accountPeerId: self.accountPeerId, 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, conferenceCall: conferenceCall, disposable: (acceptCallSession(accountPeerId: self.accountPeerId, postbox: self.postbox, network: self.network, stableId: id, accessHash: accessHash, b: b, maxLayer: self.maxLayer, versions: acceptVersions) |> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
if case .accepting = context.state {
|
||||
switch result {
|
||||
@ -835,7 +879,7 @@ private final class CallSessionManagerContext {
|
||||
switch call {
|
||||
case .phoneCallEmpty:
|
||||
break
|
||||
case let .phoneCallAccepted(_, id, _, _, _, _, gB, remoteProtocol):
|
||||
case let .phoneCallAccepted(_, id, _, _, _, _, gB, remoteProtocol, conferenceCall):
|
||||
let remoteVersions: [String]
|
||||
switch remoteProtocol {
|
||||
case let .phoneCallProtocol(_, _, _, versions):
|
||||
@ -849,7 +893,7 @@ private final class CallSessionManagerContext {
|
||||
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .requested(_, accessHash, a, gA, config, _):
|
||||
case let .requested(_, accessHash, a, gA, config, _, _):
|
||||
let p = config.p.makeData()
|
||||
if !MTCheckIsSafeGAOrB(self.network.encryptionProvider, gA, p) {
|
||||
self.drop(internalId: internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
@ -874,10 +918,14 @@ private final class CallSessionManagerContext {
|
||||
|
||||
let keyVisualHash = MTSha256(key + gA)
|
||||
|
||||
context.state = .confirming(id: id, accessHash: accessHash, key: key, keyId: keyId, keyVisualHash: keyVisualHash, disposable: (confirmCallSession(network: self.network, stableId: id, accessHash: accessHash, gA: gA, keyFingerprint: keyId, maxLayer: self.maxLayer, versions: selectedVersions) |> deliverOnMainQueue).start(next: { [weak self] updatedCall in
|
||||
context.state = .confirming(id: id, accessHash: accessHash, key: key, keyId: keyId, keyVisualHash: keyVisualHash, conferenceCall: conferenceCall.flatMap(GroupCallReference.init), disposable: (confirmCallSession(network: self.network, stableId: id, accessHash: accessHash, gA: gA, keyFingerprint: keyId, maxLayer: self.maxLayer, versions: selectedVersions) |> deliverOnMainQueue).start(next: { [weak self] updatedCall in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId], case .confirming = context.state {
|
||||
if let updatedCall = updatedCall {
|
||||
strongSelf.updateSession(updatedCall, completion: { _ in })
|
||||
|
||||
if let pendingConference = context.pendingConference {
|
||||
strongSelf.dropToConference(internalId: internalId, encryptedGroupKey: pendingConference.encryptionKey)
|
||||
}
|
||||
} else {
|
||||
strongSelf.drop(internalId: internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
}
|
||||
@ -891,7 +939,8 @@ private final class CallSessionManagerContext {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .phoneCallDiscarded(flags, id, reason, _):
|
||||
case let .phoneCallDiscarded(flags, id, reason, _, conferenceCall):
|
||||
let _ = conferenceCall
|
||||
let reportRating = (flags & (1 << 2)) != 0
|
||||
let sendDebugLogs = (flags & (1 << 3)) != 0
|
||||
if let internalId = self.contextIdByStableId[id] {
|
||||
@ -899,47 +948,53 @@ private final class CallSessionManagerContext {
|
||||
let parsedReason: CallSessionTerminationReason
|
||||
if let reason = reason {
|
||||
switch reason {
|
||||
case .phoneCallDiscardReasonBusy:
|
||||
parsedReason = .ended(.busy)
|
||||
case .phoneCallDiscardReasonDisconnect:
|
||||
parsedReason = .error(.disconnected)
|
||||
case .phoneCallDiscardReasonHangup:
|
||||
parsedReason = .ended(.hungUp)
|
||||
case .phoneCallDiscardReasonMissed:
|
||||
parsedReason = .ended(.missed)
|
||||
case .phoneCallDiscardReasonBusy:
|
||||
parsedReason = .ended(.busy)
|
||||
case .phoneCallDiscardReasonDisconnect:
|
||||
parsedReason = .error(.disconnected)
|
||||
case .phoneCallDiscardReasonHangup:
|
||||
parsedReason = .ended(.hungUp)
|
||||
case .phoneCallDiscardReasonMissed:
|
||||
parsedReason = .ended(.missed)
|
||||
case .phoneCallDiscardReasonAllowGroupCall:
|
||||
parsedReason = .ended(.hungUp)
|
||||
}
|
||||
} else {
|
||||
parsedReason = .ended(.hungUp)
|
||||
}
|
||||
|
||||
switch context.state {
|
||||
case let .accepting(id, accessHash, _, _, disposable):
|
||||
disposable.dispose()
|
||||
case let .accepting(id, accessHash, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .active(id, accessHash, _, _, _, _, _, _, _, _, _, conferenceCall):
|
||||
if let conferenceCall, case let .phoneCallDiscardReasonAllowGroupCall(encryptedGroupKey) = reason {
|
||||
context.state = .switchedToConference(key: encryptedGroupKey.makeData(), keyVisualHash: MTSha256(encryptedGroupKey.makeData()), conferenceCall: conferenceCall)
|
||||
} else {
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .active(id, accessHash, _, _, _, _, _, _, _, _, _, _):
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .awaitingConfirmation(id, accessHash, _, _, _):
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .requested(id, accessHash, _, _, _, _):
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .confirming(id, accessHash, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .requesting(_, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(id: nil, accessHash: nil, reason: parsedReason, reportRating: false, sendDebugLogs: false)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .ringing(id, accessHash, _, _, _):
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.ringingStatesUpdated()
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .dropping, .terminated:
|
||||
break
|
||||
}
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .awaitingConfirmation(id, accessHash, _, _, _):
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .requested(id, accessHash, _, _, _, _, _):
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .confirming(id, accessHash, _, _, _, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .requesting(_, _, disposable):
|
||||
disposable.dispose()
|
||||
context.state = .terminated(id: nil, accessHash: nil, reason: parsedReason, reportRating: false, sendDebugLogs: false)
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case let .ringing(id, accessHash, _, _, _, _):
|
||||
context.state = .terminated(id: id, accessHash: accessHash, reason: parsedReason, reportRating: reportRating, sendDebugLogs: sendDebugLogs)
|
||||
self.ringingStatesUpdated()
|
||||
self.contextUpdated(internalId: internalId)
|
||||
case .dropping, .terminated, .switchedToConference:
|
||||
break
|
||||
}
|
||||
} else {
|
||||
//assertionFailure()
|
||||
@ -950,7 +1005,7 @@ private final class CallSessionManagerContext {
|
||||
if let internalId = self.contextIdByStableId[id] {
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case .accepting, .active, .dropping, .requesting, .ringing, .terminated, .requested:
|
||||
case .accepting, .active, .dropping, .requesting, .ringing, .terminated, .requested, .switchedToConference:
|
||||
break
|
||||
case let .awaitingConfirmation(_, accessHash, gAHash, b, config):
|
||||
if let (key, calculatedKeyId, keyVisualHash) = self.makeSessionEncryptionKey(config: config, gAHash: gAHash, b: b, gA: gAOrB.makeData()) {
|
||||
@ -981,7 +1036,7 @@ private final class CallSessionManagerContext {
|
||||
} else {
|
||||
self.drop(internalId: internalId, reason: .disconnect, debugLog: .single(nil))
|
||||
}
|
||||
case let .confirming(id, accessHash, key, keyId, keyVisualHash, _):
|
||||
case let .confirming(id, accessHash, key, keyId, keyVisualHash, _, _):
|
||||
switch callProtocol {
|
||||
case let .phoneCallProtocol(_, _, maxLayer, versions):
|
||||
if !versions.isEmpty {
|
||||
@ -1007,7 +1062,7 @@ private final class CallSessionManagerContext {
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .phoneCallRequested(flags, id, accessHash, date, adminId, _, gAHash, requestedProtocol):
|
||||
case let .phoneCallRequested(flags, id, accessHash, date, adminId, _, gAHash, requestedProtocol, conferenceCall):
|
||||
let isVideo = (flags & (1 << 6)) != 0
|
||||
let versions: [String]
|
||||
switch requestedProtocol {
|
||||
@ -1015,7 +1070,7 @@ private final class CallSessionManagerContext {
|
||||
versions = libraryVersions
|
||||
}
|
||||
if self.contextIdByStableId[id] == nil {
|
||||
let internalId = self.addIncoming(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), stableId: id, accessHash: accessHash, timestamp: date, gAHash: gAHash.makeData(), versions: versions, isVideo: isVideo)
|
||||
let internalId = self.addIncoming(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), stableId: id, accessHash: accessHash, timestamp: date, gAHash: gAHash.makeData(), versions: versions, isVideo: isVideo, conferenceCall: conferenceCall.flatMap(GroupCallReference.init))
|
||||
if let internalId = internalId {
|
||||
var resultRingingStateValue: CallSessionRingingState?
|
||||
for ringingState in self.ringingStatesValue() {
|
||||
@ -1032,13 +1087,13 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .phoneCallWaiting(_, id, _, _, _, _, _, receiveDate):
|
||||
case let .phoneCallWaiting(_, id, _, _, _, _, _, receiveDate, conferenceCall):
|
||||
if let internalId = self.contextIdByStableId[id] {
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .requested(id, accessHash, a, gA, config, remoteConfirmationTimestamp):
|
||||
case let .requested(id, accessHash, a, gA, config, remoteConfirmationTimestamp, _):
|
||||
if let receiveDate = receiveDate, remoteConfirmationTimestamp == nil {
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: receiveDate)
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: receiveDate, conferenceCall: conferenceCall.flatMap(GroupCallReference.init))
|
||||
self.contextUpdated(internalId: internalId)
|
||||
}
|
||||
default:
|
||||
@ -1101,17 +1156,17 @@ private final class CallSessionManagerContext {
|
||||
return (key, keyId, keyVisualHash)
|
||||
}
|
||||
|
||||
func request(peerId: PeerId, internalId: CallSessionInternalId, isVideo: Bool, enableVideo: Bool) -> CallSessionInternalId? {
|
||||
func request(peerId: PeerId, internalId: CallSessionInternalId, isVideo: Bool, enableVideo: Bool, conferenceCall: (conference: GroupCallReference, encryptionKey: Data)?) -> CallSessionInternalId? {
|
||||
let aBytes = malloc(256)!
|
||||
let randomStatus = SecRandomCopyBytes(nil, 256, aBytes.assumingMemoryBound(to: UInt8.self))
|
||||
let a = Data(bytesNoCopy: aBytes, count: 256, deallocator: .free)
|
||||
if randomStatus == 0 {
|
||||
self.contexts[internalId] = CallSessionContext(peerId: peerId, isOutgoing: true, type: isVideo ? .video : .audio, 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: true), 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, pendingConference: conferenceCall, state: .requesting(a: a, conferenceCall: conferenceCall?.conference, disposable: (requestCallSession(postbox: self.postbox, network: self.network, peerId: peerId, a: a, maxLayer: self.maxLayer, versions: self.filteredVersions(enableVideo: true), isVideo: isVideo, conferenceCall: conferenceCall?.conference) |> deliverOn(queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
if case .requesting = context.state {
|
||||
switch result {
|
||||
case let .success(id, accessHash, config, gA, remoteConfirmationTimestamp):
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: remoteConfirmationTimestamp)
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: remoteConfirmationTimestamp, conferenceCall: conferenceCall?.conference)
|
||||
strongSelf.contextIdByStableId[id] = internalId
|
||||
strongSelf.contextUpdated(internalId: internalId)
|
||||
strongSelf.deliverCallSignalingData(id: id)
|
||||
@ -1206,12 +1261,12 @@ public final class CallSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func request(peerId: PeerId, isVideo: Bool, enableVideo: Bool, internalId: CallSessionInternalId = CallSessionInternalId()) -> Signal<CallSessionInternalId, NoError> {
|
||||
public func request(peerId: PeerId, isVideo: Bool, enableVideo: Bool, conferenceCall: (conference: GroupCallReference, encryptionKey: Data)?, internalId: CallSessionInternalId = CallSessionInternalId()) -> Signal<CallSessionInternalId, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self?.withContext { context in
|
||||
if let internalId = context.request(peerId: peerId, internalId: internalId, isVideo: isVideo, enableVideo: enableVideo) {
|
||||
if let internalId = context.request(peerId: peerId, internalId: internalId, isVideo: isVideo, enableVideo: enableVideo, conferenceCall: conferenceCall) {
|
||||
subscriber.putNext(internalId)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
@ -1358,7 +1413,7 @@ private enum RequestCallSessionResult {
|
||||
case failed(CallSessionError)
|
||||
}
|
||||
|
||||
private func requestCallSession(postbox: Postbox, network: Network, peerId: PeerId, a: Data, maxLayer: Int32, versions: [String], isVideo: Bool) -> Signal<RequestCallSessionResult, NoError> {
|
||||
private func requestCallSession(postbox: Postbox, network: Network, peerId: PeerId, a: Data, maxLayer: Int32, versions: [String], isVideo: Bool, conferenceCall: GroupCallReference?) -> Signal<RequestCallSessionResult, NoError> {
|
||||
return validatedEncryptionConfig(postbox: postbox, network: network)
|
||||
|> mapToSignal { config -> Signal<RequestCallSessionResult, NoError> in
|
||||
return postbox.transaction { transaction -> Signal<RequestCallSessionResult, NoError> in
|
||||
@ -1378,15 +1433,18 @@ private func requestCallSession(postbox: Postbox, network: Network, peerId: Peer
|
||||
if isVideo {
|
||||
callFlags |= 1 << 0
|
||||
}
|
||||
if conferenceCall != nil {
|
||||
callFlags |= 1 << 1
|
||||
}
|
||||
|
||||
return network.request(Api.functions.phone.requestCall(flags: callFlags, userId: inputUser, randomId: Int32(bitPattern: arc4random()), gAHash: Buffer(data: gAHash), protocol: .phoneCallProtocol(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions)))
|
||||
return network.request(Api.functions.phone.requestCall(flags: callFlags, userId: inputUser, conferenceCall: conferenceCall.flatMap { Api.InputGroupCall.inputGroupCall(id: $0.id, accessHash: $0.accessHash) }, randomId: Int32(bitPattern: arc4random()), gAHash: Buffer(data: gAHash), protocol: .phoneCallProtocol(flags: (1 << 0) | (1 << 1), minLayer: minLayer, maxLayer: maxLayer, libraryVersions: versions)))
|
||||
|> map { result -> RequestCallSessionResult in
|
||||
switch result {
|
||||
case let .phoneCall(phoneCall, _):
|
||||
switch phoneCall {
|
||||
case let .phoneCallRequested(_, id, accessHash, _, _, _, _, _):
|
||||
case let .phoneCallRequested(_, id, accessHash, _, _, _, _, _, _):
|
||||
return .success(id: id, accessHash: accessHash, config: config, gA: ga, remoteConfirmationTimestamp: nil)
|
||||
case let .phoneCallWaiting(_, id, accessHash, _, _, _, _, receiveDate):
|
||||
case let .phoneCallWaiting(_, id, accessHash, _, _, _, _, receiveDate, _):
|
||||
return .success(id: id, accessHash: accessHash, config: config, gA: ga, remoteConfirmationTimestamp: receiveDate)
|
||||
default:
|
||||
return .failed(.generic)
|
||||
@ -1439,23 +1497,26 @@ private enum DropCallSessionReason {
|
||||
case busy
|
||||
case disconnect
|
||||
case missed
|
||||
case switchToConference(encryptedGroupKey: Data)
|
||||
}
|
||||
|
||||
private func dropCallSession(network: Network, addUpdates: @escaping (Api.Updates) -> Void, stableId: CallSessionStableId, accessHash: Int64, isVideo: Bool, reason: DropCallSessionReason) -> Signal<(Bool, Bool), NoError> {
|
||||
var mappedReason: Api.PhoneCallDiscardReason
|
||||
var duration: Int32 = 0
|
||||
switch reason {
|
||||
case .abort:
|
||||
mappedReason = .phoneCallDiscardReasonHangup
|
||||
case let .hangUp(value):
|
||||
duration = value
|
||||
mappedReason = .phoneCallDiscardReasonHangup
|
||||
case .busy:
|
||||
mappedReason = .phoneCallDiscardReasonBusy
|
||||
case .disconnect:
|
||||
mappedReason = .phoneCallDiscardReasonDisconnect
|
||||
case .missed:
|
||||
mappedReason = .phoneCallDiscardReasonMissed
|
||||
case .abort:
|
||||
mappedReason = .phoneCallDiscardReasonHangup
|
||||
case let .hangUp(value):
|
||||
duration = value
|
||||
mappedReason = .phoneCallDiscardReasonHangup
|
||||
case .busy:
|
||||
mappedReason = .phoneCallDiscardReasonBusy
|
||||
case .disconnect:
|
||||
mappedReason = .phoneCallDiscardReasonDisconnect
|
||||
case .missed:
|
||||
mappedReason = .phoneCallDiscardReasonMissed
|
||||
case let .switchToConference(encryptedGroupKey):
|
||||
mappedReason = .phoneCallDiscardReasonAllowGroupCall(encryptedKey: Buffer(data: encryptedGroupKey))
|
||||
}
|
||||
|
||||
var callFlags: Int32 = 0
|
||||
@ -1478,7 +1539,7 @@ private func dropCallSession(network: Network, addUpdates: @escaping (Api.Update
|
||||
switch update {
|
||||
case .updatePhoneCall(let phoneCall):
|
||||
switch phoneCall {
|
||||
case let .phoneCallDiscarded(flags, _, _, _):
|
||||
case let .phoneCallDiscarded(flags, _, _, _, _):
|
||||
reportRating = (flags & (1 << 2)) != 0
|
||||
sendDebugLogs = (flags & (1 << 3)) != 0
|
||||
default:
|
||||
@ -1501,33 +1562,7 @@ private func dropCallSession(network: Network, addUpdates: @escaping (Api.Update
|
||||
}
|
||||
|
||||
private func createConferenceCall(postbox: Postbox, network: Network, accountPeerId: PeerId, callId: CallId) -> Signal<GroupCallReference?, NoError> {
|
||||
#if DEBUG && false
|
||||
if "".isEmpty {
|
||||
return _internal_resolvePeerByName(postbox: postbox, network: network, accountPeerId: accountPeerId, name: "qwfqwfqwefqwef22", referrer: nil)
|
||||
|> mapToSignal { result -> Signal<PeerId?, NoError> in
|
||||
switch result {
|
||||
case .progress:
|
||||
return .never()
|
||||
case let .result(peerId):
|
||||
return .single(peerId)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { peerId -> Signal<GroupCallReference?, NoError> in
|
||||
guard let peerId else {
|
||||
return .single(nil)
|
||||
}
|
||||
return _internal_updatedCurrentPeerGroupCall(postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId)
|
||||
|> map { result -> GroupCallReference? in
|
||||
guard let result else {
|
||||
return nil
|
||||
}
|
||||
return GroupCallReference(id: result.id, accessHash: result.accessHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return network.request(Api.functions.phone.createConferenceCall(peer: .inputPhoneCall(id: callId.id, accessHash: callId.accessHash)))
|
||||
return network.request(Api.functions.phone.createConferenceCall(peer: .inputPhoneCall(id: callId.id, accessHash: callId.accessHash), keyFingerprint: 1))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.phone.PhoneCall?, NoError> in
|
||||
return .single(nil)
|
||||
|
@ -1745,7 +1745,7 @@ public final class PendingMessageManager {
|
||||
if message.scheduleTime != nil && message.scheduleTime == apiMessage.timestamp {
|
||||
isScheduled = true
|
||||
}
|
||||
if case let .message(_, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = apiMessage {
|
||||
if case let .message(_, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = apiMessage {
|
||||
if (flags2 & (1 << 4)) != 0 {
|
||||
isScheduled = true
|
||||
}
|
||||
@ -1780,7 +1780,7 @@ public final class PendingMessageManager {
|
||||
namespace = Namespaces.Message.QuickReplyCloud
|
||||
} else if let apiMessage = result.messages.first, message.scheduleTime != nil && message.scheduleTime == apiMessage.timestamp {
|
||||
namespace = Namespaces.Message.ScheduledCloud
|
||||
} else if let apiMessage = result.messages.first, case let .message(_, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = apiMessage, (flags2 & (1 << 4)) != 0 {
|
||||
} else if let apiMessage = result.messages.first, case let .message(_, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = apiMessage, (flags2 & (1 << 4)) != 0 {
|
||||
namespace = Namespaces.Message.ScheduledCloud
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
||||
self.putNext(groups)
|
||||
}
|
||||
case let .updateShortChatMessage(flags, id, fromId, chatId, message, pts, ptsCount, date, fwdFrom, viaBotId, replyHeader, entities, ttlPeriod):
|
||||
let generatedMessage = Api.Message.message(flags: flags, flags2: 0, id: id, fromId: .peerUser(userId: fromId), fromBoostsApplied: nil, peerId: Api.Peer.peerChat(chatId: chatId), savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil)
|
||||
let generatedMessage = Api.Message.message(flags: flags, flags2: 0, id: id, fromId: .peerUser(userId: fromId), fromBoostsApplied: nil, peerId: Api.Peer.peerChat(chatId: chatId), savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil, reportDeliveryUntilDate: nil)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
@ -74,7 +74,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
||||
|
||||
let generatedPeerId = Api.Peer.peerUser(userId: userId)
|
||||
|
||||
let generatedMessage = Api.Message.message(flags: flags, flags2: 0, id: id, fromId: generatedFromId, fromBoostsApplied: nil, peerId: generatedPeerId, savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil)
|
||||
let generatedMessage = Api.Message.message(flags: flags, flags2: 0, id: id, fromId: generatedFromId, fromBoostsApplied: nil, peerId: generatedPeerId, savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil, reportDeliveryUntilDate: nil)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
|
@ -104,7 +104,7 @@ extension Api.MessageMedia {
|
||||
extension Api.Message {
|
||||
var rawId: Int32 {
|
||||
switch self {
|
||||
case let .message(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return id
|
||||
case let .messageEmpty(_, id, _):
|
||||
return id
|
||||
@ -115,7 +115,7 @@ extension Api.Message {
|
||||
|
||||
func id(namespace: MessageId.Namespace = Namespaces.Message.Cloud) -> MessageId? {
|
||||
switch self {
|
||||
case let .message(_, flags2, id, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, flags2, id, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
var namespace = namespace
|
||||
if (flags2 & (1 << 4)) != 0 {
|
||||
namespace = Namespaces.Message.ScheduledCloud
|
||||
@ -136,7 +136,7 @@ extension Api.Message {
|
||||
|
||||
var peerId: PeerId? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
let peerId: PeerId = messagePeerId.peerId
|
||||
return peerId
|
||||
case let .messageEmpty(_, _, peerId):
|
||||
@ -149,7 +149,7 @@ extension Api.Message {
|
||||
|
||||
var timestamp: Int32? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return date
|
||||
case let .messageService(_, _, _, _, _, date, _, _, _):
|
||||
return date
|
||||
@ -160,7 +160,7 @@ extension Api.Message {
|
||||
|
||||
var preCachedResources: [(MediaResource, Data)]? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return media?.preCachedResources
|
||||
default:
|
||||
return nil
|
||||
@ -169,7 +169,7 @@ extension Api.Message {
|
||||
|
||||
var preCachedStories: [StoryId: Api.StoryItem]? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return media?.preCachedStories
|
||||
default:
|
||||
return nil
|
||||
|
@ -435,7 +435,7 @@ public struct JoinGroupCallResult {
|
||||
public var jsonParams: String
|
||||
}
|
||||
|
||||
func _internal_joinGroupCall(account: Account, peerId: PeerId?, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
|
||||
func _internal_joinGroupCall(account: Account, peerId: PeerId?, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil, keyFingerprint: Int64?) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
if let joinAs = joinAs {
|
||||
return transaction.getPeer(joinAs).flatMap(apiInputPeer)
|
||||
@ -457,8 +457,11 @@ func _internal_joinGroupCall(account: Account, peerId: PeerId?, joinAs: PeerId?,
|
||||
if let _ = inviteHash {
|
||||
flags |= (1 << 1)
|
||||
}
|
||||
|
||||
let joinRequest = account.network.request(Api.functions.phone.joinGroupCall(flags: flags, call: .inputGroupCall(id: callId, accessHash: accessHash), joinAs: inputJoinAs, inviteHash: inviteHash, params: .dataJSON(data: joinPayload)))
|
||||
if keyFingerprint != nil {
|
||||
flags |= (1 << 3)
|
||||
}
|
||||
|
||||
let joinRequest = account.network.request(Api.functions.phone.joinGroupCall(flags: flags, call: .inputGroupCall(id: callId, accessHash: accessHash), joinAs: inputJoinAs, inviteHash: inviteHash, keyFingerprint: keyFingerprint, params: .dataJSON(data: joinPayload)))
|
||||
|> `catch` { error -> Signal<Api.Updates, JoinGroupCallError> in
|
||||
if error.errorDescription == "GROUPCALL_ANONYMOUS_FORBIDDEN" {
|
||||
return .fail(.anonymousNotAllowed)
|
||||
|
@ -57,8 +57,8 @@ public extension TelegramEngine {
|
||||
return _internal_getGroupCallParticipants(account: self.account, callId: callId, accessHash: accessHash, offset: offset, ssrcs: ssrcs, limit: limit, sortAscending: sortAscending)
|
||||
}
|
||||
|
||||
public func joinGroupCall(peerId: PeerId?, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
|
||||
return _internal_joinGroupCall(account: self.account, peerId: peerId, joinAs: joinAs, callId: callId, accessHash: accessHash, preferMuted: preferMuted, joinPayload: joinPayload, peerAdminIds: peerAdminIds, inviteHash: inviteHash)
|
||||
public func joinGroupCall(peerId: PeerId?, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil, keyFingerprint: Int64?) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
|
||||
return _internal_joinGroupCall(account: self.account, peerId: peerId, joinAs: joinAs, callId: callId, accessHash: accessHash, preferMuted: preferMuted, joinPayload: joinPayload, peerAdminIds: peerAdminIds, inviteHash: inviteHash, keyFingerprint: keyFingerprint)
|
||||
}
|
||||
|
||||
public func joinGroupCallAsScreencast(callId: Int64, accessHash: Int64, joinPayload: String) -> Signal<JoinGroupCallAsScreencastResult, JoinGroupCallError> {
|
||||
|
@ -226,6 +226,7 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu
|
||||
public var backAction: (() -> Void)?
|
||||
public var closeAction: (() -> Void)?
|
||||
public var restoreUIForPictureInPicture: ((@escaping (Bool) -> Void) -> Void)?
|
||||
public var conferenceAddParticipant: (() -> Void)?
|
||||
|
||||
private let pipView: PrivateCallPictureInPictureView
|
||||
private var pipContentSource: AnyObject?
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 965c46f32425cb270e88ab0aab7c3593b5be574e
|
||||
Subproject commit ab50f4e095d5793c39dc54b740a982fc3ba27ea5
|
Loading…
x
Reference in New Issue
Block a user