Stars reactions improvements

This commit is contained in:
Isaac 2024-08-13 21:14:59 +08:00
parent 524ce21f5e
commit da45de818a
5 changed files with 121 additions and 31 deletions

View File

@ -842,12 +842,11 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
case let .peer(peerId):
if peerId != item.context.account.peerId {
if peerId.isGroupOrChannel && item.message.author != nil {
var isBroadcastChannel = false
if let peer = item.message.peers[item.message.id.peerId] as? TelegramChannel, case .broadcast = peer.info {
isBroadcastChannel = true
}
if !isBroadcastChannel {
if let peer = item.message.peers[item.message.id.peerId] as? TelegramChannel, case let .broadcast(info) = peer.info {
if item.message.author?.id != peer.id, info.flags.contains(.messagesShouldHaveProfiles) {
hasAvatar = incoming
}
} else {
hasAvatar = true
}
}

View File

@ -464,14 +464,15 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
case let .peer(peerId):
if !peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
if peerId.isGroupOrChannel && item.message.author != nil {
var isBroadcastChannel = false
if let peer = item.message.peers[item.message.id.peerId] as? TelegramChannel, case .broadcast = peer.info {
isBroadcastChannel = true
if let peer = item.message.peers[item.message.id.peerId] as? TelegramChannel, case let .broadcast(info) = peer.info {
if item.message.author?.id != peer.id, info.flags.contains(.messagesShouldHaveProfiles) {
hasAvatar = incoming
}
} else {
hasAvatar = true
}
if !isBroadcastChannel {
hasAvatar = true
} else if case .customChatContents = item.chatLocation {
if case .customChatContents = item.chatLocation {
hasAvatar = false
}
}

View File

@ -479,14 +479,14 @@ private final class PeerComponent: Component {
let theme: PresentationTheme
let strings: PresentationStrings
let peer: EnginePeer?
let count: Int
let count: String
init(
context: AccountContext,
theme: PresentationTheme,
strings: PresentationStrings,
peer: EnginePeer?,
count: Int
count: String
) {
self.context = context
self.theme = theme
@ -555,7 +555,7 @@ private final class PeerComponent: Component {
transition: .immediate,
component: AnyComponent(PeerBadgeComponent(
theme: component.theme,
title: "\(component.count)"
title: component.count
)),
environment: {},
containerSize: CGSize(width: 200.0, height: 200.0)
@ -1046,6 +1046,7 @@ private final class ChatSendStarsScreenComponent: Component {
private var balance: Int64?
private var amount: Amount = Amount(realValue: 1, maxRealValue: 1000, maxSliderValue: 1000, isLogarithmic: true)
private var didChangeAmount: Bool = false
private var isAnonymous: Bool = false
private var cachedStarImage: (UIImage, PresentationTheme)?
@ -1291,6 +1292,7 @@ private final class ChatSendStarsScreenComponent: Component {
return
}
self.amount = self.amount.withSliderValue(value)
self.didChangeAmount = true
self.state?.updated(transition: ComponentTransition(animation: .none).withUserData(IsAdjustingAmountHint()))
@ -1640,10 +1642,16 @@ private final class ChatSendStarsScreenComponent: Component {
if let index = mappedTopPeers.firstIndex(where: { $0.isMy }) {
mappedTopPeers.remove(at: index)
}
var myCount = Int(self.amount.realValue)
var myCount = 0
if let myTopPeer = component.myTopPeer {
myCount += myTopPeer.count
}
var myCountAddition = 0
if self.didChangeAmount {
myCountAddition = Int(self.amount.realValue)
}
myCount += myCountAddition
mappedTopPeers.append(ChatSendStarsScreen.TopPeer(
peer: self.isAnonymous ? nil : component.myPeer,
isMy: true,
@ -1676,6 +1684,11 @@ private final class ChatSendStarsScreenComponent: Component {
self.topPeerItems[topPeer.id] = itemView
}
var itemCountString = "\(topPeer.count)"
if topPeer.isMy && myCountAddition != 0 && topPeer.count > myCountAddition {
itemCountString = "\(topPeer.count - myCountAddition) +\(myCountAddition)"
}
let itemSize = itemView.update(
transition: .immediate,
component: AnyComponent(PlainButtonComponent(
@ -1684,7 +1697,7 @@ private final class ChatSendStarsScreenComponent: Component {
theme: environment.theme,
strings: environment.strings,
peer: topPeer.peer,
count: topPeer.count
count: itemCountString
)),
effectAlignment: .center,
action: { [weak self] in

View File

@ -387,8 +387,46 @@ extension ChatControllerImpl {
}
}
self.context.engine.messages.sendStarsReaction(id: message.id, count: 1, isAnonymous: false)
self.displayOrUpdateSendStarsUndo(messageId: message.id, count: 1)
guard let starsContext = self.context.starsContext else {
return
}
let _ = (starsContext.state
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] state in
guard let strongSelf = self, let balance = state?.balance else {
return
}
if balance < 1 {
controller?.dismiss(completion: {
guard let strongSelf = self else {
return
}
let _ = (strongSelf.context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { [weak strongSelf] options in
guard let strongSelf, let peerId = strongSelf.chatLocation.peerId else {
return
}
guard let starsContext = strongSelf.context.starsContext else {
return
}
let purchaseScreen = strongSelf.context.sharedContext.makeStarsPurchaseScreen(context: strongSelf.context, starsContext: starsContext, options: options, purpose: .transfer(peerId: peerId, requiredStars: 1), completion: { result in
let _ = result
//TODO:release
})
strongSelf.push(purchaseScreen)
})
})
return
}
strongSelf.context.engine.messages.sendStarsReaction(id: message.id, count: 1, isAnonymous: false)
strongSelf.displayOrUpdateSendStarsUndo(messageId: message.id, count: 1)
})
} else {
let chosenReaction: MessageReaction.Reaction = chosenUpdatedReaction.reaction

View File

@ -29,6 +29,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
private let elevatedLayout: Bool
private let placementPosition: UndoOverlayController.Position
private var statusNode: RadialStatusNode?
private var didStartStatusNode: Bool = false
private let timerTextNode: ImmediateTextNode
private let avatarNode: AvatarNode?
private let iconNode: ASImageNode?
@ -67,6 +68,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
private var isTimeoutDisabled: Bool = false
private var originalRemainingSeconds: Double
private var remainingSeconds: Double
private let undoTextColor: UIColor
private var timer: SwiftSignalKit.Timer?
private var validLayout: ContainerViewLayout?
@ -413,8 +415,10 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
self.animatedTextItems = textItems
displayUndo = true
self.originalRemainingSeconds = 4.5
self.originalRemainingSeconds = 4.9
isUserInteractionEnabled = true
self.statusNode = RadialStatusNode(backgroundNodeColor: .clear)
case let .messagesUnpinned(title, text, undo, isHidden):
self.avatarNode = nil
self.iconNode = nil
@ -1246,6 +1250,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
}
self.remainingSeconds = self.originalRemainingSeconds
self.undoTextColor = undoTextColor
self.undoButtonTextNode = ImmediateTextNode()
self.undoButtonTextNode.displaysAsynchronously = false
@ -1271,7 +1276,15 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
switch content {
case .removedChat:
self.panelWrapperNode.addSubnode(self.timerTextNode)
case .archivedChat, .hidArchive, .revealedArchive, .autoDelete, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert, .invitedToVoiceChat, .linkCopied, .banned, .importedMessage, .audioRate, .forward, .gigagroupConversion, .linkRevoked, .voiceChatRecording, .voiceChatFlag, .voiceChatCanSpeak, .copy, .mediaSaved, .paymentSent, .starsSent, .image, .inviteRequestSent, .notificationSoundAdded, .universal, .premiumPaywall, .peers, .messageTagged:
case .starsSent:
self.panelWrapperNode.addSubnode(self.timerTextNode)
if self.textNode.tapAttributeAction != nil || displayUndo {
self.isUserInteractionEnabled = true
} else {
self.isUserInteractionEnabled = false
}
case .archivedChat, .hidArchive, .revealedArchive, .autoDelete, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert, .invitedToVoiceChat, .linkCopied, .banned, .importedMessage, .audioRate, .forward, .gigagroupConversion, .linkRevoked, .voiceChatRecording, .voiceChatFlag, .voiceChatCanSpeak, .copy, .mediaSaved, .paymentSent, .image, .inviteRequestSent, .notificationSoundAdded, .universal, .premiumPaywall, .peers, .messageTagged:
if self.textNode.tapAttributeAction != nil || displayUndo {
self.isUserInteractionEnabled = true
} else {
@ -1420,7 +1433,8 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
let _ = self.action(.commit)
self.dismiss()
} else {
if Int(self.remainingSeconds) != previousRemainingSeconds || (self.timerTextNode.attributedText?.string ?? "").isEmpty {
let remainingSecondsString = "\(Int(self.remainingSeconds))"
if Int(self.remainingSeconds) != previousRemainingSeconds || self.timerTextNode.attributedText?.string != remainingSecondsString {
if !self.timerTextNode.bounds.size.width.isZero, let snapshot = self.timerTextNode.view.snapshotContentTree() {
self.panelNode.view.insertSubview(snapshot, aboveSubview: self.timerTextNode.view)
snapshot.frame = self.timerTextNode.frame
@ -1431,7 +1445,13 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
snapshot?.removeFromSuperview()
})
}
self.timerTextNode.attributedText = NSAttributedString(string: "\(Int(self.remainingSeconds))", font: Font.regular(16.0), textColor: .white)
let timerColor: UIColor
if case .starsSent = self.content {
timerColor = self.undoTextColor
} else {
timerColor = .white
}
self.timerTextNode.attributedText = NSAttributedString(string: remainingSecondsString, font: Font.regular(16.0), textColor: timerColor)
if let validLayout = self.validLayout {
self.containerLayoutUpdated(layout: validLayout, transition: .immediate)
}
@ -1450,6 +1470,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
self.timer?.invalidate()
self.timer = nil
self.remainingSeconds = self.originalRemainingSeconds
self.didStartStatusNode = false
self.checkTimer()
}
@ -1508,7 +1529,6 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
}
func containerLayoutUpdated(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
let firstLayout = self.validLayout == nil
self.validLayout = layout
var preferredSize: CGSize?
@ -1630,10 +1650,14 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
transition.updateFrame(node: self.panelWrapperNode, frame: panelWrapperFrame)
self.effectView.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width - leftMargin * 2.0 - layout.safeInsets.left - layout.safeInsets.right, height: contentHeight)
let buttonTextFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - leftMargin * 2.0, y: floor((contentHeight - buttonTextSize.height) / 2.0)), size: buttonTextSize)
var buttonTextFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - leftMargin * 2.0, y: floor((contentHeight - buttonTextSize.height) / 2.0)), size: buttonTextSize)
var undoButtonFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - leftMargin * 2.0, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + leftMargin, height: contentHeight))
if case .starsSent = self.content {
let buttonOffset: CGFloat = -34.0
undoButtonFrame.origin.x += buttonOffset
buttonTextFrame.origin.x += buttonOffset
}
transition.updateFrame(node: self.undoButtonTextNode, frame: buttonTextFrame)
let undoButtonFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - leftMargin * 2.0, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + leftMargin, height: contentHeight))
self.undoButtonNode.frame = undoButtonFrame
self.buttonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: self.undoButtonNode.supernode == nil ? panelFrame.width : undoButtonFrame.minX, height: contentHeight))
@ -1728,13 +1752,28 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
}
let timerTextSize = self.timerTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
transition.updateFrame(node: self.timerTextNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - timerTextSize.width) / 2.0), y: floor((contentHeight - timerTextSize.height) / 2.0)), size: timerTextSize))
if case .starsSent = self.content {
transition.updateFrame(node: self.timerTextNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset + floor((rightInset - timerTextSize.width) * 0.5) - 46.0)), y: floor((contentHeight - timerTextSize.height) / 2.0)), size: timerTextSize))
} else {
transition.updateFrame(node: self.timerTextNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - timerTextSize.width) / 2.0), y: floor((contentHeight - timerTextSize.height) / 2.0)), size: timerTextSize))
}
if let statusNode = self.statusNode {
let statusSize: CGFloat = 30.0
transition.updateFrame(node: statusNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize)))
if firstLayout {
statusNode.transitionToState(.secretTimeout(color: .white, icon: .none, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {})
var statusFrame = CGRect(origin: CGPoint(x: floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize))
if case .starsSent = self.content {
statusFrame.origin.x = layout.size.width - layout.safeInsets.left - layout.safeInsets.right - rightInset - statusSize - 23.0
}
transition.updateFrame(node: statusNode, frame: statusFrame)
if !self.didStartStatusNode {
let statusColor: UIColor
if case .starsSent = self.content {
statusColor = self.undoTextColor
} else {
statusColor = .white
}
statusNode.transitionToState(.secretTimeout(color: statusColor, icon: .none, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {})
self.didStartStatusNode = true
}
}