diff --git a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift index 4d8cebf90d..093c11e33e 100644 --- a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift +++ b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift @@ -468,6 +468,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { let hasTopGroupInset: Bool let noInsets: Bool let noCorners: Bool + let style: ItemListStyle public let tag: ItemListItemTag? let header: ListViewItemHeader? let shimmering: ItemListPeerItemShimmering? @@ -508,6 +509,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { hasTopGroupInset: Bool = true, noInsets: Bool = false, noCorners: Bool = false, + style: ItemListStyle = .blocks, tag: ItemListItemTag? = nil, header: ListViewItemHeader? = nil, shimmering: ItemListPeerItemShimmering? = nil, @@ -547,6 +549,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { self.hasTopGroupInset = hasTopGroupInset self.noInsets = noInsets self.noCorners = noCorners + self.style = style self.tag = tag self.header = header self.shimmering = shimmering @@ -588,6 +591,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { hasTopGroupInset: Bool = true, noInsets: Bool = false, noCorners: Bool = false, + style: ItemListStyle = .blocks, tag: ItemListItemTag? = nil, header: ListViewItemHeader? = nil, shimmering: ItemListPeerItemShimmering? = nil, @@ -627,6 +631,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { self.hasTopGroupInset = hasTopGroupInset self.noInsets = noInsets self.noCorners = noCorners + self.style = style self.tag = tag self.header = header self.shimmering = shimmering @@ -889,7 +894,6 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo return { item, params, neighbors, headerAtTop in var updateArrowImage: UIImage? - var updatedTheme: PresentationTheme? let statusFontSize: CGFloat = floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0) let labelFontSize: CGFloat = floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0) @@ -938,7 +942,6 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo let badgeDiameter: CGFloat = 20.0 if currentItem?.presentationData.theme !== item.presentationData.theme { - updatedTheme = item.presentationData.theme updateArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.presentationData.theme) if let badgeColor = badgeColor { updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: badgeColor) @@ -1247,13 +1250,22 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo strongSelf.labelArrowNode?.image = updateArrowImage } - if let _ = updatedTheme { - strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor - strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor - strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor - strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor + let itemBackgroundColor: UIColor + let itemSeparatorColor: UIColor + switch item.style { + case .plain: + itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor + itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor + case .blocks: + itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor + itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor } + strongSelf.topStripeNode.backgroundColor = itemSeparatorColor + strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor + strongSelf.backgroundNode.backgroundColor = itemBackgroundColor + strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor + let revealOffset = strongSelf.revealOffset let transition: ContainedViewLayoutTransition diff --git a/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift b/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift index ee01ff53fd..809deb1ba6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift +++ b/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift @@ -108,6 +108,17 @@ public enum ChatHistoryEntry: Identifiable, Comparable { return MessageIndex.absoluteLowerBound() } } + + public var timestamp: Int32? { + switch self { + case let .MessageEntry(message, _, _, _, _, _): + return message.timestamp + case let .MessageGroupEntry(_, messages, _): + return messages[0].0.timestamp + default: + return nil + } + } public static func ==(lhs: ChatHistoryEntry, rhs: ChatHistoryEntry) -> Bool { switch lhs { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGroupsInCommonPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGroupsInCommonPaneNode.swift index 673fd6f5c0..01c912103e 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGroupsInCommonPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGroupsInCommonPaneNode.swift @@ -44,7 +44,7 @@ private struct GroupsInCommonListEntry: Comparable, Identifiable { }, removePeer: { _ in }, contextAction: { node, gesture in openPeerContextAction(peer, node, gesture) - }, hasTopStripe: false, noInsets: true, noCorners: true) + }, hasTopStripe: false, noInsets: true, noCorners: true, style: .plain) } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedChannelsPane.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedChannelsPane.swift index d36445ea24..ce226d65bf 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedChannelsPane.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoRecommendedChannelsPane.swift @@ -72,7 +72,7 @@ private enum RecommendedChannelsListEntry: Comparable, Identifiable { }, removePeer: { _ in }, contextAction: { node, gesture in openPeerContextAction(peer._asPeer(), node, gesture) - }, hasTopStripe: false, noInsets: true, noCorners: true, disableInteractiveTransitionIfNecessary: true) + }, hasTopStripe: false, noInsets: true, noCorners: true, style: .plain, disableInteractiveTransitionIfNecessary: true) } } } @@ -106,7 +106,7 @@ final class PeerInfoRecommendedChannelsPaneNode: ASDisplayNode, PeerInfoPaneNode private var unlockText: ComponentView? private var unlockButton: SolidRoundedButtonNode? - private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, isScrollingLockedAtTop: Bool)? + private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, isScrollingLockedAtTop: Bool, presentationData: PresentationData)? private var theme: PresentationTheme? private let presentationDataPromise = Promise() @@ -190,7 +190,7 @@ final class PeerInfoRecommendedChannelsPaneNode: ASDisplayNode, PeerInfoPaneNode func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) { let isFirstLayout = self.currentParams == nil - self.currentParams = (size, sideInset, bottomInset, isScrollingLockedAtTop) + self.currentParams = (size, sideInset, bottomInset, isScrollingLockedAtTop, presentationData) self.presentationDataPromise.set(.single(presentationData)) transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size)) @@ -237,10 +237,19 @@ final class PeerInfoRecommendedChannelsPaneNode: ASDisplayNode, PeerInfoPaneNode self.enqueuedTransactions.append(transaction) self.dequeueTransaction() + self.layoutUnlockPanel() + } + + private func layoutUnlockPanel() { + guard let (_, isPremium) = self.currentState, let currentParams = self.currentParams else { + return + } if !isPremium { - guard let size = self.currentParams?.size, let sideInset = self.currentParams?.sideInset, let bottomInset = self.currentParams?.bottomInset else { - return - } + let size = currentParams.size + let sideInset = currentParams.sideInset + let bottomInset = currentParams.bottomInset + let presentationData = currentParams.presentationData + let themeUpdated = self.theme !== presentationData.theme self.theme = presentationData.theme @@ -281,13 +290,12 @@ final class PeerInfoRecommendedChannelsPaneNode: ASDisplayNode, PeerInfoPaneNode } if themeUpdated { - let topColor = presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.0) - let bottomColor = presentationData.theme.list.itemBlocksBackgroundColor + let topColor = presentationData.theme.list.plainBackgroundColor.withAlphaComponent(0.0) + let bottomColor = presentationData.theme.list.plainBackgroundColor unlockBackground.image = generateGradientImage(size: CGSize(width: 1.0, height: 170.0), colors: [topColor, bottomColor, bottomColor], locations: [0.0, 0.3, 1.0]) unlockButton.updateTheme(SolidRoundedButtonTheme(theme: presentationData.theme)) } - let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } let textFont = Font.regular(15.0) let boldTextFont = Font.semibold(15.0) let textColor = presentationData.theme.list.itemSecondaryTextColor @@ -296,6 +304,11 @@ final class PeerInfoRecommendedChannelsPaneNode: ASDisplayNode, PeerInfoPaneNode return nil }) + var scrollOffset: CGFloat = 0.0 + if case let .known(offset) = self.listNode.visibleBottomContentOffset() { + scrollOffset = min(0.0, offset + bottomInset + 80.0) + } + let unlockSize = unlockText.update( transition: .immediate, component: AnyComponent( @@ -314,14 +327,14 @@ final class PeerInfoRecommendedChannelsPaneNode: ASDisplayNode, PeerInfoPaneNode view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.unlockPressed))) self.view.addSubview(view) } - view.frame = CGRect(origin: CGPoint(x: floor((size.width - unlockSize.width) / 2.0), y: size.height - bottomInset - unlockSize.height - 13.0), size: unlockSize) + view.frame = CGRect(origin: CGPoint(x: floor((size.width - unlockSize.width) / 2.0), y: size.height - bottomInset - unlockSize.height - 13.0 + scrollOffset), size: unlockSize) } - unlockBackground.frame = CGRect(x: 0.0, y: size.height - bottomInset - 170.0, width: size.width, height: bottomInset + 170.0) + unlockBackground.frame = CGRect(x: 0.0, y: size.height - bottomInset - 170.0 + scrollOffset, width: size.width, height: bottomInset + 170.0) let buttonSideInset = sideInset + 16.0 let buttonSize = CGSize(width: size.width - buttonSideInset * 2.0, height: 50.0) - unlockButton.frame = CGRect(origin: CGPoint(x: buttonSideInset, y: size.height - bottomInset - unlockSize.height - buttonSize.height - 26.0), size: buttonSize) + unlockButton.frame = CGRect(origin: CGPoint(x: buttonSideInset, y: size.height - bottomInset - unlockSize.height - buttonSize.height - 26.0 + scrollOffset), size: buttonSize) let _ = unlockButton.updateLayout(width: buttonSize.width, transition: .immediate) } else { self.unlockBackground?.removeFromSuperview() diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift index 695fbeb214..d9eadc9668 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift @@ -131,12 +131,6 @@ func chatHistoryEntriesForView( } } - if let maybeJoinMessage = joinMessage { - if message.timestamp > maybeJoinMessage.timestamp, (!view.holeEarlier || count > 0) { - entries.append(.MessageEntry(maybeJoinMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false, authorStoryStats: nil))) - joinMessage = nil - } - } count += 1 if let customThreadOutgoingReadState = customThreadOutgoingReadState { @@ -234,7 +228,7 @@ func chatHistoryEntriesForView( entries.append(.MessageEntry(message, presentationData, isRead, entry.location, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: message.index == associatedData.currentlyPlayingMessageId, isCentered: false, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] }))) } } - + if !groupBucket.isEmpty { assert(groupMessages || reverseGroupedMessages) if reverseGroupedMessages { @@ -253,11 +247,25 @@ func chatHistoryEntriesForView( } } - if let maybeJoinMessage = joinMessage, !view.holeLater { - entries.append(.MessageEntry(maybeJoinMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false, authorStoryStats: nil))) - joinMessage = nil + if let lowerTimestamp = view.entries.last?.message.timestamp, let upperTimestamp = view.entries.first?.message.timestamp { + if let joinMessage { + var insertAtPosition: Int? + if joinMessage.timestamp >= lowerTimestamp && view.laterId == nil { + insertAtPosition = entries.count + } else if joinMessage.timestamp < lowerTimestamp && joinMessage.timestamp > upperTimestamp { + for i in 0 ..< entries.count { + if let timestamp = entries[i].timestamp, timestamp > joinMessage.timestamp { + insertAtPosition = i + break + } + } + } + if let insertAtPosition { + entries.insert(.MessageEntry(joinMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false, authorStoryStats: nil)), at: insertAtPosition) + } + } } - + if let maxReadIndex = view.maxReadIndex, includeUnreadEntry { var i = 0 let unreadEntry: ChatHistoryEntry = .UnreadEntry(maxReadIndex, presentationData)