Various fixes

This commit is contained in:
Ilya Laktyushin 2024-12-28 23:54:32 +04:00
parent 3bbb677b0d
commit 45fa1b5ddb
4 changed files with 176 additions and 15 deletions

View File

@ -264,6 +264,7 @@
"PUSH_MESSAGE_SAME_WALLPAPER" = "%1$@ set the same wallpaper for the chat with you";
"PUSH_MESSAGE_UNIQUE_STARGIFT" = "%1$@ sent you a Gift";
"PUSH_MESSAGE_STARGIFT_UPGRADE" = "%1$@ upgraded your Gift";
"PUSH_REMINDER_TITLE" = "🗓 Reminder";
"PUSH_SENDER_YOU" = "📅 You";

View File

@ -1266,6 +1266,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
var verifiedIconComponent: EmojiStatusComponent?
var credibilityIconView: ComponentHostView<Empty>?
var credibilityIconComponent: EmojiStatusComponent?
var statusIconView: ComponentHostView<Empty>?
var statusIconComponent: EmojiStatusComponent?
let mutedIconNode: ASImageNode
var itemTagList: ComponentView<Empty>?
var actionButtonTitleNode: TextNode?
@ -2142,6 +2144,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
var currentMutedIconImage: UIImage?
var currentCredibilityIconContent: EmojiStatusComponent.Content?
var currentVerifiedIconContent: EmojiStatusComponent.Content?
var currentStatusIconContent: EmojiStatusComponent.Content?
var currentSecretIconImage: UIImage?
var currentForwardedIcon: UIImage?
var currentStoryIcon: UIImage?
@ -3098,7 +3101,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
} else if peer.isFake {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
currentStatusIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconContent = .premium(color: item.presentationData.theme.list.itemAccentColor)
}
@ -3126,7 +3129,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
} else if peer.isFake {
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
currentStatusIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconContent = .premium(color: item.presentationData.theme.list.itemAccentColor)
}
@ -3180,6 +3183,22 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
}
}
if let currentStatusIconContent {
if titleIconsWidth.isZero {
titleIconsWidth += 4.0
} else {
titleIconsWidth += 2.0
}
switch currentStatusIconContent {
case let .text(_, string):
let textString = NSAttributedString(string: string, font: Font.bold(10.0), textColor: .black, paragraphAlignment: .center)
let stringRect = textString.boundingRect(with: CGSize(width: 100.0, height: 16.0), options: .usesLineFragmentOrigin, context: nil)
titleIconsWidth += floor(stringRect.width) + 11.0
default:
titleIconsWidth += 8.0
}
}
let layoutOffset: CGFloat = 0.0
let rawContentWidth = params.width - leftInset - params.rightInset - 10.0 - editingOffset
@ -4514,6 +4533,41 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
} else {
lastLineRect = CGRect(origin: CGPoint(), size: titleLayout.size)
}
if let currentStatusIconContent {
let statusIconView: ComponentHostView<Empty>
if let current = strongSelf.statusIconView {
statusIconView = current
} else {
statusIconView = ComponentHostView<Empty>()
strongSelf.statusIconView = statusIconView
strongSelf.mainContentContainerNode.view.addSubview(statusIconView)
}
let statusIconComponent = EmojiStatusComponent(
context: item.context,
animationCache: item.interaction.animationCache,
animationRenderer: item.interaction.animationRenderer,
content: currentStatusIconContent,
isVisibleForAnimations: strongSelf.visibilityStatus && item.context.sharedContext.energyUsageSettings.loopEmoji,
action: nil
)
strongSelf.statusIconComponent = statusIconComponent
let iconOrigin: CGFloat = nextTitleIconOrigin
let containerSize = CGSize(width: 20.0, height: 20.0)
let iconSize = statusIconView.update(
transition: .immediate,
component: AnyComponent(statusIconComponent),
environment: {},
containerSize: containerSize
)
transition.updateFrame(view: statusIconView, frame: CGRect(origin: CGPoint(x: iconOrigin, y: floorToScreenPixels(titleFrame.maxY - lastLineRect.height * 0.5 - iconSize.height / 2.0) - UIScreenPixel), size: iconSize))
nextTitleIconOrigin += statusIconView.bounds.width + 4.0
} else if let statusIconView = strongSelf.statusIconView {
strongSelf.statusIconView = nil
statusIconView.removeFromSuperview()
}
if let currentCredibilityIconContent {
let credibilityIconView: ComponentHostView<Empty>

View File

@ -950,12 +950,13 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
titleTransition = .immediate
}
let iconSpacing: CGFloat = 2.0
let titleSideInset: CGFloat = 6.0
var titleFrame: CGRect
if size.height > 40.0 {
var titleInsets: UIEdgeInsets = .zero
if case .emojiStatus = self.titleVerifiedIcon, verifiedIconWidth > 0.0 {
titleInsets.left = verifiedIconWidth + 2.0
titleInsets.left = verifiedIconWidth + iconSpacing
}
var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - verifiedIconWidth - statusIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), insets: titleInsets, animated: titleTransition.isAnimated)

View File

@ -123,6 +123,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let titleExpandedVerifiedIconView: ComponentHostView<Empty>
var titleExpandedVerifiedIconSize: CGSize?
let titleStatusIconView: ComponentHostView<Empty>
var statusIconSize: CGSize?
let titleExpandedStatusIconView: ComponentHostView<Empty>
var titleExpandedStatusIconSize: CGSize?
let subtitleNodeContainer: ASDisplayNode
let subtitleNodeRawContainer: ASDisplayNode
let subtitleNode: MultiScaleTextNode
@ -217,6 +222,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.titleExpandedVerifiedIconView = ComponentHostView<Empty>()
self.titleNode.stateNode(forKey: TitleNodeStateExpanded)?.view.addSubview(self.titleExpandedVerifiedIconView)
self.titleStatusIconView = ComponentHostView<Empty>()
self.titleNode.stateNode(forKey: TitleNodeStateRegular)?.view.addSubview(self.titleStatusIconView)
self.titleExpandedStatusIconView = ComponentHostView<Empty>()
self.titleNode.stateNode(forKey: TitleNodeStateExpanded)?.view.addSubview(self.titleExpandedStatusIconView)
self.subtitleNodeContainer = ASDisplayNode()
self.subtitleNodeRawContainer = ASDisplayNode()
self.subtitleNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
@ -465,6 +476,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
private var currentCredibilityIcon: CredibilityIcon?
private var currentVerifiedIcon: CredibilityIcon?
private var currentStatusIcon: CredibilityIcon?
private var currentPanelStatusData: PeerInfoStatusData?
func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, paneContainerY: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, threadData: MessageHistoryThreadData?, peerNotificationSettings: TelegramPeerNotificationSettings?, threadNotificationSettings: TelegramPeerNotificationSettings?, globalNotificationSettings: EngineGlobalNotificationSettings?, statusData: PeerInfoStatusData?, panelStatusData: (PeerInfoStatusData?, PeerInfoStatusData?, CGFloat?), isSecretChat: Bool, isContact: Bool, isSettings: Bool, state: PeerInfoState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition, additive: Bool, animateHeader: Bool) -> CGFloat {
@ -521,9 +533,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.presentationData = presentationData
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
var credibilityIcon: CredibilityIcon
var credibilityIcon: CredibilityIcon = .none
var verifiedIcon: CredibilityIcon = .none
if let peer = peer {
var statusIcon: CredibilityIcon = .none
if let peer {
if peer.id == self.context.account.peerId && !self.isSettings && !self.isMyProfile {
credibilityIcon = .none
} else if peer.isFake {
@ -531,7 +544,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} else if peer.isScam {
credibilityIcon = .scam
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
credibilityIcon = .emojiStatus(emojiStatus)
statusIcon = .emojiStatus(emojiStatus)
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled && (peer.id != self.context.account.peerId || self.isSettings || self.isMyProfile) {
credibilityIcon = .premium
} else {
@ -543,8 +556,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
if let verificationIconFileId = peer.verificationIconFileId {
verifiedIcon = .emojiStatus(PeerEmojiStatus(fileId: verificationIconFileId, expirationDate: nil))
}
} else {
credibilityIcon = .none
}
var isForum = false
@ -808,7 +819,70 @@ final class PeerInfoHeaderNode: ASDisplayNode {
guard let strongSelf = self else {
return
}
strongSelf.displayPremiumIntro?(strongSelf.titleCredibilityIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), false)
if case .premium = strongSelf.currentCredibilityIcon {
strongSelf.displayPremiumIntro?(strongSelf.titleCredibilityIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), false)
}
}
)),
environment: {},
containerSize: CGSize(width: 26.0, height: 26.0)
)
let expandedIconSize = self.titleExpandedCredibilityIconView.update(
transition: ComponentTransition(navigationTransition),
component: AnyComponent(EmojiStatusComponent(
context: self.context,
animationCache: self.animationCache,
animationRenderer: self.animationRenderer,
content: emojiExpandedStatusContent,
isVisibleForAnimations: true,
useSharedAnimation: true,
action: { [weak self] in
guard let strongSelf = self else {
return
}
if case .premium = strongSelf.currentCredibilityIcon {
strongSelf.displayPremiumIntro?(strongSelf.titleExpandedCredibilityIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), true)
}
}
)),
environment: {},
containerSize: CGSize(width: 26.0, height: 26.0)
)
self.credibilityIconSize = iconSize
self.titleExpandedCredibilityIconSize = expandedIconSize
}
do {
self.currentStatusIcon = statusIcon
var currentEmojiStatus: PeerEmojiStatus?
let emojiRegularStatusContent: EmojiStatusComponent.Content
let emojiExpandedStatusContent: EmojiStatusComponent.Content
switch statusIcon {
case let .emojiStatus(emojiStatus):
currentEmojiStatus = emojiStatus
emojiRegularStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: presentationData.theme.list.mediaPlaceholderColor, themeColor: navigationContentsAccentColor, loopMode: .forever)
emojiExpandedStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: navigationContentsAccentColor, themeColor: navigationContentsAccentColor, loopMode: .forever)
default:
emojiRegularStatusContent = .none
emojiExpandedStatusContent = .none
}
let iconSize = self.titleStatusIconView.update(
transition: ComponentTransition(navigationTransition),
component: AnyComponent(EmojiStatusComponent(
context: self.context,
animationCache: self.animationCache,
animationRenderer: self.animationRenderer,
content: emojiRegularStatusContent,
isVisibleForAnimations: true,
useSharedAnimation: true,
action: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.displayPremiumIntro?(strongSelf.titleStatusIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), false)
},
emojiFileUpdated: { [weak self] emojiFile in
guard let strongSelf = self else {
@ -851,7 +925,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
environment: {},
containerSize: CGSize(width: 26.0, height: 26.0)
)
let expandedIconSize = self.titleExpandedCredibilityIconView.update(
let expandedIconSize = self.titleExpandedStatusIconView.update(
transition: ComponentTransition(navigationTransition),
component: AnyComponent(EmojiStatusComponent(
context: self.context,
@ -864,15 +938,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
guard let strongSelf = self else {
return
}
strongSelf.displayPremiumIntro?(strongSelf.titleExpandedCredibilityIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), true)
strongSelf.displayPremiumIntro?(strongSelf.titleExpandedStatusIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), true)
}
)),
environment: {},
containerSize: CGSize(width: 26.0, height: 26.0)
)
self.credibilityIconSize = iconSize
self.titleExpandedCredibilityIconSize = expandedIconSize
self.statusIconSize = iconSize
self.titleExpandedStatusIconSize = expandedIconSize
}
do {
@ -1307,6 +1381,25 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var nextIconX: CGFloat = titleSize.width
var nextExpandedIconX: CGFloat = titleExpandedSize.width
if let statusIconSize = self.statusIconSize, let titleExpandedStatusIconSize = self.titleExpandedStatusIconSize, statusIconSize.width > 0.0 {
let offset = (statusIconSize.width + 4.0) / 2.0
let leftOffset: CGFloat = nextIconX + 4.0
let leftExpandedOffset: CGFloat = nextExpandedIconX + 4.0
titleHorizontalOffset -= offset
var collapsedTransitionOffset: CGFloat = 0.0
if let navigationTransition = self.navigationTransition {
collapsedTransitionOffset = -10.0 * navigationTransition.fraction
}
transition.updateFrame(view: self.titleStatusIconView, frame: CGRect(origin: CGPoint(x: leftOffset + collapsedTransitionOffset, y: floor((titleSize.height - statusIconSize.height) / 2.0)), size: statusIconSize))
transition.updateFrame(view: self.titleExpandedStatusIconView, frame: CGRect(origin: CGPoint(x: leftExpandedOffset, y: floor((titleExpandedSize.height - titleExpandedStatusIconSize.height) / 2.0) + 1.0), size: titleExpandedStatusIconSize))
nextIconX += 4.0 + statusIconSize.width
nextExpandedIconX += 4.0 + titleExpandedStatusIconSize.width
}
if let credibilityIconSize = self.credibilityIconSize, let titleExpandedCredibilityIconSize = self.titleExpandedCredibilityIconSize, credibilityIconSize.width > 0.0 {
let offset = (credibilityIconSize.width + 4.0) / 2.0
@ -1325,7 +1418,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
nextIconX += 4.0 + credibilityIconSize.width
nextExpandedIconX += 4.0 + titleExpandedCredibilityIconSize.width
}
if let verifiedIconSize = self.verifiedIconSize, let titleExpandedVerifiedIconSize = self.titleExpandedVerifiedIconSize, verifiedIconSize.width > 0.0 {
let leftOffset: CGFloat
let leftExpandedOffset: CGFloat
@ -2220,7 +2313,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
if !(self.state?.isEditing ?? false) {
switch self.currentCredibilityIcon {
case .premium, .emojiStatus:
case .premium:
let iconFrame = self.titleCredibilityIconView.convert(self.titleCredibilityIconView.bounds, to: self.view)
let expandedIconFrame = self.titleExpandedCredibilityIconView.convert(self.titleExpandedCredibilityIconView.bounds, to: self.view)
if expandedIconFrame.contains(point) && self.isAvatarExpanded {
@ -2231,6 +2324,18 @@ final class PeerInfoHeaderNode: ASDisplayNode {
default:
break
}
switch self.currentStatusIcon {
case .emojiStatus:
let iconFrame = self.titleStatusIconView.convert(self.titleStatusIconView.bounds, to: self.view)
let expandedIconFrame = self.titleExpandedStatusIconView.convert(self.titleExpandedStatusIconView.bounds, to: self.view)
if expandedIconFrame.contains(point) && self.isAvatarExpanded {
return self.titleExpandedStatusIconView.hitTest(self.view.convert(point, to: self.titleExpandedStatusIconView), with: event)
} else if iconFrame.contains(point) {
return self.titleStatusIconView.hitTest(self.view.convert(point, to: self.titleStatusIconView), with: event)
}
default:
break
}
}
if let subtitleBackgroundButton = self.subtitleBackgroundButton, subtitleBackgroundButton.view.convert(subtitleBackgroundButton.bounds, to: self.view).contains(point) {