mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Support video streaming API (PoC)
This commit is contained in:
parent
d331e943df
commit
d1078f1e90
@ -3,7 +3,7 @@
|
||||
@implementation Serialization
|
||||
|
||||
- (NSUInteger)currentLayer {
|
||||
return 131;
|
||||
return 132;
|
||||
}
|
||||
|
||||
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
||||
|
BIN
Telegram/Telegram-iOS/Resources/chunk2.ch2.q1.mp4
Normal file
BIN
Telegram/Telegram-iOS/Resources/chunk2.ch2.q1.mp4
Normal file
Binary file not shown.
@ -737,6 +737,7 @@ public protocol AccountContext: AnyObject {
|
||||
|
||||
func chatLocationInput(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> ChatLocationInput
|
||||
func chatLocationOutgoingReadState(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<MessageId?, NoError>
|
||||
func chatLocationUnreadCount(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<Int, NoError>
|
||||
func applyMaxReadIndex(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>, messageIndex: MessageIndex)
|
||||
|
||||
func scheduleGroupCall(peerId: PeerId)
|
||||
|
@ -82,16 +82,30 @@ class MessageHistoryThreadsTable: Table {
|
||||
return indices
|
||||
}
|
||||
|
||||
func getMessageCountInRange(threadId: Int64, peerId: PeerId, namespace: MessageId.Namespace, lowerBound: MessageIndex, upperBound: MessageIndex) -> Int {
|
||||
precondition(lowerBound.id.namespace == namespace)
|
||||
precondition(upperBound.id.namespace == namespace)
|
||||
var lowerBoundKey = self.key(threadId: threadId, index: lowerBound)
|
||||
if lowerBound.timestamp > 1 {
|
||||
lowerBoundKey = lowerBoundKey.predecessor
|
||||
func getMessageCountInRange(threadId: Int64, peerId: PeerId, namespace: MessageId.Namespace, lowerBound: MessageIndex?, upperBound: MessageIndex?) -> Int {
|
||||
if let lowerBound = lowerBound {
|
||||
precondition(lowerBound.id.namespace == namespace)
|
||||
}
|
||||
var upperBoundKey = self.key(threadId: threadId, index: upperBound)
|
||||
if upperBound.timestamp < Int32.max - 1 {
|
||||
upperBoundKey = upperBoundKey.successor
|
||||
if let upperBound = upperBound {
|
||||
precondition(upperBound.id.namespace == namespace)
|
||||
}
|
||||
var lowerBoundKey: ValueBoxKey
|
||||
if let lowerBound = lowerBound {
|
||||
lowerBoundKey = self.key(threadId: threadId, index: lowerBound)
|
||||
if lowerBound.timestamp > 1 {
|
||||
lowerBoundKey = lowerBoundKey.predecessor
|
||||
}
|
||||
} else {
|
||||
lowerBoundKey = self.lowerBound(threadId: threadId, peerId: peerId, namespace: namespace)
|
||||
}
|
||||
var upperBoundKey: ValueBoxKey
|
||||
if let upperBound = upperBound {
|
||||
upperBoundKey = self.key(threadId: threadId, index: upperBound)
|
||||
if upperBound.timestamp < Int32.max - 1 {
|
||||
upperBoundKey = upperBoundKey.successor
|
||||
}
|
||||
} else {
|
||||
upperBoundKey = self.upperBound(threadId: threadId, peerId: peerId, namespace: namespace)
|
||||
}
|
||||
return Int(self.valueBox.count(self.table, start: lowerBoundKey, end: upperBoundKey))
|
||||
}
|
||||
|
@ -87,6 +87,22 @@ public final class Transaction {
|
||||
assert(!self.disposed)
|
||||
return self.postbox!.messageHistoryThreadHoleIndexTable.closest(peerId: peerId, threadId: threadId, namespace: namespace, space: .everywhere, range: 1 ... (Int32.max - 1))
|
||||
}
|
||||
|
||||
public func getThreadMessageCount(peerId: PeerId, threadId: Int64, namespace: MessageId.Namespace, fromId: Int32?, toIndex: MessageIndex) -> Int? {
|
||||
assert(!self.disposed)
|
||||
let fromIndex: MessageIndex?
|
||||
if let fromId = fromId {
|
||||
fromIndex = self.postbox!.messageHistoryIndexTable.closestIndex(id: MessageId(peerId: peerId, namespace: namespace, id: fromId))
|
||||
} else {
|
||||
fromIndex = nil
|
||||
}
|
||||
|
||||
if let fromIndex = fromIndex {
|
||||
return self.postbox!.messageHistoryThreadsTable.getMessageCountInRange(threadId: threadId, peerId: peerId, namespace: namespace, lowerBound: fromIndex, upperBound: toIndex)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public func doesChatListGroupContainHoles(groupId: PeerGroupId) -> Bool {
|
||||
assert(!self.disposed)
|
||||
|
@ -480,7 +480,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-438840932] = { return Api.messages.ChatFull.parse_chatFull($0) }
|
||||
dict[1578088377] = { return Api.messages.HistoryImportParsed.parse_historyImportParsed($0) }
|
||||
dict[-618540889] = { return Api.InputSecureValue.parse_inputSecureValue($0) }
|
||||
dict[-170029155] = { return Api.messages.DiscussionMessage.parse_discussionMessage($0) }
|
||||
dict[-1506535550] = { return Api.messages.DiscussionMessage.parse_discussionMessage($0) }
|
||||
dict[1722786150] = { return Api.help.DeepLinkInfo.parse_deepLinkInfoEmpty($0) }
|
||||
dict[1783556146] = { return Api.help.DeepLinkInfo.parse_deepLinkInfo($0) }
|
||||
dict[-313079300] = { return Api.account.WebAuthorizations.parse_webAuthorizations($0) }
|
||||
@ -683,7 +683,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-667654413] = { return Api.InputFileLocation.parse_inputPhotoLegacyFileLocation($0) }
|
||||
dict[925204121] = { return Api.InputFileLocation.parse_inputPeerPhotoFileLocation($0) }
|
||||
dict[-1652231205] = { return Api.InputFileLocation.parse_inputStickerSetThumb($0) }
|
||||
dict[-1146808775] = { return Api.InputFileLocation.parse_inputGroupCallStream($0) }
|
||||
dict[93890858] = { return Api.InputFileLocation.parse_inputGroupCallStream($0) }
|
||||
dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) }
|
||||
dict[-1297942941] = { return Api.GeoPoint.parse_geoPoint($0) }
|
||||
dict[506920429] = { return Api.InputPhoneCall.parse_inputPhoneCall($0) }
|
||||
@ -705,7 +705,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-433014407] = { return Api.InputWallPaper.parse_inputWallPaper($0) }
|
||||
dict[1913199744] = { return Api.InputWallPaper.parse_inputWallPaperSlug($0) }
|
||||
dict[-1770371538] = { return Api.InputWallPaper.parse_inputWallPaperNoFile($0) }
|
||||
dict[-1118798639] = { return Api.InputThemeSettings.parse_inputThemeSettings($0) }
|
||||
dict[-13043438] = { return Api.InputThemeSettings.parse_inputThemeSettings($0) }
|
||||
dict[1251549527] = { return Api.InputStickeredMedia.parse_inputStickeredMediaPhoto($0) }
|
||||
dict[70813275] = { return Api.InputStickeredMedia.parse_inputStickeredMediaDocument($0) }
|
||||
dict[1421174295] = { return Api.WebPageAttribute.parse_webPageAttributeTheme($0) }
|
||||
@ -857,7 +857,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[42930452] = { return Api.Theme.parse_theme($0) }
|
||||
dict[-1290580579] = { return Api.contacts.Found.parse_found($0) }
|
||||
dict[-368018716] = { return Api.ChannelAdminLogEventsFilter.parse_channelAdminLogEventsFilter($0) }
|
||||
dict[-1676371894] = { return Api.ThemeSettings.parse_themeSettings($0) }
|
||||
dict[-1917524116] = { return Api.ThemeSettings.parse_themeSettings($0) }
|
||||
dict[-1353671392] = { return Api.PeerNotifySettings.parse_peerNotifySettings($0) }
|
||||
dict[-1995686519] = { return Api.InputBotInlineMessageID.parse_inputBotInlineMessageID($0) }
|
||||
dict[-1282352120] = { return Api.PageRelatedArticle.parse_pageRelatedArticle($0) }
|
||||
|
@ -1011,13 +1011,13 @@ public struct messages {
|
||||
|
||||
}
|
||||
public enum DiscussionMessage: TypeConstructorDescription {
|
||||
case discussionMessage(flags: Int32, messages: [Api.Message], maxId: Int32?, readInboxMaxId: Int32?, readOutboxMaxId: Int32?, chats: [Api.Chat], users: [Api.User])
|
||||
case discussionMessage(flags: Int32, messages: [Api.Message], maxId: Int32?, readInboxMaxId: Int32?, readOutboxMaxId: Int32?, unreadCount: Int32, chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let chats, let users):
|
||||
case .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-170029155)
|
||||
buffer.appendInt32(-1506535550)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
@ -1028,6 +1028,7 @@ public struct messages {
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(maxId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(readInboxMaxId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(readOutboxMaxId!, buffer: buffer, boxed: false)}
|
||||
serializeInt32(unreadCount, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
@ -1044,8 +1045,8 @@ public struct messages {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let chats, let users):
|
||||
return ("discussionMessage", [("flags", flags), ("messages", messages), ("maxId", maxId), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("chats", chats), ("users", users)])
|
||||
case .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chats, let users):
|
||||
return ("discussionMessage", [("flags", flags), ("messages", messages), ("maxId", maxId), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chats", chats), ("users", users)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -1062,13 +1063,15 @@ public struct messages {
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() }
|
||||
var _6: [Api.Chat]?
|
||||
var _6: Int32?
|
||||
_6 = reader.readInt32()
|
||||
var _7: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _7: [Api.User]?
|
||||
var _8: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
@ -1077,8 +1080,9 @@ public struct messages {
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.messages.DiscussionMessage.discussionMessage(flags: _1!, messages: _2!, maxId: _3, readInboxMaxId: _4, readOutboxMaxId: _5, chats: _6!, users: _7!)
|
||||
let _c8 = _8 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||
return Api.messages.DiscussionMessage.discussionMessage(flags: _1!, messages: _2!, maxId: _3, readInboxMaxId: _4, readOutboxMaxId: _5, unreadCount: _6!, chats: _7!, users: _8!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -17375,7 +17375,7 @@ public extension Api {
|
||||
case inputPhotoLegacyFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, volumeId: Int64, localId: Int32, secret: Int64)
|
||||
case inputPeerPhotoFileLocation(flags: Int32, peer: Api.InputPeer, photoId: Int64)
|
||||
case inputStickerSetThumb(stickerset: Api.InputStickerSet, thumbVersion: Int32)
|
||||
case inputGroupCallStream(call: Api.InputGroupCall, timeMs: Int64, scale: Int32)
|
||||
case inputGroupCallStream(flags: Int32, call: Api.InputGroupCall, timeMs: Int64, scale: Int32, videoChannel: Int32?, videoQuality: Int32?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -17452,13 +17452,16 @@ public extension Api {
|
||||
stickerset.serialize(buffer, true)
|
||||
serializeInt32(thumbVersion, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputGroupCallStream(let call, let timeMs, let scale):
|
||||
case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1146808775)
|
||||
buffer.appendInt32(93890858)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
serializeInt64(timeMs, buffer: buffer, boxed: false)
|
||||
serializeInt32(scale, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoChannel!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoQuality!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -17483,8 +17486,8 @@ public extension Api {
|
||||
return ("inputPeerPhotoFileLocation", [("flags", flags), ("peer", peer), ("photoId", photoId)])
|
||||
case .inputStickerSetThumb(let stickerset, let thumbVersion):
|
||||
return ("inputStickerSetThumb", [("stickerset", stickerset), ("thumbVersion", thumbVersion)])
|
||||
case .inputGroupCallStream(let call, let timeMs, let scale):
|
||||
return ("inputGroupCallStream", [("call", call), ("timeMs", timeMs), ("scale", scale)])
|
||||
case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality):
|
||||
return ("inputGroupCallStream", [("flags", flags), ("call", call), ("timeMs", timeMs), ("scale", scale), ("videoChannel", videoChannel), ("videoQuality", videoQuality)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -17641,19 +17644,28 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
public static func parse_inputGroupCallStream(_ reader: BufferReader) -> InputFileLocation? {
|
||||
var _1: Api.InputGroupCall?
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputGroupCall?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputGroupCall
|
||||
}
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
|
||||
var _6: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.InputFileLocation.inputGroupCallStream(call: _1!, timeMs: _2!, scale: _3!)
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputFileLocation.inputGroupCallStream(flags: _1!, call: _2!, timeMs: _3!, scale: _4!, videoChannel: _5, videoQuality: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -18390,19 +18402,22 @@ public extension Api {
|
||||
|
||||
}
|
||||
public enum InputThemeSettings: TypeConstructorDescription {
|
||||
case inputThemeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, messageTopColor: Int32?, messageBottomColor: Int32?, wallpaper: Api.InputWallPaper?, wallpaperSettings: Api.WallPaperSettings?)
|
||||
case inputThemeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, messageColors: [Int32]?, wallpaper: Api.InputWallPaper?, wallpaperSettings: Api.WallPaperSettings?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let messageTopColor, let messageBottomColor, let wallpaper, let wallpaperSettings):
|
||||
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let messageColors, let wallpaper, let wallpaperSettings):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1118798639)
|
||||
buffer.appendInt32(-13043438)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
baseTheme.serialize(buffer, true)
|
||||
serializeInt32(accentColor, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(messageTopColor!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(messageBottomColor!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(messageColors!.count))
|
||||
for item in messageColors! {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {wallpaperSettings!.serialize(buffer, true)}
|
||||
break
|
||||
@ -18411,8 +18426,8 @@ public extension Api {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let messageTopColor, let messageBottomColor, let wallpaper, let wallpaperSettings):
|
||||
return ("inputThemeSettings", [("flags", flags), ("baseTheme", baseTheme), ("accentColor", accentColor), ("messageTopColor", messageTopColor), ("messageBottomColor", messageBottomColor), ("wallpaper", wallpaper), ("wallpaperSettings", wallpaperSettings)])
|
||||
case .inputThemeSettings(let flags, let baseTheme, let accentColor, let messageColors, let wallpaper, let wallpaperSettings):
|
||||
return ("inputThemeSettings", [("flags", flags), ("baseTheme", baseTheme), ("accentColor", accentColor), ("messageColors", messageColors), ("wallpaper", wallpaper), ("wallpaperSettings", wallpaperSettings)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -18425,27 +18440,26 @@ public extension Api {
|
||||
}
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
|
||||
var _6: Api.InputWallPaper?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.InputWallPaper
|
||||
var _4: [Int32]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
|
||||
} }
|
||||
var _7: Api.WallPaperSettings?
|
||||
var _5: Api.InputWallPaper?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.InputWallPaper
|
||||
} }
|
||||
var _6: Api.WallPaperSettings?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.InputThemeSettings.inputThemeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, messageTopColor: _4, messageBottomColor: _5, wallpaper: _6, wallpaperSettings: _7)
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.InputThemeSettings.inputThemeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, messageColors: _4, wallpaper: _5, wallpaperSettings: _6)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -21932,19 +21946,22 @@ public extension Api {
|
||||
|
||||
}
|
||||
public enum ThemeSettings: TypeConstructorDescription {
|
||||
case themeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, messageTopColor: Int32?, messageBottomColor: Int32?, wallpaper: Api.WallPaper?)
|
||||
case themeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, messageColors: [Int32]?, wallpaper: Api.WallPaper?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .themeSettings(let flags, let baseTheme, let accentColor, let messageTopColor, let messageBottomColor, let wallpaper):
|
||||
case .themeSettings(let flags, let baseTheme, let accentColor, let messageColors, let wallpaper):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1676371894)
|
||||
buffer.appendInt32(-1917524116)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
baseTheme.serialize(buffer, true)
|
||||
serializeInt32(accentColor, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(messageTopColor!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(messageBottomColor!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(messageColors!.count))
|
||||
for item in messageColors! {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)}
|
||||
break
|
||||
}
|
||||
@ -21952,8 +21969,8 @@ public extension Api {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .themeSettings(let flags, let baseTheme, let accentColor, let messageTopColor, let messageBottomColor, let wallpaper):
|
||||
return ("themeSettings", [("flags", flags), ("baseTheme", baseTheme), ("accentColor", accentColor), ("messageTopColor", messageTopColor), ("messageBottomColor", messageBottomColor), ("wallpaper", wallpaper)])
|
||||
case .themeSettings(let flags, let baseTheme, let accentColor, let messageColors, let wallpaper):
|
||||
return ("themeSettings", [("flags", flags), ("baseTheme", baseTheme), ("accentColor", accentColor), ("messageColors", messageColors), ("wallpaper", wallpaper)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -21966,22 +21983,21 @@ public extension Api {
|
||||
}
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() }
|
||||
var _5: Int32?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
|
||||
var _6: Api.WallPaper?
|
||||
var _4: [Int32]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
|
||||
} }
|
||||
var _5: Api.WallPaper?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.WallPaper
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.WallPaper
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.ThemeSettings.themeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, messageTopColor: _4, messageBottomColor: _5, wallpaper: _6)
|
||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.ThemeSettings.themeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, messageColors: _4, wallpaper: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -8010,11 +8010,12 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func getGroupCall(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.phone.GroupCall>) {
|
||||
public static func getGroupCall(call: Api.InputGroupCall, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.phone.GroupCall>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(209498135)
|
||||
buffer.appendInt32(68699611)
|
||||
call.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "phone.getGroupCall", parameters: [("call", call)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCall? in
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "phone.getGroupCall", parameters: [("call", call), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCall? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.phone.GroupCall?
|
||||
if let signature = reader.readInt32() {
|
||||
|
@ -4891,6 +4891,8 @@ public final class VoiceChatController: ViewController {
|
||||
memberPeer = user.withUpdatedPhoto([photo])
|
||||
}
|
||||
}
|
||||
|
||||
joinedVideo = true
|
||||
|
||||
if let videoEndpointId = member.videoEndpointId {
|
||||
peerIdToCameraEndpointId[member.peer.id] = videoEndpointId
|
||||
|
@ -46,12 +46,8 @@ extension TelegramBaseTheme {
|
||||
extension TelegramThemeSettings {
|
||||
convenience init?(apiThemeSettings: Api.ThemeSettings) {
|
||||
switch apiThemeSettings {
|
||||
case let .themeSettings(_, baseTheme, accentColor, messageTopColor, messageBottomColor, wallpaper):
|
||||
var messageColors: [UInt32] = []
|
||||
if let messageTopColor = messageTopColor, let messageBottomColor = messageBottomColor {
|
||||
messageColors = [UInt32(bitPattern: messageTopColor), UInt32(bitPattern: messageBottomColor)]
|
||||
}
|
||||
self.init(baseTheme: TelegramBaseTheme(apiBaseTheme: baseTheme), accentColor: UInt32(bitPattern: accentColor), messageColors: messageColors, wallpaper: wallpaper.flatMap(TelegramWallpaper.init(apiWallpaper:)))
|
||||
case let .themeSettings(_, baseTheme, accentColor, messageColors, wallpaper):
|
||||
self.init(baseTheme: TelegramBaseTheme(apiBaseTheme: baseTheme), accentColor: UInt32(bitPattern: accentColor), messageColors: messageColors?.map(UInt32.init(bitPattern:)) ?? [], wallpaper: wallpaper.flatMap(TelegramWallpaper.init(apiWallpaper:)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,16 +65,6 @@ extension TelegramThemeSettings {
|
||||
flags |= 1 << 1
|
||||
}
|
||||
|
||||
var messageTopColor: Int32?
|
||||
var messageBottomColor: Int32?
|
||||
if self.messageColors.count > 0 {
|
||||
messageTopColor = Int32(bitPattern: self.messageColors[0])
|
||||
messageBottomColor = messageTopColor
|
||||
}
|
||||
if self.messageColors.count > 1 {
|
||||
messageBottomColor = Int32(bitPattern: self.messageColors[1])
|
||||
}
|
||||
|
||||
return .inputThemeSettings(flags: flags, baseTheme: self.baseTheme.apiBaseTheme, accentColor: Int32(bitPattern: self.accentColor), messageTopColor: messageTopColor, messageBottomColor: messageBottomColor, wallpaper: inputWallpaper, wallpaperSettings: inputWallpaperSettings)
|
||||
return .inputThemeSettings(flags: flags, baseTheme: self.baseTheme.apiBaseTheme, accentColor: Int32(bitPattern: self.accentColor), messageColors: self.messageColors.isEmpty ? nil : self.messageColors.map(Int32.init(bitPattern:)), wallpaper: inputWallpaper, wallpaperSettings: inputWallpaperSettings)
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 131
|
||||
return 132
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
@ -80,7 +80,7 @@ public enum GetCurrentGroupCallError {
|
||||
}
|
||||
|
||||
func _internal_getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal<GroupCallSummary?, GetCurrentGroupCallError> {
|
||||
return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash)))
|
||||
return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), limit: 4))
|
||||
|> mapError { _ -> GetCurrentGroupCallError in
|
||||
return .generic
|
||||
}
|
||||
@ -2363,7 +2363,7 @@ public final class AudioBroadcastDataSource {
|
||||
}
|
||||
|
||||
func _internal_getAudioBroadcastDataSource(account: Account, callId: Int64, accessHash: Int64) -> Signal<AudioBroadcastDataSource?, NoError> {
|
||||
return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash)))
|
||||
return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), limit: 4))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.phone.GroupCall?, NoError> in
|
||||
return .single(nil)
|
||||
@ -2396,6 +2396,11 @@ public struct GetAudioBroadcastPartResult {
|
||||
|
||||
public var status: Status
|
||||
public var responseTimestamp: Double
|
||||
|
||||
public init(status: Status, responseTimestamp: Double) {
|
||||
self.status = status
|
||||
self.responseTimestamp = responseTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_getAudioBroadcastPart(dataSource: AudioBroadcastDataSource, callId: Int64, accessHash: Int64, timestampIdMilliseconds: Int64, durationMilliseconds: Int64) -> Signal<GetAudioBroadcastPartResult, NoError> {
|
||||
@ -2409,7 +2414,58 @@ func _internal_getAudioBroadcastPart(dataSource: AudioBroadcastDataSource, callI
|
||||
return .single(GetAudioBroadcastPartResult(status: .notReady, responseTimestamp: Double(timestampIdMilliseconds) / 1000.0))
|
||||
}
|
||||
|
||||
return dataSource.download.requestWithAdditionalData(Api.functions.upload.getFile(flags: 0, location: .inputGroupCallStream(call: .inputGroupCall(id: callId, accessHash: accessHash), timeMs: timestampIdMilliseconds, scale: scale), offset: 0, limit: 128 * 1024), automaticFloodWait: false, failOnServerErrors: true)
|
||||
return dataSource.download.requestWithAdditionalData(Api.functions.upload.getFile(flags: 0, location: .inputGroupCallStream(flags: 0, call: .inputGroupCall(id: callId, accessHash: accessHash), timeMs: timestampIdMilliseconds, scale: scale, videoChannel: nil, videoQuality: nil), offset: 0, limit: 128 * 1024), automaticFloodWait: false, failOnServerErrors: true)
|
||||
|> map { result, responseTimestamp -> GetAudioBroadcastPartResult in
|
||||
switch result {
|
||||
case let .file(_, _, bytes):
|
||||
return GetAudioBroadcastPartResult(
|
||||
status: .data(bytes.makeData()),
|
||||
responseTimestamp: responseTimestamp
|
||||
)
|
||||
case .fileCdnRedirect:
|
||||
return GetAudioBroadcastPartResult(
|
||||
status: .notReady,
|
||||
responseTimestamp: responseTimestamp
|
||||
)
|
||||
}
|
||||
}
|
||||
|> `catch` { error, responseTimestamp -> Signal<GetAudioBroadcastPartResult, NoError> in
|
||||
if error.errorDescription == "GROUPCALL_JOIN_MISSING" {
|
||||
return .single(GetAudioBroadcastPartResult(
|
||||
status: .rejoinNeeded,
|
||||
responseTimestamp: responseTimestamp
|
||||
))
|
||||
} else if error.errorDescription.hasPrefix("FLOOD_WAIT") || error.errorDescription == "TIME_TOO_BIG" {
|
||||
return .single(GetAudioBroadcastPartResult(
|
||||
status: .notReady,
|
||||
responseTimestamp: responseTimestamp
|
||||
))
|
||||
} else if error.errorDescription == "TIME_INVALID" || error.errorDescription == "TIME_TOO_SMALL" {
|
||||
return .single(GetAudioBroadcastPartResult(
|
||||
status: .resyncNeeded,
|
||||
responseTimestamp: responseTimestamp
|
||||
))
|
||||
} else {
|
||||
return .single(GetAudioBroadcastPartResult(
|
||||
status: .resyncNeeded,
|
||||
responseTimestamp: responseTimestamp
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_getVideoBroadcastPart(dataSource: AudioBroadcastDataSource, callId: Int64, accessHash: Int64, timestampIdMilliseconds: Int64, durationMilliseconds: Int64) -> Signal<GetAudioBroadcastPartResult, NoError> {
|
||||
let scale: Int32
|
||||
switch durationMilliseconds {
|
||||
case 1000:
|
||||
scale = 0
|
||||
case 500:
|
||||
scale = 1
|
||||
default:
|
||||
return .single(GetAudioBroadcastPartResult(status: .notReady, responseTimestamp: Double(timestampIdMilliseconds) / 1000.0))
|
||||
}
|
||||
|
||||
return dataSource.download.requestWithAdditionalData(Api.functions.upload.getFile(flags: 0, location: .inputGroupCallStream(flags: 1 << 0, call: .inputGroupCall(id: callId, accessHash: accessHash), timeMs: timestampIdMilliseconds, scale: scale, videoChannel: 1, videoQuality: 0), offset: 0, limit: 512 * 1024), automaticFloodWait: false, failOnServerErrors: true)
|
||||
|> map { result, responseTimestamp -> GetAudioBroadcastPartResult in
|
||||
switch result {
|
||||
case let .file(_, _, bytes):
|
||||
|
@ -104,6 +104,10 @@ public extension TelegramEngine {
|
||||
return _internal_getAudioBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds)
|
||||
}
|
||||
|
||||
public func getVideoBroadcastPart(dataSource: AudioBroadcastDataSource, callId: Int64, accessHash: Int64, timestampIdMilliseconds: Int64, durationMilliseconds: Int64) -> Signal<GetAudioBroadcastPartResult, NoError> {
|
||||
return _internal_getVideoBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds)
|
||||
}
|
||||
|
||||
public func groupCall(peerId: PeerId, myPeerId: PeerId, id: Int64, accessHash: Int64, state: GroupCallParticipantsContext.State, previousServiceState: GroupCallParticipantsContext.ServiceState?) -> GroupCallParticipantsContext {
|
||||
return GroupCallParticipantsContext(account: self.account, peerId: peerId, myPeerId: myPeerId, id: id, accessHash: accessHash, state: state, previousServiceState: previousServiceState)
|
||||
}
|
||||
|
@ -4,12 +4,13 @@ import SwiftSignalKit
|
||||
import TelegramApi
|
||||
|
||||
private struct DiscussionMessage {
|
||||
public var messageId: MessageId
|
||||
public var channelMessageId: MessageId?
|
||||
public var isChannelPost: Bool
|
||||
public var maxMessage: MessageId?
|
||||
public var maxReadIncomingMessageId: MessageId?
|
||||
public var maxReadOutgoingMessageId: MessageId?
|
||||
var messageId: MessageId
|
||||
var channelMessageId: MessageId?
|
||||
var isChannelPost: Bool
|
||||
var maxMessage: MessageId?
|
||||
var maxReadIncomingMessageId: MessageId?
|
||||
var maxReadOutgoingMessageId: MessageId?
|
||||
var unreadCount: Int
|
||||
}
|
||||
|
||||
private class ReplyThreadHistoryContextImpl {
|
||||
@ -45,6 +46,17 @@ private class ReplyThreadHistoryContextImpl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var maxReadIncomingMessageIdValue: MessageId?
|
||||
|
||||
let unreadCount = Promise<Int>()
|
||||
private var unreadCountValue: Int = 0 {
|
||||
didSet {
|
||||
if self.unreadCountValue != oldValue {
|
||||
self.unreadCount.set(.single(self.unreadCountValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var initialStateDisposable: Disposable?
|
||||
private var holesDisposable: Disposable?
|
||||
@ -59,6 +71,11 @@ private class ReplyThreadHistoryContextImpl {
|
||||
|
||||
self.maxReadOutgoingMessageIdValue = data.maxReadOutgoingMessageId
|
||||
self.maxReadOutgoingMessageId.set(.single(self.maxReadOutgoingMessageIdValue))
|
||||
|
||||
self.maxReadIncomingMessageIdValue = data.maxReadIncomingMessageId
|
||||
|
||||
self.unreadCountValue = data.unreadCount
|
||||
self.unreadCount.set(.single(self.unreadCountValue))
|
||||
|
||||
self.initialStateDisposable = (account.postbox.transaction { transaction -> State in
|
||||
var indices = transaction.getThreadIndexHoles(peerId: data.messageId.peerId, threadId: makeMessageThreadId(data.messageId), namespace: Namespaces.Message.Cloud)
|
||||
@ -134,7 +151,7 @@ private class ReplyThreadHistoryContextImpl {
|
||||
|> mapToSignal { discussionMessage -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
|
||||
return account.postbox.transaction { transaction -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
|
||||
switch discussionMessage {
|
||||
case let .discussionMessage(_, messages, maxId, readInboxMaxId, readOutboxMaxId, chats, users):
|
||||
case let .discussionMessage(_, messages, maxId, readInboxMaxId, readOutboxMaxId, unreadCount, chats, users):
|
||||
let parsedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
StoreMessage(apiMessage: message)
|
||||
}
|
||||
@ -233,7 +250,8 @@ private class ReplyThreadHistoryContextImpl {
|
||||
maxReadIncomingMessageId: maxReadIncomingMessageId,
|
||||
maxReadOutgoingMessageId: readOutboxMaxId.flatMap { readMaxId in
|
||||
MessageId(peerId: parsedIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId)
|
||||
}
|
||||
},
|
||||
unreadCount: Int(unreadCount)
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -294,14 +312,27 @@ private class ReplyThreadHistoryContextImpl {
|
||||
}
|
||||
|
||||
func applyMaxReadIndex(messageIndex: MessageIndex) {
|
||||
let account = self.account
|
||||
let messageId = self.messageId
|
||||
|
||||
if messageIndex.id.namespace != messageId.namespace {
|
||||
return
|
||||
}
|
||||
|
||||
guard let _ = self.stateValue else {
|
||||
return
|
||||
}
|
||||
|
||||
let fromId: Int32?
|
||||
let toIndex = messageIndex
|
||||
if let maxReadIncomingMessageId = self.maxReadIncomingMessageIdValue {
|
||||
fromId = maxReadIncomingMessageId.id + 1
|
||||
} else {
|
||||
fromId = nil
|
||||
}
|
||||
|
||||
let account = self.account
|
||||
|
||||
let signal = self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
let _ = (self.account.postbox.transaction { transaction -> (Api.InputPeer?, MessageId?, Int?) in
|
||||
if let message = transaction.getMessage(messageId) {
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||
@ -337,20 +368,84 @@ private class ReplyThreadHistoryContextImpl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let inputPeer = transaction.getPeer(messageIndex.id.peerId).flatMap(apiInputPeer)
|
||||
let readCount = transaction.getThreadMessageCount(peerId: messageId.peerId, threadId: makeMessageThreadId(messageId), namespace: messageId.namespace, fromId: fromId, toIndex: toIndex)
|
||||
let topMessageId = transaction.getMessagesWithThreadId(peerId: messageId.peerId, namespace: messageId.namespace, threadId: makeMessageThreadId(messageId), from: MessageIndex.upperBound(peerId: messageId.peerId, namespace: messageId.namespace), includeFrom: false, to: MessageIndex.lowerBound(peerId: messageId.peerId, namespace: messageId.namespace), limit: 1).first?.id
|
||||
|
||||
return transaction.getPeer(messageIndex.id.peerId).flatMap(apiInputPeer)
|
||||
return (inputPeer, topMessageId, readCount)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<Never, NoError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .complete()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] inputPeer, topMessageId, readCount in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
return account.network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: messageId.id, readMaxId: messageIndex.id.id))
|
||||
|
||||
guard let inputPeer = inputPeer else {
|
||||
return
|
||||
}
|
||||
|
||||
var revalidate = false
|
||||
|
||||
strongSelf.maxReadIncomingMessageIdValue = messageIndex.id
|
||||
var unreadCountValue = strongSelf.unreadCountValue
|
||||
if let readCount = readCount {
|
||||
unreadCountValue = max(0, unreadCountValue - Int(readCount))
|
||||
} else {
|
||||
revalidate = true
|
||||
}
|
||||
|
||||
if let topMessageId = topMessageId {
|
||||
if topMessageId.id <= messageIndex.id.id {
|
||||
unreadCountValue = 0
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.unreadCountValue = unreadCountValue
|
||||
|
||||
if let state = strongSelf.stateValue {
|
||||
if let indices = state.holeIndices[messageIndex.id.namespace] {
|
||||
let fromIdInt = Int(fromId ?? 1)
|
||||
let toIdInt = Int(toIndex.id.id)
|
||||
if fromIdInt <= toIdInt, indices.intersects(integersIn: fromIdInt ..< toIdInt) {
|
||||
revalidate = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var signal = strongSelf.account.network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: messageId.id, readMaxId: messageIndex.id.id))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(.boolFalse)
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
self.readDisposable.set(signal.start())
|
||||
if revalidate {
|
||||
let validateSignal = strongSelf.account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: messageId.id))
|
||||
|> map { result -> (MessageId?, Int) in
|
||||
switch result {
|
||||
case let .discussionMessage(_, _, _, readInboxMaxId, _, unreadCount, _, _):
|
||||
return (readInboxMaxId.flatMap({ MessageId(peerId: messageId.peerId, namespace: messageId.namespace, id: $0) }), Int(unreadCount))
|
||||
}
|
||||
}
|
||||
|> `catch` { _ -> Signal<(MessageId?, Int)?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> afterNext { result in
|
||||
guard let (incomingMesageId, count) = result else {
|
||||
return
|
||||
}
|
||||
Queue.mainQueue().async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.maxReadIncomingMessageIdValue = incomingMesageId
|
||||
strongSelf.unreadCountValue = count
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
signal = signal
|
||||
|> then(validateSignal)
|
||||
}
|
||||
strongSelf.readDisposable.set(signal.start())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,6 +499,20 @@ public class ReplyThreadHistoryContext {
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
public var unreadCount: Signal<Int, NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
disposable.set(impl.unreadCount.get().start(next: { value in
|
||||
subscriber.putNext(value)
|
||||
}))
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
public init(account: Account, peerId: PeerId, data: ChatReplyThreadMessage) {
|
||||
let queue = self.queue
|
||||
@ -431,17 +540,19 @@ public struct ChatReplyThreadMessage: Equatable {
|
||||
public var maxMessage: MessageId?
|
||||
public var maxReadIncomingMessageId: MessageId?
|
||||
public var maxReadOutgoingMessageId: MessageId?
|
||||
public var unreadCount: Int
|
||||
public var initialFilledHoles: IndexSet
|
||||
public var initialAnchor: Anchor
|
||||
public var isNotAvailable: Bool
|
||||
|
||||
fileprivate init(messageId: MessageId, channelMessageId: MessageId?, isChannelPost: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, initialFilledHoles: IndexSet, initialAnchor: Anchor, isNotAvailable: Bool) {
|
||||
fileprivate init(messageId: MessageId, channelMessageId: MessageId?, isChannelPost: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, unreadCount: Int, initialFilledHoles: IndexSet, initialAnchor: Anchor, isNotAvailable: Bool) {
|
||||
self.messageId = messageId
|
||||
self.channelMessageId = channelMessageId
|
||||
self.isChannelPost = isChannelPost
|
||||
self.maxMessage = maxMessage
|
||||
self.maxReadIncomingMessageId = maxReadIncomingMessageId
|
||||
self.maxReadOutgoingMessageId = maxReadOutgoingMessageId
|
||||
self.unreadCount = unreadCount
|
||||
self.initialFilledHoles = initialFilledHoles
|
||||
self.initialAnchor = initialAnchor
|
||||
self.isNotAvailable = isNotAvailable
|
||||
@ -463,7 +574,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
||||
}
|
||||
|
||||
let replyInfo = Promise<AccountViewTracker.UpdatedMessageReplyInfo?>()
|
||||
replyInfo.set(account.viewTracker.replyInfoForMessageId(messageId))
|
||||
replyInfo.set(.single(nil))
|
||||
|
||||
let remoteDiscussionMessageSignal: Signal<DiscussionMessage?, NoError> = account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: messageId.id))
|
||||
|> map(Optional.init)
|
||||
@ -476,7 +587,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
||||
}
|
||||
return account.postbox.transaction { transaction -> DiscussionMessage? in
|
||||
switch discussionMessage {
|
||||
case let .discussionMessage(_, messages, maxId, readInboxMaxId, readOutboxMaxId, chats, users):
|
||||
case let .discussionMessage(_, messages, maxId, readInboxMaxId, readOutboxMaxId, unreadCount, chats, users):
|
||||
let parsedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
StoreMessage(apiMessage: message)
|
||||
}
|
||||
@ -546,7 +657,8 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
||||
},
|
||||
maxReadOutgoingMessageId: readOutboxMaxId.flatMap { readMaxId in
|
||||
MessageId(peerId: parsedIndex.id.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId)
|
||||
}
|
||||
},
|
||||
unreadCount: Int(unreadCount)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -583,7 +695,8 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
||||
isChannelPost: true,
|
||||
maxMessage: replyInfo.maxMessageId,
|
||||
maxReadIncomingMessageId: replyInfo.maxReadIncomingMessageId,
|
||||
maxReadOutgoingMessageId: nil
|
||||
maxReadOutgoingMessageId: nil,
|
||||
unreadCount: 0
|
||||
)
|
||||
}
|
||||
})
|
||||
@ -785,6 +898,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
||||
maxMessage: discussionMessage.maxMessage,
|
||||
maxReadIncomingMessageId: discussionMessage.maxReadIncomingMessageId,
|
||||
maxReadOutgoingMessageId: discussionMessage.maxReadOutgoingMessageId,
|
||||
unreadCount: discussionMessage.unreadCount,
|
||||
initialFilledHoles: initialFilledHoles?.removedIndices ?? IndexSet(),
|
||||
initialAnchor: initialAnchor,
|
||||
isNotAvailable: initialFilledHoles == nil
|
||||
|
@ -290,6 +290,28 @@ public final class AccountContextImpl: AccountContext {
|
||||
return context.maxReadOutgoingMessageId
|
||||
}
|
||||
}
|
||||
|
||||
public func chatLocationUnreadCount(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<Int, NoError> {
|
||||
switch location {
|
||||
case let .peer(peerId):
|
||||
let unreadCountsKey: PostboxViewKey = .unreadCounts(items: [.peer(peerId), .total(nil)])
|
||||
return self.account.postbox.combinedView(keys: [unreadCountsKey])
|
||||
|> map { views in
|
||||
var unreadCount: Int32 = 0
|
||||
|
||||
if let view = views.views[unreadCountsKey] as? UnreadMessageCountsView {
|
||||
if let count = view.count(for: .peer(peerId)) {
|
||||
unreadCount = count
|
||||
}
|
||||
}
|
||||
|
||||
return Int(unreadCount)
|
||||
}
|
||||
case let .replyThread(data):
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
return context.unreadCount
|
||||
}
|
||||
}
|
||||
|
||||
public func applyMaxReadIndex(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>, messageIndex: MessageIndex) {
|
||||
switch location {
|
||||
|
@ -318,6 +318,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
private var buttonKeyboardMessageDisposable: Disposable?
|
||||
private var cachedDataDisposable: Disposable?
|
||||
private var chatUnreadCountDisposable: Disposable?
|
||||
private var buttonUnreadCountDisposable: Disposable?
|
||||
private var chatUnreadMentionCountDisposable: Disposable?
|
||||
private var peerInputActivitiesDisposable: Disposable?
|
||||
|
||||
@ -3887,6 +3888,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.cachedDataDisposable?.dispose()
|
||||
self.resolveUrlDisposable?.dispose()
|
||||
self.chatUnreadCountDisposable?.dispose()
|
||||
self.buttonUnreadCountDisposable?.dispose()
|
||||
self.chatUnreadMentionCountDisposable?.dispose()
|
||||
self.peerInputActivitiesDisposable?.dispose()
|
||||
self.recentlyUsedInlineBotsDisposable?.dispose()
|
||||
@ -6822,6 +6824,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let peerId = self.chatLocation.peerId
|
||||
if let subject = self.subject, case .scheduledMessages = subject {
|
||||
} else {
|
||||
self.buttonUnreadCountDisposable = (self.context.chatLocationUnreadCount(for: self.chatLocation, contextHolder: self.chatLocationContextHolder)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] count in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.navigateButtons.unreadCount = Int32(count)
|
||||
})
|
||||
|
||||
if case .peer = self.chatLocation {
|
||||
let unreadCountsKey: PostboxViewKey = .unreadCounts(items: [.peer(peerId), .total(nil)])
|
||||
let notificationSettingsKey: PostboxViewKey = .peerNotificationSettings(peerIds: Set([peerId]))
|
||||
@ -6842,8 +6852,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.chatDisplayNode.navigateButtons.unreadCount = unreadCount
|
||||
|
||||
if let view = views.views[notificationSettingsKey] as? PeerNotificationSettingsView, let notificationSettings = view.notificationSettings[peerId] {
|
||||
var globalRemainingUnreadChatCount = totalChatCount
|
||||
if !notificationSettings.isRemovedFromTotalUnreadCount(default: false) && unreadCount > 0 {
|
||||
@ -7097,7 +7105,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
nextFolderId = nil
|
||||
}
|
||||
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: strongSelf.currentChatListFilter, completion: { nextController in
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: nextFolderId, completion: { nextController in
|
||||
(nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState)
|
||||
}))
|
||||
}
|
||||
|
@ -1260,12 +1260,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
if expandProgress < 0.1 {
|
||||
chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: nil)
|
||||
} else if expandProgress >= 0.99 {
|
||||
if chatControllerNode.inputPanelOverscrollNode?.text.0 != swipeText.0 {
|
||||
chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: swipeText, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 1))
|
||||
if chatControllerNode.inputPanelOverscrollNode?.text.0 != releaseText.0 {
|
||||
chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: releaseText, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 1))
|
||||
}
|
||||
} else {
|
||||
if chatControllerNode.inputPanelOverscrollNode?.text.0 != releaseText.0 {
|
||||
chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: releaseText, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 2))
|
||||
if chatControllerNode.inputPanelOverscrollNode?.text.0 != swipeText.0 {
|
||||
chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: swipeText, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 2))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -28,8 +28,13 @@ private final class ContextQueueImpl: NSObject, OngoingCallThreadLocalContextQue
|
||||
}
|
||||
}
|
||||
|
||||
private enum BroadcastPartSubject {
|
||||
case audio
|
||||
case video
|
||||
}
|
||||
|
||||
private protocol BroadcastPartSource: AnyObject {
|
||||
func requestPart(timestampMilliseconds: Int64, durationMilliseconds: Int64, completion: @escaping (OngoingGroupCallBroadcastPart) -> Void, rejoinNeeded: @escaping () -> Void) -> Disposable
|
||||
func requestPart(timestampMilliseconds: Int64, durationMilliseconds: Int64, subject: BroadcastPartSubject, completion: @escaping (OngoingGroupCallBroadcastPart) -> Void, rejoinNeeded: @escaping () -> Void) -> Disposable
|
||||
}
|
||||
|
||||
private final class NetworkBroadcastPartSource: BroadcastPartSource {
|
||||
@ -46,7 +51,7 @@ private final class NetworkBroadcastPartSource: BroadcastPartSource {
|
||||
self.accessHash = accessHash
|
||||
}
|
||||
|
||||
func requestPart(timestampMilliseconds: Int64, durationMilliseconds: Int64, completion: @escaping (OngoingGroupCallBroadcastPart) -> Void, rejoinNeeded: @escaping () -> Void) -> Disposable {
|
||||
func requestPart(timestampMilliseconds: Int64, durationMilliseconds: Int64, subject: BroadcastPartSubject, completion: @escaping (OngoingGroupCallBroadcastPart) -> Void, rejoinNeeded: @escaping () -> Void) -> Disposable {
|
||||
let timestampIdMilliseconds: Int64
|
||||
if timestampMilliseconds != 0 {
|
||||
timestampIdMilliseconds = timestampMilliseconds
|
||||
@ -71,8 +76,35 @@ private final class NetworkBroadcastPartSource: BroadcastPartSource {
|
||||
|> mapToSignal { [weak self] dataSource -> Signal<GetAudioBroadcastPartResult?, NoError> in
|
||||
if let dataSource = dataSource {
|
||||
self?.dataSource = dataSource
|
||||
return engine.calls.getAudioBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds)
|
||||
|> map(Optional.init)
|
||||
switch subject {
|
||||
case .audio:
|
||||
return engine.calls.getAudioBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds)
|
||||
|> map(Optional.init)
|
||||
case .video:
|
||||
#if DEBUG && false
|
||||
return engine.calls.getAudioBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds)
|
||||
|> map { result -> GetAudioBroadcastPartResult in
|
||||
switch result.status {
|
||||
case .data:
|
||||
guard let path = Bundle.main.path(forResource: "chunk2.ch2.q1", ofType: "mp4"), let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
|
||||
return GetAudioBroadcastPartResult(
|
||||
status: .notReady,
|
||||
responseTimestamp: result.responseTimestamp
|
||||
)
|
||||
}
|
||||
return GetAudioBroadcastPartResult(
|
||||
status: .data(data),
|
||||
responseTimestamp: result.responseTimestamp
|
||||
)
|
||||
default:
|
||||
return result
|
||||
}
|
||||
}
|
||||
#else
|
||||
return engine.calls.getVideoBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds)
|
||||
|> map(Optional.init)
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
|> delay(2.0, queue: queue)
|
||||
@ -403,17 +435,28 @@ public final class OngoingGroupCallContext {
|
||||
|
||||
return OngoingGroupCallMediaChannelDescriptionTaskImpl(disposable: disposable)
|
||||
},
|
||||
requestBroadcastPart: { timestampMilliseconds, durationMilliseconds, completion in
|
||||
requestAudioBroadcastPart: { timestampMilliseconds, durationMilliseconds, completion in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
queue.async {
|
||||
disposable.set(broadcastPartsSource?.requestPart(timestampMilliseconds: timestampMilliseconds, durationMilliseconds: durationMilliseconds, completion: completion, rejoinNeeded: {
|
||||
disposable.set(broadcastPartsSource?.requestPart(timestampMilliseconds: timestampMilliseconds, durationMilliseconds: durationMilliseconds, subject: .audio, completion: completion, rejoinNeeded: {
|
||||
rejoinNeeded()
|
||||
}))
|
||||
}
|
||||
|
||||
return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable)
|
||||
},
|
||||
requestVideoBroadcastPart: { timestampMilliseconds, durationMilliseconds, completion in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
queue.async {
|
||||
disposable.set(broadcastPartsSource?.requestPart(timestampMilliseconds: timestampMilliseconds, durationMilliseconds: durationMilliseconds, subject: .video, completion: completion, rejoinNeeded: {
|
||||
rejoinNeeded()
|
||||
}))
|
||||
}
|
||||
|
||||
return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable)
|
||||
},
|
||||
outgoingAudioBitrateKbit: outgoingAudioBitrateKbit ?? 32,
|
||||
videoContentType: _videoContentType,
|
||||
enableNoiseSuppression: enableNoiseSuppression
|
||||
|
@ -344,7 +344,8 @@ typedef NS_ENUM(int32_t, OngoingGroupCallRequestedVideoQuality) {
|
||||
outputDeviceId:(NSString * _Nonnull)outputDeviceId
|
||||
videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer
|
||||
requestMediaChannelDescriptions:(id<OngoingGroupCallMediaChannelDescriptionTask> _Nonnull (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull, void (^ _Nonnull)(NSArray<OngoingGroupCallMediaChannelDescription *> * _Nonnull)))requestMediaChannelDescriptions
|
||||
requestBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart
|
||||
requestAudioBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestAudioBroadcastPart
|
||||
requestVideoBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestVideoBroadcastPart
|
||||
outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit
|
||||
videoContentType:(OngoingGroupCallVideoContentType)videoContentType
|
||||
enableNoiseSuppression:(bool)enableNoiseSuppression;
|
||||
|
@ -1361,7 +1361,8 @@ private:
|
||||
outputDeviceId:(NSString * _Nonnull)outputDeviceId
|
||||
videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer
|
||||
requestMediaChannelDescriptions:(id<OngoingGroupCallMediaChannelDescriptionTask> _Nonnull (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull, void (^ _Nonnull)(NSArray<OngoingGroupCallMediaChannelDescription *> * _Nonnull)))requestMediaChannelDescriptions
|
||||
requestBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart
|
||||
requestAudioBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestAudioBroadcastPart
|
||||
requestVideoBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestVideoBroadcastPart
|
||||
outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit
|
||||
videoContentType:(OngoingGroupCallVideoContentType)videoContentType
|
||||
enableNoiseSuppression:(bool)enableNoiseSuppression {
|
||||
@ -1433,8 +1434,8 @@ private:
|
||||
.initialInputDeviceId = inputDeviceId.UTF8String,
|
||||
.initialOutputDeviceId = outputDeviceId.UTF8String,
|
||||
.videoCapture = [_videoCapturer getInterface],
|
||||
.requestBroadcastPart = [requestBroadcastPart](int64_t timestampMilliseconds, int64_t durationMilliseconds, std::function<void(tgcalls::BroadcastPart &&)> completion) -> std::shared_ptr<tgcalls::BroadcastPartTask> {
|
||||
id<OngoingGroupCallBroadcastPartTask> task = requestBroadcastPart(timestampMilliseconds, durationMilliseconds, ^(OngoingGroupCallBroadcastPart * _Nullable part) {
|
||||
.requestAudioBroadcastPart = [requestAudioBroadcastPart](int64_t timestampMilliseconds, int64_t durationMilliseconds, std::function<void(tgcalls::BroadcastPart &&)> completion) -> std::shared_ptr<tgcalls::BroadcastPartTask> {
|
||||
id<OngoingGroupCallBroadcastPartTask> task = requestAudioBroadcastPart(timestampMilliseconds, durationMilliseconds, ^(OngoingGroupCallBroadcastPart * _Nullable part) {
|
||||
tgcalls::BroadcastPart parsedPart;
|
||||
parsedPart.timestampMilliseconds = part.timestampMilliseconds;
|
||||
|
||||
@ -1461,13 +1462,48 @@ private:
|
||||
}
|
||||
parsedPart.status = mappedStatus;
|
||||
|
||||
parsedPart.oggData.resize(part.oggData.length);
|
||||
[part.oggData getBytes:parsedPart.oggData.data() length:part.oggData.length];
|
||||
parsedPart.data.resize(part.oggData.length);
|
||||
[part.oggData getBytes:parsedPart.data.data() length:part.oggData.length];
|
||||
|
||||
completion(std::move(parsedPart));
|
||||
});
|
||||
return std::make_shared<BroadcastPartTaskImpl>(task);
|
||||
},
|
||||
.requestVideoBroadcastPart = [requestVideoBroadcastPart](int64_t timestampMilliseconds, int64_t durationMilliseconds, std::function<void(tgcalls::BroadcastPart &&)> completion) -> std::shared_ptr<tgcalls::BroadcastPartTask> {
|
||||
id<OngoingGroupCallBroadcastPartTask> task = requestVideoBroadcastPart(timestampMilliseconds, durationMilliseconds, ^(OngoingGroupCallBroadcastPart * _Nullable part) {
|
||||
tgcalls::BroadcastPart parsedPart;
|
||||
parsedPart.timestampMilliseconds = part.timestampMilliseconds;
|
||||
|
||||
parsedPart.responseTimestamp = part.responseTimestamp;
|
||||
|
||||
tgcalls::BroadcastPart::Status mappedStatus;
|
||||
switch (part.status) {
|
||||
case OngoingGroupCallBroadcastPartStatusSuccess: {
|
||||
mappedStatus = tgcalls::BroadcastPart::Status::Success;
|
||||
break;
|
||||
}
|
||||
case OngoingGroupCallBroadcastPartStatusNotReady: {
|
||||
mappedStatus = tgcalls::BroadcastPart::Status::NotReady;
|
||||
break;
|
||||
}
|
||||
case OngoingGroupCallBroadcastPartStatusResyncNeeded: {
|
||||
mappedStatus = tgcalls::BroadcastPart::Status::ResyncNeeded;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
mappedStatus = tgcalls::BroadcastPart::Status::NotReady;
|
||||
break;
|
||||
}
|
||||
}
|
||||
parsedPart.status = mappedStatus;
|
||||
|
||||
parsedPart.data.resize(part.oggData.length);
|
||||
[part.oggData getBytes:parsedPart.data.data() length:part.oggData.length];
|
||||
|
||||
completion(std::move(parsedPart));
|
||||
});
|
||||
return std::make_shared<BroadcastPartTaskImpl>(task);
|
||||
},
|
||||
.outgoingAudioBitrateKbit = outgoingAudioBitrateKbit,
|
||||
.disableOutgoingAudioProcessing = disableOutgoingAudioProcessing,
|
||||
.videoContentType = _videoContentType,
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 68eadd0cb31ceedcfbf7f810dc86d2ebc7dabf9d
|
||||
Subproject commit 2147fc156116311b21c305c17e296d010e581755
|
Loading…
x
Reference in New Issue
Block a user