From 4e287679b781fad56f41c5cb709199fc6616aecd Mon Sep 17 00:00:00 2001 From: Mikhail Filimonov Date: Tue, 21 Jan 2025 09:00:04 +0400 Subject: [PATCH 1/3] -reload gifts --- .../Sources/TelegramEngine/Payments/StarGifts.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift index 164a487f41..4e8c628e94 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift @@ -939,6 +939,12 @@ private final class ProfileGiftsContextImpl { self.actionDisposable.dispose() } + func reload() { + gifts = [] + dataState = .ready(canLoadMore: true, nextOffset: nil) + self.loadMore() + } + func loadMore() { let peerId = self.peerId let accountPeerId = self.account.peerId @@ -1278,6 +1284,12 @@ public final class ProfileGiftsContext { } } + public func reload() { + self.impl.with { impl in + impl.reload() + } + } + public func updateStarGiftAddedToProfile(reference: StarGiftReference, added: Bool) { self.impl.with { impl in impl.updateStarGiftAddedToProfile(reference: reference, added: added) From 4bf5df909cc1d763df97b335229df00b7ef4bf0f Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 21 Jan 2025 16:33:49 +0400 Subject: [PATCH 2/3] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 9 ++ .../Sources/GiftViewScreen.swift | 10 +- .../PeerInfoVisualMediaPaneNode/BUILD | 1 + .../Sources/PeerInfoGiftsPaneNode.swift | 124 +++++++++++++++++- .../ChatInterfaceStateContextMenus.swift | 2 +- 5 files changed, 142 insertions(+), 4 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index b2c01b8a1a..166ad92b4b 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -13761,3 +13761,12 @@ Sorry for the inconvenience."; "PeerInfo.Gifts.Unique" = "Unique"; "PeerInfo.Gifts.Displayed" = "Displayed"; "PeerInfo.Gifts.Hidden" = "Hidden"; + +"PeerInfo.Gifts.NoResults" = "No Matching Gifts"; +"PeerInfo.Gifts.NoResults.ViewAll" = "View All Gifts"; + + +"Gift.Displayed.ChannelText" = "The gift is now shown on channel's Page."; +"Gift.Hidden.ChannelText" = "The gift is removed from channel's Page."; + +"Gift.Upgrade.AddChannelName" = "Add channel name to the gift"; diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 1c05403951..7bbc3497ac 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -927,7 +927,7 @@ private final class GiftViewSheetContent: CombinedComponent { ) let keepInfoText: String if let nameHidden = subject.arguments?.nameHidden, nameHidden { - keepInfoText = strings.Gift_Upgrade_AddMyName + keepInfoText = isChannelGift ? strings.Gift_Upgrade_AddChannelName : strings.Gift_Upgrade_AddMyName } else { keepInfoText = text != nil ? strings.Gift_Upgrade_AddNameAndComment : strings.Gift_Upgrade_AddName } @@ -2415,7 +2415,13 @@ public class GiftViewScreen: ViewControllerComponentContainer { self.dismissAnimated() - let text = added ? presentationData.strings.Gift_Displayed_NewText : presentationData.strings.Gift_Hidden_NewText + let text: String + if arguments.peerId?.namespace == Namespaces.Peer.CloudChannel { + text = added ? presentationData.strings.Gift_Displayed_ChannelText : presentationData.strings.Gift_Hidden_ChannelText + } else { + text = added ? presentationData.strings.Gift_Displayed_NewText : presentationData.strings.Gift_Hidden_NewText + } + if let navigationController = self.navigationController as? NavigationController { Queue.mainQueue().after(0.5) { if let lastController = navigationController.viewControllers.last as? ViewController, let animationFile { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD index 57f936066c..2b06f96f7d 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/BUILD @@ -53,6 +53,7 @@ swift_library( "//submodules/TelegramUI/Components/ButtonComponent", "//submodules/Components/BalancedTextComponent", "//submodules/TelegramUI/Components/CheckComponent", + "//submodules/TelegramUI/Components/LottieComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift index 694f25da70..e7cf196b8e 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift @@ -24,6 +24,7 @@ import GiftViewScreen import SolidRoundedButtonNode import UndoUI import CheckComponent +import LottieComponent public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate { private let context: AccountContext @@ -47,6 +48,10 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr private var panelButton: SolidRoundedButtonNode? private var panelCheck: ComponentView? + private let emptyResultsAnimation = ComponentView() + private let emptyResultsTitle = ComponentView() + private let emptyResultsAction = ComponentView() + private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)? private var theme: PresentationTheme? @@ -69,8 +74,9 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr } private var starsProducts: [ProfileGiftsContext.State.StarGift]? - private var starsItems: [AnyHashable: ComponentView] = [:] + private var resultsAreFiltered = false + private var resultsAreEmpty = false public init(context: AccountContext, peerId: PeerId, chatControllerInteraction: ChatControllerInteraction, openPeerContextAction: @escaping (Bool, Peer, ASDisplayNode, ContextGesture?) -> Void, profileGifts: ProfileGiftsContext, canManage: Bool) { self.context = context @@ -98,6 +104,9 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.statusPromise.set(.single(PeerInfoStatusData(text: presentationData.strings.SharedMedia_GiftCount(state.count ?? 0), isActivity: true, key: .gifts))) self.starsProducts = state.filteredGifts + self.resultsAreFiltered = state.filter != .All + self.resultsAreEmpty = state.filter != .All && state.filteredGifts.isEmpty + if !self.didSetReady { self.didSetReady = true self.ready.set(.single(true)) @@ -278,6 +287,11 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr if let itemView = visibleItem.view { if itemView.superview == nil { self.scrollNode.view.addSubview(itemView) + + if !transition.animation.isImmediate { + itemView.layer.animateScale(from: 0.01, to: 1.0, duration: 0.25) + itemView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) + } } itemTransition.setFrame(view: itemView, frame: itemFrame) } @@ -465,6 +479,114 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr transition.setFrame(view: panelSeparator.view, frame: CGRect(x: 0.0, y: size.height - bottomPanelHeight - scrollOffset, width: size.width, height: UIScreenPixel)) transition.setAlpha(view: panelSeparator.view, alpha: panelAlpha) + let fadeTransition = ComponentTransition.easeInOut(duration: 0.25) + if self.resultsAreEmpty { + let sideInset: CGFloat = 44.0 + let emptyAnimationHeight = 148.0 + let topInset: CGFloat = 0.0 + let bottomInset: CGFloat = bottomPanelHeight + let visibleHeight = params.visibleHeight + let emptyAnimationSpacing: CGFloat = 20.0 + let emptyTextSpacing: CGFloat = 18.0 + + let emptyResultsTitleSize = self.emptyResultsTitle.update( + transition: .immediate, + component: AnyComponent( + MultilineTextComponent( + text: .plain(NSAttributedString(string: presentationData.strings.PeerInfo_Gifts_NoResults, font: Font.semibold(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor)), + horizontalAlignment: .center + ) + ), + environment: {}, + containerSize: params.size + ) + let emptyResultsActionSize = self.emptyResultsAction.update( + transition: .immediate, + component: AnyComponent( + PlainButtonComponent( + content: AnyComponent( + MultilineTextComponent( + text: .plain(NSAttributedString(string: presentationData.strings.PeerInfo_Gifts_NoResults_ViewAll, font: Font.regular(17.0), textColor: presentationData.theme.list.itemAccentColor)), + horizontalAlignment: .center, + maximumNumberOfLines: 0 + ) + ), + effectAlignment: .center, + action: { [weak self] in + guard let self else { + return + } + self.profileGifts.updateFilter(.All) + } + ) + ), + environment: {}, + containerSize: CGSize(width: params.size.width - sideInset * 2.0, height: visibleHeight) + ) + let emptyResultsAnimationSize = self.emptyResultsAnimation.update( + transition: .immediate, + component: AnyComponent(LottieComponent( + content: LottieComponent.AppBundleContent(name: "ChatListNoResults") + )), + environment: {}, + containerSize: CGSize(width: emptyAnimationHeight, height: emptyAnimationHeight) + ) + + let emptyTotalHeight = emptyAnimationHeight + emptyAnimationSpacing + emptyResultsTitleSize.height + emptyResultsActionSize.height + emptyTextSpacing + let emptyAnimationY = topInset + floorToScreenPixels((visibleHeight - topInset - bottomInset - emptyTotalHeight) / 2.0) + + let emptyResultsAnimationFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.size.width - emptyResultsAnimationSize.width) / 2.0), y: emptyAnimationY), size: emptyResultsAnimationSize) + + let emptyResultsTitleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.size.width - emptyResultsTitleSize.width) / 2.0), y: emptyResultsAnimationFrame.maxY + emptyAnimationSpacing), size: emptyResultsTitleSize) + + let emptyResultsActionFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((params.size.width - emptyResultsActionSize.width) / 2.0), y: emptyResultsTitleFrame.maxY + emptyTextSpacing), size: emptyResultsActionSize) + + if let view = self.emptyResultsAnimation.view as? LottieComponent.View { + if view.superview == nil { + view.alpha = 0.0 + fadeTransition.setAlpha(view: view, alpha: 1.0) + self.scrollNode.view.addSubview(view) + view.playOnce() + } + view.bounds = CGRect(origin: .zero, size: emptyResultsAnimationFrame.size) + transition.setPosition(view: view, position: emptyResultsAnimationFrame.center) + } + if let view = self.emptyResultsTitle.view { + if view.superview == nil { + view.alpha = 0.0 + fadeTransition.setAlpha(view: view, alpha: 1.0) + self.scrollNode.view.addSubview(view) + } + view.bounds = CGRect(origin: .zero, size: emptyResultsTitleFrame.size) + transition.setPosition(view: view, position: emptyResultsTitleFrame.center) + } + if let view = self.emptyResultsAction.view { + if view.superview == nil { + view.alpha = 0.0 + fadeTransition.setAlpha(view: view, alpha: 1.0) + self.scrollNode.view.addSubview(view) + } + view.bounds = CGRect(origin: .zero, size: emptyResultsActionFrame.size) + transition.setPosition(view: view, position: emptyResultsActionFrame.center) + } + } else { + if let view = self.emptyResultsAnimation.view { + fadeTransition.setAlpha(view: view, alpha: 0.0, completion: { _ in + view.removeFromSuperview() + }) + } + if let view = self.emptyResultsTitle.view { + fadeTransition.setAlpha(view: view, alpha: 0.0, completion: { _ in + view.removeFromSuperview() + }) + } + if let view = self.emptyResultsAction.view { + fadeTransition.setAlpha(view: view, alpha: 0.0, completion: { _ in + view.removeFromSuperview() + }) + } + } + if self.peerId == self.context.account.peerId { let footerText: ComponentView if let current = self.footerText { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 337eb32034..e55a832cb6 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -1121,7 +1121,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState } } - if data.messageActions.options.contains(.sendGift) { + if data.messageActions.options.contains(.sendGift), !message.id.peerId.isTelegramNotifications { let sendGiftTitle: String var isIncoming = message.effectivelyIncoming(context.account.peerId) for media in message.media { From d596e18260ad3f08ae069e89f6e80bf123e8e9b7 Mon Sep 17 00:00:00 2001 From: Mikhail Filimonov Date: Tue, 21 Jan 2025 21:04:45 +0400 Subject: [PATCH 3/3] improvements --- .../Sources/SyncCore/SyncCore_TelegramMediaAction.swift | 9 +++++++++ .../Sources/TelegramEngine/Data/PeersData.swift | 7 +++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift index e45b7d8596..6dc1fdecb2 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift @@ -662,6 +662,15 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { peerIds.append(senderId) } return peerIds + case let .starGiftUnique(_, _, _, _, _, _, _, peerId, senderId, _): + var peerIds: [PeerId] = [] + if let peerId { + peerIds.append(peerId) + } + if let senderId { + peerIds.append(senderId) + } + return peerIds default: return [] } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift index 53c4260259..2a7532b66b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift @@ -753,9 +753,12 @@ public extension TelegramEngine.EngineData.Item { } if let cachedData = view.cachedPeerData as? CachedUserData { return cachedData.starGiftsCount - } else { - return nil } + if let cachedData = view.cachedPeerData as? CachedChannelData { + return cachedData.starGiftsCount + } + return nil + } }