Anonymous top peers

This commit is contained in:
Isaac 2024-08-12 03:56:41 +04:00
parent 65a88ae93f
commit bf9f0030d8

View File

@ -736,10 +736,14 @@ private final class SliderBackgroundComponent: Component {
} }
private final class ChatSendStarsScreenComponent: Component { private final class ChatSendStarsScreenComponent: Component {
private final class IsAdjustingAmountHint {
}
typealias EnvironmentType = ViewControllerComponentContainer.Environment typealias EnvironmentType = ViewControllerComponentContainer.Environment
let context: AccountContext let context: AccountContext
let peer: EnginePeer let peer: EnginePeer
let myPeer: EnginePeer
let messageId: EngineMessage.Id let messageId: EngineMessage.Id
let maxAmount: Int let maxAmount: Int
let balance: Int64? let balance: Int64?
@ -751,6 +755,7 @@ private final class ChatSendStarsScreenComponent: Component {
init( init(
context: AccountContext, context: AccountContext,
peer: EnginePeer, peer: EnginePeer,
myPeer: EnginePeer,
messageId: EngineMessage.Id, messageId: EngineMessage.Id,
maxAmount: Int, maxAmount: Int,
balance: Int64?, balance: Int64?,
@ -761,6 +766,7 @@ private final class ChatSendStarsScreenComponent: Component {
) { ) {
self.context = context self.context = context
self.peer = peer self.peer = peer
self.myPeer = myPeer
self.messageId = messageId self.messageId = messageId
self.maxAmount = maxAmount self.maxAmount = maxAmount
self.balance = balance self.balance = balance
@ -777,6 +783,9 @@ private final class ChatSendStarsScreenComponent: Component {
if lhs.peer != rhs.peer { if lhs.peer != rhs.peer {
return false return false
} }
if lhs.myPeer != rhs.myPeer {
return false
}
if lhs.maxAmount != rhs.maxAmount { if lhs.maxAmount != rhs.maxAmount {
return false return false
} }
@ -1071,7 +1080,7 @@ private final class ChatSendStarsScreenComponent: Component {
return return
} }
self.amount = 1 + Int64(value) self.amount = 1 + Int64(value)
self.state?.updated(transition: .immediate) self.state?.updated(transition: ComponentTransition(animation: .none).withUserData(IsAdjustingAmountHint()))
let sliderValue = Float(value) / Float(component.maxAmount) let sliderValue = Float(value) / Float(component.maxAmount)
let currentTimestamp = CACurrentMediaTime() let currentTimestamp = CACurrentMediaTime()
@ -1404,9 +1413,36 @@ private final class ChatSendStarsScreenComponent: Component {
transition.setFrame(layer: topPeersLeftSeparator, frame: CGRect(origin: CGPoint(x: sideInset, y: separatorY), size: CGSize(width: max(0.0, topPeersBackgroundFrame.minX - separatorSpacing - sideInset), height: UIScreenPixel))) transition.setFrame(layer: topPeersLeftSeparator, frame: CGRect(origin: CGPoint(x: sideInset, y: separatorY), size: CGSize(width: max(0.0, topPeersBackgroundFrame.minX - separatorSpacing - sideInset), height: UIScreenPixel)))
transition.setFrame(layer: topPeersRightSeparator, frame: CGRect(origin: CGPoint(x: topPeersBackgroundFrame.maxX + separatorSpacing, y: separatorY), size: CGSize(width: max(0.0, availableSize.width - sideInset - (topPeersBackgroundFrame.maxX + separatorSpacing)), height: UIScreenPixel))) transition.setFrame(layer: topPeersRightSeparator, frame: CGRect(origin: CGPoint(x: topPeersBackgroundFrame.maxX + separatorSpacing, y: separatorY), size: CGSize(width: max(0.0, availableSize.width - sideInset - (topPeersBackgroundFrame.maxX + separatorSpacing)), height: UIScreenPixel)))
var mappedTopPeers = component.topPeers
if let index = mappedTopPeers.firstIndex(where: { $0.isMy }) {
mappedTopPeers.remove(at: index)
}
var myCount = Int(self.amount)
if let myTopPeer = component.myTopPeer {
myCount += myTopPeer.count
}
mappedTopPeers.append(ChatSendStarsScreen.TopPeer(
peer: self.isAnonymous ? nil : component.myPeer,
isMy: true,
count: myCount
))
mappedTopPeers.sort(by: { $0.count > $1.count })
if mappedTopPeers.count > 3 {
mappedTopPeers = Array(mappedTopPeers.prefix(3))
}
var animateItems = false
var itemPositionTransition = transition
var itemAlphaTransition = transition
if transition.userData(IsAdjustingAmountHint.self) != nil {
animateItems = true
itemPositionTransition = .spring(duration: 0.4)
itemAlphaTransition = .easeInOut(duration: 0.2)
}
var validIds: [ChatSendStarsScreen.TopPeer.Id] = [] var validIds: [ChatSendStarsScreen.TopPeer.Id] = []
var items: [(itemView: ComponentView<Empty>, size: CGSize)] = [] var items: [(itemView: ComponentView<Empty>, size: CGSize)] = []
for topPeer in component.topPeers { for topPeer in mappedTopPeers {
validIds.append(topPeer.id) validIds.append(topPeer.id)
let itemView: ComponentView<Empty> let itemView: ComponentView<Empty>
@ -1456,7 +1492,17 @@ private final class ChatSendStarsScreenComponent: Component {
for (id, itemView) in self.topPeerItems { for (id, itemView) in self.topPeerItems {
if !validIds.contains(id) { if !validIds.contains(id) {
removedIds.append(id) removedIds.append(id)
itemView.view?.removeFromSuperview()
if animateItems {
if let itemComponentView = itemView.view {
itemPositionTransition.setScale(view: itemComponentView, scale: 0.001)
itemAlphaTransition.setAlpha(view: itemComponentView, alpha: 0.0, completion: { [weak itemComponentView] _ in
itemComponentView?.removeFromSuperview()
})
}
} else {
itemView.view?.removeFromSuperview()
}
} }
} }
for id in removedIds { for id in removedIds {
@ -1476,10 +1522,26 @@ private final class ChatSendStarsScreenComponent: Component {
var itemX: CGFloat = floor((availableSize.width - totalWidth) * 0.5) + itemSpacing var itemX: CGFloat = floor((availableSize.width - totalWidth) * 0.5) + itemSpacing
for (itemView, itemSize) in items { for (itemView, itemSize) in items {
if let itemComponentView = itemView.view { if let itemComponentView = itemView.view {
var animateItem = animateItems
if itemComponentView.superview == nil { if itemComponentView.superview == nil {
self.scrollContentView.addSubview(itemComponentView) self.scrollContentView.addSubview(itemComponentView)
animateItem = false
ComponentTransition.immediate.setScale(view: itemComponentView, scale: 0.001)
itemComponentView.alpha = 0.0
} }
itemComponentView.frame = CGRect(origin: CGPoint(x: itemX, y: contentHeight + 56.0), size: itemSize)
let itemFrame = CGRect(origin: CGPoint(x: itemX, y: contentHeight + 56.0), size: itemSize)
if animateItem {
itemPositionTransition.setPosition(view: itemComponentView, position: itemFrame.center)
itemPositionTransition.setBounds(view: itemComponentView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size))
} else {
itemComponentView.center = itemFrame.center
itemComponentView.bounds = CGRect(origin: CGPoint(), size: itemFrame.size)
}
itemPositionTransition.setScale(view: itemComponentView, scale: 1.0)
itemAlphaTransition.setAlpha(view: itemComponentView, alpha: 1.0)
} }
itemX += itemSize.width + itemSpacing itemX += itemSize.width + itemSpacing
} }
@ -1724,6 +1786,7 @@ private final class ChatSendStarsScreenComponent: Component {
public class ChatSendStarsScreen: ViewControllerComponentContainer { public class ChatSendStarsScreen: ViewControllerComponentContainer {
public final class InitialData { public final class InitialData {
fileprivate let peer: EnginePeer fileprivate let peer: EnginePeer
fileprivate let myPeer: EnginePeer
fileprivate let messageId: EngineMessage.Id fileprivate let messageId: EngineMessage.Id
fileprivate let balance: Int64? fileprivate let balance: Int64?
fileprivate let currentSentAmount: Int? fileprivate let currentSentAmount: Int?
@ -1732,6 +1795,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
fileprivate init( fileprivate init(
peer: EnginePeer, peer: EnginePeer,
myPeer: EnginePeer,
messageId: EngineMessage.Id, messageId: EngineMessage.Id,
balance: Int64?, balance: Int64?,
currentSentAmount: Int?, currentSentAmount: Int?,
@ -1739,6 +1803,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
myTopPeer: ChatSendStarsScreen.TopPeer? myTopPeer: ChatSendStarsScreen.TopPeer?
) { ) {
self.peer = peer self.peer = peer
self.myPeer = myPeer
self.messageId = messageId self.messageId = messageId
self.balance = balance self.balance = balance
self.currentSentAmount = currentSentAmount self.currentSentAmount = currentSentAmount
@ -1748,16 +1813,20 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
} }
fileprivate final class TopPeer: Equatable { fileprivate final class TopPeer: Equatable {
struct Id: Hashable { enum Id: Hashable {
var value: EnginePeer.Id? case anonymous
case my
init(_ value: EnginePeer.Id?) { case peer(EnginePeer.Id)
self.value = value
}
} }
var id: Id { var id: Id {
return Id(self.peer?.id) if self.isMy {
return .my
} else if let peer = self.peer {
return .peer(peer.id)
} else {
return .anonymous
}
} }
var isAnonymous: Bool { var isAnonymous: Bool {
@ -1765,10 +1834,12 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
} }
let peer: EnginePeer? let peer: EnginePeer?
let isMy: Bool
let count: Int let count: Int
init(peer: EnginePeer?, count: Int) { init(peer: EnginePeer?, isMy: Bool, count: Int) {
self.peer = peer self.peer = peer
self.isMy = isMy
self.count = count self.count = count
} }
@ -1776,6 +1847,9 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
if lhs.peer != rhs.peer { if lhs.peer != rhs.peer {
return false return false
} }
if lhs.isMy != rhs.isMy {
return false
}
if lhs.count != rhs.count { if lhs.count != rhs.count {
return false return false
} }
@ -1809,6 +1883,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
super.init(context: context, component: ChatSendStarsScreenComponent( super.init(context: context, component: ChatSendStarsScreenComponent(
context: context, context: context,
peer: initialData.peer, peer: initialData.peer,
myPeer: initialData.myPeer,
messageId: initialData.messageId, messageId: initialData.messageId,
maxAmount: maxAmount, maxAmount: maxAmount,
balance: initialData.balance, balance: initialData.balance,
@ -1874,18 +1949,20 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
return combineLatest( return combineLatest(
context.engine.data.get( context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId), TelegramEngine.EngineData.Item.Peer.Peer(id: peerId),
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
EngineDataMap(allPeerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:))) EngineDataMap(allPeerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
), ),
balance balance
) )
|> map { peerAndTopPeerMap, balance -> InitialData? in |> map { peerAndTopPeerMap, balance -> InitialData? in
let (peer, topPeerMap) = peerAndTopPeerMap let (peer, myPeer, topPeerMap) = peerAndTopPeerMap
guard let peer else { guard let peer, let myPeer else {
return nil return nil
} }
return InitialData( return InitialData(
peer: peer, peer: peer,
myPeer: myPeer,
messageId: messageId, messageId: messageId,
balance: balance, balance: balance,
currentSentAmount: currentSentAmount, currentSentAmount: currentSentAmount,
@ -1893,6 +1970,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
guard let topPeerId = topPeer.peerId else { guard let topPeerId = topPeer.peerId else {
return ChatSendStarsScreen.TopPeer( return ChatSendStarsScreen.TopPeer(
peer: nil, peer: nil,
isMy: topPeer.isMy,
count: Int(topPeer.count) count: Int(topPeer.count)
) )
} }
@ -1904,6 +1982,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
} }
return ChatSendStarsScreen.TopPeer( return ChatSendStarsScreen.TopPeer(
peer: topPeer.isAnonymous ? nil : topPeerValue, peer: topPeer.isAnonymous ? nil : topPeerValue,
isMy: topPeer.isMy,
count: Int(topPeer.count) count: Int(topPeer.count)
) )
}, },
@ -1911,6 +1990,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
guard let topPeerId = topPeer.peerId else { guard let topPeerId = topPeer.peerId else {
return ChatSendStarsScreen.TopPeer( return ChatSendStarsScreen.TopPeer(
peer: nil, peer: nil,
isMy: topPeer.isMy,
count: Int(topPeer.count) count: Int(topPeer.count)
) )
} }
@ -1922,6 +2002,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer {
} }
return ChatSendStarsScreen.TopPeer( return ChatSendStarsScreen.TopPeer(
peer: topPeer.isAnonymous ? nil : topPeerValue, peer: topPeer.isAnonymous ? nil : topPeerValue,
isMy: topPeer.isMy,
count: Int(topPeer.count) count: Int(topPeer.count)
) )
} }