diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 4b2a01ef9b..3c73dfa600 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -16160,3 +16160,9 @@ Error: %8$@"; "MediaPlayer.PlaylistYourTitle" = "Your Playlist"; "MediaPlayer.AudioForwardedToSavedMesagesTooltip" = "Audio forwarded to Saved Messages."; + +"Attachment.ProfileMusic" = "PROFILE MUSIC"; +"Attachment.ChatsMusic" = "YOUR CHATS"; +"Attachment.PublicMusic" = "PUBLIC CHATS"; + +"PeerInfo.UnofficialSecurityRisk" = "%@ uses an unofficial Telegram client – messages to this user may be less secure."; diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index bfd2e6adf3..b824d68588 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -1780,10 +1780,7 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate, ASGestureRecog } private func updateMediaAccessoryPanel(frame: CGRect?, transition: ContainedViewLayoutTransition) { - guard case .glass = self.panelStyle, - self.hasMediaAccessoryPanel, - let frame, - let (item, previousItem, nextItem, order, type, _) = self.playlistStateAndType else { + guard case .glass = self.panelStyle, self.hasMediaAccessoryPanel, let frame, let (item, previousItem, nextItem, order, type, _) = self.playlistStateAndType else { self.dismissMediaAccessoryPanel(transition: transition) return } @@ -1825,6 +1822,8 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate, ASGestureRecog transition.updateFrame(node: mediaAccessoryPanel, frame: frame) mediaAccessoryPanel.updateLayout(size: frame.size, leftInset: inset, rightInset: inset, isHidden: false, transition: transition) } + + transition.updateAlpha(node: mediaAccessoryPanel.containerNode.headerNode.separatorNode, alpha: self.hideButtons ? 0.0 : 1.0) } func updateBackgroundAlpha(_ alpha: CGFloat, transition: ContainedViewLayoutTransition) { diff --git a/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift b/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift index bf1132496f..b21392f866 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift @@ -17,6 +17,11 @@ public enum InfoListItemLinkAction { } public class InfoListItem: ListViewItem { + public enum InfoStyle { + case `default` + case compact + } + public let selectable: Bool = false let presentationData: ItemListPresentationData @@ -26,10 +31,11 @@ public class InfoListItem: ListViewItem { let style: ItemListStyle let hasDecorations: Bool let isWarning: Bool + let infoStyle: InfoStyle let linkAction: ((InfoListItemLinkAction) -> Void)? let closeAction: (() -> Void)? - public init(presentationData: ItemListPresentationData, systemStyle: ItemListSystemStyle = .legacy, title: String, text: InfoListItemText, style: ItemListStyle, hasDecorations: Bool = true, isWarning: Bool = false, linkAction: ((InfoListItemLinkAction) -> Void)? = nil, closeAction: (() -> Void)?) { + public init(presentationData: ItemListPresentationData, systemStyle: ItemListSystemStyle = .legacy, title: String, text: InfoListItemText, style: ItemListStyle, hasDecorations: Bool = true, isWarning: Bool = false, infoStyle: InfoStyle = .default, linkAction: ((InfoListItemLinkAction) -> Void)? = nil, closeAction: (() -> Void)?) { self.presentationData = presentationData self.systemStyle = systemStyle self.title = title @@ -37,6 +43,7 @@ public class InfoListItem: ListViewItem { self.style = style self.hasDecorations = hasDecorations self.isWarning = isWarning + self.infoStyle = infoStyle self.linkAction = linkAction self.closeAction = closeAction } @@ -226,6 +233,7 @@ public class InfoItemNode: ListViewItemNode { let smallerTextFont = Font.regular(item.presentationData.fontSize.itemListBaseLabelFontSize / 14.0 * 15.0) let textFont = Font.regular(item.presentationData.fontSize.itemListBaseLabelFontSize / 14.0 * 16.0) let textBoldFont = Font.semibold(item.presentationData.fontSize.itemListBaseLabelFontSize / 14.0 * 16.0) + let smallBadgeFont = Font.semibold(11.0) let badgeFont = Font.regular(15.0) let largeBadgeFont = Font.regular(24.0) @@ -234,7 +242,18 @@ public class InfoItemNode: ListViewItemNode { var updatedCloseIcon: UIImage? - let badgeDiameter: CGFloat = item.isWarning ? 30.0 : 22.0 + let badgeDiameter: CGFloat + let effectiveBadgeFont: UIFont + if item.isWarning { + badgeDiameter = 30.0 + effectiveBadgeFont = largeBadgeFont + } else if case .compact = item.infoStyle { + badgeDiameter = 15.0 + effectiveBadgeFont = smallBadgeFont + } else { + badgeDiameter = 22.0 + effectiveBadgeFont = badgeFont + } if currentItem?.presentationData.theme !== item.presentationData.theme { updatedTheme = item.presentationData.theme updatedBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: item.presentationData.theme.list.itemDestructiveColor) @@ -267,21 +286,33 @@ public class InfoItemNode: ListViewItemNode { case let .plain(text): attributedText = NSAttributedString(string: text, font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor) case let .markdown(text): - attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: item.isWarning ? smallerTextFont : textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), bold: MarkdownAttributeSet(font: textBoldFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), link: MarkdownAttributeSet(font: textFont, textColor: item.presentationData.theme.list.itemAccentColor), linkAttribute: { contents in + attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: item.isWarning || item.infoStyle == .compact ? smallerTextFont : textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), bold: MarkdownAttributeSet(font: textBoldFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), link: MarkdownAttributeSet(font: textFont, textColor: item.presentationData.theme.list.itemAccentColor), linkAttribute: { contents in return (TelegramTextAttributes.URL, contents) })) } - let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.isWarning ? "⚠️" : "!", font: item.isWarning ? largeBadgeFont : badgeFont, textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 3, truncationType: .end, constrainedSize: CGSize(width: 100.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + var textCutout: TextNodeCutout? + if case .compact = item.infoStyle, item.title.isEmpty { + textCutout = TextNodeCutout(topLeft: CGSize(width: 22.0, height: 8.0), topRight: nil, bottomRight: nil) + } + + let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.isWarning ? "⚠️" : "!", font: effectiveBadgeFont, textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 3, truncationType: .end, constrainedSize: CGSize(width: 100.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - badgeDiameter - 8.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: textCutout, insets: UIEdgeInsets())) var verticalInset: CGFloat = 0.0 if case .glass = item.systemStyle { verticalInset = 4.0 } - let contentSize = CGSize(width: params.width, height: titleLayout.size.height + textLayout.size.height + 38.0 + verticalInset * 2.0) + var contentHeight: CGFloat = titleLayout.size.height + textLayout.size.height + verticalInset * 2.0 + if case .compact = item.infoStyle { + contentHeight += 13.0 + } else { + contentHeight += 38.0 + } + + let contentSize = CGSize(width: params.width, height: contentHeight) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) return (layout, { [weak self] in @@ -345,6 +376,9 @@ public class InfoItemNode: ListViewItemNode { bottomStripeInset = leftInset if !item.hasDecorations { strongSelf.topStripeNode.isHidden = true + if case .compact = item.infoStyle { + strongSelf.bottomStripeNode.isHidden = true + } } } @@ -369,13 +403,34 @@ public class InfoItemNode: ListViewItemNode { strongSelf.closeButton.setImage(updatedCloseIcon, for: []) } - strongSelf.badgeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset + 15.0 + (item.isWarning ? 4.0 : 0.0)), size: CGSize(width: badgeDiameter, height: badgeDiameter)) + var badgeOriginX: CGFloat = leftInset + let badgeOriginY: CGFloat + var labelOffset: CGPoint = .zero + if item.isWarning { + badgeOriginY = verticalInset + 15.0 + 4.0 + } else if case .compact = item.infoStyle { + badgeOriginY = 12.0 + badgeOriginX += 1 + labelOffset = CGPoint(x: UIScreenPixel, y: -1.0) + } else { + badgeOriginY = verticalInset + 15.0 + } - strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: strongSelf.badgeNode.frame.midX - labelLayout.size.width / 2.0, y: strongSelf.badgeNode.frame.minY + 2.0 + UIScreenPixel), size: labelLayout.size) + strongSelf.badgeNode.frame = CGRect(origin: CGPoint(x: badgeOriginX, y: badgeOriginY), size: CGSize(width: badgeDiameter, height: badgeDiameter)) + + strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels(strongSelf.badgeNode.frame.midX - labelLayout.size.width / 2.0) + labelOffset.x, y: strongSelf.badgeNode.frame.minY + 2.0 + UIScreenPixel + labelOffset.y), size: labelLayout.size) strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: strongSelf.badgeNode.frame.maxX + 8.0, y: verticalInset + 16.0), size: titleLayout.size) - strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: strongSelf.titleNode.frame.maxY + 9.0), size: textLayout.size) + let textOriginY: CGFloat + if titleLayout.size.height > 0.0 { + textOriginY = strongSelf.titleNode.frame.maxY + 9.0 + } else if case .compact = item.infoStyle { + textOriginY = 11.0 + } else { + textOriginY = verticalInset + 16.0 + } + strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: textOriginY), size: textLayout.size) strongSelf.closeButton.frame = CGRect(x: params.width - rightInset - 26.0, y: verticalInset + 10.0, width: 32.0, height: 32.0) } diff --git a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift index fdf79ae74c..63b601b3e9 100644 --- a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift @@ -561,7 +561,13 @@ public final class ListMessageFileItemNode: ListMessageNode { guard let item = self.item, let message = item.message else { return } - item.interaction.toggleMediaPlayback?(message) + if let resourceStatus = self.resourceStatus, case .playbackStatus = resourceStatus { + if let context = self.context { + context.sharedContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: nil) + } + } else { + item.interaction.toggleMediaPlayback?(message) + } } override public func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) { @@ -1696,7 +1702,11 @@ public final class ListMessageFileItemNode: ListMessageNode { } case .playbackStatus: if let context = self.context { - context.sharedContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: nil) + if let item = self.item, let message = item.message, let interaction = self.interaction, item.isStoryMusic { + let _ = interaction.openMessage(message, .default) + } else { + context.sharedContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: nil) + } } } } diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index abc82754de..6a56740d86 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -1065,7 +1065,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1898850301] = { return Api.StoriesStealthMode.parse_storiesStealthMode($0) } dict[-1826262950] = { return Api.StoryAlbum.parse_storyAlbum($0) } dict[-1205411504] = { return Api.StoryFwdHeader.parse_storyFwdHeader($0) } - dict[-302947087] = { return Api.StoryItem.parse_storyItem($0) } + dict[379894076] = { return Api.StoryItem.parse_storyItem($0) } dict[1374088783] = { return Api.StoryItem.parse_storyItemDeleted($0) } dict[-5388013] = { return Api.StoryItem.parse_storyItemSkipped($0) } dict[1620104917] = { return Api.StoryReaction.parse_storyReaction($0) } diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index 0394a490ae..eb5b139182 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -430,7 +430,8 @@ public extension Api { public var views: Api.StoryViews? public var sentReaction: Api.Reaction? public var albums: [Int32]? - public init(flags: Int32, id: Int32, date: Int32, fromId: Api.Peer?, fwdFrom: Api.StoryFwdHeader?, expireDate: Int32, caption: String?, entities: [Api.MessageEntity]?, media: Api.MessageMedia, mediaAreas: [Api.MediaArea]?, privacy: [Api.PrivacyRule]?, views: Api.StoryViews?, sentReaction: Api.Reaction?, albums: [Int32]?) { + public var music: Api.Document? + public init(flags: Int32, id: Int32, date: Int32, fromId: Api.Peer?, fwdFrom: Api.StoryFwdHeader?, expireDate: Int32, caption: String?, entities: [Api.MessageEntity]?, media: Api.MessageMedia, mediaAreas: [Api.MediaArea]?, privacy: [Api.PrivacyRule]?, views: Api.StoryViews?, sentReaction: Api.Reaction?, albums: [Int32]?, music: Api.Document?) { self.flags = flags self.id = id self.date = date @@ -445,9 +446,10 @@ public extension Api { self.views = views self.sentReaction = sentReaction self.albums = albums + self.music = music } public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) { - return ("storyItem", [("flags", ConstructorParameterDescription(self.flags)), ("id", ConstructorParameterDescription(self.id)), ("date", ConstructorParameterDescription(self.date)), ("fromId", ConstructorParameterDescription(self.fromId)), ("fwdFrom", ConstructorParameterDescription(self.fwdFrom)), ("expireDate", ConstructorParameterDescription(self.expireDate)), ("caption", ConstructorParameterDescription(self.caption)), ("entities", ConstructorParameterDescription(self.entities)), ("media", ConstructorParameterDescription(self.media)), ("mediaAreas", ConstructorParameterDescription(self.mediaAreas)), ("privacy", ConstructorParameterDescription(self.privacy)), ("views", ConstructorParameterDescription(self.views)), ("sentReaction", ConstructorParameterDescription(self.sentReaction)), ("albums", ConstructorParameterDescription(self.albums))]) + return ("storyItem", [("flags", ConstructorParameterDescription(self.flags)), ("id", ConstructorParameterDescription(self.id)), ("date", ConstructorParameterDescription(self.date)), ("fromId", ConstructorParameterDescription(self.fromId)), ("fwdFrom", ConstructorParameterDescription(self.fwdFrom)), ("expireDate", ConstructorParameterDescription(self.expireDate)), ("caption", ConstructorParameterDescription(self.caption)), ("entities", ConstructorParameterDescription(self.entities)), ("media", ConstructorParameterDescription(self.media)), ("mediaAreas", ConstructorParameterDescription(self.mediaAreas)), ("privacy", ConstructorParameterDescription(self.privacy)), ("views", ConstructorParameterDescription(self.views)), ("sentReaction", ConstructorParameterDescription(self.sentReaction)), ("albums", ConstructorParameterDescription(self.albums)), ("music", ConstructorParameterDescription(self.music))]) } } public class Cons_storyItemDeleted: TypeConstructorDescription { @@ -482,7 +484,7 @@ public extension Api { switch self { case .storyItem(let _data): if boxed { - buffer.appendInt32(-302947087) + buffer.appendInt32(379894076) } serializeInt32(_data.flags, buffer: buffer, boxed: false) serializeInt32(_data.id, buffer: buffer, boxed: false) @@ -532,6 +534,9 @@ public extension Api { serializeInt32(item, buffer: buffer, boxed: false) } } + if Int(_data.flags) & Int(1 << 20) != 0 { + _data.music!.serialize(buffer, true) + } break case .storyItemDeleted(let _data): if boxed { @@ -554,7 +559,7 @@ public extension Api { public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) { switch self { case .storyItem(let _data): - return ("storyItem", [("flags", ConstructorParameterDescription(_data.flags)), ("id", ConstructorParameterDescription(_data.id)), ("date", ConstructorParameterDescription(_data.date)), ("fromId", ConstructorParameterDescription(_data.fromId)), ("fwdFrom", ConstructorParameterDescription(_data.fwdFrom)), ("expireDate", ConstructorParameterDescription(_data.expireDate)), ("caption", ConstructorParameterDescription(_data.caption)), ("entities", ConstructorParameterDescription(_data.entities)), ("media", ConstructorParameterDescription(_data.media)), ("mediaAreas", ConstructorParameterDescription(_data.mediaAreas)), ("privacy", ConstructorParameterDescription(_data.privacy)), ("views", ConstructorParameterDescription(_data.views)), ("sentReaction", ConstructorParameterDescription(_data.sentReaction)), ("albums", ConstructorParameterDescription(_data.albums))]) + return ("storyItem", [("flags", ConstructorParameterDescription(_data.flags)), ("id", ConstructorParameterDescription(_data.id)), ("date", ConstructorParameterDescription(_data.date)), ("fromId", ConstructorParameterDescription(_data.fromId)), ("fwdFrom", ConstructorParameterDescription(_data.fwdFrom)), ("expireDate", ConstructorParameterDescription(_data.expireDate)), ("caption", ConstructorParameterDescription(_data.caption)), ("entities", ConstructorParameterDescription(_data.entities)), ("media", ConstructorParameterDescription(_data.media)), ("mediaAreas", ConstructorParameterDescription(_data.mediaAreas)), ("privacy", ConstructorParameterDescription(_data.privacy)), ("views", ConstructorParameterDescription(_data.views)), ("sentReaction", ConstructorParameterDescription(_data.sentReaction)), ("albums", ConstructorParameterDescription(_data.albums)), ("music", ConstructorParameterDescription(_data.music))]) case .storyItemDeleted(let _data): return ("storyItemDeleted", [("id", ConstructorParameterDescription(_data.id))]) case .storyItemSkipped(let _data): @@ -627,6 +632,12 @@ public extension Api { _14 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) } } + var _15: Api.Document? + if Int(_1!) & Int(1 << 20) != 0 { + if let signature = reader.readInt32() { + _15 = Api.parse(reader, signature: signature) as? Api.Document + } + } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -641,8 +652,9 @@ public extension Api { let _c12 = (Int(_1!) & Int(1 << 3) == 0) || _12 != nil let _c13 = (Int(_1!) & Int(1 << 15) == 0) || _13 != nil let _c14 = (Int(_1!) & Int(1 << 19) == 0) || _14 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 { - return Api.StoryItem.storyItem(Cons_storyItem(flags: _1!, id: _2!, date: _3!, fromId: _4, fwdFrom: _5, expireDate: _6!, caption: _7, entities: _8, media: _9!, mediaAreas: _10, privacy: _11, views: _12, sentReaction: _13, albums: _14)) + let _c15 = (Int(_1!) & Int(1 << 20) == 0) || _15 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { + return Api.StoryItem.storyItem(Cons_storyItem(flags: _1!, id: _2!, date: _3!, fromId: _4, fwdFrom: _5, expireDate: _6!, caption: _7, entities: _8, media: _9!, mediaAreas: _10, privacy: _11, views: _12, sentReaction: _13, albums: _14, music: _15)) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api40.swift b/submodules/TelegramApi/Sources/Api40.swift index cc6a0f7a60..3ed3e4f75b 100644 --- a/submodules/TelegramApi/Sources/Api40.swift +++ b/submodules/TelegramApi/Sources/Api40.swift @@ -12788,9 +12788,9 @@ public extension Api.functions.stories { } } public extension Api.functions.stories { - static func editStory(flags: Int32, peer: Api.InputPeer, id: Int32, media: Api.InputMedia?, mediaAreas: [Api.MediaArea]?, caption: String?, entities: [Api.MessageEntity]?, privacyRules: [Api.InputPrivacyRule]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func editStory(flags: Int32, peer: Api.InputPeer, id: Int32, media: Api.InputMedia?, mediaAreas: [Api.MediaArea]?, caption: String?, entities: [Api.MessageEntity]?, privacyRules: [Api.InputPrivacyRule]?, music: Api.InputDocument?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-1249658298) + buffer.appendInt32(744728363) serializeInt32(flags, buffer: buffer, boxed: false) peer.serialize(buffer, true) serializeInt32(id, buffer: buffer, boxed: false) @@ -12821,7 +12821,10 @@ public extension Api.functions.stories { item.serialize(buffer, true) } } - return (FunctionDescription(name: "stories.editStory", parameters: [("flags", ConstructorParameterDescription(flags)), ("peer", ConstructorParameterDescription(peer)), ("id", ConstructorParameterDescription(id)), ("media", ConstructorParameterDescription(media)), ("mediaAreas", ConstructorParameterDescription(mediaAreas)), ("caption", ConstructorParameterDescription(caption)), ("entities", ConstructorParameterDescription(entities)), ("privacyRules", ConstructorParameterDescription(privacyRules))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + if Int(flags) & Int(1 << 4) != 0 { + music!.serialize(buffer, true) + } + return (FunctionDescription(name: "stories.editStory", parameters: [("flags", ConstructorParameterDescription(flags)), ("peer", ConstructorParameterDescription(peer)), ("id", ConstructorParameterDescription(id)), ("media", ConstructorParameterDescription(media)), ("mediaAreas", ConstructorParameterDescription(mediaAreas)), ("caption", ConstructorParameterDescription(caption)), ("entities", ConstructorParameterDescription(entities)), ("privacyRules", ConstructorParameterDescription(privacyRules)), ("music", ConstructorParameterDescription(music))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { @@ -13204,9 +13207,9 @@ public extension Api.functions.stories { } } public extension Api.functions.stories { - static func sendStory(flags: Int32, peer: Api.InputPeer, media: Api.InputMedia, mediaAreas: [Api.MediaArea]?, caption: String?, entities: [Api.MessageEntity]?, privacyRules: [Api.InputPrivacyRule], randomId: Int64, period: Int32?, fwdFromId: Api.InputPeer?, fwdFromStory: Int32?, albums: [Int32]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func sendStory(flags: Int32, peer: Api.InputPeer, media: Api.InputMedia, mediaAreas: [Api.MediaArea]?, caption: String?, entities: [Api.MessageEntity]?, privacyRules: [Api.InputPrivacyRule], randomId: Int64, period: Int32?, fwdFromId: Api.InputPeer?, fwdFromStory: Int32?, albums: [Int32]?, music: Api.InputDocument?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(1937752812) + buffer.appendInt32(-1885443944) serializeInt32(flags, buffer: buffer, boxed: false) peer.serialize(buffer, true) media.serialize(buffer, true) @@ -13249,7 +13252,10 @@ public extension Api.functions.stories { serializeInt32(item, buffer: buffer, boxed: false) } } - return (FunctionDescription(name: "stories.sendStory", parameters: [("flags", ConstructorParameterDescription(flags)), ("peer", ConstructorParameterDescription(peer)), ("media", ConstructorParameterDescription(media)), ("mediaAreas", ConstructorParameterDescription(mediaAreas)), ("caption", ConstructorParameterDescription(caption)), ("entities", ConstructorParameterDescription(entities)), ("privacyRules", ConstructorParameterDescription(privacyRules)), ("randomId", ConstructorParameterDescription(randomId)), ("period", ConstructorParameterDescription(period)), ("fwdFromId", ConstructorParameterDescription(fwdFromId)), ("fwdFromStory", ConstructorParameterDescription(fwdFromStory)), ("albums", ConstructorParameterDescription(albums))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + if Int(flags) & Int(1 << 9) != 0 { + music!.serialize(buffer, true) + } + return (FunctionDescription(name: "stories.sendStory", parameters: [("flags", ConstructorParameterDescription(flags)), ("peer", ConstructorParameterDescription(peer)), ("media", ConstructorParameterDescription(media)), ("mediaAreas", ConstructorParameterDescription(mediaAreas)), ("caption", ConstructorParameterDescription(caption)), ("entities", ConstructorParameterDescription(entities)), ("privacyRules", ConstructorParameterDescription(privacyRules)), ("randomId", ConstructorParameterDescription(randomId)), ("period", ConstructorParameterDescription(period)), ("fwdFromId", ConstructorParameterDescription(fwdFromId)), ("fwdFromStory", ConstructorParameterDescription(fwdFromStory)), ("albums", ConstructorParameterDescription(albums)), ("music", ConstructorParameterDescription(music))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift index e052415e73..4cca7d51fe 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift @@ -176,7 +176,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, ASScrollVi } } - private let separatorNode: ASDisplayNode + public let separatorNode: ASDisplayNode private var tapRecognizer: UITapGestureRecognizer? diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index da3df8516c..fa9819893f 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -629,6 +629,7 @@ public struct CachedUserFlags: OptionSet { public static let displayGiftButton = CachedUserFlags(rawValue: 1 << 7) public static let myCopyProtectionEnabled = CachedUserFlags(rawValue: 1 << 8) public static let copyProtectionEnabled = CachedUserFlags(rawValue: 1 << 9) + public static let unofficialSecurityRisk = CachedUserFlags(rawValue: 1 << 10) } public final class EditableBotInfo: PostboxCoding, Equatable { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift index ed1f838395..065cf8fe7b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift @@ -1373,6 +1373,8 @@ func _internal_uploadStoryImpl( flags |= 1 << 8 } + //var apiMusic: Api.InputDocument? + return network.request(Api.functions.stories.sendStory( flags: flags, peer: inputPeer, @@ -1385,7 +1387,8 @@ func _internal_uploadStoryImpl( period: Int32(period), fwdFromId: fwdFromId, fwdFromStory: fwdFromStory, - albums: folders.isEmpty ? nil : folders.map(Int32.init(clamping:)) + albums: folders.isEmpty ? nil : folders.map(Int32.init(clamping:)), + music: nil )) |> map(Optional.init) |> `catch` { _ -> Signal in @@ -1798,7 +1801,8 @@ func _internal_editStory(account: Account, peerId: PeerId, id: Int32, media: Eng mediaAreas: inputMediaAreas, caption: apiCaption, entities: apiEntities, - privacyRules: privacyRules + privacyRules: privacyRules, + music: nil )) |> map(Optional.init) |> `catch` { _ -> Signal in @@ -1907,7 +1911,7 @@ func _internal_editStoryPrivacy(account: Account, id: Int32, privacy: EngineStor var flags: Int32 = 0 flags |= 1 << 2 - return account.network.request(Api.functions.stories.editStory(flags: flags, peer: .inputPeerSelf, id: id, media: nil, mediaAreas: nil, caption: nil, entities: nil, privacyRules: inputRules)) + return account.network.request(Api.functions.stories.editStory(flags: flags, peer: .inputPeerSelf, id: id, media: nil, mediaAreas: nil, caption: nil, entities: nil, privacyRules: inputRules, music: nil)) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 2da300a3dd..5f1a6d6d8a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -299,6 +299,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee let displayGiftButton = (userFullFlags2 & (1 << 16)) != 0 let myCopyProtectionEnabled = (userFullFlags2 & (1 << 23)) != 0 let copyProtectionEnabled = (userFullFlags2 & (1 << 24)) != 0 + let unofficialSecurityRisk = (userFullFlags2 & (1 << 26)) != 0 var flags: CachedUserFlags = previous.flags if premiumRequired { @@ -346,6 +347,11 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee } else { flags.remove(.copyProtectionEnabled) } + if unofficialSecurityRisk { + flags.insert(.unofficialSecurityRisk) + } else { + flags.remove(.unofficialSecurityRisk) + } let callsPrivate = (userFullFlags & (1 << 5)) != 0 let canPinMessages = (userFullFlags & (1 << 7)) != 0 diff --git a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift index 54020f8041..d69c236735 100644 --- a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift +++ b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift @@ -337,12 +337,12 @@ private func attachmentFileControllerEntries( case .recent: listTitle = presentationData.strings.Attachment_RecentlySentFiles case .audio: - listTitle = presentationData.strings.Attachment_SharedAudio + listTitle = presentationData.strings.Attachment_ChatsMusic } if case let .audio(audioMode) = mode, audioMode != .savedMusic { if let savedMusic, savedMusic.count > 0 { - entries.append(.savedHeader(presentationData.theme, presentationData.strings.MediaEditor_Audio_SavedMusic.uppercased())) + entries.append(.savedHeader(presentationData.theme, presentationData.strings.Attachment_ProfileMusic.uppercased())) var savedMusic = savedMusic var hasShowMore = false diff --git a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift index 008f97b418..d9931d830c 100644 --- a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift +++ b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift @@ -484,11 +484,13 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon send(message) self?.listNode.clearHighlightAnimated(true) }, - toggleMediaPlayback: { message in + toggleMediaPlayback: { [weak self] message in didPreviewAudio() let playlistLocation: PeerMessagesPlaylistLocation = .custom(messages: .single(([message], 0, false)), canReorder: false, at: message.id, loadMore: nil, hidePanel: true) context.sharedContext.mediaManager.setPlaylist((context, PeerMessagesMediaPlaylist(context: context, location: playlistLocation, chatLocationContextHolder: nil)), type: .music, control: .playback(.togglePlayPause)) + + self?.view.window?.endEditing(true) }, expandSection: { [weak self] section in self?.expandedSections.insert(section) @@ -631,7 +633,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon var index: Int32 = 0 if let savedMusic, !savedMusic.isEmpty { - entries.append(.header(title: "PROFILE MUSIC", section: section)) + entries.append(.header(title: presentationData.strings.Attachment_ProfileMusic, section: section)) var savedMusic = savedMusic var hasShowMore = false @@ -652,7 +654,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon section += 1 if !messages.isEmpty { - entries.append(.header(title: "YOUR CHATS", section: section)) + entries.append(.header(title: presentationData.strings.Attachment_ChatsMusic, section: section)) var messages = messages var hasShowMore = false if messages.count > 4 && !expandedSections.contains(section) { @@ -672,7 +674,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon index = 0 section += 1 - entries.append(.header(title: "PUBLIC CHATS", section: section)) + entries.append(.header(title: presentationData.strings.Attachment_PublicMusic, section: section)) for message in globalMusic { entries.append(.file(index: index, message: message, section: section)) index += 1 diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenInfoItem.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenInfoItem.swift index 4dd64be939..9dab9b2ccc 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenInfoItem.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenInfoItem.swift @@ -15,6 +15,7 @@ final class PeerInfoScreenInfoItem: PeerInfoScreenItem { let title: String let text: InfoListItemText let isWarning: Bool + let style: InfoListItem.InfoStyle let linkAction: ((InfoListItemLinkAction) -> Void)? init( @@ -22,12 +23,14 @@ final class PeerInfoScreenInfoItem: PeerInfoScreenItem { title: String, text: InfoListItemText, isWarning: Bool = false, + style: InfoListItem.InfoStyle = .default, linkAction: ((InfoListItemLinkAction) -> Void)? ) { self.id = id self.title = title self.text = text self.isWarning = isWarning + self.style = style self.linkAction = linkAction } @@ -67,7 +70,7 @@ private final class PeerInfoScreenInfoItemNode: PeerInfoScreenItemNode { self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor - let infoItem = InfoListItem(presentationData: ItemListPresentationData(presentationData), systemStyle: .glass, title: item.title, text: item.text, style: .blocks, hasDecorations: false, isWarning: item.isWarning, linkAction: { link in + let infoItem = InfoListItem(presentationData: ItemListPresentationData(presentationData), systemStyle: .glass, title: item.title, text: item.text, style: .blocks, hasDecorations: false, isWarning: item.isWarning, infoStyle: item.style, linkAction: { link in item.linkAction?(link) }, closeAction: nil) let params = ListViewItemLayoutParams(width: width, leftInset: safeInsets.left, rightInset: safeInsets.right, availableHeight: 1000.0) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift index 5efc444d18..d24b90a11c 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift @@ -22,6 +22,7 @@ private let enabledPublicBioEntities: EnabledEntityTypes = [.allUrl, .mention, . private let enabledPrivateBioEntities: EnabledEntityTypes = [.internalUrl, .mention, .hashtag] enum InfoSection: Int, CaseIterable { + case unofficial case groupLocation case calls case personalChannel @@ -98,6 +99,10 @@ func infoItems(data: PeerInfoScreenData?, context: AccountContext, presentationD let ItemBotAddToChatInfo = 9003 let ItemVerification = 9004 + if let cachedUserData = data.cachedData as? CachedUserData, cachedUserData.flags.contains(.unofficialSecurityRisk) { + items[.unofficial]!.append(PeerInfoScreenInfoItem(id: 0, title: "", text: .markdown(presentationData.strings.PeerInfo_UnofficialSecurityRisk(EnginePeer(user).compactDisplayTitle).string), style: .compact, linkAction: nil)) + } + if !callMessages.isEmpty { items[.calls]!.append(PeerInfoScreenCallListItem(id: ItemCallList, messages: callMessages)) }