mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branches 'master' and 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
22dd971d51
@ -3,7 +3,7 @@
|
|||||||
@implementation Serialization
|
@implementation Serialization
|
||||||
|
|
||||||
- (NSUInteger)currentLayer {
|
- (NSUInteger)currentLayer {
|
||||||
return 125;
|
return 126;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
||||||
|
@ -6297,3 +6297,5 @@ Sorry for the inconvenience.";
|
|||||||
"VoiceChat.ForwardTooltip.Chat" = "Invite link forwarded to **%@**";
|
"VoiceChat.ForwardTooltip.Chat" = "Invite link forwarded to **%@**";
|
||||||
"VoiceChat.ForwardTooltip.TwoChats" = "Invite link forwarded to **%@** and **%@**";
|
"VoiceChat.ForwardTooltip.TwoChats" = "Invite link forwarded to **%@** and **%@**";
|
||||||
"VoiceChat.ForwardTooltip.ManyChats" = "Invite link forwarded to **%@** and %@ others";
|
"VoiceChat.ForwardTooltip.ManyChats" = "Invite link forwarded to **%@** and %@ others";
|
||||||
|
|
||||||
|
"GroupRemoved.ViewChannelInfo" = "View Channel";
|
||||||
|
@ -1023,6 +1023,8 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
|||||||
} else {
|
} else {
|
||||||
updateFlags = []
|
updateFlags = []
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
updateFlags = adminInfo?.rights.rights
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentRank = rank
|
currentRank = rank
|
||||||
|
@ -389,8 +389,16 @@ private func channelAdminsControllerEntries(presentationData: PresentationData,
|
|||||||
if id == accountPeerId {
|
if id == accountPeerId {
|
||||||
canEdit = false
|
canEdit = false
|
||||||
} else if let adminInfo = adminInfo {
|
} else if let adminInfo = adminInfo {
|
||||||
if peer.flags.contains(.isCreator) || adminInfo.promotedBy == accountPeerId {
|
if peer.flags.contains(.isCreator) {
|
||||||
canEdit = true
|
canEdit = true
|
||||||
|
canOpen = true
|
||||||
|
} else if adminInfo.promotedBy == accountPeerId {
|
||||||
|
canEdit = true
|
||||||
|
if let adminRights = peer.adminRights {
|
||||||
|
if adminRights.rights.isEmpty {
|
||||||
|
canOpen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
canEdit = false
|
canEdit = false
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,8 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
|
|||||||
let updateState: ((ChannelBlacklistControllerState) -> ChannelBlacklistControllerState) -> Void = { f in
|
let updateState: ((ChannelBlacklistControllerState) -> ChannelBlacklistControllerState) -> Void = { f in
|
||||||
statePromise.set(stateValue.modify { f($0) })
|
statePromise.set(stateValue.modify { f($0) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var getNavigationControllerImpl: (() -> NavigationController?)?
|
||||||
var presentControllerImpl: ((ViewController, Any?) -> Void)?
|
var presentControllerImpl: ((ViewController, Any?) -> Void)?
|
||||||
var pushControllerImpl: ((ViewController) -> Void)?
|
var pushControllerImpl: ((ViewController) -> Void)?
|
||||||
var dismissInputImpl: (() -> Void)?
|
var dismissInputImpl: (() -> Void)?
|
||||||
@ -364,9 +365,19 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
|
|||||||
if !participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder).isEmpty {
|
if !participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder).isEmpty {
|
||||||
items.append(ActionSheetTextItem(title: participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)))
|
items.append(ActionSheetTextItem(title: participant.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)))
|
||||||
}
|
}
|
||||||
items.append(ActionSheetButtonItem(title: presentationData.strings.GroupRemoved_ViewUserInfo, action: { [weak actionSheet] in
|
let viewInfoTitle: String
|
||||||
|
if participant.peer is TelegramChannel {
|
||||||
|
viewInfoTitle = presentationData.strings.GroupRemoved_ViewChannelInfo
|
||||||
|
} else {
|
||||||
|
viewInfoTitle = presentationData.strings.GroupRemoved_ViewUserInfo
|
||||||
|
}
|
||||||
|
items.append(ActionSheetButtonItem(title: viewInfoTitle, action: { [weak actionSheet] in
|
||||||
actionSheet?.dismissAnimated()
|
actionSheet?.dismissAnimated()
|
||||||
if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: participant.peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if participant.peer is TelegramChannel {
|
||||||
|
if let navigationController = getNavigationControllerImpl?() {
|
||||||
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(participant.peer.id)))
|
||||||
|
}
|
||||||
|
} else if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: participant.peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushControllerImpl?(infoController)
|
pushControllerImpl?(infoController)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@ -520,6 +531,9 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
|
|||||||
(controller.navigationController as? NavigationController)?.pushViewController(c)
|
(controller.navigationController as? NavigationController)?.pushViewController(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
getNavigationControllerImpl = { [weak controller] in
|
||||||
|
return controller?.navigationController as? NavigationController
|
||||||
|
}
|
||||||
dismissInputImpl = { [weak controller] in
|
dismissInputImpl = { [weak controller] in
|
||||||
controller?.view.endEditing(true)
|
controller?.view.endEditing(true)
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-347535331] = { return Api.RecentMeUrl.parse_recentMeUrlChatInvite($0) }
|
dict[-347535331] = { return Api.RecentMeUrl.parse_recentMeUrlChatInvite($0) }
|
||||||
dict[-1140172836] = { return Api.RecentMeUrl.parse_recentMeUrlStickerSet($0) }
|
dict[-1140172836] = { return Api.RecentMeUrl.parse_recentMeUrlStickerSet($0) }
|
||||||
dict[-797791052] = { return Api.RestrictionReason.parse_restrictionReason($0) }
|
dict[-797791052] = { return Api.RestrictionReason.parse_restrictionReason($0) }
|
||||||
dict[-177282392] = { return Api.channels.ChannelParticipants.parse_channelParticipants($0) }
|
dict[-1699676497] = { return Api.channels.ChannelParticipants.parse_channelParticipants($0) }
|
||||||
dict[-266911767] = { return Api.channels.ChannelParticipants.parse_channelParticipantsNotModified($0) }
|
dict[-266911767] = { return Api.channels.ChannelParticipants.parse_channelParticipantsNotModified($0) }
|
||||||
dict[-599948721] = { return Api.RichText.parse_textEmpty($0) }
|
dict[-599948721] = { return Api.RichText.parse_textEmpty($0) }
|
||||||
dict[1950782688] = { return Api.RichText.parse_textPlain($0) }
|
dict[1950782688] = { return Api.RichText.parse_textPlain($0) }
|
||||||
@ -122,7 +122,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[84438264] = { return Api.WallPaperSettings.parse_wallPaperSettings($0) }
|
dict[84438264] = { return Api.WallPaperSettings.parse_wallPaperSettings($0) }
|
||||||
dict[-1519029347] = { return Api.EmojiURL.parse_emojiURL($0) }
|
dict[-1519029347] = { return Api.EmojiURL.parse_emojiURL($0) }
|
||||||
dict[1611985938] = { return Api.StatsGroupTopAdmin.parse_statsGroupTopAdmin($0) }
|
dict[1611985938] = { return Api.StatsGroupTopAdmin.parse_statsGroupTopAdmin($0) }
|
||||||
dict[-791039645] = { return Api.channels.ChannelParticipant.parse_channelParticipant($0) }
|
dict[-541588713] = { return Api.channels.ChannelParticipant.parse_channelParticipant($0) }
|
||||||
dict[-1736378792] = { return Api.InputCheckPasswordSRP.parse_inputCheckPasswordEmpty($0) }
|
dict[-1736378792] = { return Api.InputCheckPasswordSRP.parse_inputCheckPasswordEmpty($0) }
|
||||||
dict[-763367294] = { return Api.InputCheckPasswordSRP.parse_inputCheckPasswordSRP($0) }
|
dict[-763367294] = { return Api.InputCheckPasswordSRP.parse_inputCheckPasswordSRP($0) }
|
||||||
dict[-1432995067] = { return Api.storage.FileType.parse_fileUnknown($0) }
|
dict[-1432995067] = { return Api.storage.FileType.parse_fileUnknown($0) }
|
||||||
@ -287,7 +287,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1557620115] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) }
|
dict[-1557620115] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) }
|
||||||
dict[1149094475] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
|
dict[1149094475] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
|
||||||
dict[-859915345] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
dict[-859915345] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
||||||
dict[470789295] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
|
dict[1352785878] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
|
||||||
dict[-1010402965] = { return Api.ChannelParticipant.parse_channelParticipantLeft($0) }
|
dict[-1010402965] = { return Api.ChannelParticipant.parse_channelParticipantLeft($0) }
|
||||||
dict[-1567730343] = { return Api.MessageUserVote.parse_messageUserVote($0) }
|
dict[-1567730343] = { return Api.MessageUserVote.parse_messageUserVote($0) }
|
||||||
dict[909603888] = { return Api.MessageUserVote.parse_messageUserVoteInputOption($0) }
|
dict[909603888] = { return Api.MessageUserVote.parse_messageUserVoteInputOption($0) }
|
||||||
@ -471,6 +471,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1036572727] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) }
|
dict[-1036572727] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) }
|
||||||
dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) }
|
dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) }
|
||||||
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
|
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
|
||||||
|
dict[423690591] = { return Api.ChatBannedRights.parse_chatBannedRightsChannel($0) }
|
||||||
dict[1968737087] = { return Api.InputClientProxy.parse_inputClientProxy($0) }
|
dict[1968737087] = { return Api.InputClientProxy.parse_inputClientProxy($0) }
|
||||||
dict[649453030] = { return Api.messages.MessageEditData.parse_messageEditData($0) }
|
dict[649453030] = { return Api.messages.MessageEditData.parse_messageEditData($0) }
|
||||||
dict[-886477832] = { return Api.LabeledPrice.parse_labeledPrice($0) }
|
dict[-886477832] = { return Api.LabeledPrice.parse_labeledPrice($0) }
|
||||||
|
@ -7362,7 +7362,7 @@ public extension Api {
|
|||||||
case channelParticipantSelf(userId: Int32, inviterId: Int32, date: Int32)
|
case channelParticipantSelf(userId: Int32, inviterId: Int32, date: Int32)
|
||||||
case channelParticipantCreator(flags: Int32, userId: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
case channelParticipantCreator(flags: Int32, userId: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
||||||
case channelParticipantAdmin(flags: Int32, userId: Int32, inviterId: Int32?, promotedBy: Int32, date: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
case channelParticipantAdmin(flags: Int32, userId: Int32, inviterId: Int32?, promotedBy: Int32, date: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
||||||
case channelParticipantBanned(flags: Int32, userId: Int32, kickedBy: Int32, date: Int32, bannedRights: Api.ChatBannedRights)
|
case channelParticipantBanned(flags: Int32, peer: Api.Peer, kickedBy: Int32, date: Int32, bannedRights: Api.ChatBannedRights)
|
||||||
case channelParticipantLeft(userId: Int32)
|
case channelParticipantLeft(userId: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
@ -7403,12 +7403,12 @@ public extension Api {
|
|||||||
adminRights.serialize(buffer, true)
|
adminRights.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(rank!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 2) != 0 {serializeString(rank!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .channelParticipantBanned(let flags, let userId, let kickedBy, let date, let bannedRights):
|
case .channelParticipantBanned(let flags, let peer, let kickedBy, let date, let bannedRights):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(470789295)
|
buffer.appendInt32(1352785878)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
peer.serialize(buffer, true)
|
||||||
serializeInt32(kickedBy, buffer: buffer, boxed: false)
|
serializeInt32(kickedBy, buffer: buffer, boxed: false)
|
||||||
serializeInt32(date, buffer: buffer, boxed: false)
|
serializeInt32(date, buffer: buffer, boxed: false)
|
||||||
bannedRights.serialize(buffer, true)
|
bannedRights.serialize(buffer, true)
|
||||||
@ -7432,8 +7432,8 @@ public extension Api {
|
|||||||
return ("channelParticipantCreator", [("flags", flags), ("userId", userId), ("adminRights", adminRights), ("rank", rank)])
|
return ("channelParticipantCreator", [("flags", flags), ("userId", userId), ("adminRights", adminRights), ("rank", rank)])
|
||||||
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights, let rank):
|
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights, let rank):
|
||||||
return ("channelParticipantAdmin", [("flags", flags), ("userId", userId), ("inviterId", inviterId), ("promotedBy", promotedBy), ("date", date), ("adminRights", adminRights), ("rank", rank)])
|
return ("channelParticipantAdmin", [("flags", flags), ("userId", userId), ("inviterId", inviterId), ("promotedBy", promotedBy), ("date", date), ("adminRights", adminRights), ("rank", rank)])
|
||||||
case .channelParticipantBanned(let flags, let userId, let kickedBy, let date, let bannedRights):
|
case .channelParticipantBanned(let flags, let peer, let kickedBy, let date, let bannedRights):
|
||||||
return ("channelParticipantBanned", [("flags", flags), ("userId", userId), ("kickedBy", kickedBy), ("date", date), ("bannedRights", bannedRights)])
|
return ("channelParticipantBanned", [("flags", flags), ("peer", peer), ("kickedBy", kickedBy), ("date", date), ("bannedRights", bannedRights)])
|
||||||
case .channelParticipantLeft(let userId):
|
case .channelParticipantLeft(let userId):
|
||||||
return ("channelParticipantLeft", [("userId", userId)])
|
return ("channelParticipantLeft", [("userId", userId)])
|
||||||
}
|
}
|
||||||
@ -7526,8 +7526,10 @@ public extension Api {
|
|||||||
public static func parse_channelParticipantBanned(_ reader: BufferReader) -> ChannelParticipant? {
|
public static func parse_channelParticipantBanned(_ reader: BufferReader) -> ChannelParticipant? {
|
||||||
var _1: Int32?
|
var _1: Int32?
|
||||||
_1 = reader.readInt32()
|
_1 = reader.readInt32()
|
||||||
var _2: Int32?
|
var _2: Api.Peer?
|
||||||
_2 = reader.readInt32()
|
if let signature = reader.readInt32() {
|
||||||
|
_2 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
|
}
|
||||||
var _3: Int32?
|
var _3: Int32?
|
||||||
_3 = reader.readInt32()
|
_3 = reader.readInt32()
|
||||||
var _4: Int32?
|
var _4: Int32?
|
||||||
@ -7542,7 +7544,7 @@ public extension Api {
|
|||||||
let _c4 = _4 != nil
|
let _c4 = _4 != nil
|
||||||
let _c5 = _5 != nil
|
let _c5 = _5 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||||
return Api.ChannelParticipant.channelParticipantBanned(flags: _1!, userId: _2!, kickedBy: _3!, date: _4!, bannedRights: _5!)
|
return Api.ChannelParticipant.channelParticipantBanned(flags: _1!, peer: _2!, kickedBy: _3!, date: _4!, bannedRights: _5!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
@ -12067,6 +12069,7 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public enum ChatBannedRights: TypeConstructorDescription {
|
public enum ChatBannedRights: TypeConstructorDescription {
|
||||||
case chatBannedRights(flags: Int32, untilDate: Int32)
|
case chatBannedRights(flags: Int32, untilDate: Int32)
|
||||||
|
case chatBannedRightsChannel(flags: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -12077,6 +12080,12 @@ public extension Api {
|
|||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt32(untilDate, buffer: buffer, boxed: false)
|
serializeInt32(untilDate, buffer: buffer, boxed: false)
|
||||||
break
|
break
|
||||||
|
case .chatBannedRightsChannel(let flags):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(423690591)
|
||||||
|
}
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12084,6 +12093,8 @@ public extension Api {
|
|||||||
switch self {
|
switch self {
|
||||||
case .chatBannedRights(let flags, let untilDate):
|
case .chatBannedRights(let flags, let untilDate):
|
||||||
return ("chatBannedRights", [("flags", flags), ("untilDate", untilDate)])
|
return ("chatBannedRights", [("flags", flags), ("untilDate", untilDate)])
|
||||||
|
case .chatBannedRightsChannel(let flags):
|
||||||
|
return ("chatBannedRightsChannel", [("flags", flags)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12101,6 +12112,17 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_chatBannedRightsChannel(_ reader: BufferReader) -> ChatBannedRights? {
|
||||||
|
var _1: Int32?
|
||||||
|
_1 = reader.readInt32()
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.ChatBannedRights.chatBannedRightsChannel(flags: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public enum InputClientProxy: TypeConstructorDescription {
|
public enum InputClientProxy: TypeConstructorDescription {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
public extension Api {
|
public extension Api {
|
||||||
public struct channels {
|
public struct channels {
|
||||||
public enum ChannelParticipants: TypeConstructorDescription {
|
public enum ChannelParticipants: TypeConstructorDescription {
|
||||||
case channelParticipants(count: Int32, participants: [Api.ChannelParticipant], users: [Api.User])
|
case channelParticipants(count: Int32, participants: [Api.ChannelParticipant], chats: [Api.Chat], users: [Api.User])
|
||||||
case channelParticipantsNotModified
|
case channelParticipantsNotModified
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .channelParticipants(let count, let participants, let users):
|
case .channelParticipants(let count, let participants, let chats, let users):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-177282392)
|
buffer.appendInt32(-1699676497)
|
||||||
}
|
}
|
||||||
serializeInt32(count, buffer: buffer, boxed: false)
|
serializeInt32(count, buffer: buffer, boxed: false)
|
||||||
buffer.appendInt32(481674261)
|
buffer.appendInt32(481674261)
|
||||||
@ -17,6 +17,11 @@ public struct channels {
|
|||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
}
|
}
|
||||||
buffer.appendInt32(481674261)
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(chats.count))
|
||||||
|
for item in chats {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
buffer.appendInt32(Int32(users.count))
|
buffer.appendInt32(Int32(users.count))
|
||||||
for item in users {
|
for item in users {
|
||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
@ -33,8 +38,8 @@ public struct channels {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .channelParticipants(let count, let participants, let users):
|
case .channelParticipants(let count, let participants, let chats, let users):
|
||||||
return ("channelParticipants", [("count", count), ("participants", participants), ("users", users)])
|
return ("channelParticipants", [("count", count), ("participants", participants), ("chats", chats), ("users", users)])
|
||||||
case .channelParticipantsNotModified:
|
case .channelParticipantsNotModified:
|
||||||
return ("channelParticipantsNotModified", [])
|
return ("channelParticipantsNotModified", [])
|
||||||
}
|
}
|
||||||
@ -47,15 +52,20 @@ public struct channels {
|
|||||||
if let _ = reader.readInt32() {
|
if let _ = reader.readInt32() {
|
||||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelParticipant.self)
|
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelParticipant.self)
|
||||||
}
|
}
|
||||||
var _3: [Api.User]?
|
var _3: [Api.Chat]?
|
||||||
if let _ = reader.readInt32() {
|
if let _ = reader.readInt32() {
|
||||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||||
|
}
|
||||||
|
var _4: [Api.User]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||||
}
|
}
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = _3 != nil
|
let _c3 = _3 != nil
|
||||||
if _c1 && _c2 && _c3 {
|
let _c4 = _4 != nil
|
||||||
return Api.channels.ChannelParticipants.channelParticipants(count: _1!, participants: _2!, users: _3!)
|
if _c1 && _c2 && _c3 && _c4 {
|
||||||
|
return Api.channels.ChannelParticipants.channelParticipants(count: _1!, participants: _2!, chats: _3!, users: _4!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
@ -67,16 +77,21 @@ public struct channels {
|
|||||||
|
|
||||||
}
|
}
|
||||||
public enum ChannelParticipant: TypeConstructorDescription {
|
public enum ChannelParticipant: TypeConstructorDescription {
|
||||||
case channelParticipant(participant: Api.ChannelParticipant, users: [Api.User])
|
case channelParticipant(participant: Api.ChannelParticipant, chats: [Api.Chat], users: [Api.User])
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .channelParticipant(let participant, let users):
|
case .channelParticipant(let participant, let chats, let users):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-791039645)
|
buffer.appendInt32(-541588713)
|
||||||
}
|
}
|
||||||
participant.serialize(buffer, true)
|
participant.serialize(buffer, true)
|
||||||
buffer.appendInt32(481674261)
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(chats.count))
|
||||||
|
for item in chats {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
buffer.appendInt32(Int32(users.count))
|
buffer.appendInt32(Int32(users.count))
|
||||||
for item in users {
|
for item in users {
|
||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
@ -87,8 +102,8 @@ public struct channels {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .channelParticipant(let participant, let users):
|
case .channelParticipant(let participant, let chats, let users):
|
||||||
return ("channelParticipant", [("participant", participant), ("users", users)])
|
return ("channelParticipant", [("participant", participant), ("chats", chats), ("users", users)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,14 +112,19 @@ public struct channels {
|
|||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
_1 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant
|
_1 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant
|
||||||
}
|
}
|
||||||
var _2: [Api.User]?
|
var _2: [Api.Chat]?
|
||||||
if let _ = reader.readInt32() {
|
if let _ = reader.readInt32() {
|
||||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||||
|
}
|
||||||
|
var _3: [Api.User]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||||
}
|
}
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
if _c1 && _c2 {
|
let _c3 = _3 != nil
|
||||||
return Api.channels.ChannelParticipant.channelParticipant(participant: _1!, users: _2!)
|
if _c1 && _c2 && _c3 {
|
||||||
|
return Api.channels.ChannelParticipant.channelParticipant(participant: _1!, chats: _2!, users: _3!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -4376,12 +4376,12 @@ public extension Api {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func getParticipant(channel: Api.InputChannel, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.channels.ChannelParticipant>) {
|
public static func getParticipant(channel: Api.InputChannel, participant: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.channels.ChannelParticipant>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(1416484774)
|
buffer.appendInt32(-1599378234)
|
||||||
channel.serialize(buffer, true)
|
channel.serialize(buffer, true)
|
||||||
userId.serialize(buffer, true)
|
participant.serialize(buffer, true)
|
||||||
return (FunctionDescription(name: "channels.getParticipant", parameters: [("channel", channel), ("userId", userId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.ChannelParticipant? in
|
return (FunctionDescription(name: "channels.getParticipant", parameters: [("channel", channel), ("participant", participant)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.ChannelParticipant? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.channels.ChannelParticipant?
|
var result: Api.channels.ChannelParticipant?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
@ -4624,13 +4624,13 @@ public extension Api {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func editBanned(channel: Api.InputChannel, userId: Api.InputUser, bannedRights: Api.ChatBannedRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
public static func editBanned(channel: Api.InputChannel, participant: Api.InputPeer, bannedRights: Api.ChatBannedRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(1920559378)
|
buffer.appendInt32(-1763259007)
|
||||||
channel.serialize(buffer, true)
|
channel.serialize(buffer, true)
|
||||||
userId.serialize(buffer, true)
|
participant.serialize(buffer, true)
|
||||||
bannedRights.serialize(buffer, true)
|
bannedRights.serialize(buffer, true)
|
||||||
return (FunctionDescription(name: "channels.editBanned", parameters: [("channel", channel), ("userId", userId), ("bannedRights", bannedRights)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
return (FunctionDescription(name: "channels.editBanned", parameters: [("channel", channel), ("participant", participant), ("bannedRights", bannedRights)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
@ -3,6 +3,17 @@ import SwiftSignalKit
|
|||||||
import AVFoundation
|
import AVFoundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
private var managedAudioSessionLogger: (String) -> Void = { _ in }
|
||||||
|
|
||||||
|
public func setManagedAudioSessionLogger(_ f: @escaping (String) -> Void) {
|
||||||
|
managedAudioSessionLogger = f
|
||||||
|
}
|
||||||
|
|
||||||
|
func managedAudioSessionLog(_ what: @autoclosure () -> String) {
|
||||||
|
managedAudioSessionLogger(what())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum ManagedAudioSessionType: Equatable {
|
public enum ManagedAudioSessionType: Equatable {
|
||||||
case ambient
|
case ambient
|
||||||
case play
|
case play
|
||||||
@ -208,11 +219,15 @@ public final class ManagedAudioSession {
|
|||||||
})
|
})
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(forName: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance(), queue: nil, using: { [weak self] notification in
|
NotificationCenter.default.addObserver(forName: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance(), queue: nil, using: { [weak self] notification in
|
||||||
|
managedAudioSessionLog("Interruption received")
|
||||||
|
|
||||||
guard let info = notification.userInfo,
|
guard let info = notification.userInfo,
|
||||||
let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
|
let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
|
||||||
let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
|
let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
managedAudioSessionLog("Interruption type: \(type)")
|
||||||
|
|
||||||
queue.async {
|
queue.async {
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -222,6 +237,17 @@ public final class ManagedAudioSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(forName: AVAudioSession.mediaServicesWereLostNotification, object: AVAudioSession.sharedInstance(), queue: nil, using: { [weak self] _ in
|
||||||
|
managedAudioSessionLog("Media Services were lost")
|
||||||
|
queue.after(1.0, {
|
||||||
|
if let strongSelf = self {
|
||||||
|
if let (type, outputMode) = strongSelf.currentTypeAndOutputMode {
|
||||||
|
strongSelf.setup(type: type, outputMode: outputMode, activateNow: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
queue.async {
|
queue.async {
|
||||||
self.isHeadsetPluggedInValue = self.isHeadsetPluggedIn()
|
self.isHeadsetPluggedInValue = self.isHeadsetPluggedIn()
|
||||||
@ -524,7 +550,7 @@ public final class ManagedAudioSession {
|
|||||||
private func updateHolders(interruption: Bool = false) {
|
private func updateHolders(interruption: Bool = false) {
|
||||||
assert(self.queue.isCurrent())
|
assert(self.queue.isCurrent())
|
||||||
|
|
||||||
print("holder count \(self.holders.count)")
|
managedAudioSessionLog("holder count \(self.holders.count)")
|
||||||
|
|
||||||
if !self.holders.isEmpty {
|
if !self.holders.isEmpty {
|
||||||
var activeIndex: Int?
|
var activeIndex: Int?
|
||||||
@ -625,7 +651,7 @@ public final class ManagedAudioSession {
|
|||||||
assert(self.queue.isCurrent())
|
assert(self.queue.isCurrent())
|
||||||
|
|
||||||
let route = AVAudioSession.sharedInstance().currentRoute
|
let route = AVAudioSession.sharedInstance().currentRoute
|
||||||
//print("\(route)")
|
//managedAudioSessionLog("\(route)")
|
||||||
for desc in route.outputs {
|
for desc in route.outputs {
|
||||||
if desc.portType == .headphones || desc.portType == .bluetoothA2DP || desc.portType == .bluetoothHFP {
|
if desc.portType == .headphones || desc.portType == .bluetoothA2DP || desc.portType == .bluetoothHFP {
|
||||||
return true
|
return true
|
||||||
@ -643,13 +669,13 @@ public final class ManagedAudioSession {
|
|||||||
let wasPlaybackActive = self.currentTypeAndOutputMode?.0.isPlay ?? false
|
let wasPlaybackActive = self.currentTypeAndOutputMode?.0.isPlay ?? false
|
||||||
self.currentTypeAndOutputMode = nil
|
self.currentTypeAndOutputMode = nil
|
||||||
|
|
||||||
print("ManagedAudioSession setting active false")
|
managedAudioSessionLog("ManagedAudioSession setting active false")
|
||||||
do {
|
do {
|
||||||
try AVAudioSession.sharedInstance().setActive(false, options: [.notifyOthersOnDeactivation])
|
try AVAudioSession.sharedInstance().setActive(false, options: [.notifyOthersOnDeactivation])
|
||||||
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
|
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
|
||||||
try AVAudioSession.sharedInstance().setPreferredInput(nil)
|
try AVAudioSession.sharedInstance().setPreferredInput(nil)
|
||||||
} catch let error {
|
} catch let error {
|
||||||
print("ManagedAudioSession applyNone error \(error), waiting")
|
managedAudioSessionLog("ManagedAudioSession applyNone error \(error), waiting")
|
||||||
|
|
||||||
Thread.sleep(forTimeInterval: 2.0)
|
Thread.sleep(forTimeInterval: 2.0)
|
||||||
|
|
||||||
@ -658,7 +684,7 @@ public final class ManagedAudioSession {
|
|||||||
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
|
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
|
||||||
try AVAudioSession.sharedInstance().setPreferredInput(nil)
|
try AVAudioSession.sharedInstance().setPreferredInput(nil)
|
||||||
} catch let error {
|
} catch let error {
|
||||||
print("ManagedAudioSession applyNone repeated error \(error), giving up")
|
managedAudioSessionLog("ManagedAudioSession applyNone repeated error \(error), giving up")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,7 +713,7 @@ public final class ManagedAudioSession {
|
|||||||
do {
|
do {
|
||||||
let nativeCategory = nativeCategoryForType(type, headphones: self.isHeadsetPluggedInValue, outputMode: outputMode)
|
let nativeCategory = nativeCategoryForType(type, headphones: self.isHeadsetPluggedInValue, outputMode: outputMode)
|
||||||
|
|
||||||
print("ManagedAudioSession setting category for \(type) (native: \(nativeCategory)) activateNow: \(activateNow)")
|
managedAudioSessionLog("ManagedAudioSession setting category for \(type) (native: \(nativeCategory)) activateNow: \(activateNow)")
|
||||||
var options: AVAudioSession.CategoryOptions = []
|
var options: AVAudioSession.CategoryOptions = []
|
||||||
switch type {
|
switch type {
|
||||||
case .play, .ambient:
|
case .play, .ambient:
|
||||||
@ -703,7 +729,7 @@ public final class ManagedAudioSession {
|
|||||||
case .record, .voiceCall, .videoCall:
|
case .record, .voiceCall, .videoCall:
|
||||||
options.insert(.allowBluetooth)
|
options.insert(.allowBluetooth)
|
||||||
}
|
}
|
||||||
print("ManagedAudioSession setting active true")
|
managedAudioSessionLog("ManagedAudioSession setting active true")
|
||||||
let mode: AVAudioSession.Mode
|
let mode: AVAudioSession.Mode
|
||||||
switch type {
|
switch type {
|
||||||
case .voiceCall:
|
case .voiceCall:
|
||||||
@ -720,7 +746,7 @@ public final class ManagedAudioSession {
|
|||||||
try AVAudioSession.sharedInstance().setMode(mode)
|
try AVAudioSession.sharedInstance().setMode(mode)
|
||||||
}
|
}
|
||||||
} catch let error {
|
} catch let error {
|
||||||
print("ManagedAudioSession setup error \(error)")
|
managedAudioSessionLog("ManagedAudioSession setup error \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,7 +767,7 @@ public final class ManagedAudioSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func setupOutputMode(_ outputMode: AudioSessionOutputMode, type: ManagedAudioSessionType) throws {
|
private func setupOutputMode(_ outputMode: AudioSessionOutputMode, type: ManagedAudioSessionType) throws {
|
||||||
print("ManagedAudioSession setup \(outputMode) for \(type)")
|
managedAudioSessionLog("ManagedAudioSession setup \(outputMode) for \(type)")
|
||||||
var resetToBuiltin = false
|
var resetToBuiltin = false
|
||||||
switch outputMode {
|
switch outputMode {
|
||||||
case .system:
|
case .system:
|
||||||
@ -831,21 +857,21 @@ public final class ManagedAudioSession {
|
|||||||
|
|
||||||
try AVAudioSession.sharedInstance().setActive(true, options: [.notifyOthersOnDeactivation])
|
try AVAudioSession.sharedInstance().setActive(true, options: [.notifyOthersOnDeactivation])
|
||||||
|
|
||||||
print("\(CFAbsoluteTimeGetCurrent()) AudioSession activate: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
managedAudioSessionLog("\(CFAbsoluteTimeGetCurrent()) AudioSession activate: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
||||||
|
|
||||||
try self.setupOutputMode(outputMode, type: type)
|
try self.setupOutputMode(outputMode, type: type)
|
||||||
|
|
||||||
print("\(CFAbsoluteTimeGetCurrent()) AudioSession setupOutputMode: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
managedAudioSessionLog("\(CFAbsoluteTimeGetCurrent()) AudioSession setupOutputMode: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
||||||
|
|
||||||
self.updateCurrentAudioRouteInfo()
|
self.updateCurrentAudioRouteInfo()
|
||||||
|
|
||||||
print("\(CFAbsoluteTimeGetCurrent()) AudioSession updateCurrentAudioRouteInfo: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
managedAudioSessionLog("\(CFAbsoluteTimeGetCurrent()) AudioSession updateCurrentAudioRouteInfo: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
||||||
|
|
||||||
if case .voiceCall = type {
|
if case .voiceCall = type {
|
||||||
try AVAudioSession.sharedInstance().setPreferredIOBufferDuration(0.005)
|
try AVAudioSession.sharedInstance().setPreferredIOBufferDuration(0.005)
|
||||||
}
|
}
|
||||||
} catch let error {
|
} catch let error {
|
||||||
print("ManagedAudioSession activate error \(error)")
|
managedAudioSessionLog("ManagedAudioSession activate error \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -858,7 +884,7 @@ public final class ManagedAudioSession {
|
|||||||
|
|
||||||
public func callKitActivatedAudioSession() {
|
public func callKitActivatedAudioSession() {
|
||||||
/*self.queue.async {
|
/*self.queue.async {
|
||||||
print("ManagedAudioSession callKitDeactivatedAudioSession")
|
managedAudioSessionLog("ManagedAudioSession callKitDeactivatedAudioSession")
|
||||||
self.callKitAudioSessionIsActive = true
|
self.callKitAudioSessionIsActive = true
|
||||||
self.updateHolders()
|
self.updateHolders()
|
||||||
}*/
|
}*/
|
||||||
@ -866,7 +892,7 @@ public final class ManagedAudioSession {
|
|||||||
|
|
||||||
public func callKitDeactivatedAudioSession() {
|
public func callKitDeactivatedAudioSession() {
|
||||||
/*self.queue.async {
|
/*self.queue.async {
|
||||||
print("ManagedAudioSession callKitDeactivatedAudioSession")
|
managedAudioSessionLog("ManagedAudioSession callKitDeactivatedAudioSession")
|
||||||
self.callKitAudioSessionIsActive = false
|
self.callKitAudioSessionIsActive = false
|
||||||
self.updateHolders()
|
self.updateHolders()
|
||||||
}*/
|
}*/
|
||||||
|
@ -1174,6 +1174,19 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
strongSelf.accountContext.sharedContext.mainWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.VoiceChat_ChatFullAlertText, actions: [
|
strongSelf.accountContext.sharedContext.mainWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.VoiceChat_ChatFullAlertText, actions: [
|
||||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
|
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
|
||||||
]), on: .root, blockInteraction: false, completion: {})
|
]), on: .root, blockInteraction: false, completion: {})
|
||||||
|
} else if case .invalidJoinAsPeer = error {
|
||||||
|
let peerId = strongSelf.peerId
|
||||||
|
let _ = (strongSelf.accountContext.account.postbox.transaction { transaction -> Void in
|
||||||
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||||
|
if let current = current as? CachedChannelData {
|
||||||
|
return current.withUpdatedCallJoinPeerId(nil)
|
||||||
|
} else if let current = current as? CachedGroupData {
|
||||||
|
return current.withUpdatedCallJoinPeerId(nil)
|
||||||
|
} else {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).start()
|
||||||
}
|
}
|
||||||
strongSelf.markAsCanBeRemoved()
|
strongSelf.markAsCanBeRemoved()
|
||||||
}))
|
}))
|
||||||
@ -1364,7 +1377,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
var initialState = initialState
|
var initialState = initialState
|
||||||
var serviceState: GroupCallParticipantsContext.ServiceState?
|
var serviceState: GroupCallParticipantsContext.ServiceState?
|
||||||
if let participantsContext = self.participantsContext, let immediateState = participantsContext.immediateState {
|
if let participantsContext = self.participantsContext, let immediateState = participantsContext.immediateState {
|
||||||
initialState.mergeActivity(from: immediateState, myPeerId: myPeerId, previousMyPeerId: self.ignorePreviousJoinAsPeerId?.0)
|
initialState.mergeActivity(from: immediateState, myPeerId: myPeerId, previousMyPeerId: self.ignorePreviousJoinAsPeerId?.0, mergeActivityTimestamps: true)
|
||||||
serviceState = participantsContext.serviceState
|
serviceState = participantsContext.serviceState
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1678,16 +1691,23 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
strongSelf.isRequestingMissingSsrcs = false
|
strongSelf.isRequestingMissingSsrcs = false
|
||||||
strongSelf.missingSsrcs.subtract(requestedSsrcs)
|
strongSelf.missingSsrcs.subtract(requestedSsrcs)
|
||||||
|
|
||||||
var addedParticipants: [(UInt32, String?)] = []
|
var addedParticipants: [(UInt32, Int32?, String?)] = []
|
||||||
|
|
||||||
for participant in state.participants {
|
for participant in state.participants {
|
||||||
if let ssrc = participant.ssrc {
|
if let ssrc = participant.ssrc {
|
||||||
addedParticipants.append((ssrc, participant.jsonParams))
|
addedParticipants.append((ssrc, participant.volume, participant.jsonParams))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !addedParticipants.isEmpty {
|
if !addedParticipants.isEmpty {
|
||||||
strongSelf.callContext?.addParticipants(participants: addedParticipants)
|
for (ssrc, volume, _) in addedParticipants {
|
||||||
|
if let volume = volume {
|
||||||
|
strongSelf.callContext?.setVolume(ssrc: ssrc, volume: Double(volume) / 10000.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strongSelf.callContext?.addParticipants(participants: addedParticipants.map { ssrc, _, params in
|
||||||
|
return (ssrc, params)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.maybeRequestMissingSsrcs()
|
strongSelf.maybeRequestMissingSsrcs()
|
||||||
|
@ -1285,7 +1285,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
f(.dismissWithoutContent)
|
f(.dismissWithoutContent)
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if let callState = strongSelf.callState, (callState.canManageCall && !callState.adminIds.contains(peer.id) && peer.id.namespace != Namespaces.Peer.CloudChannel) {
|
if let callState = strongSelf.callState, (callState.canManageCall && !callState.adminIds.contains(peer.id)) {
|
||||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_RemovePeer, textColor: .destructive, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_RemovePeer, textColor: .destructive, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.destructiveActionTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.destructiveActionTextColor)
|
||||||
}, action: { [weak self] c, _ in
|
}, action: { [weak self] c, _ in
|
||||||
@ -3187,7 +3187,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
if allEqual {
|
if allEqual {
|
||||||
disableAnimation = true
|
disableAnimation = true
|
||||||
}
|
}
|
||||||
} else if abs(previousEntries.count - entries.count) > 2 {
|
} else if abs(previousEntries.count - entries.count) > 10 {
|
||||||
disableAnimation = true
|
disableAnimation = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ extension ChannelParticipant {
|
|||||||
case let .channelParticipantBanned(flags, userId, restrictedBy, date, bannedRights):
|
case let .channelParticipantBanned(flags, userId, restrictedBy, date, bannedRights):
|
||||||
let hasLeft = (flags & (1 << 0)) != 0
|
let hasLeft = (flags & (1 << 0)) != 0
|
||||||
let banInfo = ChannelParticipantBannedInfo(rights: TelegramChatBannedRights(apiBannedRights: bannedRights), restrictedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: restrictedBy), timestamp: date, isMember: !hasLeft)
|
let banInfo = ChannelParticipantBannedInfo(rights: TelegramChatBannedRights(apiBannedRights: bannedRights), restrictedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: restrictedBy), timestamp: date, isMember: !hasLeft)
|
||||||
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: nil, banInfo: banInfo, rank: nil)
|
self = .member(id: userId.peerId, invitedAt: date, adminInfo: nil, banInfo: banInfo, rank: nil)
|
||||||
case let .channelParticipantAdmin(flags, userId, _, promotedBy, date, adminRights, rank: rank):
|
case let .channelParticipantAdmin(flags, userId, _, promotedBy, date, adminRights, rank: rank):
|
||||||
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights) ?? TelegramChatAdminRights(rights: []), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: promotedBy), canBeEditedByAccountPeer: (flags & (1 << 0)) != 0), banInfo: nil, rank: rank)
|
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights) ?? TelegramChatAdminRights(rights: []), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: promotedBy), canBeEditedByAccountPeer: (flags & (1 << 0)) != 0), banInfo: nil, rank: rank)
|
||||||
case let .channelParticipantSelf(userId, _, date):
|
case let .channelParticipantSelf(userId, _, date):
|
||||||
|
@ -13,7 +13,7 @@ public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedC
|
|||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> mapToSignal { result -> Signal<[RenderedChannelParticipant], NoError> in
|
|> mapToSignal { result -> Signal<[RenderedChannelParticipant], NoError> in
|
||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipants(count, participants, users):
|
case let .channelParticipants(count, participants, chats, users):
|
||||||
var items: [RenderedChannelParticipant] = []
|
var items: [RenderedChannelParticipant] = []
|
||||||
|
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
@ -58,7 +58,7 @@ public func channelAdminIds(postbox: Postbox, network: Network, peerId: PeerId,
|
|||||||
let api = Api.functions.channels.getParticipants(channel: apiChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100, hash: hash)
|
let api = Api.functions.channels.getParticipants(channel: apiChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100, hash: hash)
|
||||||
return network.request(api) |> retryRequest |> mapToSignal { result in
|
return network.request(api) |> retryRequest |> mapToSignal { result in
|
||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipants(_, participants, users):
|
case let .channelParticipants(_, participants, _, users):
|
||||||
let users = users.filter({ user in
|
let users = users.filter({ user in
|
||||||
return participants.contains(where: { participant in
|
return participants.contains(where: { participant in
|
||||||
switch participant {
|
switch participant {
|
||||||
|
@ -26,9 +26,9 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha
|
|||||||
|> map { result -> [RenderedChannelParticipant] in
|
|> map { result -> [RenderedChannelParticipant] in
|
||||||
var items: [RenderedChannelParticipant] = []
|
var items: [RenderedChannelParticipant] = []
|
||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipants(_, participants, users):
|
case let .channelParticipants(_, participants, chats, users):
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
var presences:[PeerId: PeerPresence] = [:]
|
var presences: [PeerId: PeerPresence] = [:]
|
||||||
for user in users {
|
for user in users {
|
||||||
let peer = TelegramUser(user: user)
|
let peer = TelegramUser(user: user)
|
||||||
peers[peer.id] = peer
|
peers[peer.id] = peer
|
||||||
@ -36,6 +36,11 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha
|
|||||||
presences[peer.id] = presence
|
presences[peer.id] = presence
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for chat in chats {
|
||||||
|
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||||
|
peers[groupOrChannel.id] = groupOrChannel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
||||||
if let peer = peers[participant.peerId] {
|
if let peer = peers[participant.peerId] {
|
||||||
@ -133,7 +138,7 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
|
|||||||
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
||||||
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
||||||
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
||||||
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer), let _ = transaction.getPeer(account.peerId), let memberPeer = transaction.getPeer(memberId), let inputUser = apiInputUser(memberPeer) {
|
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer), let _ = transaction.getPeer(account.peerId), let memberPeer = transaction.getPeer(memberId), let inputPeer = apiInputPeer(memberPeer) {
|
||||||
let updatedParticipant: ChannelParticipant
|
let updatedParticipant: ChannelParticipant
|
||||||
if let currentParticipant = currentParticipant, case let .member(_, invitedAt, _, currentBanInfo, _) = currentParticipant {
|
if let currentParticipant = currentParticipant, case let .member(_, invitedAt, _, currentBanInfo, _) = currentParticipant {
|
||||||
let banInfo: ChannelParticipantBannedInfo?
|
let banInfo: ChannelParticipantBannedInfo?
|
||||||
@ -152,8 +157,23 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
|
|||||||
}
|
}
|
||||||
updatedParticipant = ChannelParticipant.member(id: memberId, invitedAt: Int32(Date().timeIntervalSince1970), adminInfo: nil, banInfo: banInfo, rank: nil)
|
updatedParticipant = ChannelParticipant.member(id: memberId, invitedAt: Int32(Date().timeIntervalSince1970), adminInfo: nil, banInfo: banInfo, rank: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let apiRights: Api.ChatBannedRights
|
||||||
|
if let rights = rights, !rights.flags.isEmpty {
|
||||||
|
if memberId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
apiRights = .chatBannedRightsChannel(flags: 1 << 0)
|
||||||
|
} else {
|
||||||
|
apiRights = rights.apiBannedRights
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if memberId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
apiRights = .chatBannedRightsChannel(flags: 0)
|
||||||
|
} else {
|
||||||
|
apiRights = .chatBannedRights(flags: 0, untilDate: 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return account.network.request(Api.functions.channels.editBanned(channel: inputChannel, userId: inputUser, bannedRights: rights?.apiBannedRights ?? Api.ChatBannedRights.chatBannedRights(flags: 0, untilDate: 0)))
|
return account.network.request(Api.functions.channels.editBanned(channel: inputChannel, participant: inputPeer, bannedRights: apiRights))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> mapToSignal { result -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
|> mapToSignal { result -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
||||||
account.stateManager.addUpdates(result)
|
account.stateManager.addUpdates(result)
|
||||||
|
@ -83,7 +83,7 @@ public func channelMembers(postbox: Postbox, network: Network, accountPeerId: Pe
|
|||||||
return postbox.transaction { transaction -> [RenderedChannelParticipant]? in
|
return postbox.transaction { transaction -> [RenderedChannelParticipant]? in
|
||||||
var items: [RenderedChannelParticipant] = []
|
var items: [RenderedChannelParticipant] = []
|
||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipants(_, participants, users):
|
case let .channelParticipants(_, participants, chats, users):
|
||||||
var peers: [PeerId: Peer] = [:]
|
var peers: [PeerId: Peer] = [:]
|
||||||
var presences: [PeerId: PeerPresence] = [:]
|
var presences: [PeerId: PeerPresence] = [:]
|
||||||
for user in users {
|
for user in users {
|
||||||
@ -93,6 +93,11 @@ public func channelMembers(postbox: Postbox, network: Network, accountPeerId: Pe
|
|||||||
presences[peer.id] = presence
|
presences[peer.id] = presence
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for chat in chats {
|
||||||
|
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||||
|
peers[groupOrChannel.id] = groupOrChannel
|
||||||
|
}
|
||||||
|
}
|
||||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in
|
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in
|
||||||
return updated
|
return updated
|
||||||
})
|
})
|
||||||
|
@ -38,7 +38,7 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa
|
|||||||
if let current = current as? CachedChannelData {
|
if let current = current as? CachedChannelData {
|
||||||
let adminCount: Int32
|
let adminCount: Int32
|
||||||
switch admins {
|
switch admins {
|
||||||
case let .channelParticipants(count, _, _):
|
case let .channelParticipants(count, _, _, _):
|
||||||
adminCount = count
|
adminCount = count
|
||||||
case .channelParticipantsNotModified:
|
case .channelParticipantsNotModified:
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
@ -46,7 +46,7 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa
|
|||||||
}
|
}
|
||||||
let memberCount: Int32
|
let memberCount: Int32
|
||||||
switch members {
|
switch members {
|
||||||
case let .channelParticipants(count, _, _):
|
case let .channelParticipants(count, _, _, _):
|
||||||
memberCount = count
|
memberCount = count
|
||||||
case .channelParticipantsNotModified:
|
case .channelParticipantsNotModified:
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
@ -54,7 +54,7 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa
|
|||||||
}
|
}
|
||||||
let bannedCount: Int32
|
let bannedCount: Int32
|
||||||
switch banned {
|
switch banned {
|
||||||
case let .channelParticipants(count, _, _):
|
case let .channelParticipants(count, _, _, _):
|
||||||
bannedCount = count
|
bannedCount = count
|
||||||
case .channelParticipantsNotModified:
|
case .channelParticipantsNotModified:
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
@ -62,7 +62,7 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa
|
|||||||
}
|
}
|
||||||
let kickedCount: Int32
|
let kickedCount: Int32
|
||||||
switch kicked {
|
switch kicked {
|
||||||
case let .channelParticipants(count, _, _):
|
case let .channelParticipants(count, _, _, _):
|
||||||
kickedCount = count
|
kickedCount = count
|
||||||
case .channelParticipantsNotModified:
|
case .channelParticipantsNotModified:
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
|
@ -367,6 +367,7 @@ public enum JoinGroupCallError {
|
|||||||
case generic
|
case generic
|
||||||
case anonymousNotAllowed
|
case anonymousNotAllowed
|
||||||
case tooManyParticipants
|
case tooManyParticipants
|
||||||
|
case invalidJoinAsPeer
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct JoinGroupCallResult {
|
public struct JoinGroupCallResult {
|
||||||
@ -408,6 +409,8 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
|
|||||||
return .anonymousNotAllowed
|
return .anonymousNotAllowed
|
||||||
} else if error.errorDescription == "GROUPCALL_PARTICIPANTS_TOO_MUCH" {
|
} else if error.errorDescription == "GROUPCALL_PARTICIPANTS_TOO_MUCH" {
|
||||||
return .tooManyParticipants
|
return .tooManyParticipants
|
||||||
|
} else if error.errorDescription == "JOIN_AS_PEER_INVALID" {
|
||||||
|
return .invalidJoinAsPeer
|
||||||
}
|
}
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
@ -745,9 +748,11 @@ public final class GroupCallParticipantsContext {
|
|||||||
self.about = about
|
self.about = about
|
||||||
}
|
}
|
||||||
|
|
||||||
public mutating func mergeActivity(from other: Participant) {
|
public mutating func mergeActivity(from other: Participant, mergeActivityTimestamp: Bool) {
|
||||||
self.activityRank = other.activityRank
|
self.activityRank = other.activityRank
|
||||||
self.activityTimestamp = other.activityTimestamp
|
if mergeActivityTimestamp {
|
||||||
|
self.activityTimestamp = other.activityTimestamp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Participant, rhs: Participant) -> Bool {
|
public static func ==(lhs: Participant, rhs: Participant) -> Bool {
|
||||||
@ -847,7 +852,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
public var totalCount: Int
|
public var totalCount: Int
|
||||||
public var version: Int32
|
public var version: Int32
|
||||||
|
|
||||||
public mutating func mergeActivity(from other: State, myPeerId: PeerId, previousMyPeerId: PeerId?) {
|
public mutating func mergeActivity(from other: State, myPeerId: PeerId?, previousMyPeerId: PeerId?, mergeActivityTimestamps: Bool) {
|
||||||
var indexMap: [PeerId: Int] = [:]
|
var indexMap: [PeerId: Int] = [:]
|
||||||
for i in 0 ..< other.participants.count {
|
for i in 0 ..< other.participants.count {
|
||||||
indexMap[other.participants[i].peer.id] = i
|
indexMap[other.participants[i].peer.id] = i
|
||||||
@ -855,7 +860,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
|
|
||||||
for i in 0 ..< self.participants.count {
|
for i in 0 ..< self.participants.count {
|
||||||
if let index = indexMap[self.participants[i].peer.id] {
|
if let index = indexMap[self.participants[i].peer.id] {
|
||||||
self.participants[i].mergeActivity(from: other.participants[index])
|
self.participants[i].mergeActivity(from: other.participants[index], mergeActivityTimestamp: mergeActivityTimestamps)
|
||||||
if self.participants[i].peer.id == myPeerId || self.participants[i].peer.id == previousMyPeerId {
|
if self.participants[i].peer.id == myPeerId || self.participants[i].peer.id == previousMyPeerId {
|
||||||
self.participants[i].joinTimestamp = other.participants[index].joinTimestamp
|
self.participants[i].joinTimestamp = other.participants[index].joinTimestamp
|
||||||
}
|
}
|
||||||
@ -1510,6 +1515,8 @@ public final class GroupCallParticipantsContext {
|
|||||||
}
|
}
|
||||||
strongSelf.isLoadingMore = false
|
strongSelf.isLoadingMore = false
|
||||||
strongSelf.shouldResetStateFromServer = false
|
strongSelf.shouldResetStateFromServer = false
|
||||||
|
var state = state
|
||||||
|
state.mergeActivity(from: strongSelf.stateValue.state, myPeerId: nil, previousMyPeerId: nil, mergeActivityTimestamps: false)
|
||||||
strongSelf.stateValue.state = state
|
strongSelf.stateValue.state = state
|
||||||
strongSelf.endedProcessingUpdate()
|
strongSelf.endedProcessingUpdate()
|
||||||
}))
|
}))
|
||||||
@ -2129,12 +2136,12 @@ public func getAudioBroadcastPart(dataSource: AudioBroadcastDataSource, callId:
|
|||||||
status: .rejoinNeeded,
|
status: .rejoinNeeded,
|
||||||
responseTimestamp: responseTimestamp
|
responseTimestamp: responseTimestamp
|
||||||
))
|
))
|
||||||
} else if error.errorDescription.hasPrefix("FLOOD_WAIT") {
|
} else if error.errorDescription.hasPrefix("FLOOD_WAIT") || error.errorDescription == "TIME_TOO_BIG" {
|
||||||
return .single(GetAudioBroadcastPartResult(
|
return .single(GetAudioBroadcastPartResult(
|
||||||
status: .notReady,
|
status: .notReady,
|
||||||
responseTimestamp: responseTimestamp
|
responseTimestamp: responseTimestamp
|
||||||
))
|
))
|
||||||
} else if error.errorDescription == "TIME_INVALID" || error.errorDescription == "TIME_TOO_SMALL" || error.errorDescription == "TIME_TOO_BIG" {
|
} else if error.errorDescription == "TIME_INVALID" || error.errorDescription == "TIME_TOO_SMALL" {
|
||||||
return .single(GetAudioBroadcastPartResult(
|
return .single(GetAudioBroadcastPartResult(
|
||||||
status: .resyncNeeded,
|
status: .resyncNeeded,
|
||||||
responseTimestamp: responseTimestamp
|
responseTimestamp: responseTimestamp
|
||||||
|
@ -38,7 +38,7 @@ public func joinChannel(account: Account, peerId: PeerId, hash: String?) -> Sign
|
|||||||
|> mapToSignal { updates -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
|> mapToSignal { updates -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
||||||
account.stateManager.addUpdates(updates)
|
account.stateManager.addUpdates(updates)
|
||||||
|
|
||||||
return account.network.request(Api.functions.channels.getParticipant(channel: inputChannel, userId: .inputUserSelf))
|
return account.network.request(Api.functions.channels.getParticipant(channel: inputChannel, participant: .inputPeerSelf))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.channels.ChannelParticipant?, JoinChannelError> in
|
|> `catch` { _ -> Signal<Api.channels.ChannelParticipant?, JoinChannelError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
@ -59,7 +59,7 @@ public func joinChannel(account: Account, peerId: PeerId, hash: String?) -> Sign
|
|||||||
}
|
}
|
||||||
let updatedParticipant: ChannelParticipant
|
let updatedParticipant: ChannelParticipant
|
||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipant(participant, _):
|
case let .channelParticipant(participant, _, _):
|
||||||
updatedParticipant = ChannelParticipant(apiParticipant: participant)
|
updatedParticipant = ChannelParticipant(apiParticipant: participant)
|
||||||
}
|
}
|
||||||
if case let .member(_, _, maybeAdminInfo, _, _) = updatedParticipant {
|
if case let .member(_, _, maybeAdminInfo, _, _) = updatedParticipant {
|
||||||
|
@ -129,12 +129,12 @@ public enum UpdateChannelAdminRightsError {
|
|||||||
|
|
||||||
public func fetchChannelParticipant(account: Account, peerId: PeerId, participantId: PeerId) -> Signal<ChannelParticipant?, NoError> {
|
public func fetchChannelParticipant(account: Account, peerId: PeerId, participantId: PeerId) -> Signal<ChannelParticipant?, NoError> {
|
||||||
return account.postbox.transaction { transaction -> Signal<ChannelParticipant?, NoError> in
|
return account.postbox.transaction { transaction -> Signal<ChannelParticipant?, NoError> in
|
||||||
if let peer = transaction.getPeer(peerId), let adminPeer = transaction.getPeer(participantId), let inputUser = apiInputUser(adminPeer) {
|
if let peer = transaction.getPeer(peerId), let adminPeer = transaction.getPeer(participantId), let inputPeer = apiInputPeer(adminPeer) {
|
||||||
if let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) {
|
if let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) {
|
||||||
return account.network.request(Api.functions.channels.getParticipant(channel: inputChannel, userId: inputUser))
|
return account.network.request(Api.functions.channels.getParticipant(channel: inputChannel, participant: inputPeer))
|
||||||
|> map { result -> ChannelParticipant? in
|
|> map { result -> ChannelParticipant? in
|
||||||
switch result {
|
switch result {
|
||||||
case let .channelParticipant(participant, _):
|
case let .channelParticipant(participant, _, _):
|
||||||
return ChannelParticipant(apiParticipant: participant)
|
return ChannelParticipant(apiParticipant: participant)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||||||
|
|
||||||
public class Serialization: NSObject, MTSerialization {
|
public class Serialization: NSObject, MTSerialization {
|
||||||
public func currentLayer() -> UInt {
|
public func currentLayer() -> UInt {
|
||||||
return 125
|
return 126
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseMessage(_ data: Data!) -> Any! {
|
public func parseMessage(_ data: Data!) -> Any! {
|
||||||
|
@ -9,6 +9,9 @@ extension TelegramChatBannedRights {
|
|||||||
switch apiBannedRights {
|
switch apiBannedRights {
|
||||||
case let .chatBannedRights(flags, untilDate):
|
case let .chatBannedRights(flags, untilDate):
|
||||||
self.init(flags: TelegramChatBannedRightsFlags(rawValue: flags), untilDate: untilDate)
|
self.init(flags: TelegramChatBannedRightsFlags(rawValue: flags), untilDate: untilDate)
|
||||||
|
case let .chatBannedRightsChannel(flags):
|
||||||
|
let isKicked = (flags & (1 << 0)) != 0
|
||||||
|
self.init(flags: [.banReadMessages], untilDate: Int32.max)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
|||||||
}
|
}
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
}
|
}
|
||||||
let participantSignal = network.request(Api.functions.channels.getParticipant(channel: inputChannel, userId: .inputUserSelf))
|
let participantSignal = network.request(Api.functions.channels.getParticipant(channel: inputChannel, participant: .inputPeerSelf))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { error -> Signal<Api.channels.ChannelParticipant?, NoError> in
|
|> `catch` { error -> Signal<Api.channels.ChannelParticipant?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
@ -442,7 +442,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
|||||||
|
|
||||||
if let participantResult = participantResult {
|
if let participantResult = participantResult {
|
||||||
switch participantResult {
|
switch participantResult {
|
||||||
case let .channelParticipant(_, users):
|
case let .channelParticipant(_, chats, users):
|
||||||
for user in users {
|
for user in users {
|
||||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||||
peers.append(telegramUser)
|
peers.append(telegramUser)
|
||||||
@ -451,6 +451,11 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for chat in chats {
|
||||||
|
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||||
|
peers.append(groupOrChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +487,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
|||||||
var invitedBy: PeerId?
|
var invitedBy: PeerId?
|
||||||
if let participantResult = participantResult {
|
if let participantResult = participantResult {
|
||||||
switch participantResult {
|
switch participantResult {
|
||||||
case let.channelParticipant(participant, _):
|
case let.channelParticipant(participant, _, _):
|
||||||
switch participant {
|
switch participant {
|
||||||
case let .channelParticipantSelf(_, inviterId, _):
|
case let .channelParticipantSelf(_, inviterId, _):
|
||||||
invitedBy = PeerId(namespace: Namespaces.Peer.CloudUser, id: inviterId)
|
invitedBy = PeerId(namespace: Namespaces.Peer.CloudUser, id: inviterId)
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -32,6 +32,7 @@ import TelegramIntents
|
|||||||
import AccountUtils
|
import AccountUtils
|
||||||
import CoreSpotlight
|
import CoreSpotlight
|
||||||
import LightweightAccountData
|
import LightweightAccountData
|
||||||
|
import TelegramAudio
|
||||||
|
|
||||||
#if canImport(BackgroundTasks)
|
#if canImport(BackgroundTasks)
|
||||||
import BackgroundTasks
|
import BackgroundTasks
|
||||||
@ -438,6 +439,11 @@ final class SharedApplicationContext {
|
|||||||
let logsPath = rootPath + "/logs"
|
let logsPath = rootPath + "/logs"
|
||||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
||||||
Logger.setSharedLogger(Logger(rootPath: rootPath, basePath: logsPath))
|
Logger.setSharedLogger(Logger(rootPath: rootPath, basePath: logsPath))
|
||||||
|
|
||||||
|
setManagedAudioSessionLogger({ s in
|
||||||
|
Logger.shared.log("ManagedAudioSession", s)
|
||||||
|
Logger.shared.shortLog("ManagedAudioSession", s)
|
||||||
|
})
|
||||||
|
|
||||||
if let contents = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: rootPath + "/accounts-metadata"), includingPropertiesForKeys: nil, options: [.skipsSubdirectoryDescendants]) {
|
if let contents = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: rootPath + "/accounts-metadata"), includingPropertiesForKeys: nil, options: [.skipsSubdirectoryDescendants]) {
|
||||||
for url in contents {
|
for url in contents {
|
||||||
|
@ -4327,7 +4327,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
//effectiveCachedDataReady = .single(true)
|
//effectiveCachedDataReady = .single(true)
|
||||||
effectiveCachedDataReady = self.cachedDataReady.get()
|
effectiveCachedDataReady = self.cachedDataReady.get()
|
||||||
}
|
}
|
||||||
self.ready.set(combineLatest(self.chatDisplayNode.historyNode.historyState.get(), self._chatLocationInfoReady.get(), effectiveCachedDataReady, initialData) |> map { _, chatLocationInfoReady, cachedDataReady, _ in
|
self.ready.set(combineLatest(queue: .mainQueue(),
|
||||||
|
self.chatDisplayNode.historyNode.historyState.get(),
|
||||||
|
self._chatLocationInfoReady.get(),
|
||||||
|
effectiveCachedDataReady,
|
||||||
|
initialData
|
||||||
|
)
|
||||||
|
|> map { _, chatLocationInfoReady, cachedDataReady, _ in
|
||||||
return chatLocationInfoReady && cachedDataReady
|
return chatLocationInfoReady && cachedDataReady
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -512,6 +512,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
let canReadHistory = Promise<Bool>()
|
let canReadHistory = Promise<Bool>()
|
||||||
private var canReadHistoryValue: Bool = false
|
private var canReadHistoryValue: Bool = false
|
||||||
private var canReadHistoryDisposable: Disposable?
|
private var canReadHistoryDisposable: Disposable?
|
||||||
|
|
||||||
|
private var messageIdsScheduledForMarkAsSeen = Set<MessageId>()
|
||||||
|
|
||||||
private var chatHistoryLocationValue: ChatHistoryLocationInput? {
|
private var chatHistoryLocationValue: ChatHistoryLocationInput? {
|
||||||
didSet {
|
didSet {
|
||||||
@ -669,12 +671,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
self.messageMentionProcessingManager.process = { [weak self, weak context] messageIds in
|
self.messageMentionProcessingManager.process = { [weak self, weak context] messageIds in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let _ = (strongSelf.canReadHistory.get()
|
if strongSelf.canReadHistoryValue {
|
||||||
|> take(1)).start(next: { [weak context] canReadHistory in
|
context?.account.viewTracker.updateMarkMentionsSeenForMessageIds(messageIds: messageIds)
|
||||||
if canReadHistory {
|
} else {
|
||||||
context?.account.viewTracker.updateMarkMentionsSeenForMessageIds(messageIds: messageIds)
|
strongSelf.messageIdsScheduledForMarkAsSeen.formUnion(messageIds)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,11 +1074,17 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
self.readHistoryDisposable.set(readHistory.start())
|
self.readHistoryDisposable.set(readHistory.start())
|
||||||
|
|
||||||
self.canReadHistoryDisposable = (self.canReadHistory.get() |> deliverOnMainQueue).start(next: { [weak self] value in
|
self.canReadHistoryDisposable = (self.canReadHistory.get() |> deliverOnMainQueue).start(next: { [weak self, weak context] value in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if strongSelf.canReadHistoryValue != value {
|
if strongSelf.canReadHistoryValue != value {
|
||||||
strongSelf.canReadHistoryValue = value
|
strongSelf.canReadHistoryValue = value
|
||||||
strongSelf.updateReadHistoryActions()
|
strongSelf.updateReadHistoryActions()
|
||||||
|
|
||||||
|
if strongSelf.canReadHistoryValue && !strongSelf.messageIdsScheduledForMarkAsSeen.isEmpty {
|
||||||
|
let messageIds = strongSelf.messageIdsScheduledForMarkAsSeen
|
||||||
|
strongSelf.messageIdsScheduledForMarkAsSeen.removeAll()
|
||||||
|
context?.account.viewTracker.updateMarkMentionsSeenForMessageIds(messageIds: messageIds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -100,7 +100,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
self.closeButton.displaysAsynchronously = false
|
self.closeButton.displaysAsynchronously = false
|
||||||
|
|
||||||
self.lineNode = ASImageNode()
|
self.lineNode = ASImageNode()
|
||||||
self.lineNode.displayWithoutProcessing = true
|
self.lineNode.displayWithoutProcessing = false
|
||||||
self.lineNode.displaysAsynchronously = false
|
self.lineNode.displaysAsynchronously = false
|
||||||
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
||||||
|
|
||||||
@ -158,6 +158,11 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
strongSelf.actionArea.accessibilityLabel = "\(headerString). From: \(authors).\n\(text)"
|
strongSelf.actionArea.accessibilityLabel = "\(headerString). From: \(authors).\n\(text)"
|
||||||
|
|
||||||
strongSelf.setNeedsLayout()
|
strongSelf.setNeedsLayout()
|
||||||
|
if let subnodes = strongSelf.subnodes {
|
||||||
|
for subnode in subnodes {
|
||||||
|
subnode.setNeedsDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -196,6 +201,9 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||||
return CGSize(width: constrainedSize.width, height: 45.0)
|
return CGSize(width: constrainedSize.width, height: 45.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func updateState(size: CGSize, interfaceState: ChatPresentationInterfaceState) {
|
||||||
|
}
|
||||||
|
|
||||||
override func layout() {
|
override func layout() {
|
||||||
super.layout()
|
super.layout()
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit c0a62629f968091c21fcdb3d5519f1e77d593079
|
Subproject commit 194449a2dd5a2bcb56a487e691842111bf5adf5f
|
Loading…
x
Reference in New Issue
Block a user