diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e1a30a8f7a..54dbd0d1bf 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8684,9 +8684,9 @@ Sorry for the inconvenience."; "RequestPeer.Requirement.Channel.Rights.Anonymous" = "remain anonymous"; "RequestPeer.Requirement.Channel.Rights.AddAdmins" = "add new admins"; -"RequestPeer.SelectionConfirmationText" = "Are you sure you want to send %1$@ to %2$@?"; -"RequestPeer.SelectionConfirmationInviteText" = "Are you sure you want to send %1$@ to %2$@? This will also add %3$@ to %4$@."; -"RequestPeer.SelectionConfirmationInviteWithRightsText" = "Are you sure you want to send %1$@ to %2$@? This will also add %3$@ to %4$@ with the following rights: %5$@."; +"RequestPeer.SelectionConfirmationTitle" = "Are you sure you want to send %1$@ to %2$@?"; +"RequestPeer.SelectionConfirmationInviteText" = "This will also add %1$@ to %2$@."; +"RequestPeer.SelectionConfirmationInviteWithRightsText" = "This will also add %1$@ to %2$@ with the following rights:\n\n%3$@."; "RequestPeer.SelectionConfirmationSend" = "Send"; "CreateGroup.PublicLinkTitle" = "SET A PUBLIC LINK"; @@ -8699,3 +8699,10 @@ Sorry for the inconvenience."; "Conversation.HoldForAudioOnly" = "Hold to record audio."; "Conversation.HoldForVideoOnly" = "Hold to record video."; +"Conversation.Translation.TranslateTo" = "Translate to %@"; +"Conversation.Translation.ShowOriginal" = "Show Original"; +"Conversation.Translation.ChooseLanguage" = "Choose Another Language"; +"Conversation.Translation.DoNotTranslate" = "Do Not Translate %@"; +"Conversation.Translation.Hide" = "Hide"; +"Conversation.Translation.AddedToDoNotTranslateText" = "**%@** is added to the Do Not Translate list."; +"Conversation.Translation.TranslationBarHiddenText" = "Translation bar is now hidden for this channel."; diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGVideoEditAdjustments.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGVideoEditAdjustments.h index f8af7a8b09..d2ae68296c 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGVideoEditAdjustments.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGVideoEditAdjustments.h @@ -27,6 +27,9 @@ typedef enum @property (nonatomic, readonly) NSTimeInterval trimEndValue; @property (nonatomic, readonly) TGMediaVideoConversionPreset preset; +@property (nonatomic, readonly) int64_t documentId; +@property (nonatomic, strong, readonly) NSArray *colors; + - (CMTimeRange)trimTimeRange; - (bool)trimApplied; @@ -39,6 +42,7 @@ typedef enum - (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset videoStartValue:(NSTimeInterval)videoStartValue trimStartValue:(NSTimeInterval)trimStartValue trimEndValue:(NSTimeInterval)trimEndValue; + (instancetype)editAdjustmentsWithOriginalSize:(CGSize)originalSize preset:(TGMediaVideoConversionPreset)preset; + (instancetype)editAdjustmentsWithPhotoEditorValues:(PGPhotoEditorValues *)values preset:(TGMediaVideoConversionPreset)preset; ++ (instancetype)editAdjustmentsWithPhotoEditorValues:(PGPhotoEditorValues *)values preset:(TGMediaVideoConversionPreset)preset documentId:(int64_t)documentId colors:(NSArray *)colors; + (instancetype)editAdjustmentsWithDictionary:(NSDictionary *)dictionary; + (instancetype)editAdjustmentsWithOriginalSize:(CGSize)originalSize diff --git a/submodules/LegacyComponents/Sources/TGVideoEditAdjustments.m b/submodules/LegacyComponents/Sources/TGVideoEditAdjustments.m index 4c8b2d5e36..db6b510d2e 100644 --- a/submodules/LegacyComponents/Sources/TGVideoEditAdjustments.m +++ b/submodules/LegacyComponents/Sources/TGVideoEditAdjustments.m @@ -130,6 +130,27 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5; return adjustments; } ++ (instancetype)editAdjustmentsWithPhotoEditorValues:(PGPhotoEditorValues *)values preset:(TGMediaVideoConversionPreset)preset documentId:(int64_t)documentId colors:(NSArray *)colors { + TGVideoEditAdjustments *adjustments = [[[self class] alloc] init]; + adjustments->_originalSize = values.originalSize; + CGRect cropRect = values.cropRect; + if (CGRectIsEmpty(cropRect)) { + cropRect = CGRectMake(0.0f, 0.0f, values.originalSize.width, values.originalSize.height); + } + adjustments->_cropRect = cropRect; + adjustments->_cropOrientation = values.cropOrientation; + adjustments->_cropRotation = values.cropRotation; + adjustments->_cropLockedAspectRatio = values.cropLockedAspectRatio; + adjustments->_cropMirrored = values.cropMirrored; + adjustments->_paintingData = [values.paintingData dataForAnimation]; + adjustments->_sendAsGif = true; + adjustments->_preset = preset; + adjustments->_documentId = documentId; + adjustments->_colors = colors; + + return adjustments; +} + - (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset maxDuration:(NSTimeInterval)maxDuration { TGVideoEditAdjustments *adjustments = [[[self class] alloc] init]; diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index 722045ef8b..a06d161be3 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -916,7 +916,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr case let .image(_, reference, _, _, _, _, _, messageId, _, _, isFallback): if self.peer.id == self.context.account.peerId { if isFallback { - let _ = self.context.engine.accountData.updateFallbackPhoto(resource: nil, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start() + let _ = self.context.engine.accountData.updateFallbackPhoto(resource: nil, videoResource: nil, videoStartTimestamp: nil, fileId: nil, backgroundColors: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start() } else if let reference = reference { let _ = self.context.engine.accountData.removeAccountPhoto(reference: reference).start() } diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index b0898371bb..cee0bc09a6 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -622,7 +622,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) } dict[512535275] = { return Api.PostAddress.parse_postAddress($0) } dict[1958953753] = { return Api.PremiumGiftOption.parse_premiumGiftOption($0) } - dict[-1225711938] = { return Api.PremiumSubscriptionOption.parse_premiumSubscriptionOption($0) } + dict[1596792306] = { return Api.PremiumSubscriptionOption.parse_premiumSubscriptionOption($0) } dict[1124062251] = { return Api.PrivacyKey.parse_privacyKeyAddedByPhone($0) } dict[1343122938] = { return Api.PrivacyKey.parse_privacyKeyChatInvite($0) } dict[1777096355] = { return Api.PrivacyKey.parse_privacyKeyForwards($0) } @@ -762,6 +762,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1087454222] = { return Api.StickerSetCovered.parse_stickerSetFullCovered($0) } dict[872932635] = { return Api.StickerSetCovered.parse_stickerSetMultiCovered($0) } dict[2008112412] = { return Api.StickerSetCovered.parse_stickerSetNoCovered($0) } + dict[1964978502] = { return Api.TextWithEntities.parse_textWithEntities($0) } dict[-1609668650] = { return Api.Theme.parse_theme($0) } dict[-94849324] = { return Api.ThemeSettings.parse_themeSettings($0) } dict[-305282981] = { return Api.TopPeer.parse_topPeer($0) } @@ -906,6 +907,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-496024847] = { return Api.UserStatus.parse_userStatusRecently($0) } dict[-1274595769] = { return Api.Username.parse_username($0) } dict[-567037804] = { return Api.VideoSize.parse_videoSize($0) } + dict[195933766] = { return Api.VideoSize.parse_videoSizeEmojiMarkup($0) } dict[-1539849235] = { return Api.WallPaper.parse_wallPaper($0) } dict[-528465642] = { return Api.WallPaper.parse_wallPaperNoFile($0) } dict[499236004] = { return Api.WallPaperSettings.parse_wallPaperSettings($0) } @@ -1073,6 +1075,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-244016606] = { return Api.messages.Stickers.parse_stickersNotModified($0) } dict[-1821037486] = { return Api.messages.TranscribedAudio.parse_transcribedAudio($0) } dict[1741309751] = { return Api.messages.TranslatedText.parse_translateNoResult($0) } + dict[870003448] = { return Api.messages.TranslatedText.parse_translateResult($0) } dict[-1575684144] = { return Api.messages.TranslatedText.parse_translateResultText($0) } dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) } dict[1042605427] = { return Api.payments.BankCardData.parse_bankCardData($0) } @@ -1638,6 +1641,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.StickerSetCovered: _1.serialize(buffer, boxed) + case let _1 as Api.TextWithEntities: + _1.serialize(buffer, boxed) case let _1 as Api.Theme: _1.serialize(buffer, boxed) case let _1 as Api.ThemeSettings: diff --git a/submodules/TelegramApi/Sources/Api17.swift b/submodules/TelegramApi/Sources/Api17.swift index 7be386d4cc..f78c8d5144 100644 --- a/submodules/TelegramApi/Sources/Api17.swift +++ b/submodules/TelegramApi/Sources/Api17.swift @@ -654,15 +654,16 @@ public extension Api { } public extension Api { enum PremiumSubscriptionOption: TypeConstructorDescription { - case premiumSubscriptionOption(flags: Int32, months: Int32, currency: String, amount: Int64, botUrl: String, storeProduct: String?) + case premiumSubscriptionOption(flags: Int32, transaction: String?, months: Int32, currency: String, amount: Int64, botUrl: String, storeProduct: String?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .premiumSubscriptionOption(let flags, let months, let currency, let amount, let botUrl, let storeProduct): + case .premiumSubscriptionOption(let flags, let transaction, let months, let currency, let amount, let botUrl, let storeProduct): if boxed { - buffer.appendInt32(-1225711938) + buffer.appendInt32(1596792306) } serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {serializeString(transaction!, buffer: buffer, boxed: false)} serializeInt32(months, buffer: buffer, boxed: false) serializeString(currency, buffer: buffer, boxed: false) serializeInt64(amount, buffer: buffer, boxed: false) @@ -674,32 +675,35 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .premiumSubscriptionOption(let flags, let months, let currency, let amount, let botUrl, let storeProduct): - return ("premiumSubscriptionOption", [("flags", flags as Any), ("months", months as Any), ("currency", currency as Any), ("amount", amount as Any), ("botUrl", botUrl as Any), ("storeProduct", storeProduct as Any)]) + case .premiumSubscriptionOption(let flags, let transaction, let months, let currency, let amount, let botUrl, let storeProduct): + return ("premiumSubscriptionOption", [("flags", flags as Any), ("transaction", transaction as Any), ("months", months as Any), ("currency", currency as Any), ("amount", amount as Any), ("botUrl", botUrl as Any), ("storeProduct", storeProduct as Any)]) } } public static func parse_premiumSubscriptionOption(_ reader: BufferReader) -> PremiumSubscriptionOption? { var _1: Int32? _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - var _4: Int64? - _4 = reader.readInt64() - var _5: String? - _5 = parseString(reader) + var _2: String? + if Int(_1!) & Int(1 << 3) != 0 {_2 = parseString(reader) } + var _3: Int32? + _3 = reader.readInt32() + var _4: String? + _4 = parseString(reader) + var _5: Int64? + _5 = reader.readInt64() var _6: String? - if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } + _6 = parseString(reader) + var _7: String? + if Int(_1!) & Int(1 << 0) != 0 {_7 = parseString(reader) } let _c1 = _1 != nil - let _c2 = _2 != nil + let _c2 = (Int(_1!) & Int(1 << 3) == 0) || _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.PremiumSubscriptionOption.premiumSubscriptionOption(flags: _1!, months: _2!, currency: _3!, amount: _4!, botUrl: _5!, storeProduct: _6) + let _c6 = _6 != nil + let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.PremiumSubscriptionOption.premiumSubscriptionOption(flags: _1!, transaction: _2, months: _3!, currency: _4!, amount: _5!, botUrl: _6!, storeProduct: _7) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api21.swift b/submodules/TelegramApi/Sources/Api21.swift index cc61c83526..0c5bd6c730 100644 --- a/submodules/TelegramApi/Sources/Api21.swift +++ b/submodules/TelegramApi/Sources/Api21.swift @@ -326,6 +326,52 @@ public extension Api { } } +public extension Api { + enum TextWithEntities: TypeConstructorDescription { + case textWithEntities(text: String, entities: [Api.MessageEntity]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .textWithEntities(let text, let entities): + if boxed { + buffer.appendInt32(1964978502) + } + serializeString(text, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities.count)) + for item in entities { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .textWithEntities(let text, let entities): + return ("textWithEntities", [("text", text as Any), ("entities", entities as Any)]) + } + } + + public static func parse_textWithEntities(_ reader: BufferReader) -> TextWithEntities? { + var _1: String? + _1 = parseString(reader) + var _2: [Api.MessageEntity]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.TextWithEntities.textWithEntities(text: _1!, entities: _2!) + } + else { + return nil + } + } + + } +} public extension Api { enum Theme: TypeConstructorDescription { case theme(flags: Int32, id: Int64, accessHash: Int64, slug: String, title: String, document: Api.Document?, settings: [Api.ThemeSettings]?, emoticon: String?, installsCount: Int32?) diff --git a/submodules/TelegramApi/Sources/Api22.swift b/submodules/TelegramApi/Sources/Api22.swift index b5885f7aff..cc96d76e11 100644 --- a/submodules/TelegramApi/Sources/Api22.swift +++ b/submodules/TelegramApi/Sources/Api22.swift @@ -917,6 +917,7 @@ public extension Api { public extension Api { enum VideoSize: TypeConstructorDescription { case videoSize(flags: Int32, type: String, w: Int32, h: Int32, size: Int32, videoStartTs: Double?) + case videoSizeEmojiMarkup(type: String, emojiId: Int64, backgroundColors: [Int32]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -931,6 +932,18 @@ public extension Api { serializeInt32(size, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} break + case .videoSizeEmojiMarkup(let type, let emojiId, let backgroundColors): + if boxed { + buffer.appendInt32(195933766) + } + serializeString(type, buffer: buffer, boxed: false) + serializeInt64(emojiId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(backgroundColors.count)) + for item in backgroundColors { + serializeInt32(item, buffer: buffer, boxed: false) + } + break } } @@ -938,6 +951,8 @@ public extension Api { switch self { case .videoSize(let flags, let type, let w, let h, let size, let videoStartTs): return ("videoSize", [("flags", flags as Any), ("type", type as Any), ("w", w as Any), ("h", h as Any), ("size", size as Any), ("videoStartTs", videoStartTs as Any)]) + case .videoSizeEmojiMarkup(let type, let emojiId, let backgroundColors): + return ("videoSizeEmojiMarkup", [("type", type as Any), ("emojiId", emojiId as Any), ("backgroundColors", backgroundColors as Any)]) } } @@ -967,6 +982,25 @@ public extension Api { return nil } } + public static func parse_videoSizeEmojiMarkup(_ reader: BufferReader) -> VideoSize? { + var _1: String? + _1 = parseString(reader) + var _2: Int64? + _2 = reader.readInt64() + var _3: [Int32]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.VideoSize.videoSizeEmojiMarkup(type: _1!, emojiId: _2!, backgroundColors: _3!) + } + else { + return nil + } + } } } diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index 5824ec2484..ba46e29edf 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -1247,6 +1247,7 @@ public extension Api.messages { public extension Api.messages { enum TranslatedText: TypeConstructorDescription { case translateNoResult + case translateResult(result: [Api.TextWithEntities]) case translateResultText(text: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { @@ -1256,6 +1257,16 @@ public extension Api.messages { buffer.appendInt32(1741309751) } + break + case .translateResult(let result): + if boxed { + buffer.appendInt32(870003448) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(result.count)) + for item in result { + item.serialize(buffer, true) + } break case .translateResultText(let text): if boxed { @@ -1270,6 +1281,8 @@ public extension Api.messages { switch self { case .translateNoResult: return ("translateNoResult", []) + case .translateResult(let result): + return ("translateResult", [("result", result as Any)]) case .translateResultText(let text): return ("translateResultText", [("text", text as Any)]) } @@ -1278,6 +1291,19 @@ public extension Api.messages { public static func parse_translateNoResult(_ reader: BufferReader) -> TranslatedText? { return Api.messages.TranslatedText.translateNoResult } + public static func parse_translateResult(_ reader: BufferReader) -> TranslatedText? { + var _1: [Api.TextWithEntities]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.TextWithEntities.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.messages.TranslatedText.translateResult(result: _1!) + } + else { + return nil + } + } public static func parse_translateResultText(_ reader: BufferReader) -> TranslatedText? { var _1: String? _1 = parseString(reader) @@ -1356,49 +1382,3 @@ public extension Api.messages { } } -public extension Api.payments { - enum BankCardData: TypeConstructorDescription { - case bankCardData(title: String, openUrls: [Api.BankCardOpenUrl]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .bankCardData(let title, let openUrls): - if boxed { - buffer.appendInt32(1042605427) - } - serializeString(title, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(openUrls.count)) - for item in openUrls { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .bankCardData(let title, let openUrls): - return ("bankCardData", [("title", title as Any), ("openUrls", openUrls as Any)]) - } - } - - public static func parse_bankCardData(_ reader: BufferReader) -> BankCardData? { - var _1: String? - _1 = parseString(reader) - var _2: [Api.BankCardOpenUrl]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BankCardOpenUrl.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.payments.BankCardData.bankCardData(title: _1!, openUrls: _2!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api28.swift b/submodules/TelegramApi/Sources/Api28.swift index 1e2ad08f89..508590d536 100644 --- a/submodules/TelegramApi/Sources/Api28.swift +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -1,3 +1,49 @@ +public extension Api.payments { + enum BankCardData: TypeConstructorDescription { + case bankCardData(title: String, openUrls: [Api.BankCardOpenUrl]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .bankCardData(let title, let openUrls): + if boxed { + buffer.appendInt32(1042605427) + } + serializeString(title, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(openUrls.count)) + for item in openUrls { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .bankCardData(let title, let openUrls): + return ("bankCardData", [("title", title as Any), ("openUrls", openUrls as Any)]) + } + } + + public static func parse_bankCardData(_ reader: BufferReader) -> BankCardData? { + var _1: String? + _1 = parseString(reader) + var _2: [Api.BankCardOpenUrl]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BankCardOpenUrl.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.payments.BankCardData.bankCardData(title: _1!, openUrls: _2!) + } + else { + return nil + } + } + + } +} public extension Api.payments { enum ExportedInvoice: TypeConstructorDescription { case exportedInvoice(url: String) @@ -1408,175 +1454,3 @@ public extension Api.storage { } } -public extension Api.updates { - enum ChannelDifference: TypeConstructorDescription { - case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User]) - case channelDifferenceEmpty(flags: Int32, pts: Int32, timeout: Int32?) - case channelDifferenceTooLong(flags: Int32, timeout: Int32?, dialog: Api.Dialog, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): - if boxed { - buffer.appendInt32(543450958) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(newMessages.count)) - for item in newMessages { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(otherUpdates.count)) - for item in otherUpdates { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - case .channelDifferenceEmpty(let flags, let pts, let timeout): - if boxed { - buffer.appendInt32(1041346555) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} - break - case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): - if boxed { - buffer.appendInt32(-1531132162) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} - dialog.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): - return ("channelDifference", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any), ("newMessages", newMessages as Any), ("otherUpdates", otherUpdates as Any), ("chats", chats as Any), ("users", users as Any)]) - case .channelDifferenceEmpty(let flags, let pts, let timeout): - return ("channelDifferenceEmpty", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any)]) - case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): - return ("channelDifferenceTooLong", [("flags", flags as Any), ("timeout", timeout as Any), ("dialog", dialog as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)]) - } - } - - public static func parse_channelDifference(_ reader: BufferReader) -> ChannelDifference? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } - var _4: [Api.Message]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _5: [Api.Update]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) - } - var _6: [Api.Chat]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _7: [Api.User]? - if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.updates.ChannelDifference.channelDifference(flags: _1!, pts: _2!, timeout: _3, newMessages: _4!, otherUpdates: _5!, chats: _6!, users: _7!) - } - else { - return nil - } - } - public static func parse_channelDifferenceEmpty(_ reader: BufferReader) -> ChannelDifference? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.updates.ChannelDifference.channelDifferenceEmpty(flags: _1!, pts: _2!, timeout: _3) - } - else { - return nil - } - } - public static func parse_channelDifferenceTooLong(_ reader: BufferReader) -> ChannelDifference? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } - var _3: Api.Dialog? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Dialog - } - var _4: [Api.Message]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _5: [Api.Chat]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _6: [Api.User]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.updates.ChannelDifference.channelDifferenceTooLong(flags: _1!, timeout: _2, dialog: _3!, messages: _4!, chats: _5!, users: _6!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index f6d0dc14fb..477390eda6 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -1,3 +1,175 @@ +public extension Api.updates { + enum ChannelDifference: TypeConstructorDescription { + case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User]) + case channelDifferenceEmpty(flags: Int32, pts: Int32, timeout: Int32?) + case channelDifferenceTooLong(flags: Int32, timeout: Int32?, dialog: Api.Dialog, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): + if boxed { + buffer.appendInt32(543450958) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newMessages.count)) + for item in newMessages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUpdates.count)) + for item in otherUpdates { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + case .channelDifferenceEmpty(let flags, let pts, let timeout): + if boxed { + buffer.appendInt32(1041346555) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + break + case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): + if boxed { + buffer.appendInt32(-1531132162) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + dialog.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): + return ("channelDifference", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any), ("newMessages", newMessages as Any), ("otherUpdates", otherUpdates as Any), ("chats", chats as Any), ("users", users as Any)]) + case .channelDifferenceEmpty(let flags, let pts, let timeout): + return ("channelDifferenceEmpty", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any)]) + case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): + return ("channelDifferenceTooLong", [("flags", flags as Any), ("timeout", timeout as Any), ("dialog", dialog as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)]) + } + } + + public static func parse_channelDifference(_ reader: BufferReader) -> ChannelDifference? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } + var _4: [Api.Message]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _5: [Api.Update]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) + } + var _6: [Api.Chat]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _7: [Api.User]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.updates.ChannelDifference.channelDifference(flags: _1!, pts: _2!, timeout: _3, newMessages: _4!, otherUpdates: _5!, chats: _6!, users: _7!) + } + else { + return nil + } + } + public static func parse_channelDifferenceEmpty(_ reader: BufferReader) -> ChannelDifference? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.updates.ChannelDifference.channelDifferenceEmpty(flags: _1!, pts: _2!, timeout: _3) + } + else { + return nil + } + } + public static func parse_channelDifferenceTooLong(_ reader: BufferReader) -> ChannelDifference? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } + var _3: Api.Dialog? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Dialog + } + var _4: [Api.Message]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _5: [Api.Chat]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _6: [Api.User]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.updates.ChannelDifference.channelDifferenceTooLong(flags: _1!, timeout: _2, dialog: _3!, messages: _4!, chats: _5!, users: _6!) + } + else { + return nil + } + } + + } +} public extension Api.updates { enum Difference: TypeConstructorDescription { case difference(newMessages: [Api.Message], newEncryptedMessages: [Api.EncryptedMessage], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User], state: Api.updates.State) diff --git a/submodules/TelegramApi/Sources/Api30.swift b/submodules/TelegramApi/Sources/Api30.swift index c43ba14a37..a34000dc6e 100644 --- a/submodules/TelegramApi/Sources/Api30.swift +++ b/submodules/TelegramApi/Sources/Api30.swift @@ -6727,16 +6727,23 @@ public extension Api.functions.messages { } } public extension Api.functions.messages { - static func translateText(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, text: String?, fromLang: String?, toLang: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func translateText(flags: Int32, peer: Api.InputPeer?, id: [Int32]?, text: [Api.TextWithEntities]?, toLang: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(617508334) + buffer.appendInt32(1662529584) serializeInt32(flags, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {peer!.serialize(buffer, true)} - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(text!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(fromLang!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id!.count)) + for item in id! { + serializeInt32(item, buffer: buffer, boxed: false) + }} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(text!.count)) + for item in text! { + item.serialize(buffer, true) + }} serializeString(toLang, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.translateText", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("text", String(describing: text)), ("fromLang", String(describing: fromLang)), ("toLang", String(describing: toLang))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.TranslatedText? in + return (FunctionDescription(name: "messages.translateText", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("text", String(describing: text)), ("toLang", String(describing: toLang))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.TranslatedText? in let reader = BufferReader(buffer) var result: Api.messages.TranslatedText? if let signature = reader.readInt32() { @@ -7667,14 +7674,15 @@ public extension Api.functions.photos { } } public extension Api.functions.photos { - static func uploadProfilePhoto(flags: Int32, file: Api.InputFile?, video: Api.InputFile?, videoStartTs: Double?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func uploadProfilePhoto(flags: Int32, file: Api.InputFile?, video: Api.InputFile?, videoStartTs: Double?, videoEmojiMarkup: Api.VideoSize?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-1980559511) + buffer.appendInt32(-771759753) serializeInt32(flags, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {file!.serialize(buffer, true)} if Int(flags) & Int(1 << 1) != 0 {video!.serialize(buffer, true)} if Int(flags) & Int(1 << 2) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "photos.uploadProfilePhoto", parameters: [("flags", String(describing: flags)), ("file", String(describing: file)), ("video", String(describing: video)), ("videoStartTs", String(describing: videoStartTs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in + if Int(flags) & Int(1 << 3) != 0 {videoEmojiMarkup!.serialize(buffer, true)} + return (FunctionDescription(name: "photos.uploadProfilePhoto", parameters: [("flags", String(describing: flags)), ("file", String(describing: file)), ("video", String(describing: video)), ("videoStartTs", String(describing: videoStartTs)), ("videoEmojiMarkup", String(describing: videoEmojiMarkup))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in let reader = BufferReader(buffer) var result: Api.photos.Photo? if let signature = reader.readInt32() { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index 758d9e66b6..ed5592fdb3 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -6245,7 +6245,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController self.updateAvatarPromise.set(.single((representation, 0.0))) let postbox = self.call.account.postbox - let signal = peerId.namespace == Namespaces.Peer.CloudUser ? self.call.accountContext.engine.accountData.updateAccountPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { resource, representations in + let signal = peerId.namespace == Namespaces.Peer.CloudUser ? self.call.accountContext.engine.accountData.updateAccountPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, fileId: nil, backgroundColors: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) }) : self.call.accountContext.engine.peers.updatePeerPhoto(peerId: peerId, photo: self.call.accountContext.engine.peers.uploadedPeerPhoto(resource: resource), mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) @@ -6365,7 +6365,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController self.updateAvatarDisposable.set((signal |> mapToSignal { videoResource -> Signal in if peerId.namespace == Namespaces.Peer.CloudUser { - return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in + return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, fileId: nil, backgroundColors: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations) }) } else { diff --git a/submodules/TelegramCore/Sources/Account/AccountManager.swift b/submodules/TelegramCore/Sources/Account/AccountManager.swift index e773fda7a9..664df0b395 100644 --- a/submodules/TelegramCore/Sources/Account/AccountManager.swift +++ b/submodules/TelegramCore/Sources/Account/AccountManager.swift @@ -192,6 +192,7 @@ private var declaredEncodables: Void = { declareEncodable(TelegramExtendedMedia.self, f: { TelegramExtendedMedia(decoder: $0) }) declareEncodable(TelegramPeerUsername.self, f: { TelegramPeerUsername(decoder: $0) }) declareEncodable(MediaSpoilerMessageAttribute.self, f: { MediaSpoilerMessageAttribute(decoder: $0) }) + declareEncodable(TranslationMessageAttribute.self, f: { TranslationMessageAttribute(decoder: $0) }) return }() diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift index 99f83f6aba..48a3f37522 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift @@ -172,6 +172,8 @@ func telegramMediaFileFromApiDocument(_ document: Api.Document) -> TelegramMedia videoThumbnails.append(TelegramMediaFile.VideoThumbnail( dimensions: PixelDimensions(width: w, height: h), resource: resource)) + case .videoSizeEmojiMarkup: + break } } } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaImage.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaImage.swift index f12e13eec1..a66a1d228e 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaImage.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaImage.swift @@ -41,19 +41,22 @@ func telegramMediaImageFromApiPhoto(_ photo: Api.Photo) -> TelegramMediaImage? { } var videoRepresentations: [TelegramMediaImage.VideoRepresentation] = [] + var emojiMarkup: TelegramMediaImage.EmojiMarkup? if let videoSizes = videoSizes { for size in videoSizes { switch size { - case let .videoSize(_, type, w, h, size, videoStartTs): - let resource: TelegramMediaResource - resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference.makeData()) - - videoRepresentations.append(TelegramMediaImage.VideoRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, startTimestamp: videoStartTs)) + case let .videoSize(_, type, w, h, size, videoStartTs): + let resource: TelegramMediaResource + resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference.makeData()) + + videoRepresentations.append(TelegramMediaImage.VideoRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, startTimestamp: videoStartTs)) + case let .videoSizeEmojiMarkup(_, emojiId, backgroundColors): + emojiMarkup = TelegramMediaImage.EmojiMarkup(fileId: emojiId, backgroundColors: backgroundColors) } } } - return TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudImage, id: id), representations: representations, videoRepresentations: videoRepresentations, immediateThumbnailData: immediateThumbnailData, reference: .cloud(imageId: id, accessHash: accessHash, fileReference: fileReference.makeData()), partialReference: nil, flags: imageFlags) + return TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudImage, id: id), representations: representations, videoRepresentations: videoRepresentations, immediateThumbnailData: immediateThumbnailData, emojiMarkup: emojiMarkup, reference: .cloud(imageId: id, accessHash: accessHash, fileReference: fileReference.makeData()), partialReference: nil, flags: imageFlags) case .photoEmpty: return nil } diff --git a/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift b/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift index d09cddb7a4..23535332e9 100644 --- a/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift +++ b/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift @@ -79,8 +79,9 @@ private extension PremiumPromoConfiguration { var productOptions: [PremiumProductOption] = [] for option in options { - if case let .premiumSubscriptionOption(_, months, currency, amount, botUrl, storeProduct) = option { - productOptions.append(PremiumProductOption(months: months, currency: currency, amount: amount, botUrl: botUrl, storeProductId: storeProduct)) + + if case let .premiumSubscriptionOption(flags, transaction, months, currency, amount, botUrl, storeProduct) = option { + productOptions.append(PremiumProductOption(isCurrent: (flags & (1 << 1)) != 0, months: months, currency: currency, amount: amount, botUrl: botUrl, transactionId: transaction, availableForUpgrade: (flags & (1 << 2)) != 0, storeProductId: storeProduct)) } } self.premiumProductOptions = productOptions diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift index de3e960f3e..efe97ae82d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift @@ -34,38 +34,59 @@ public struct PremiumPromoConfiguration: Codable, Equatable { } public struct PremiumProductOption: Codable, Equatable { + enum CodingKeys: String, CodingKey { + case isCurrent + case months + case currency + case amount + case botUrl + case transactionId + case availableForUpgrade + case storeProductId + } + + public let isCurrent: Bool public let months: Int32 public let currency: String public let amount: Int64 public let botUrl: String + public let transactionId: String? + public let availableForUpgrade: Bool public let storeProductId: String? - public init(months: Int32, currency: String, amount: Int64, botUrl: String, storeProductId: String?) { + public init(isCurrent: Bool, months: Int32, currency: String, amount: Int64, botUrl: String, transactionId: String?, availableForUpgrade: Bool, storeProductId: String?) { + self.isCurrent = isCurrent self.months = months self.currency = currency self.amount = amount self.botUrl = botUrl + self.transactionId = transactionId + self.availableForUpgrade = availableForUpgrade self.storeProductId = storeProductId } - public init(decoder: PostboxDecoder) { - self.months = decoder.decodeInt32ForKey("months", orElse: 0) - self.currency = decoder.decodeStringForKey("currency", orElse: "") - self.amount = decoder.decodeInt64ForKey("amount", orElse: 0) - self.botUrl = decoder.decodeStringForKey("botUrl", orElse: "") - self.storeProductId = decoder.decodeOptionalStringForKey("storeProductId") + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.isCurrent = try container.decode(Bool.self, forKey: .isCurrent) + self.months = try container.decode(Int32.self, forKey: .months) + self.currency = try container.decode(String.self, forKey: .currency) + self.amount = try container.decode(Int64.self, forKey: .amount) + self.botUrl = try container.decode(String.self, forKey: .botUrl) + self.transactionId = try container.decodeIfPresent(String.self, forKey: .transactionId) + self.availableForUpgrade = try container.decode(Bool.self, forKey: .availableForUpgrade) + self.storeProductId = try container.decodeIfPresent(String.self, forKey: .storeProductId) } - public func encode(_ encoder: PostboxEncoder) { - encoder.encodeInt32(self.months, forKey: "months") - encoder.encodeString(self.currency, forKey: "currency") - encoder.encodeInt64(self.amount, forKey: "amount") - encoder.encodeString(self.botUrl, forKey: "botUrl") - if let storeProductId = self.storeProductId { - encoder.encodeString(storeProductId, forKey: "storeProductId") - } else { - encoder.encodeNil(forKey: "storeProductId") - } + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.isCurrent, forKey: .isCurrent) + try container.encode(self.months, forKey: .months) + try container.encode(self.currency, forKey: .currency) + try container.encode(self.amount, forKey: .amount) + try container.encode(self.botUrl, forKey: .botUrl) + try container.encodeIfPresent(self.transactionId, forKey: .transactionId) + try container.encode(self.availableForUpgrade, forKey: .availableForUpgrade) + try container.encodeIfPresent(self.storeProductId, forKey: .storeProductId) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaImage.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaImage.swift index c4c1c85ff9..520f39517f 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaImage.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaImage.swift @@ -130,10 +130,42 @@ public final class TelegramMediaImage: Media, Equatable, Codable { } } + public final class EmojiMarkup: Equatable, PostboxCoding { + public let fileId: Int64 + public let backgroundColors: [Int32] + + public init(fileId: Int64, backgroundColors: [Int32]) { + self.fileId = fileId + self.backgroundColors = backgroundColors + } + + public init(decoder: PostboxDecoder) { + self.fileId = decoder.decodeInt64ForKey("f", orElse: 0) + self.backgroundColors = decoder.decodeInt32ArrayForKey("b") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt64(self.fileId, forKey: "f") + encoder.encodeInt32Array(self.backgroundColors, forKey: "b") + } + + public static func ==(lhs: EmojiMarkup, rhs: EmojiMarkup) -> Bool { + if lhs.fileId != rhs.fileId { + return false + } + if lhs.backgroundColors != rhs.backgroundColors { + return false + } + return true + } + } + + public let imageId: MediaId public let representations: [TelegramMediaImageRepresentation] public let videoRepresentations: [TelegramMediaImage.VideoRepresentation] public let immediateThumbnailData: Data? + public let emojiMarkup: TelegramMediaImage.EmojiMarkup? public let reference: TelegramMediaImageReference? public let partialReference: PartialMediaReference? public let peerIds: [PeerId] = [] @@ -143,11 +175,12 @@ public final class TelegramMediaImage: Media, Equatable, Codable { return self.imageId } - public init(imageId: MediaId, representations: [TelegramMediaImageRepresentation], videoRepresentations: [TelegramMediaImage.VideoRepresentation] = [], immediateThumbnailData: Data?, reference: TelegramMediaImageReference?, partialReference: PartialMediaReference?, flags: TelegramMediaImageFlags) { + public init(imageId: MediaId, representations: [TelegramMediaImageRepresentation], videoRepresentations: [TelegramMediaImage.VideoRepresentation] = [], immediateThumbnailData: Data?, emojiMarkup: TelegramMediaImage.EmojiMarkup? = nil, reference: TelegramMediaImageReference?, partialReference: PartialMediaReference?, flags: TelegramMediaImageFlags) { self.imageId = imageId self.representations = representations self.videoRepresentations = videoRepresentations self.immediateThumbnailData = immediateThumbnailData + self.emojiMarkup = emojiMarkup self.reference = reference self.partialReference = partialReference self.flags = flags @@ -158,6 +191,7 @@ public final class TelegramMediaImage: Media, Equatable, Codable { self.representations = decoder.decodeObjectArrayForKey("r") self.videoRepresentations = decoder.decodeObjectArrayForKey("vr") self.immediateThumbnailData = decoder.decodeDataForKey("itd") + self.emojiMarkup = decoder.decodeObjectForKey("em", decoder: { TelegramMediaImage.EmojiMarkup(decoder: $0) }) as? TelegramMediaImage.EmojiMarkup self.reference = decoder.decodeObjectForKey("rf", decoder: { TelegramMediaImageReference(decoder: $0) }) as? TelegramMediaImageReference self.partialReference = decoder.decodeAnyObjectForKey("prf", decoder: { PartialMediaReference(decoder: $0) }) as? PartialMediaReference self.flags = TelegramMediaImageFlags(rawValue: decoder.decodeInt32ForKey("fl", orElse: 0)) @@ -174,6 +208,11 @@ public final class TelegramMediaImage: Media, Equatable, Codable { } else { encoder.encodeNil(forKey: "itd") } + if let emojiMarkup = self.emojiMarkup { + encoder.encodeObject(emojiMarkup, forKey: "em") + } else { + encoder.encodeNil(forKey: "em") + } if let reference = self.reference { encoder.encodeObject(reference, forKey: "rf") } else { @@ -198,6 +237,7 @@ public final class TelegramMediaImage: Media, Equatable, Codable { self.representations = object.representations self.videoRepresentations = object.videoRepresentations self.immediateThumbnailData = object.immediateThumbnailData + self.emojiMarkup = object.emojiMarkup self.reference = object.reference self.partialReference = object.partialReference self.flags = object.flags @@ -252,10 +292,13 @@ public final class TelegramMediaImage: Media, Equatable, Codable { if other.immediateThumbnailData != self.immediateThumbnailData { return false } - if self.partialReference != other.partialReference { + if other.emojiMarkup != self.emojiMarkup { return false } - if self.flags != other.flags { + if other.partialReference != self.partialReference { + return false + } + if other.flags != self.flags { return false } return true diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TranslationMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TranslationMessageAttribute.swift new file mode 100644 index 0000000000..5ac69146ac --- /dev/null +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TranslationMessageAttribute.swift @@ -0,0 +1,46 @@ +import Postbox + +public class TranslationMessageAttribute: MessageAttribute, Equatable { + public let text: String + public let entities: [MessageTextEntity] + public let toLang: String + + public var associatedPeerIds: [PeerId] { + return [] + } + + public init( + text: String, + entities: [MessageTextEntity], + toLang: String + ) { + self.text = text + self.entities = entities + self.toLang = toLang + } + + required public init(decoder: PostboxDecoder) { + self.text = decoder.decodeStringForKey("text", orElse: "") + self.entities = decoder.decodeObjectArrayWithDecoderForKey("entities") + self.toLang = decoder.decodeStringForKey("toLang", orElse: "") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeString(self.text, forKey: "text") + encoder.encodeObjectArray(self.entities, forKey: "entities") + encoder.encodeString(self.toLang, forKey: "toLang") + } + + public static func ==(lhs: TranslationMessageAttribute, rhs: TranslationMessageAttribute) -> Bool { + if lhs.text != rhs.text { + return false + } + if lhs.entities != rhs.entities { + return false + } + if lhs.toLang != rhs.toLang { + return false + } + return true + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift index 5a1b3fa536..692618950b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift @@ -43,8 +43,8 @@ public extension TelegramEngine { return _internal_registerNotificationToken(account: self.account, token: token, type: type, sandbox: sandbox, otherAccountUserIds: otherAccountUserIds, excludeMutedChats: excludeMutedChats) } - public func updateAccountPhoto(resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { - return _internal_updateAccountPhoto(account: self.account, resource: resource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, fallback: false, mapResourceToAvatarSizes: mapResourceToAvatarSizes) + public func updateAccountPhoto(resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, fileId: Int64?, backgroundColors: [Int32]?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { + return _internal_updateAccountPhoto(account: self.account, resource: resource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, fileId: fileId, backgroundColors: backgroundColors, fallback: false, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } public func updatePeerPhotoExisting(reference: TelegramMediaImageReference) -> Signal { @@ -55,8 +55,8 @@ public extension TelegramEngine { return _internal_removeAccountPhoto(account: self.account, reference: reference, fallback: false) } - public func updateFallbackPhoto(resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { - return _internal_updateAccountPhoto(account: self.account, resource: resource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, fallback: true, mapResourceToAvatarSizes: mapResourceToAvatarSizes) + public func updateFallbackPhoto(resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, fileId: Int64?, backgroundColors: [Int32]?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { + return _internal_updateAccountPhoto(account: self.account, resource: resource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, fileId: fileId, backgroundColors: backgroundColors, fallback: true, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } public func removeFallbackPhoto(reference: TelegramMediaImageReference?) -> Signal { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index 217b37fd35..00c1e83abe 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -360,6 +360,10 @@ public extension TelegramEngine { return _internal_translate(network: self.account.network, text: text, fromLang: fromLang, toLang: toLang) } + public func translateMessages(messageIds: [EngineMessage.Id], toLang: String) -> Signal { + return _internal_translateMessages(postbox: self.account.postbox, network: self.account.network, messageIds: messageIds, toLang: toLang) + } + public func transcribeAudio(messageId: MessageId) -> Signal { return _internal_transcribeAudio(postbox: self.account.postbox, network: self.account.network, messageId: messageId) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift index 74ed81476b..f5c1e4f113 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift @@ -7,11 +7,8 @@ import MtProtoKit func _internal_translate(network: Network, text: String, fromLang: String?, toLang: String) -> Signal { var flags: Int32 = 0 flags |= (1 << 1) - if let _ = fromLang { - flags |= (1 << 2) - } - - return network.request(Api.functions.messages.translateText(flags: flags, peer: nil, msgId: nil, text: text, fromLang: fromLang, toLang: toLang)) + + return network.request(Api.functions.messages.translateText(flags: flags, peer: nil, id: nil, text: [.textWithEntities(text: text, entities: [])], toLang: toLang)) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) @@ -21,10 +18,63 @@ func _internal_translate(network: Network, text: String, fromLang: String?, toLa return .complete() } switch result { - case .translateNoResult: - return .single(nil) - case let .translateResultText(text): + case .translateNoResult: + return .single(nil) + case let .translateResultText(text): + return .single(text) + case let .translateResult(results): + if case let .textWithEntities(text, _) = results.first { return .single(text) + } else { + return .single(nil) + } + } + } +} + +func _internal_translateMessages(postbox: Postbox, network: Network, messageIds: [EngineMessage.Id], toLang: String) -> Signal { + guard let peerId = messageIds.first?.peerId else { + return .never() + } + return postbox.transaction { transaction -> Api.InputPeer? in + return transaction.getPeer(peerId).flatMap(apiInputPeer) + } + |> mapToSignal { inputPeer -> Signal in + guard let inputPeer = inputPeer else { + return .never() + } + + var flags: Int32 = 0 + flags |= (1 << 0) + + let id: [Int32] = messageIds.map { $0.id } + return network.request(Api.functions.messages.translateText(flags: flags, peer: inputPeer, id: id, text: nil, toLang: toLang)) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignal { result -> Signal in + guard let result = result, case let .translateResult(results) = result else { + return .complete() + } + return postbox.transaction { transaction in + var index = 0 + for result in results { + let messageId = messageIds[index] + if case let .textWithEntities(text, entities) = result { + let updatedAttribute: TranslationMessageAttribute = TranslationMessageAttribute(text: text, entities: messageTextEntitiesFromApiEntities(entities), toLang: toLang) + transaction.updateMessage(messageId, update: { currentMessage in + let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init) + var attributes = currentMessage.attributes.filter { !($0 is TranslationMessageAttribute) } + + attributes.append(updatedAttribute) + + return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) + }) + } + index += 1 + } + } } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index 2038043834..2991d6eb2d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -12,6 +12,7 @@ public enum AssignAppStoreTransactionError { public enum AppStoreTransactionPurpose { case subscription + case upgrade case gift(peerId: EnginePeer.Id, currency: String, amount: Int64) case restore } @@ -19,10 +20,15 @@ public enum AppStoreTransactionPurpose { func _internal_sendAppStoreReceipt(account: Account, receipt: Data, purpose: AppStoreTransactionPurpose) -> Signal { var purposeSignal: Signal switch purpose { - case .subscription, .restore: + case .subscription, .upgrade, .restore: var flags: Int32 = 0 - if case .restore = purpose { + switch purpose { + case .upgrade: + flags |= (1 << 1) + case .restore: flags |= (1 << 0) + default: + break } purposeSignal = .single(.inputStorePaymentPremiumSubscription(flags: flags)) case let .gift(peerId, currency, amount): @@ -61,7 +67,7 @@ public enum RestoreAppStoreReceiptError { func _internal_canPurchasePremium(account: Account, purpose: AppStoreTransactionPurpose) -> Signal { var purposeSignal: Signal switch purpose { - case .subscription, .restore: + case .subscription, .restore, .upgrade: var flags: Int32 = 0 if case .restore = purpose { flags |= (1 << 0) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift index a5d362c9e5..8a788821e7 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift @@ -14,7 +14,7 @@ public enum UploadPeerPhotoError { case generic } -func _internal_updateAccountPhoto(account: Account, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, fallback: Bool, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { +func _internal_updateAccountPhoto(account: Account, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, fileId: Int64?, backgroundColors: [Int32]?, fallback: Bool, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: account.peerId, photo: resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, fallback: fallback, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } @@ -76,11 +76,11 @@ func _internal_uploadedPeerVideo(postbox: Postbox, network: Network, messageMedi } } -func _internal_updatePeerPhoto(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peerId: PeerId, photo: Signal?, video: Signal? = nil, videoStartTimestamp: Double? = nil, fallback: Bool = false, customPeerPhotoMode: SetCustomPeerPhotoMode? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { +func _internal_updatePeerPhoto(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peerId: PeerId, photo: Signal?, video: Signal? = nil, videoStartTimestamp: Double? = nil, fileId: Int64? = nil, backgroundColors: [Int32]? = nil, fallback: Bool = false, customPeerPhotoMode: SetCustomPeerPhotoMode? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { return _internal_updatePeerPhotoInternal(postbox: postbox, network: network, stateManager: stateManager, accountPeerId: accountPeerId, peer: postbox.loadedPeerWithId(peerId), photo: photo, video: video, videoStartTimestamp: videoStartTimestamp, fallback: fallback, customPeerPhotoMode: customPeerPhotoMode, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } -func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peer: Signal, photo: Signal?, video: Signal?, videoStartTimestamp: Double?, fallback: Bool = false, customPeerPhotoMode: SetCustomPeerPhotoMode? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { +func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peer: Signal, photo: Signal?, video: Signal?, videoStartTimestamp: Double?, fileId: Int64? = nil, backgroundColors: [Int32]? = nil, fallback: Bool = false, customPeerPhotoMode: SetCustomPeerPhotoMode? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { return peer |> mapError { _ -> UploadPeerPhotoError in } |> mapToSignal { peer -> Signal in @@ -150,12 +150,19 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state flags |= (1 << 2) } } + + var videoEmojiMarkup: Api.VideoSize? + if let fileId, let backgroundColors { + videoEmojiMarkup = .videoSizeEmojiMarkup(type: "e", emojiId: fileId, backgroundColors: backgroundColors) + flags |= (1 << 4) + } + let request: Signal if peer.id == accountPeerId { if fallback { flags |= (1 << 3) } - request = network.request(Api.functions.photos.uploadProfilePhoto(flags: flags, file: file, video: videoFile, videoStartTs: videoStartTimestamp)) + request = network.request(Api.functions.photos.uploadProfilePhoto(flags: flags, file: file, video: videoFile, videoStartTs: videoStartTimestamp, videoEmojiMarkup: videoEmojiMarkup)) } else if let inputUser = apiInputUser(peer) { if let customPeerPhotoMode = customPeerPhotoMode { switch customPeerPhotoMode { @@ -205,11 +212,13 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state if let videoSizes = videoSizes { for size in videoSizes { switch size { - case let .videoSize(_, type, w, h, size, videoStartTs): - let resource: TelegramMediaResource - resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference.makeData()) - - videoRepresentations.append(TelegramMediaImage.VideoRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, startTimestamp: videoStartTs)) + case let .videoSize(_, type, w, h, size, videoStartTs): + let resource: TelegramMediaResource + resource = CloudPhotoSizeMediaResource(datacenterId: dcId, photoId: id, accessHash: accessHash, sizeSpec: type, size: Int64(size), fileReference: fileReference.makeData()) + + videoRepresentations.append(TelegramMediaImage.VideoRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, startTimestamp: videoStartTs)) + case .videoSizeEmojiMarkup: + break } } } diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift index 9b4dd67c51..3c1876b3be 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift @@ -74,19 +74,31 @@ final class AvatarEditorScreenComponent: Component { let context: AccountContext let ready: Promise + let initialFileId: Int64? + let initialBackgroundColors: [Int32]? init( context: AccountContext, - ready: Promise + ready: Promise, + initialFileId: Int64?, + initialBackgroundColors: [Int32]? ) { self.context = context self.ready = ready + self.initialFileId = initialFileId + self.initialBackgroundColors = initialBackgroundColors } static func ==(lhs: AvatarEditorScreenComponent, rhs: AvatarEditorScreenComponent) -> Bool { if lhs.context !== rhs.context { return false } + if lhs.initialFileId != rhs.initialFileId { + return false + } + if lhs.initialBackgroundColors != rhs.initialBackgroundColors { + return false + } return true } @@ -94,26 +106,49 @@ final class AvatarEditorScreenComponent: Component { let context: AccountContext var selectedBackground: AvatarBackground - var selectedItem: EmojiPagerContentComponent.Item? + var selectedFile: TelegramMediaFile? var keyboardContentId: AnyHashable = "emoji" var expanded: Bool = false var editingColor: Bool = false var previousColor: AvatarBackground + var previousCustomColor: AvatarBackground? + var customColor: AvatarBackground? + var isSearchActive: Bool = false - init(context: AccountContext) { + init(context: AccountContext, initialFileId: Int64?, initialBackgroundColors: [Int32]?) { self.context = context - + self.selectedBackground = defaultBackgrounds.first! self.previousColor = self.selectedBackground + + super.init() + + if let initialFileId, let initialBackgroundColors { + let _ = context.engine.stickers.resolveInlineStickers(fileIds: [initialFileId]) + |> map { [weak self] files in + if let strongSelf = self, let file = files.values.first { + strongSelf.selectedFile = file + strongSelf.updated(transition: .immediate) + } + } + self.selectedBackground = .gradient(initialBackgroundColors.map { UInt32(bitPattern: $0) }) + self.previousColor = self.selectedBackground + } else { + self.selectedBackground = defaultBackgrounds.first! + } + + self.previousColor = self.selectedBackground } } func makeState() -> State { return State( - context: self.context + context: self.context, + initialFileId: self.initialFileId, + initialBackgroundColors: self.initialBackgroundColors ) } @@ -194,7 +229,7 @@ final class AvatarEditorScreenComponent: Component { private func updateData(_ data: KeyboardInputData) { self.data = data - self.state?.selectedItem = data.emoji.panelItemGroups.first?.items.first + self.state?.selectedFile = data.emoji.panelItemGroups.first?.items.first?.itemFile self.state?.updated(transition: .immediate) let updateSearchQuery: (String, String) -> Void = { [weak self] rawQuery, languageCode in @@ -366,7 +401,7 @@ final class AvatarEditorScreenComponent: Component { guard let self, let _ = item.itemFile else { return } - self.state?.selectedItem = item + self.state?.selectedFile = item.itemFile self.state?.updated(transition: .easeInOut(duration: 0.2)) }, deleteBackwards: nil, @@ -487,7 +522,7 @@ final class AvatarEditorScreenComponent: Component { guard let self, let _ = item.itemFile else { return } - self.state?.selectedItem = item + self.state?.selectedFile = item.itemFile self.state?.updated(transition: .easeInOut(duration: 0.2)) }, deleteBackwards: nil, @@ -756,7 +791,7 @@ final class AvatarEditorScreenComponent: Component { AvatarPreviewComponent( context: component.context, background: state.selectedBackground, - file: state.selectedItem?.itemFile, + file: state.selectedFile, tapped: { [weak state] in if let state, !state.editingColor { state.expanded = !state.expanded @@ -825,6 +860,7 @@ final class AvatarEditorScreenComponent: Component { theme: environment.theme, values: defaultBackgrounds, selectedValue: state.selectedBackground, + customValue: state.customColor, updateValue: { [weak state] value in if let state { state.selectedBackground = value @@ -835,6 +871,7 @@ final class AvatarEditorScreenComponent: Component { if let state { state.editingColor = true state.previousColor = state.selectedBackground + state.previousCustomColor = state.customColor state.updated(transition: .easeInOut(duration: 0.3)) } } @@ -857,9 +894,11 @@ final class AvatarEditorScreenComponent: Component { ColorPickerComponent( theme: environment.theme, strings: environment.strings, + isVisible: state.editingColor, colors: state.selectedBackground.colors, colorsChanged: { [weak state] colors in if let state { + state.customColor = .gradient(colors) state.selectedBackground = .gradient(colors) state.updated(transition: .immediate) } @@ -867,6 +906,7 @@ final class AvatarEditorScreenComponent: Component { cancel: { [weak state] in if let state { state.selectedBackground = state.previousColor + state.customColor = state.previousCustomColor state.editingColor = false state.updated(transition: .easeInOut(duration: 0.3)) } @@ -874,6 +914,7 @@ final class AvatarEditorScreenComponent: Component { done: { [weak state] in if let state { state.editingColor = false + state.customColor = state.selectedBackground state.updated(transition: .easeInOut(duration: 0.3)) } } @@ -1106,7 +1147,7 @@ final class AvatarEditorScreenComponent: Component { } func complete() { - guard let state = self.state, let item = state.selectedItem, let itemFile = item.itemFile, let previewView = self.previewView.view else { + guard let state = self.state, let itemFile = state.selectedFile, let previewView = self.previewView.view else { return } let size = CGSize(width: 1920.0, height: 1920.0) @@ -1120,8 +1161,15 @@ final class AvatarEditorScreenComponent: Component { entity.position = CGPoint(x: size.width / 2.0, y: size.height / 2.0) entity.scale = 3.3 + var documentId: Int64 = 0 + if case let .file(file) = entity.content { + documentId = file.fileId.id + } + + let colors: [NSNumber] = state.selectedBackground.colors.map { Int32(bitPattern: $0) as NSNumber } + let entitiesData = DrawingEntitiesView.encodeEntities([entity]) - + let paintingData = TGPaintingData( drawing: nil, entitiesData: entitiesData, @@ -1156,7 +1204,7 @@ final class AvatarEditorScreenComponent: Component { previewView.layer.render(in: context) }, opaque: false)! - self.controller?()?.completion(combinedImage, tempUrl, TGVideoEditAdjustments(photoEditorValues: adjustments, preset: preset), { [weak self] in + self.controller?()?.completion(combinedImage, tempUrl, TGVideoEditAdjustments(photoEditorValues: adjustments, preset: preset, documentId: documentId, colors: colors), { [weak self] in self?.controller?()?.dismiss() }) } @@ -1182,11 +1230,11 @@ public final class AvatarEditorScreen: ViewControllerComponentContainer { public var completion: (UIImage, URL, TGVideoEditAdjustments, @escaping () -> Void) -> Void = { _, _, _, _ in } - public init(context: AccountContext) { + public init(context: AccountContext, initialFileId: Int64?, initialBackgroundColors: [Int32]?) { self.context = context let componentReady = Promise() - super.init(context: context, component: AvatarEditorScreenComponent(context: context, ready: componentReady), navigationBarAppearance: .transparent) + super.init(context: context, component: AvatarEditorScreenComponent(context: context, ready: componentReady, initialFileId: initialFileId, initialBackgroundColors: initialBackgroundColors), navigationBarAppearance: .transparent) self.navigationPresentation = .modal self.readyValue.set(componentReady.get() |> timeout(0.3, queue: .mainQueue(), alternate: .single(true))) diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift index 90190a4217..4272226fd6 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/BackgroundColorComponent.swift @@ -11,6 +11,7 @@ final class BackgroundColorComponent: Component { let theme: PresentationTheme let values: [AvatarBackground] let selectedValue: AvatarBackground + let customValue: AvatarBackground? let updateValue: (AvatarBackground) -> Void let openColorPicker: () -> Void @@ -18,12 +19,14 @@ final class BackgroundColorComponent: Component { theme: PresentationTheme, values: [AvatarBackground], selectedValue: AvatarBackground, + customValue: AvatarBackground?, updateValue: @escaping (AvatarBackground) -> Void, openColorPicker: @escaping () -> Void ) { self.theme = theme self.values = values self.selectedValue = selectedValue + self.customValue = customValue self.updateValue = updateValue self.openColorPicker = openColorPicker } @@ -38,6 +41,9 @@ final class BackgroundColorComponent: Component { if lhs.selectedValue != rhs.selectedValue { return false } + if lhs.customValue != rhs.customValue { + return false + } return true } @@ -62,8 +68,8 @@ final class BackgroundColorComponent: Component { self.state = state var values: [(AvatarBackground?, Bool)] = component.values.map { ($0, false) } - if !values.contains(where: { $0.0 == component.selectedValue }) { - values.append((component.selectedValue, true)) + if let customValue = component.customValue { + values.append((customValue, true)) } else { values.append((nil, true)) } @@ -91,9 +97,9 @@ final class BackgroundColorComponent: Component { isCustom: values[i].1, isSelected: component.selectedValue == values[i].0, action: { - if !values[i].1, let value = values[i].0 { + if let value = values[i].0, component.selectedValue != value { component.updateValue(value) - } else { + } else if values[i].1 { component.openColorPicker() } } diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift index e5c25f9aba..851f611299 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift @@ -20,6 +20,7 @@ private struct WallpaperColorPanelNodeState: Equatable { final class ColorPickerComponent: Component { let theme: PresentationTheme let strings: PresentationStrings + let isVisible: Bool let colors: [UInt32] let colorsChanged: ([UInt32]) -> Void let cancel: () -> Void @@ -28,6 +29,7 @@ final class ColorPickerComponent: Component { init( theme: PresentationTheme, strings: PresentationStrings, + isVisible: Bool, colors: [UInt32], colorsChanged: @escaping ([UInt32]) -> Void, cancel: @escaping () -> Void, @@ -35,6 +37,7 @@ final class ColorPickerComponent: Component { ) { self.theme = theme self.strings = strings + self.isVisible = isVisible self.colors = colors self.colorsChanged = colorsChanged self.cancel = cancel @@ -48,6 +51,9 @@ final class ColorPickerComponent: Component { if lhs.strings !== rhs.strings { return false } + if lhs.isVisible != rhs.isVisible { + return false + } if lhs.colors != rhs.colors { return false } @@ -381,6 +387,7 @@ final class ColorPickerComponent: Component { private var component: ColorPickerComponent? func update(component: ColorPickerComponent, availableSize: CGSize, transition: Transition) -> CGSize { let themeChanged = self.component?.theme !== component.theme + let previousIsVisible = self.component?.isVisible ?? false self.component = component let buttonHeight: CGFloat = 44.0 @@ -412,6 +419,11 @@ final class ColorPickerComponent: Component { self.updateState({ current in var updated = current updated.colors = component.colors.map { HSBColor(rgb: $0) } + + if component.isVisible != previousIsVisible && component.isVisible { + updated.selection = 0 + } + return updated }, updateLayout: true, notify: false, animated: false) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 29ff9d6a3c..2f55bb2d3d 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -7405,13 +7405,15 @@ public final class EmojiPagerContentComponent: Component { return combineLatest( context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: stickerOrderedItemListCollectionIds, namespaces: stickerNamespaces, aroundIndex: nil, count: 10000000), - forceHasPremium ? .single(true) : hasPremium(context: context, chatPeerId: chatPeerId, premiumIfSavedMessages: false), + hasPremium(context: context, chatPeerId: chatPeerId, premiumIfSavedMessages: false), hasTrending ? context.account.viewTracker.featuredStickerPacks() : .single([]), context.engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: Namespaces.CachedItemCollection.featuredStickersConfiguration, id: ValueBoxKey(length: 0))), ApplicationSpecificNotice.dismissedTrendingStickerPacks(accountManager: context.sharedContext.accountManager), peerSpecificPack ) |> map { view, hasPremium, featuredStickerPacks, featuredStickersConfiguration, dismissedTrendingStickerPacks, peerSpecificPack -> EmojiPagerContentComponent in + let actuallyHasPremium = hasPremium + let hasPremium = forceHasPremium || hasPremium struct ItemGroup { var supergroupId: AnyHashable var id: AnyHashable @@ -7597,7 +7599,7 @@ public final class EmojiPagerContentComponent: Component { } } - if let cloudPremiumStickers = cloudPremiumStickers, !cloudPremiumStickers.items.isEmpty { + if let cloudPremiumStickers = cloudPremiumStickers, !cloudPremiumStickers.items.isEmpty, actuallyHasPremium { premiumStickers.append(contentsOf: cloudPremiumStickers.items.compactMap { item -> StickerPackItem? in guard let item = item.contents.get(RecentMediaItem.self) else { return nil } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 0d8e6eb401..13c2f0a3b6 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -2391,7 +2391,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.dismissInput() strongSelf.present(controller, in: .window(.root)) case let .accepted(url): - strongSelf.openUrl(url, concealed: false, skipUrlAuth: true) + strongSelf.openUrl(url, concealed: false, forceExternal: true, skipUrlAuth: true) } } })) @@ -16021,10 +16021,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) } else { - self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(id: peer.id), subject: subject)) + if case let .channel(channel) = peer, channel.flags.contains(.isForum) { + self.effectiveNavigationController?.pushViewController(ChatListControllerImpl(context: self.context, location: .forum(peerId: channel.id), controlsHistoryPreload: false, enableDebugActions: false)) + } else { + self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(id: peer.id), subject: subject)) + } } case let .withBotStartPayload(botStart): - self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(id: peer.id), botStart: botStart)) + self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(id: peer.id), botStart: botStart)) case let .withAttachBot(attachBotStart): if let navigationController = self.effectiveNavigationController { self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), attachBotStart: attachBotStart)) diff --git a/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift b/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift index bacf1ca747..d3cc10954c 100644 --- a/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift +++ b/submodules/TelegramUIPreferences/Sources/PostboxKeys.swift @@ -73,6 +73,7 @@ private enum ApplicationSpecificItemCacheCollectionIdValues: Int8 { case visualMediaStoredState = 5 case cachedImageRecognizedContent = 6 case pendingInAppPurchaseState = 7 + case translationState = 8 } public struct ApplicationSpecificItemCacheCollectionId { @@ -84,6 +85,7 @@ public struct ApplicationSpecificItemCacheCollectionId { public static let visualMediaStoredState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.visualMediaStoredState.rawValue) public static let cachedImageRecognizedContent = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.cachedImageRecognizedContent.rawValue) public static let pendingInAppPurchaseState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.pendingInAppPurchaseState.rawValue) + public static let translationState = applicationSpecificItemCacheCollectionId(ApplicationSpecificItemCacheCollectionIdValues.translationState.rawValue) } private enum ApplicationSpecificOrderedItemListCollectionIdValues: Int32 {