mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Fix featured sticker packs UI
This commit is contained in:
parent
d5142c876e
commit
046c620242
10 changed files with 1882 additions and 1826 deletions
|
|
@ -5492,3 +5492,5 @@ Any member of this group will be able to see messages in the channel.";
|
|||
"CreatePoll.ExplanationHeader" = "EXPLANATION";
|
||||
"CreatePoll.Explanation" = "Add a Comment (Optional)";
|
||||
"CreatePoll.ExplanationInfo" = "Users will see this comment after choosing a wrong answer, good for educational purposes.";
|
||||
|
||||
"FeaturedStickers.OtherSection" = "OTHER";
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -809,10 +809,16 @@ final class ChatMediaInputNode: ChatInputNode {
|
|||
var gridEntries = chatMediaInputGridEntries(view: view, savedStickers: savedStickers, recentStickers: recentStickers, peerSpecificPack: peerSpecificPack.0, canInstallPeerSpecificPack: peerSpecificPack.1, strings: strings, theme: theme)
|
||||
|
||||
if view.higher == nil {
|
||||
var hasTopSeparator = true
|
||||
if gridEntries.count == 1, case .search = gridEntries[0] {
|
||||
hasTopSeparator = false
|
||||
}
|
||||
|
||||
var index = 0
|
||||
for item in trendingPacks {
|
||||
if !installedPacks.contains(item.info.id) {
|
||||
gridEntries.append(.trending(TrendingPanePackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: true)))
|
||||
gridEntries.append(.trending(TrendingPanePackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread, topSeparator: hasTopSeparator)))
|
||||
hasTopSeparator = true
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ final class TrendingPanePackEntry: Identifiable, Comparable {
|
|||
|
||||
func item(account: Account, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem {
|
||||
let info = self.info
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: self.theme, strings: self.strings, listAppearance: false, info: self.info, topItems: self.topItems, grid: grid, topSeparator: self.topSeparator, installed: self.installed, unread: self.unread, open: {
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: self.theme, strings: self.strings, listAppearance: false, info: self.info, topItems: self.topItems, grid: grid, topSeparator: self.topSeparator, regularInsets: false, installed: self.installed, unread: self.unread, open: {
|
||||
interaction.openPack(info)
|
||||
}, install: {
|
||||
interaction.installPack(info)
|
||||
|
|
|
|||
|
|
@ -40,8 +40,9 @@ private final class FeaturedPackEntry: Identifiable, Comparable {
|
|||
let installed: Bool
|
||||
let unread: Bool
|
||||
let topSeparator: Bool
|
||||
let regularInsets: Bool
|
||||
|
||||
init(index: Int, info: StickerPackCollectionInfo, theme: PresentationTheme, strings: PresentationStrings, topItems: [StickerPackItem], installed: Bool, unread: Bool, topSeparator: Bool) {
|
||||
init(index: Int, info: StickerPackCollectionInfo, theme: PresentationTheme, strings: PresentationStrings, topItems: [StickerPackItem], installed: Bool, unread: Bool, topSeparator: Bool, regularInsets: Bool = false) {
|
||||
self.index = index
|
||||
self.info = info
|
||||
self.theme = theme
|
||||
|
|
@ -50,6 +51,7 @@ private final class FeaturedPackEntry: Identifiable, Comparable {
|
|||
self.installed = installed
|
||||
self.unread = unread
|
||||
self.topSeparator = topSeparator
|
||||
self.regularInsets = regularInsets
|
||||
}
|
||||
|
||||
var stableId: ItemCollectionId {
|
||||
|
|
@ -81,6 +83,9 @@ private final class FeaturedPackEntry: Identifiable, Comparable {
|
|||
if lhs.topSeparator != rhs.topSeparator {
|
||||
return false
|
||||
}
|
||||
if lhs.regularInsets != rhs.regularInsets {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -88,46 +93,36 @@ private final class FeaturedPackEntry: Identifiable, Comparable {
|
|||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
func item(account: Account, interaction: FeaturedInteraction, grid: Bool) -> GridItem {
|
||||
func item(account: Account, interaction: FeaturedInteraction, isOther: Bool) -> GridItem {
|
||||
let info = self.info
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: self.theme, strings: self.strings, listAppearance: true, info: self.info, topItems: self.topItems, grid: grid, topSeparator: self.topSeparator, installed: self.installed, unread: self.unread, open: {
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: self.theme, strings: self.strings, listAppearance: true, info: self.info, topItems: self.topItems, grid: false, topSeparator: self.topSeparator, regularInsets: self.regularInsets, installed: self.installed, unread: self.unread, open: {
|
||||
interaction.openPack(info)
|
||||
}, install: {
|
||||
interaction.installPack(info, !self.installed)
|
||||
}, getItemIsPreviewed: { item in
|
||||
return interaction.getItemIsPreviewed(item)
|
||||
}, itemContext: interaction.itemContext)
|
||||
}, itemContext: interaction.itemContext, sectionTitle: isOther ? self.strings.FeaturedStickers_OtherSection : nil)
|
||||
}
|
||||
}
|
||||
|
||||
private enum FeaturedEntryId: Hashable {
|
||||
case search
|
||||
case pack(ItemCollectionId)
|
||||
}
|
||||
|
||||
private enum FeaturedEntry: Identifiable, Comparable {
|
||||
case search(theme: PresentationTheme, strings: PresentationStrings)
|
||||
case pack(FeaturedPackEntry)
|
||||
case pack(FeaturedPackEntry, Bool)
|
||||
|
||||
var stableId: FeaturedEntryId {
|
||||
switch self {
|
||||
case .search:
|
||||
return .search
|
||||
case let .pack(pack):
|
||||
case let .pack(pack, _):
|
||||
return .pack(pack.stableId)
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: FeaturedEntry, rhs: FeaturedEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .search(lhsTheme, lhsStrings):
|
||||
if case let .search(rhsTheme, rhsStrings) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .pack(pack):
|
||||
if case .pack(pack) = rhs {
|
||||
case let .pack(pack, isOther):
|
||||
if case .pack(pack, isOther) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
|
@ -137,26 +132,18 @@ private enum FeaturedEntry: Identifiable, Comparable {
|
|||
|
||||
static func <(lhs: FeaturedEntry, rhs: FeaturedEntry) -> Bool {
|
||||
switch lhs {
|
||||
case .search:
|
||||
return false
|
||||
case let .pack(lhsPack):
|
||||
case let .pack(lhsPack, _):
|
||||
switch rhs {
|
||||
case .search:
|
||||
return false
|
||||
case let .pack(rhsPack):
|
||||
case let .pack(rhsPack, _):
|
||||
return lhsPack < rhsPack
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func item(account: Account, interaction: FeaturedInteraction, grid: Bool) -> GridItem {
|
||||
func item(account: Account, interaction: FeaturedInteraction) -> GridItem {
|
||||
switch self {
|
||||
case let .search(theme, strings):
|
||||
return PaneSearchBarPlaceholderItem(theme: theme, strings: strings, type: .stickers, activate: {
|
||||
interaction.openSearch()
|
||||
})
|
||||
case let .pack(pack):
|
||||
return pack.item(account: account, interaction: interaction, grid: grid)
|
||||
case let .pack(pack, isOther):
|
||||
return pack.item(account: account, interaction: interaction, isOther: isOther)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -172,8 +159,8 @@ private func preparedTransition(from fromEntries: [FeaturedEntry], to toEntries:
|
|||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices
|
||||
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, interaction: interaction, grid: false), previousIndex: $0.2) }
|
||||
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction, grid: false)) }
|
||||
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, interaction: interaction), previousIndex: $0.2) }
|
||||
let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction)) }
|
||||
|
||||
return FeaturedTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial)
|
||||
}
|
||||
|
|
@ -185,14 +172,14 @@ private func featuredScreenEntries(featuredEntries: [FeaturedStickerPackItem], i
|
|||
for item in featuredEntries {
|
||||
if !existingIds.contains(item.info.id) {
|
||||
existingIds.insert(item.info.id)
|
||||
result.append(.pack(FeaturedPackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread || fixedUnread.contains(item.info.id), topSeparator: index != 0)))
|
||||
result.append(.pack(FeaturedPackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread || fixedUnread.contains(item.info.id), topSeparator: index != 0, regularInsets: true), false))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
for item in additionalPacks {
|
||||
if !existingIds.contains(item.info.id) {
|
||||
existingIds.insert(item.info.id)
|
||||
result.append(.pack(FeaturedPackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread || fixedUnread.contains(item.info.id), topSeparator: index != 0)))
|
||||
result.append(.pack(FeaturedPackEntry(index: index, info: item.info, theme: theme, strings: strings, topItems: item.topItems, installed: installedPacks.contains(item.info.id), unread: item.unread || fixedUnread.contains(item.info.id), topSeparator: index != 0, regularInsets: true), true))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
|
@ -238,6 +225,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
|
|||
self.sendSticker = sendSticker
|
||||
|
||||
self.gridNode = GridNode()
|
||||
self.gridNode.floatingSections = true
|
||||
|
||||
super.init()
|
||||
|
||||
|
|
@ -1040,7 +1028,7 @@ private enum FeaturedSearchEntry: Identifiable, Comparable {
|
|||
interaction.sendSticker(.standalone(media: stickerItem.file), node, rect)
|
||||
})
|
||||
case let .global(_, info, topItems, installed, topSeparator):
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, listAppearance: false, info: info, topItems: topItems, grid: false, topSeparator: topSeparator, installed: installed, unread: false, open: {
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, listAppearance: false, info: info, topItems: topItems, grid: false, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
|
||||
interaction.open(info)
|
||||
}, install: {
|
||||
interaction.install(info, topItems, !installed)
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ private enum StickerSearchEntry: Identifiable, Comparable {
|
|||
case let .global(_, info, topItems, installed, topSeparator):
|
||||
let itemContext = StickerPaneSearchGlobalItemContext()
|
||||
itemContext.canPlayMedia = true
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, listAppearance: false, info: info, topItems: topItems, grid: false, topSeparator: topSeparator, installed: installed, unread: false, open: {
|
||||
return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, listAppearance: false, info: info, topItems: topItems, grid: false, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
|
||||
interaction.open(info)
|
||||
}, install: {
|
||||
interaction.install(info, topItems, !installed)
|
||||
|
|
|
|||
|
|
@ -8,27 +8,65 @@ import SwiftSignalKit
|
|||
import Postbox
|
||||
import TelegramPresentationData
|
||||
import StickerPackPreviewUI
|
||||
import ListSectionHeaderNode
|
||||
|
||||
final class StickerPaneSearchGlobalSection: GridSection {
|
||||
let height: CGFloat = 0.0
|
||||
let title: String?
|
||||
let theme: PresentationTheme
|
||||
|
||||
var hashValue: Int {
|
||||
return 0
|
||||
var height: CGFloat {
|
||||
if let _ = self.title {
|
||||
return 28.0
|
||||
} else {
|
||||
return 0.0
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
var hashValue: Int {
|
||||
if let _ = self.title {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
init(title: String?, theme: PresentationTheme) {
|
||||
self.title = title
|
||||
self.theme = theme
|
||||
}
|
||||
|
||||
func isEqual(to: GridSection) -> Bool {
|
||||
if to is StickerPaneSearchGlobalSection {
|
||||
return true
|
||||
if let to = to as? StickerPaneSearchGlobalSection {
|
||||
return to.hashValue == self.hashValue
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func node() -> ASDisplayNode {
|
||||
return ASDisplayNode()
|
||||
return StickerPaneSearchGlobalSectionNode(theme: self.theme, title: self.title ?? "")
|
||||
}
|
||||
}
|
||||
|
||||
private final class StickerPaneSearchGlobalSectionNode: ASDisplayNode {
|
||||
private let node: ListSectionHeaderNode
|
||||
|
||||
init(theme: PresentationTheme, title: String) {
|
||||
self.node = ListSectionHeaderNode(theme: theme)
|
||||
|
||||
super.init()
|
||||
|
||||
if !title.isEmpty {
|
||||
self.node.title = title
|
||||
self.addSubnode(self.node)
|
||||
}
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
|
||||
self.node.frame = self.bounds
|
||||
self.node.updateLayout(size: self.bounds.size, leftInset: 0.0, rightInset: 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -45,6 +83,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
|
|||
let topItems: [StickerPackItem]
|
||||
let grid: Bool
|
||||
let topSeparator: Bool
|
||||
let regularInsets: Bool
|
||||
let installed: Bool
|
||||
let installing: Bool
|
||||
let unread: Bool
|
||||
|
|
@ -53,12 +92,22 @@ final class StickerPaneSearchGlobalItem: GridItem {
|
|||
let getItemIsPreviewed: (StickerPackItem) -> Bool
|
||||
let itemContext: StickerPaneSearchGlobalItemContext
|
||||
|
||||
let section: GridSection? = StickerPaneSearchGlobalSection()
|
||||
let section: GridSection?
|
||||
var fillsRowWithHeight: CGFloat? {
|
||||
return self.grid ? nil : (128.0 + (self.topSeparator ? 12.0 : 0.0))
|
||||
var additionalHeight: CGFloat = 0.0
|
||||
if self.regularInsets {
|
||||
additionalHeight = 12.0 + 12.0
|
||||
} else {
|
||||
additionalHeight += 12.0
|
||||
if self.topSeparator {
|
||||
additionalHeight += 12.0
|
||||
}
|
||||
}
|
||||
|
||||
return self.grid ? nil : (128.0 + additionalHeight)
|
||||
}
|
||||
|
||||
init(account: Account, theme: PresentationTheme, strings: PresentationStrings, listAppearance: Bool, info: StickerPackCollectionInfo, topItems: [StickerPackItem], grid: Bool, topSeparator: Bool, installed: Bool, installing: Bool = false, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, itemContext: StickerPaneSearchGlobalItemContext) {
|
||||
init(account: Account, theme: PresentationTheme, strings: PresentationStrings, listAppearance: Bool, info: StickerPackCollectionInfo, topItems: [StickerPackItem], grid: Bool, topSeparator: Bool, regularInsets: Bool, installed: Bool, installing: Bool = false, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, itemContext: StickerPaneSearchGlobalItemContext, sectionTitle: String? = nil) {
|
||||
self.account = account
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
|
|
@ -67,6 +116,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
|
|||
self.topItems = topItems
|
||||
self.grid = grid
|
||||
self.topSeparator = topSeparator
|
||||
self.regularInsets = regularInsets
|
||||
self.installed = installed
|
||||
self.installing = installing
|
||||
self.unread = unread
|
||||
|
|
@ -74,6 +124,7 @@ final class StickerPaneSearchGlobalItem: GridItem {
|
|||
self.install = install
|
||||
self.getItemIsPreviewed = getItemIsPreviewed
|
||||
self.itemContext = itemContext
|
||||
self.section = StickerPaneSearchGlobalSection(title: sectionTitle, theme: theme)
|
||||
}
|
||||
|
||||
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
||||
|
|
@ -279,13 +330,21 @@ class StickerPaneSearchGlobalItemNode: GridItemNode {
|
|||
|
||||
let params = ListViewItemLayoutParams(width: size.width, leftInset: 0.0, rightInset: 0.0, availableHeight: size.height)
|
||||
|
||||
var topOffset: CGFloat = 12.0
|
||||
if item.topSeparator {
|
||||
let topSeparatorOffset: CGFloat
|
||||
var topOffset: CGFloat = 0.0
|
||||
if item.regularInsets {
|
||||
topOffset = 12.0
|
||||
topSeparatorOffset = -UIScreenPixel
|
||||
} else {
|
||||
topSeparatorOffset = 16.0
|
||||
topOffset += 12.0
|
||||
if item.topSeparator {
|
||||
topOffset += 12.0
|
||||
}
|
||||
}
|
||||
|
||||
self.topSeparatorNode.isHidden = !item.topSeparator
|
||||
self.topSeparatorNode.frame = CGRect(origin: CGPoint(x: 16.0, y: 16.0), size: CGSize(width: params.width - 16.0 * 2.0, height: UIScreenPixel))
|
||||
self.topSeparatorNode.frame = CGRect(origin: CGPoint(x: 16.0, y: topSeparatorOffset), size: CGSize(width: params.width - 16.0 * 2.0, height: UIScreenPixel))
|
||||
if item.listAppearance {
|
||||
self.topSeparatorNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
} else {
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -449,12 +449,12 @@ public final class WalletStrings: Equatable {
|
|||
public var Wallet_SecureStorageReset_Title: String { return self._s[219]! }
|
||||
public var Wallet_Receive_CommentHeader: String { return self._s[220]! }
|
||||
public var Wallet_Info_ReceiveGrams: String { return self._s[221]! }
|
||||
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
||||
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
||||
let form = getPluralizationForm(self.lc, value)
|
||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
|
||||
}
|
||||
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
||||
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
||||
let form = getPluralizationForm(self.lc, value)
|
||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue