Various improvements

This commit is contained in:
Ilya Laktyushin 2025-07-29 21:49:26 +02:00
parent 7a99577093
commit 711f8f7b46
6 changed files with 123 additions and 75 deletions

View File

@ -14787,3 +14787,5 @@ Sorry for the inconvenience.";
"Stars.SellGift.TonAmountTitle" = "PRICE IN TON";
"Stars.SellGift.OnlyTon" = "Only Accept TON";
"Stars.SellGift.OnlyTonInfo" = "If the buyer pays you in TON, there's no risk of refunds, unlike with Stars payments.";
"Chat.ViewCollection" = "VIEW COLLECTION";

View File

@ -477,8 +477,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
case "telegram_call":
actionTitle = item.presentationData.strings.Chat_ViewGroupCall
case "telegram_collection":
//TODO:localize
actionTitle = "VIEW COLLECTION"
actionTitle = item.presentationData.strings.Chat_ViewCollection
default:
break
}

View File

@ -537,7 +537,8 @@ private final class PeerInfoPendingPane {
paneDidScroll: @escaping () -> Void,
expandIfNeeded: @escaping () -> Void,
ensureRectVisible: @escaping (UIView, CGRect) -> Void,
externalDataUpdated: @escaping (ContainedViewLayoutTransition) -> Void
externalDataUpdated: @escaping (ContainedViewLayoutTransition) -> Void,
openShareLink: @escaping (String) -> Void
) {
var chatLocationPeerId = peerId
var chatLocation = chatLocation
@ -578,7 +579,9 @@ private final class PeerInfoPendingPane {
}
}
}
paneNode = PeerInfoGiftsPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, profileGiftsCollections: data.profileGiftsCollectionsContext!, profileGifts: data.profileGiftsContext!, canManage: canManage, canGift: canGift, initialGiftCollectionId: initialGiftCollectionId)
let giftPaneNode = PeerInfoGiftsPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, profileGiftsCollections: data.profileGiftsCollectionsContext!, profileGifts: data.profileGiftsContext!, canManage: canManage, canGift: canGift, initialGiftCollectionId: initialGiftCollectionId)
giftPaneNode.openShareLink = openShareLink
paneNode = giftPaneNode
case .stories, .storyArchive, .botPreview:
var canManage = false
if let peer = data.peer {
@ -748,6 +751,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
var openMediaCalendar: (() -> Void)?
var openAddStory: (() -> Void)?
var openShareLink: ((String) -> Void)?
var paneDidScroll: (() -> Void)?
var ensurePaneRectVisible: ((UIView, CGRect) -> Void)?
@ -1181,6 +1185,12 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
return
}
self.requestUpdate?(transition)
},
openShareLink: { [weak self] url in
guard let self else {
return
}
self.openShareLink?(url)
}
)
self.pendingPanes[key] = pane

View File

@ -4103,6 +4103,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
}
self.paneContainerNode.openShareLink = { [weak self] url in
guard let self else {
return
}
self.openShareLink(url: url)
}
self.headerNode.performButtonAction = { [weak self] key, gesture in
self?.performButtonAction(key: key, gesture: gesture)
}
@ -11392,17 +11399,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
pane.addGiftsToCollection(id: id)
}
})))
if let addressName = data.peer?.addressName, !addressName.isEmpty {
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
if let pane, case let .collection(id) = pane.currentCollection {
self?.openShareLink(url: "https://t.me/\(addressName)/c/\(id)")
}
})))
}
}
if canReorder {
@ -11430,6 +11426,20 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
}
if let pane, case let .collection(id) = pane.currentCollection, let addressName = data.peer?.addressName, !addressName.isEmpty {
let shareAction: ContextMenuItem = .action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
self?.openShareLink(url: "https://t.me/\(addressName)/c/\(id)")
}))
if items.isEmpty {
items.append(shareAction)
} else {
items.insert(shareAction, at: 1)
}
}
if !items.isEmpty {
items.append(.separator)
}

View File

@ -70,6 +70,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
private let profileGifts: ProfileGiftsContext
private let canManage: Bool
private let canGift: Bool
private var peer: EnginePeer?
private let initialGiftCollectionId: Int64?
private var resultsAreEmpty = false
@ -130,6 +131,8 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
return self.giftsListView.profileGifts
}
public var openShareLink: ((String) -> Void)?
private let collectionsMaxCount: Int
public init(context: AccountContext, peerId: PeerId, chatControllerInteraction: ChatControllerInteraction, profileGiftsCollections: ProfileGiftsCollectionsContext, profileGifts: ProfileGiftsContext, canManage: Bool, canGift: Bool, initialGiftCollectionId: Int64?) {
@ -193,6 +196,15 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
if let initialGiftCollectionId {
self.setCurrentCollection(collection: .collection(Int32(initialGiftCollectionId)))
}
let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let self else {
return
}
self.peer = peer
self.updateScrolling(transition: .immediate)
})
}
deinit {
@ -485,68 +497,78 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
return
}
var canEditCollections = false
if self.peerId == self.context.account.peerId || self.canManage {
canEditCollections = true
}
var items: [ContextMenuItem] = []
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_AddGifts, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddGift"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
return
}
f(.default)
self.setCurrentCollection(collection: .collection(id))
self.addGiftsToCollection(id: id)
})))
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_RenameCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
return
}
f(.default)
Queue.mainQueue().after(0.15) {
self.renameCollection(id: id)
}
})))
// items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor)
// }, action: { [weak self] _, f in
// guard let self else {
// return
// }
// f(.default)
//
// let _ = self
// })))
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_Reorder, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] c, f in
c?.dismiss(completion: { [weak self] in
if canEditCollections {
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_AddGifts, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddGift"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
return
}
self.beginReordering()
})
})))
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_DeleteCollection, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
guard let self else {
return
}
f(.default)
f(.default)
self.setCurrentCollection(collection: .collection(id))
self.addGiftsToCollection(id: id)
})))
Queue.mainQueue().after(0.15) {
self.deleteCollection(id: id)
}
})))
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_RenameCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
return
}
f(.default)
Queue.mainQueue().after(0.15) {
self.renameCollection(id: id)
}
})))
}
if let peer = self.peer, let addressName = peer.addressName, !addressName.isEmpty {
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
return
}
f(.default)
self.openShareLink?("https://t.me/\(addressName)/c/\(id)")
})))
}
if canEditCollections {
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_Reorder, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] c, f in
c?.dismiss(completion: { [weak self] in
guard let self else {
return
}
self.beginReordering()
})
})))
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_DeleteCollection, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
guard let self else {
return
}
f(.default)
Queue.mainQueue().after(0.15) {
self.deleteCollection(id: id)
}
})))
}
let contextController = ContextController(
presentationData: params.presentationData,
@ -568,6 +590,10 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
if self.peerId == self.context.account.peerId || self.canManage {
canEditCollections = true
}
var canShare = false
if let peer = self.peer, let addressName = peer.addressName, !addressName.isEmpty {
canShare = true
}
let hasNonEmptyCollections = self.collections?.contains(where: { $0.count > 0 }) ?? false
if let collections = self.collections, !collections.isEmpty && (hasNonEmptyCollections || canEditCollections) {
@ -607,7 +633,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
)
)),
isReorderable: collections.count > 1,
contextAction: canEditCollections ? { [weak self] sourceNode, gesture in
contextAction: canEditCollections || canShare ? { [weak self] sourceNode, gesture in
guard let self else {
return
}

View File

@ -1037,15 +1037,16 @@ private final class SheetContent: CombinedComponent {
}
if case let .starGiftResell(giftToMatch, update, _) = self.mode {
let resaleConfiguration = StarsSubscriptionConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
if update {
if giftToMatch.resellForTonOnly {
if let resellStars = giftToMatch.resellAmounts?.first(where: { $0.currency == .ton }) {
self.amount = resellStars.amount
self.amount = StarsAmount(value: max(resellStars.amount.value, resaleConfiguration.starGiftResaleMinTonAmount), nanos: 0)
}
self.currency = .ton
} else {
if let resellStars = giftToMatch.resellAmounts?.first(where: { $0.currency == .stars }) {
self.amount = resellStars.amount
self.amount = StarsAmount(value: max(resellStars.amount.value, resaleConfiguration.starGiftResaleMinStarsAmount), nanos: 0)
}
self.currency = .stars
}
@ -1067,7 +1068,7 @@ private final class SheetContent: CombinedComponent {
return
}
if case let .generic(genericGift) = matchingGift, let minResaleStars = genericGift.availability?.minResaleStars {
self.amount = StarsAmount(value: minResaleStars, nanos: 0)
self.amount = StarsAmount(value: max(minResaleStars, resaleConfiguration.starGiftResaleMinStarsAmount), nanos: 0)
self.updated()
}
})