diff --git a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift index 98f2b8403a..77e1318921 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift @@ -125,7 +125,7 @@ class InviteLinkHeaderItemNode: ListViewItemNode { strongSelf.item = item strongSelf.accessibilityLabel = attributedText.string - let iconSize = CGSize(width: 96.0, height: 96.0) + let iconSize = CGSize(width: 128.0, height: 128.0) strongSelf.animationNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: -10.0), size: iconSize) strongSelf.animationNode.updateLayout(size: iconSize) diff --git a/submodules/ItemListUI/Sources/ItemListRevealOptionsNode.swift b/submodules/ItemListUI/Sources/ItemListRevealOptionsNode.swift index 0a0ae7e0b8..aaad314744 100644 --- a/submodules/ItemListUI/Sources/ItemListRevealOptionsNode.swift +++ b/submodules/ItemListUI/Sources/ItemListRevealOptionsNode.swift @@ -83,6 +83,7 @@ private final class ItemListRevealOptionNode: ASDisplayNode { private let iconNode: ASImageNode? private let animationNode: SimpleAnimationNode? + private var animationScale: CGFloat = 1.0 private var animationNodeOffset: CGFloat = 0.0 private var animationNodeFlip = false var alignment: ItemListRevealOptionAlignment? @@ -102,7 +103,8 @@ private final class ItemListRevealOptionNode: ASDisplayNode { self.iconNode = iconNode self.animationNode = nil - case let .animation(animation, _, offset, replaceColors, flip): + case let .animation(animation, scale, offset, replaceColors, flip): + self.animationScale = scale self.iconNode = nil var colors: [UInt32: UInt32] = [:] if let replaceColors = replaceColors { @@ -194,7 +196,7 @@ private final class ItemListRevealOptionNode: ASDisplayNode { } if let animationNode = self.animationNode { - let imageSize = animationNode.size + let imageSize = CGSize(width: animationNode.size.width * self.animationScale, height: animationNode.size.height * self.animationScale) let iconOffset: CGFloat = -2.0 + self.animationNodeOffset let titleIconSpacing: CGFloat = 11.0 let iconFrame = CGRect(origin: CGPoint(x: contentRect.minX + floor((baseSize.width - imageSize.width + sideInset) / 2.0), y: contentRect.midY - imageSize.height / 2.0 + iconOffset), size: imageSize) diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 6bc2c4de59..49309ad658 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -455,6 +455,7 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { case let .joinToSendEveryone(_, text, selected): return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: { arguments.updateJoinToSend(.everyone) + arguments.toggleApproveMembers(false) }) case let .joinToSendMembers(_, text, selected): return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: { @@ -816,13 +817,24 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa entries.append(.privateLinkManageInfo(presentationData.theme, presentationData.strings.InviteLink_CreateInfo)) } } + + if isGroup { + var isDiscussion = false + if let cachedData = view.cachedData as? CachedChannelData, case .known = cachedData.linkedDiscussionPeerId { + isDiscussion = true + } + + if isDiscussion { + entries.append(.joinToSendHeader(presentationData.theme, presentationData.strings.Group_Setup_WhoCanSendMessages_Title.uppercased())) + entries.append(.joinToSendEveryone(presentationData.theme, presentationData.strings.Group_Setup_WhoCanSendMessages_Everyone, joinToSend == .everyone)) + entries.append(.joinToSendMembers(presentationData.theme, presentationData.strings.Group_Setup_WhoCanSendMessages_OnlyMembers, joinToSend == .members)) + } - entries.append(.joinToSendHeader(presentationData.theme, presentationData.strings.Group_Setup_WhoCanSendMessages_Title.uppercased())) - entries.append(.joinToSendEveryone(presentationData.theme, presentationData.strings.Group_Setup_WhoCanSendMessages_Everyone, joinToSend == .everyone)) - entries.append(.joinToSendMembers(presentationData.theme, presentationData.strings.Group_Setup_WhoCanSendMessages_OnlyMembers, joinToSend == .members)) - - entries.append(.approveMembers(presentationData.theme, presentationData.strings.Group_Setup_ApproveNewMembers, approveMembers)) - entries.append(.approveMembersInfo(presentationData.theme, presentationData.strings.Group_Setup_ApproveNewMembersInfo)) + if !isDiscussion || joinToSend == .members { + entries.append(.approveMembers(presentationData.theme, presentationData.strings.Group_Setup_ApproveNewMembers, approveMembers)) + entries.append(.approveMembersInfo(presentationData.theme, presentationData.strings.Group_Setup_ApproveNewMembersInfo)) + } + } entries.append(.forwardingHeader(presentationData.theme, isGroup ? presentationData.strings.Group_Setup_ForwardingGroupTitle.uppercased() : presentationData.strings.Group_Setup_ForwardingChannelTitle.uppercased())) entries.append(.forwardingDisabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingDisabled, !forwardingEnabled)) @@ -1074,6 +1086,12 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta let toggleCopyProtectionDisposable = MetaDisposable() actionsDisposable.add(toggleCopyProtectionDisposable) + let toggleJoinToSendDisposable = MetaDisposable() + actionsDisposable.add(toggleJoinToSendDisposable) + + let toggleRequestToJoinDisposable = MetaDisposable() + actionsDisposable.add(toggleRequestToJoinDisposable) + let arguments = ChannelVisibilityControllerArguments(context: context, updateCurrentType: { type in updateState { state in return state.withUpdatedSelectedType(type) @@ -1358,11 +1376,11 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta } if let updatedJoinToSend = state.joinToSend { - toggleCopyProtectionDisposable.set(context.engine.peers.toggleChannelJoinToSend(peerId: peerId, enabled: updatedJoinToSend == .members).start()) + toggleJoinToSendDisposable.set(context.engine.peers.toggleChannelJoinToSend(peerId: peerId, enabled: updatedJoinToSend == .members).start()) } if let updatedApproveMembers = state.approveMembers { - toggleCopyProtectionDisposable.set(context.engine.peers.toggleChannelJoinRequest(peerId: peerId, enabled: updatedApproveMembers).start()) + toggleRequestToJoinDisposable.set(context.engine.peers.toggleChannelJoinRequest(peerId: peerId, enabled: updatedApproveMembers).start()) } if let updatedAddressNameValue = updatedAddressNameValue { diff --git a/submodules/TelegramCore/Sources/ApiUtils/BotInfo.swift b/submodules/TelegramCore/Sources/ApiUtils/BotInfo.swift index f99f7b8f1d..b497a0bb16 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/BotInfo.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/BotInfo.swift @@ -16,7 +16,8 @@ extension BotMenuButton { extension BotInfo { convenience init(apiBotInfo: Api.BotInfo) { switch apiBotInfo { - case let .botInfo(_, _, description, _, apiCommands, apiMenuButton): + case let .botInfo(_, _, description, descriptionPhoto, apiCommands, apiMenuButton): + let photo: TelegramMediaImage? = descriptionPhoto.flatMap(telegramMediaImageFromApiPhoto) var commands: [BotCommand] = [] if let apiCommands = apiCommands { commands = apiCommands.map { command in @@ -30,7 +31,7 @@ extension BotInfo { if let apiMenuButton = apiMenuButton { menuButton = BotMenuButton(apiBotMenuButton: apiMenuButton) } - self.init(description: description ?? "", commands: commands, menuButton: menuButton) + self.init(description: description ?? "", photo: photo, commands: commands, menuButton: menuButton) } } } diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index fa16e38ed5..114a9d19cf 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1467,14 +1467,14 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo updatedState.updateCachedPeerData(peer.peerId, { current in if peer.peerId.namespace == Namespaces.Peer.CloudUser, let previous = current as? CachedUserData { if let botInfo = previous.botInfo { - return previous.withUpdatedBotInfo(BotInfo(description: botInfo.description, commands: commands, menuButton: botInfo.menuButton)) + return previous.withUpdatedBotInfo(BotInfo(description: botInfo.description, photo: botInfo.photo, commands: commands, menuButton: botInfo.menuButton)) } } else if peer.peerId.namespace == Namespaces.Peer.CloudGroup, let previous = current as? CachedGroupData { if let index = previous.botInfos.firstIndex(where: { $0.peerId == botPeerId }) { var updatedBotInfos = previous.botInfos let previousBotInfo = updatedBotInfos[index] updatedBotInfos.remove(at: index) - updatedBotInfos.insert(CachedPeerBotInfo(peerId: botPeerId, botInfo: BotInfo(description: previousBotInfo.botInfo.description, commands: commands, menuButton: previousBotInfo.botInfo.menuButton)), at: index) + updatedBotInfos.insert(CachedPeerBotInfo(peerId: botPeerId, botInfo: BotInfo(description: previousBotInfo.botInfo.description, photo: previousBotInfo.botInfo.photo, commands: commands, menuButton: previousBotInfo.botInfo.menuButton)), at: index) return previous.withUpdatedBotInfos(updatedBotInfos) } } else if peer.peerId.namespace == Namespaces.Peer.CloudChannel, let previous = current as? CachedChannelData { @@ -1482,7 +1482,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo var updatedBotInfos = previous.botInfos let previousBotInfo = updatedBotInfos[index] updatedBotInfos.remove(at: index) - updatedBotInfos.insert(CachedPeerBotInfo(peerId: botPeerId, botInfo: BotInfo(description: previousBotInfo.botInfo.description, commands: commands, menuButton: previousBotInfo.botInfo.menuButton)), at: index) + updatedBotInfos.insert(CachedPeerBotInfo(peerId: botPeerId, botInfo: BotInfo(description: previousBotInfo.botInfo.description, photo: previousBotInfo.botInfo.photo, commands: commands, menuButton: previousBotInfo.botInfo.menuButton)), at: index) return previous.withUpdatedBotInfos(updatedBotInfos) } } @@ -1494,7 +1494,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo updatedState.updateCachedPeerData(botPeerId, { current in if let previous = current as? CachedUserData { if let botInfo = previous.botInfo { - return previous.withUpdatedBotInfo(BotInfo(description: botInfo.description, commands: botInfo.commands, menuButton: menuButton)) + return previous.withUpdatedBotInfo(BotInfo(description: botInfo.description, photo: botInfo.photo, commands: botInfo.commands, menuButton: menuButton)) } } return current diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift index e2577b248f..161992ff66 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift @@ -47,23 +47,35 @@ public enum BotMenuButton: PostboxCoding, Hashable { public final class BotInfo: PostboxCoding, Equatable { public let description: String + public let photo: TelegramMediaImage? public let commands: [BotCommand] public let menuButton: BotMenuButton - public init(description: String, commands: [BotCommand], menuButton: BotMenuButton) { + public init(description: String, photo: TelegramMediaImage?, commands: [BotCommand], menuButton: BotMenuButton) { self.description = description + self.photo = photo self.commands = commands self.menuButton = menuButton } public init(decoder: PostboxDecoder) { self.description = decoder.decodeStringForKey("d", orElse: "") + if let photo = decoder.decodeObjectForKey("ph", decoder: { TelegramMediaImage(decoder: $0) }) as? TelegramMediaImage { + self.photo = photo + } else { + self.photo = nil + } self.commands = decoder.decodeObjectArrayWithDecoderForKey("c") self.menuButton = (decoder.decodeObjectForKey("b", decoder: { BotMenuButton(decoder: $0) }) as? BotMenuButton) ?? .commands } public func encode(_ encoder: PostboxEncoder) { encoder.encodeString(self.description, forKey: "d") + if let photo = self.photo { + encoder.encodeObject(photo, forKey: "ph") + } else { + encoder.encodeNil(forKey: "ph") + } encoder.encodeObjectArray(self.commands, forKey: "c") encoder.encodeObject(self.menuButton, forKey: "b") } diff --git a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift index e97cde0fcc..eaad36093e 100644 --- a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift +++ b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift @@ -8,6 +8,8 @@ import TelegramCore import TelegramPresentationData import TextFormat import UrlEscaping +import PhotoResources +import AccountContext private let messageFont = Font.regular(17.0) private let messageBoldFont = Font.semibold(17.0) @@ -18,14 +20,18 @@ private let messageFixedFont = UIFont(name: "Menlo-Regular", size: 16.0) ?? UIFo final class ChatBotInfoItem: ListViewItem { fileprivate let title: String fileprivate let text: String + fileprivate let photo: TelegramMediaImage? fileprivate let controllerInteraction: ChatControllerInteraction fileprivate let presentationData: ChatPresentationData + fileprivate let context: AccountContext - init(title: String, text: String, controllerInteraction: ChatControllerInteraction, presentationData: ChatPresentationData) { + init(title: String, text: String, photo: TelegramMediaImage?, controllerInteraction: ChatControllerInteraction, presentationData: ChatPresentationData, context: AccountContext) { self.title = title self.text = text + self.photo = photo self.controllerInteraction = controllerInteraction self.presentationData = presentationData + self.context = context } func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { @@ -76,10 +82,13 @@ final class ChatBotInfoItemNode: ListViewItemNode { let offsetContainer: ASDisplayNode let backgroundNode: ASImageNode + let imageNode: TransformImageNode let titleNode: TextNode let textNode: TextNode private var linkHighlightingNode: LinkHighlightingNode? + private let fetchDisposable = MetaDisposable() + var currentTextAndEntities: (String, [MessageTextEntity])? private var theme: ChatPresentationThemeData? @@ -92,6 +101,7 @@ final class ChatBotInfoItemNode: ListViewItemNode { self.backgroundNode = ASImageNode() self.backgroundNode.displaysAsynchronously = false self.backgroundNode.displayWithoutProcessing = true + self.imageNode = TransformImageNode() self.textNode = TextNode() self.titleNode = TextNode() @@ -101,11 +111,16 @@ final class ChatBotInfoItemNode: ListViewItemNode { self.addSubnode(self.offsetContainer) self.offsetContainer.addSubnode(self.backgroundNode) + self.offsetContainer.addSubnode(self.imageNode) self.offsetContainer.addSubnode(self.titleNode) self.offsetContainer.addSubnode(self.textNode) self.wantsTrailingItemSpaceUpdates = true } + deinit { + self.fetchDisposable.dispose() + } + override func didLoad() { super.didLoad() @@ -134,10 +149,14 @@ final class ChatBotInfoItemNode: ListViewItemNode { } func asyncLayout() -> (_ item: ChatBotInfoItem, _ width: ListViewItemLayoutParams) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation) -> Void) { + let makeImageLayout = self.imageNode.asyncLayout() let makeTitleLayout = TextNode.asyncLayout(self.titleNode) let makeTextLayout = TextNode.asyncLayout(self.textNode) let currentTextAndEntities = self.currentTextAndEntities let currentTheme = self.theme + + let currentItem = self.item + return { [weak self] item, params in self?.item = item @@ -145,7 +164,7 @@ final class ChatBotInfoItemNode: ListViewItemNode { if currentTheme != item.presentationData.theme { updatedBackgroundImage = PresentationResourcesChat.chatInfoItemBackgroundImage(item.presentationData.theme.theme, wallpaper: !item.presentationData.theme.wallpaper.isEmpty) } - + var updatedTextAndEntities: (String, [MessageTextEntity]) if let (text, entities) = currentTextAndEntities { if text == item.text { @@ -171,11 +190,40 @@ final class ChatBotInfoItemNode: ListViewItemNode { let textSpacing: CGFloat = 1.0 let textSize = CGSize(width: max(titleLayout.size.width, textLayout.size.width), height: (titleLayout.size.height + (titleLayout.size.width.isZero ? 0.0 : textSpacing) + textLayout.size.height)) - let backgroundFrame = CGRect(origin: CGPoint(x: floor((params.width - textSize.width - horizontalContentInset * 2.0) / 2.0), y: verticalItemInset + 4.0), size: CGSize(width: textSize.width + horizontalContentInset * 2.0, height: textSize.height + verticalContentInset * 2.0)) - let titleFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + verticalContentInset), size: titleLayout.size) - let textFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + verticalContentInset + titleLayout.size.height + (titleLayout.size.width.isZero ? 0.0 : textSpacing)), size: textLayout.size) + var mediaUpdated = false + if let media = item.photo { + if let currentMedia = currentItem?.photo { + mediaUpdated = !media.isSemanticallyEqual(to: currentMedia) + } else { + mediaUpdated = true + } + } - let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: textLayout.size.height + verticalItemInset * 2.0 + verticalContentInset * 2.0 + titleLayout.size.height + (titleLayout.size.width.isZero ? 0.0 : textSpacing) - 3.0), insets: UIEdgeInsets()) + var updatedImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? + + var imageSize = CGSize() + var imageDimensions = CGSize() + var imageApply: (() -> Void)? + let imageInset: CGFloat = 1.0 + UIScreenPixel + if let image = item.photo, let dimensions = largestImageRepresentation(image.representations)?.dimensions { + imageDimensions = dimensions.cgSize.aspectFitted(CGSize(width: textSize.width + horizontalContentInset * 2.0 - imageInset * 2.0, height: CGFloat.greatestFiniteMagnitude)) + imageSize = imageDimensions + imageSize.height += 4.0 + + let arguments = TransformImageArguments(corners: ImageCorners(topLeft: .Corner(17.0), topRight: .Corner(17.0), bottomLeft: .Corner(0.0), bottomRight: .Corner(0.0)), imageSize: dimensions.cgSize.aspectFilled(imageDimensions), boundingSize: imageDimensions, intrinsicInsets: UIEdgeInsets(), emptyColor: item.presentationData.theme.theme.list.mediaPlaceholderColor) + imageApply = makeImageLayout(arguments) + + if mediaUpdated { + updatedImageSignal = chatMessagePhoto(postbox: item.context.account.postbox, photoReference: .standalone(media: image), synchronousLoad: true, highQuality: false) + } + } + + let backgroundFrame = CGRect(origin: CGPoint(x: floor((params.width - textSize.width - horizontalContentInset * 2.0) / 2.0), y: verticalItemInset + 4.0), size: CGSize(width: textSize.width + horizontalContentInset * 2.0, height: imageSize.height + textSize.height + verticalContentInset * 2.0)) + let titleFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + imageSize.height + verticalContentInset), size: titleLayout.size) + let textFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + imageSize.height + verticalContentInset + titleLayout.size.height + (titleLayout.size.width.isZero ? 0.0 : textSpacing)), size: textLayout.size) + let imageFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + imageInset, y: backgroundFrame.origin.y + imageInset), size: imageDimensions) + + let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: imageSize.height + textLayout.size.height + verticalItemInset * 2.0 + verticalContentInset * 2.0 + titleLayout.size.height + (titleLayout.size.width.isZero ? 0.0 : textSpacing) - 3.0), insets: UIEdgeInsets()) return (itemLayout, { _ in if let strongSelf = self { strongSelf.theme = item.presentationData.theme @@ -186,6 +234,22 @@ final class ChatBotInfoItemNode: ListViewItemNode { strongSelf.controllerInteraction = item.controllerInteraction strongSelf.currentTextAndEntities = updatedTextAndEntities + + + if let imageApply = imageApply { + let _ = imageApply() + if let updatedImageSignal = updatedImageSignal { + strongSelf.imageNode.setSignal(updatedImageSignal) + if let image = item.photo { + strongSelf.fetchDisposable.set(chatMessagePhotoInteractiveFetched(context: item.context, photoReference: .standalone(media: image), displayAtSize: nil, storeToDownloadsPeerType: nil).start()) + } + } + strongSelf.imageNode.isHidden = false + } else { + strongSelf.imageNode.isHidden = true + } + strongSelf.imageNode.frame = imageFrame + let _ = titleApply() let _ = textApply() strongSelf.offsetContainer.frame = CGRect(origin: CGPoint(), size: itemLayout.contentSize) diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift index 0a4e4b9325..2e74d48ebf 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift @@ -255,9 +255,9 @@ func chatHistoryEntriesForView( } } if case let .peer(peerId) = location, peerId.isReplies { - entries.insert(.ChatInfoEntry("", presentationData.strings.RepliesChat_DescriptionText, presentationData), at: 0) + entries.insert(.ChatInfoEntry("", presentationData.strings.RepliesChat_DescriptionText, nil, presentationData), at: 0) } else if let cachedPeerData = cachedPeerData as? CachedUserData, let botInfo = cachedPeerData.botInfo, !botInfo.description.isEmpty { - entries.insert(.ChatInfoEntry(presentationData.strings.Bot_DescriptionTitle, botInfo.description, presentationData), at: 0) + entries.insert(.ChatInfoEntry(presentationData.strings.Bot_DescriptionTitle, botInfo.description, botInfo.photo, presentationData), at: 0) } else { var isEmpty = true if entries.count <= 3 { diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntry.swift b/submodules/TelegramUI/Sources/ChatHistoryEntry.swift index 92295d40d6..576b987534 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryEntry.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryEntry.swift @@ -43,7 +43,7 @@ enum ChatHistoryEntry: Identifiable, Comparable { case MessageGroupEntry(MessageGroupInfo, [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)], ChatPresentationData) case UnreadEntry(MessageIndex, ChatPresentationData) case ReplyCountEntry(MessageIndex, Bool, Int, ChatPresentationData) - case ChatInfoEntry(String, String, ChatPresentationData) + case ChatInfoEntry(String, String, TelegramMediaImage?, ChatPresentationData) case SearchEntry(PresentationTheme, PresentationStrings) var stableId: UInt64 { @@ -201,8 +201,8 @@ enum ChatHistoryEntry: Identifiable, Comparable { } else { return false } - case let .ChatInfoEntry(lhsTitle, lhsText, lhsPresentationData): - if case let .ChatInfoEntry(rhsTitle, rhsText, rhsPresentationData) = rhs, lhsTitle == rhsTitle, lhsText == rhsText, lhsPresentationData === rhsPresentationData { + case let .ChatInfoEntry(lhsTitle, lhsText, lhsPhoto, lhsPresentationData): + if case let .ChatInfoEntry(rhsTitle, rhsText, rhsPhoto, rhsPresentationData) = rhs, lhsTitle == rhsTitle, lhsText == rhsText, lhsPhoto == rhsPhoto, lhsPresentationData === rhsPresentationData { return true } else { return false diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index 967024d88f..a7dff4b7ec 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -247,8 +247,8 @@ private func mappedInsertEntries(context: AccountContext, chatLocation: ChatLoca return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint) case let .ReplyCountEntry(_, isComments, count, presentationData): return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction), directionHint: entry.directionHint) - case let .ChatInfoEntry(title, text, presentationData): - return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(title: title, text: text, controllerInteraction: controllerInteraction, presentationData: presentationData), directionHint: entry.directionHint) + case let .ChatInfoEntry(title, text, photo, presentationData): + return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(title: title, text: text, photo: photo, controllerInteraction: controllerInteraction, presentationData: presentationData, context: context), directionHint: entry.directionHint) case let .SearchEntry(theme, strings): return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: { controllerInteraction.openSearch() @@ -292,8 +292,8 @@ private func mappedUpdateEntries(context: AccountContext, chatLocation: ChatLoca return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint) case let .ReplyCountEntry(_, isComments, count, presentationData): return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction), directionHint: entry.directionHint) - case let .ChatInfoEntry(title, text, presentationData): - return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(title: title, text: text, controllerInteraction: controllerInteraction, presentationData: presentationData), directionHint: entry.directionHint) + case let .ChatInfoEntry(title, text, photo, presentationData): + return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(title: title, text: text, photo: photo, controllerInteraction: controllerInteraction, presentationData: presentationData, context: context), directionHint: entry.directionHint) case let .SearchEntry(theme, strings): return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: { controllerInteraction.openSearch() diff --git a/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift b/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift index 7bc03d92d3..ce6add50ed 100644 --- a/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift +++ b/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift @@ -38,6 +38,8 @@ public enum WebEmbedType { public func webEmbedType(content: TelegramMediaWebpageLoadedContent, forcedTimestamp: Int? = nil) -> WebEmbedType { if let (videoId, timestamp) = extractYoutubeVideoIdAndTimestamp(url: content.url) { return .youtube(videoId: videoId, timestamp: forcedTimestamp ?? timestamp) + } else if let embedUrl = content.embedUrl, let (videoId, timestamp) = extractYoutubeVideoIdAndTimestamp(url: embedUrl) { + return .youtube(videoId: videoId, timestamp: forcedTimestamp ?? timestamp) } else if let (videoId, timestamp) = extractVimeoVideoIdAndTimestamp(url: content.url) { return .vimeo(videoId: videoId, timestamp: forcedTimestamp ?? timestamp) } else if let embedUrl = content.embedUrl, isTwitchVideoUrl(embedUrl) && false {