From 284d963b07967482084671c14fa967ff92f4a4db Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Mon, 27 Oct 2025 01:01:04 +0400 Subject: [PATCH] Stories --- .../Sources/AsyncListComponent.swift | 7 + .../Sources/ChatSendStarsScreen.swift | 168 +++++++++--------- .../StoryContentLiveChatComponent.swift | 22 +++ ...StoryItemSetContainerViewSendMessage.swift | 22 ++- 4 files changed, 131 insertions(+), 88 deletions(-) diff --git a/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift b/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift index bafe1552f6..0db3dca153 100644 --- a/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift +++ b/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift @@ -475,6 +475,13 @@ public final class AsyncListComponent: Component { } } + public func visibleItems() -> VisibleItems? { + guard let component = self.component else { + return nil + } + return VisibleItems(view: self, direction: component.direction) + } + func update(component: AsyncListComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: ComponentTransition) -> CGSize { let previousComponent = self.component self.component = component diff --git a/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift b/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift index aec891ec35..9b569233aa 100644 --- a/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift +++ b/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift @@ -2295,91 +2295,93 @@ private final class ChatSendStarsScreenComponent: Component { contentHeight += 2.0 } - if self.anonymousSeparator.superlayer == nil { - self.scrollContentView.layer.addSublayer(self.anonymousSeparator) - } - - self.anonymousSeparator.backgroundColor = environment.theme.list.itemPlainSeparatorColor.cgColor - - let checkTheme = CheckComponent.Theme( - backgroundColor: environment.theme.list.itemCheckColors.fillColor, - strokeColor: environment.theme.list.itemCheckColors.foregroundColor, - borderColor: environment.theme.list.itemCheckColors.strokeColor, - overlayBorder: false, - hasInset: false, - hasShadow: false - ) - let anonymousContentsSize = self.anonymousContents.update( - transition: transition, - component: AnyComponent(PlainButtonComponent( - content: AnyComponent(HStack([ - AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(CheckComponent( - theme: checkTheme, - selected: self.privacyPeer != .anonymous - ))), - AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: environment.strings.SendStarReactions_ShowMyselfInTop, font: Font.regular(17.0), textColor: environment.theme.list.itemPrimaryTextColor)) - ))) - ], spacing: 10.0)), - effectAlignment: .center, - action: { [weak self] in - guard let self, let component = self.component else { - return - } - - switch self.privacyPeer { - case .anonymous: - if let currentMyPeer = self.currentMyPeer { - if currentMyPeer.id == component.context.account.peerId { - self.privacyPeer = .account - } else { - self.privacyPeer = .peer(currentMyPeer) - } - } - default: - self.privacyPeer = .anonymous - } - self.state?.updated(transition: .easeInOut(duration: 0.2)) - - if reactData.myTopPeer != nil { - switch reactData.reactSubject { - case let .message(messageId):let mappedPrivacy: TelegramPaidReactionPrivacy - switch self.privacyPeer { - case .account: - mappedPrivacy = .default - case .anonymous: - mappedPrivacy = .anonymous - case let .peer(peer): - mappedPrivacy = .peer(peer.id) - } - - let _ = component.context.engine.messages.updateStarsReactionPrivacy(id: messageId, privacy: mappedPrivacy).startStandalone() - case .liveStream: - //TODO:release - break - } - } - }, - animateAlpha: false, - animateScale: false - )), - environment: {}, - containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0) - ) - - transition.setFrame(layer: self.anonymousSeparator, frame: CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: CGSize(width: availableSize.width - sideInset * 2.0, height: UIScreenPixel))) - - contentHeight += 21.0 - - let anonymousContentsFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - anonymousContentsSize.width) * 0.5), y: contentHeight), size: anonymousContentsSize) - if let anonymousContentsView = self.anonymousContents.view { - if anonymousContentsView.superview == nil { - self.scrollContentView.addSubview(anonymousContentsView) + if case .message = reactData.reactSubject { + if self.anonymousSeparator.superlayer == nil { + self.scrollContentView.layer.addSublayer(self.anonymousSeparator) } - transition.setFrame(view: anonymousContentsView, frame: anonymousContentsFrame) + + self.anonymousSeparator.backgroundColor = environment.theme.list.itemPlainSeparatorColor.cgColor + + let checkTheme = CheckComponent.Theme( + backgroundColor: environment.theme.list.itemCheckColors.fillColor, + strokeColor: environment.theme.list.itemCheckColors.foregroundColor, + borderColor: environment.theme.list.itemCheckColors.strokeColor, + overlayBorder: false, + hasInset: false, + hasShadow: false + ) + let anonymousContentsSize = self.anonymousContents.update( + transition: transition, + component: AnyComponent(PlainButtonComponent( + content: AnyComponent(HStack([ + AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(CheckComponent( + theme: checkTheme, + selected: self.privacyPeer != .anonymous + ))), + AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: environment.strings.SendStarReactions_ShowMyselfInTop, font: Font.regular(17.0), textColor: environment.theme.list.itemPrimaryTextColor)) + ))) + ], spacing: 10.0)), + effectAlignment: .center, + action: { [weak self] in + guard let self, let component = self.component else { + return + } + + switch self.privacyPeer { + case .anonymous: + if let currentMyPeer = self.currentMyPeer { + if currentMyPeer.id == component.context.account.peerId { + self.privacyPeer = .account + } else { + self.privacyPeer = .peer(currentMyPeer) + } + } + default: + self.privacyPeer = .anonymous + } + self.state?.updated(transition: .easeInOut(duration: 0.2)) + + if reactData.myTopPeer != nil { + switch reactData.reactSubject { + case let .message(messageId):let mappedPrivacy: TelegramPaidReactionPrivacy + switch self.privacyPeer { + case .account: + mappedPrivacy = .default + case .anonymous: + mappedPrivacy = .anonymous + case let .peer(peer): + mappedPrivacy = .peer(peer.id) + } + + let _ = component.context.engine.messages.updateStarsReactionPrivacy(id: messageId, privacy: mappedPrivacy).startStandalone() + case .liveStream: + //TODO:release + break + } + } + }, + animateAlpha: false, + animateScale: false + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0) + ) + + transition.setFrame(layer: self.anonymousSeparator, frame: CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: CGSize(width: availableSize.width - sideInset * 2.0, height: UIScreenPixel))) + + contentHeight += 21.0 + + let anonymousContentsFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - anonymousContentsSize.width) * 0.5), y: contentHeight), size: anonymousContentsSize) + if let anonymousContentsView = self.anonymousContents.view { + if anonymousContentsView.superview == nil { + self.scrollContentView.addSubview(anonymousContentsView) + } + transition.setFrame(view: anonymousContentsView, frame: anonymousContentsFrame) + } + + contentHeight += anonymousContentsSize.height + 16.0 } - - contentHeight += anonymousContentsSize.height + 16.0 case .liveStreamMessage: break } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentLiveChatComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentLiveChatComponent.swift index 26a2254daf..1218816e63 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentLiveChatComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentLiveChatComponent.swift @@ -571,6 +571,28 @@ final class StoryContentLiveChatComponent: Component { return nil } + if let listView = self.list.view as? AsyncListComponent.View, result.isDescendant(of: listView) { + if let visibleItems = listView.visibleItems() { + var maxItemY: CGFloat? + for visibleItem in visibleItems { + if let maxItemYValue = maxItemY { + maxItemY = max(maxItemYValue, visibleItem.frame.maxY) + } else { + maxItemY = visibleItem.frame.maxY + } + } + if let maxItemY { + if self.convert(point, to: listView).y >= maxItemY { + return nil + } + } else { + return nil + } + } else { + return nil + } + } + return result } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift index 99b19de36c..0ced021abd 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift @@ -4062,13 +4062,25 @@ final class StoryItemSetContainerSendMessage { } } - self.commitSendStars(view: view, count: count, delay: true) + guard let visibleItemView = view.visibleItems[component.slice.item.id]?.view.view as? StoryItemContentComponent.View else { + return + } - var totalStars = count - if let visibleItemView = view.visibleItems[component.slice.item.id]?.view.view as? StoryItemContentComponent.View { - if let pendingMyStars = visibleItemView.liveChatState?.starStats?.pendingMyStars { - totalStars += Int(pendingMyStars) + var totalStars = 0 + if let pendingMyStars = visibleItemView.liveChatState?.starStats?.pendingMyStars, pendingMyStars > 0 { + totalStars += count + totalStars += Int(pendingMyStars) + self.commitSendStars(view: view, count: count, delay: true) + } else { + var minAmount: Int64 = 1 + if let minMessagePrice = visibleItemView.liveChatState?.minMessagePrice { + minAmount = minMessagePrice } + var count = count + count = max(Int(minAmount), count) + totalStars += count + + self.commitSendStars(view: view, count: count, delay: true) } let title: String