Group boosts

This commit is contained in:
Ilya Laktyushin
2024-02-05 16:18:02 +04:00
parent 1b2b7dc403
commit b4b90b090c
65 changed files with 3569 additions and 1969 deletions

View File

@@ -771,6 +771,8 @@ private final class GroupHeaderLayer: UIView {
private var tintSubtitleLayer: SimpleLayer?
private var lockIconLayer: SimpleLayer?
private var tintLockIconLayer: SimpleLayer?
private var badgeLayer: SimpleLayer?
private var tintBadgeLayer: SimpleLayer?
private(set) var clearIconLayer: SimpleLayer?
private var tintClearIconLayer: SimpleLayer?
private var separatorLayer: SimpleLayer?
@@ -816,6 +818,7 @@ private final class GroupHeaderLayer: UIView {
actionButtonTitle: String?,
title: String,
subtitle: String?,
badge: String?,
isPremiumLocked: Bool,
hasClear: Bool,
embeddedItems: [EmojiPagerContentComponent.Item]?,
@@ -831,7 +834,7 @@ private final class GroupHeaderLayer: UIView {
self.theme = theme
themeUpdated = true
}
let needsVibrancy = !theme.overallDarkAppearance || forceNeedsVibrancy
let textOffsetY: CGFloat
@@ -978,10 +981,72 @@ private final class GroupHeaderLayer: UIView {
self.tintTextLayer.isHidden = !needsVibrancy
self.currentTextLayout = (title, color, textConstrainedWidth, textSize)
}
var badgeSize: CGSize = .zero
if let badge {
func generateBadgeImage(color: UIColor) -> UIImage? {
let string = NSAttributedString(string: badge, font: Font.semibold(11.0), textColor: .white)
let stringBounds = string.boundingRect(with: CGSize(width: 120, height: 18.0), options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
let badgeSize = CGSize(width: stringBounds.width + 8.0, height: 16.0)
return generateImage(badgeSize, opaque: false, scale: 0.0, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(color.cgColor)
context.addPath(UIBezierPath(roundedRect: CGRect(origin: .zero, size: badgeSize), cornerRadius: badgeSize.height / 2.0).cgPath)
context.fillPath()
context.setBlendMode(.clear)
UIGraphicsPushContext(context)
string.draw(with: CGRect(origin: CGPoint(x: floorToScreenPixels((badgeSize.width - stringBounds.size.width) / 2.0), y: floorToScreenPixels((badgeSize.height - stringBounds.size.height) / 2.0)), size: stringBounds.size), options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
UIGraphicsPopContext()
})
}
let badgeLayer: SimpleLayer
if let current = self.badgeLayer {
badgeLayer = current
} else {
badgeLayer = SimpleLayer()
self.badgeLayer = badgeLayer
self.layer.addSublayer(badgeLayer)
if let image = generateBadgeImage(color: color.withMultipliedAlpha(0.66)) {
badgeLayer.contents = image.cgImage
badgeLayer.bounds = CGRect(origin: .zero, size: image.size)
}
}
badgeSize = badgeLayer.bounds.size
let tintBadgeLayer: SimpleLayer
if let current = self.tintBadgeLayer {
tintBadgeLayer = current
} else {
tintBadgeLayer = SimpleLayer()
self.tintBadgeLayer = tintBadgeLayer
self.tintContentLayer.addSublayer(tintBadgeLayer)
if let image = generateBadgeImage(color: .white) {
tintBadgeLayer.contents = image.cgImage
}
}
} else {
if let badgeLayer = self.badgeLayer {
self.badgeLayer = nil
badgeLayer.removeFromSuperlayer()
}
if let tintBadgeLayer = self.tintBadgeLayer {
self.tintBadgeLayer = nil
tintBadgeLayer.removeFromSuperlayer()
}
}
let textFrame: CGRect
if subtitle == nil {
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - textSize.width) / 2.0), y: textOffsetY), size: textSize)
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - (textSize.width + badgeSize.width)) / 2.0), y: textOffsetY), size: textSize)
} else {
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize)
}
@@ -989,6 +1054,11 @@ private final class GroupHeaderLayer: UIView {
self.tintTextLayer.frame = textFrame
self.tintTextLayer.isHidden = !needsTintText
if let badgeLayer = self.badgeLayer, let tintBadgeLayer = self.tintBadgeLayer {
badgeLayer.frame = CGRect(origin: CGPoint(x: textFrame.maxX + 4.0, y: 0.0), size: badgeLayer.frame.size)
tintBadgeLayer.frame = badgeLayer.frame
}
if isPremiumLocked {
let lockIconLayer: SimpleLayer
if let current = self.lockIconLayer {
@@ -2536,6 +2606,7 @@ public final class EmojiPagerContentComponent: Component {
public let groupId: AnyHashable
public let title: String?
public let subtitle: String?
public let badge: String?
public let actionButtonTitle: String?
public let isFeatured: Bool
public let isPremiumLocked: Bool
@@ -2553,6 +2624,7 @@ public final class EmojiPagerContentComponent: Component {
groupId: AnyHashable,
title: String?,
subtitle: String?,
badge: String?,
actionButtonTitle: String?,
isFeatured: Bool,
isPremiumLocked: Bool,
@@ -2569,6 +2641,7 @@ public final class EmojiPagerContentComponent: Component {
self.groupId = groupId
self.title = title
self.subtitle = subtitle
self.badge = badge
self.actionButtonTitle = actionButtonTitle
self.isFeatured = isFeatured
self.isPremiumLocked = isPremiumLocked
@@ -2598,6 +2671,9 @@ public final class EmojiPagerContentComponent: Component {
if lhs.subtitle != rhs.subtitle {
return false
}
if lhs.badge != rhs.badge {
return false
}
if lhs.actionButtonTitle != rhs.actionButtonTitle {
return false
}
@@ -5540,6 +5616,7 @@ public final class EmojiPagerContentComponent: Component {
actionButtonTitle: actionButtonTitle,
title: title,
subtitle: itemGroup.subtitle,
badge: itemGroup.badge,
isPremiumLocked: itemGroup.isPremiumLocked,
hasClear: itemGroup.hasClear,
embeddedItems: itemGroup.isEmbedded ? itemGroup.items : nil,

View File

@@ -208,6 +208,7 @@ public extension EmojiPagerContentComponent {
var id: AnyHashable
var title: String?
var subtitle: String?
var badge: String?
var isPremiumLocked: Bool
var isFeatured: Bool
var collapsedLineCount: Int?
@@ -241,7 +242,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@@ -317,7 +318,7 @@ public extension EmojiPagerContentComponent {
itemGroupIndexById[groupId] = itemGroups.count
let title = context.sharedContext.currentPresentationData.with({ $0 }).strings.EmojiInput_TrendingEmoji
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 0, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 0, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@@ -373,7 +374,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
var existingIds = Set<MediaId>()
@@ -432,7 +433,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
var existingIds = Set<MediaId>()
@@ -592,7 +593,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
var existingIds = Set<MediaId>()
@@ -738,7 +739,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@@ -816,7 +817,7 @@ public extension EmojiPagerContentComponent {
}
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
@@ -874,7 +875,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
}
} else {
let groupId = "recent"
@@ -886,7 +887,7 @@ public extension EmojiPagerContentComponent {
}
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
}
@@ -958,7 +959,7 @@ public extension EmojiPagerContentComponent {
popularInsertIndex += 1
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && subject != .quickReaction, headerItem: nil, items: [resultItem]))
}
}
}
@@ -1023,7 +1024,7 @@ public extension EmojiPagerContentComponent {
}
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
} else if [.profilePhoto, .groupPhoto].contains(subject) {
@@ -1031,7 +1032,7 @@ public extension EmojiPagerContentComponent {
let groupId = "recent"
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: []))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: topStatusTitle?.uppercased(), subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: []))
if let featuredAvatarEmoji = featuredAvatarEmoji {
for item in featuredAvatarEmoji.items {
@@ -1100,7 +1101,7 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
}
if let featuredBackgroundIconEmoji {
@@ -1208,15 +1209,11 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: true, headerItem: nil, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, badge: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: true, headerItem: nil, items: [resultItem]))
}
}
}
if !hasPremium {
maybeAppendUnicodeEmoji()
}
var itemCollectionMapping: [ItemCollectionId: StickerPackCollectionInfo] = [:]
for (id, info, _) in view.collectionInfos {
if let info = info as? StickerPackCollectionInfo {
@@ -1260,13 +1257,18 @@ public extension EmojiPagerContentComponent {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: peerSpecificPack.peer.compactDisplayTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
//TODO:localize
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: peerSpecificPack.info.title, subtitle: nil, badge: "GROUP EMOJI", isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
}
}
let supergroupId: AnyHashable = peerSpecificPack.info.id
skippedCollectionIds.insert(supergroupId)
}
if !hasPremium {
maybeAppendUnicodeEmoji()
}
if areCustomEmojiEnabled {
for entry in view.entries {
@@ -1364,7 +1366,7 @@ public extension EmojiPagerContentComponent {
break inner
}
}
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: headerItem, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, badge: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: headerItem, items: [resultItem]))
}
}
@@ -1453,7 +1455,7 @@ public extension EmojiPagerContentComponent {
isFeatured = false
}
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: isFeatured, collapsedLineCount: 3, isClearable: false, headerItem: headerItem, items: [resultItem]))
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, badge: nil, isPremiumLocked: isPremiumLocked, isFeatured: isFeatured, collapsedLineCount: 3, isClearable: false, headerItem: headerItem, items: [resultItem]))
}
}
}
@@ -1508,6 +1510,7 @@ public extension EmojiPagerContentComponent {
groupId: group.id,
title: group.title,
subtitle: group.subtitle,
badge: group.badge,
actionButtonTitle: nil,
isFeatured: group.isFeatured,
isPremiumLocked: group.isPremiumLocked,
@@ -1994,6 +1997,7 @@ public extension EmojiPagerContentComponent {
groupId: group.id,
title: group.title,
subtitle: group.subtitle,
badge: nil,
actionButtonTitle: group.actionButtonTitle,
isFeatured: group.isFeatured,
isPremiumLocked: group.isPremiumLocked,

View File

@@ -122,6 +122,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: AnyHashable(groupItem.info.id),
title: groupItem.info.title,
subtitle: nil,
badge: nil,
actionButtonTitle: self.presentationData.strings.EmojiInput_AddPack(groupItem.info.title).string,
isFeatured: true,
isPremiumLocked: !self.hasPremiumForInstallation,
@@ -286,6 +287,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@@ -340,6 +342,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
@@ -373,6 +376,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
groupId: "search",
title: nil,
subtitle: nil,
badge: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,