mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
160 lines
7.2 KiB
Swift
160 lines
7.2 KiB
Swift
import Foundation
|
|
import AsyncDisplayKit
|
|
import Display
|
|
import SwiftSignalKit
|
|
import Postbox
|
|
import TelegramCore
|
|
|
|
private func calculateItemCustomWidth(width: CGFloat) -> CGFloat {
|
|
let itemInsets = UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 6.0)
|
|
let minimalItemWidth: CGFloat = width > 301.0 ? 70.0 : 60.0
|
|
let effectiveWidth1 = width - 12.0 - 12.0
|
|
let effectiveWidth = width - itemInsets.left - itemInsets.right
|
|
|
|
let itemsPerRow = Int(effectiveWidth1 / minimalItemWidth)
|
|
let itemWidth = floor(effectiveWidth1 / CGFloat(itemsPerRow))
|
|
|
|
let itemsInRow = Int(effectiveWidth / itemWidth)
|
|
let itemsInRowWidth = CGFloat(itemsInRow) * itemWidth
|
|
let remainingWidth = max(0.0, effectiveWidth - itemsInRowWidth)
|
|
|
|
let itemSpacing = floorToScreenPixels(remainingWidth / CGFloat(itemsInRow + 1))
|
|
|
|
return itemWidth + itemSpacing
|
|
}
|
|
|
|
final class ChatListSearchRecentPeersNode: ASDisplayNode {
|
|
private var theme: PresentationTheme
|
|
private var strings: PresentationStrings
|
|
private let mode: HorizontalPeerItemMode
|
|
private let sectionHeaderNode: ListSectionHeaderNode
|
|
private let listView: ListView
|
|
private let share: Bool
|
|
|
|
private let peerSelected: (Peer) -> Void
|
|
private let peerLongTapped: (Peer) -> Void
|
|
private let isPeerSelected: (PeerId) -> Bool
|
|
|
|
private let disposable = MetaDisposable()
|
|
|
|
private var items: [ListViewItem] = []
|
|
private var itemCustomWidth: CGFloat?
|
|
|
|
init(account: Account, theme: PresentationTheme, mode: HorizontalPeerItemMode, strings: PresentationStrings, peerSelected: @escaping (Peer) -> Void, peerLongTapped: @escaping (Peer) -> Void, isPeerSelected: @escaping (PeerId) -> Bool, share: Bool = false) {
|
|
self.theme = theme
|
|
self.strings = strings
|
|
self.mode = mode
|
|
self.share = share
|
|
self.peerSelected = peerSelected
|
|
self.peerLongTapped = peerLongTapped
|
|
self.isPeerSelected = isPeerSelected
|
|
|
|
self.sectionHeaderNode = ListSectionHeaderNode(theme: theme)
|
|
self.sectionHeaderNode.title = strings.DialogList_RecentTitlePeople.uppercased()
|
|
|
|
self.listView = ListView()
|
|
self.listView.transform = CATransform3DMakeRotation(-CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
|
|
|
super.init()
|
|
|
|
self.addSubnode(self.sectionHeaderNode)
|
|
self.addSubnode(self.listView)
|
|
|
|
self.disposable.set((recentPeers(account: account) |> filter { !$0.isEmpty } |> take(1) |> deliverOnMainQueue).start(next: { [weak self] peers in
|
|
if let strongSelf = self {
|
|
var items: [ListViewItem] = []
|
|
for peer in peers {
|
|
items.append(HorizontalPeerItem(theme: strongSelf.theme, strings: strongSelf.strings, mode: mode, account: account, peer: peer, action: peerSelected, longTapAction: { peer in
|
|
peerLongTapped(peer)
|
|
}, isPeerSelected: isPeerSelected, customWidth: strongSelf.itemCustomWidth))
|
|
}
|
|
strongSelf.items = items
|
|
strongSelf.listView.transaction(deleteIndices: [], insertIndicesAndItems: (0 ..< items.count).map({ ListViewInsertItem(index: $0, previousIndex: nil, item: items[$0], directionHint: .Down) }), updateIndicesAndItems: [], options: [], updateOpaqueState: nil)
|
|
}
|
|
}))
|
|
}
|
|
|
|
deinit {
|
|
disposable.dispose()
|
|
}
|
|
|
|
func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
|
if self.theme !== theme || self.strings !== strings {
|
|
self.theme = theme
|
|
self.strings = strings
|
|
|
|
self.sectionHeaderNode.title = strings.DialogList_RecentTitlePeople
|
|
self.sectionHeaderNode.updateTheme(theme: theme)
|
|
}
|
|
}
|
|
|
|
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
|
return CGSize(width: constrainedSize.width, height: 120.0)
|
|
}
|
|
|
|
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
|
|
self.sectionHeaderNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: 29.0))
|
|
self.sectionHeaderNode.updateLayout(size: CGSize(width: size.width, height: 29.0), leftInset: leftInset, rightInset: rightInset)
|
|
|
|
var insets = UIEdgeInsets()
|
|
insets.top += leftInset
|
|
insets.bottom += rightInset
|
|
|
|
var itemCustomWidth: CGFloat?
|
|
if self.share {
|
|
insets.top = 7.0
|
|
insets.bottom = 7.0
|
|
|
|
itemCustomWidth = calculateItemCustomWidth(width: size.width)
|
|
}
|
|
|
|
var updateItems: [ListViewUpdateItem] = []
|
|
if itemCustomWidth != self.itemCustomWidth {
|
|
self.itemCustomWidth = itemCustomWidth
|
|
|
|
for i in 0 ..< self.items.count {
|
|
if let item = self.items[i] as? HorizontalPeerItem {
|
|
self.items[i] = HorizontalPeerItem(theme: self.theme, strings: self.strings, mode: self.mode, account: item.account, peer: item.peer, action: self.peerSelected, longTapAction: self.peerLongTapped, isPeerSelected: self.isPeerSelected, customWidth: itemCustomWidth)
|
|
updateItems.append(ListViewUpdateItem(index: i, previousIndex: i, item: self.items[i], directionHint: nil))
|
|
}
|
|
}
|
|
}
|
|
|
|
self.listView.bounds = CGRect(x: 0.0, y: 0.0, width: 92.0, height: size.width)
|
|
self.listView.position = CGPoint(x: size.width / 2.0, y: 92.0 / 2.0 + 29.0)
|
|
self.listView.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: updateItems, options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: CGSize(width: 92.0, height: size.width), insets: insets, duration: 0.0, curve: .Default), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
|
}
|
|
|
|
func viewAndPeerAtPoint(_ point: CGPoint) -> (UIView, PeerId)? {
|
|
let adjustedPoint = self.view.convert(point, to: self.listView.view)
|
|
var selectedItemNode: ASDisplayNode?
|
|
self.listView.forEachItemNode { itemNode in
|
|
if itemNode.frame.contains(adjustedPoint) {
|
|
selectedItemNode = itemNode
|
|
}
|
|
}
|
|
if let selectedItemNode = selectedItemNode as? HorizontalPeerItemNode, let peer = selectedItemNode.item?.peer {
|
|
return (selectedItemNode.view, peer.id)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func removePeer(_ peerId: PeerId) {
|
|
for i in 0 ..< self.items.count {
|
|
if let item = self.items[i] as? HorizontalPeerItem, item.peer.id == peerId {
|
|
self.items.remove(at: i)
|
|
self.listView.transaction(deleteIndices: [ListViewDeleteItem(index: i, directionHint: nil)], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.AnimateInsertion], updateOpaqueState: nil)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func updateSelectedPeers(animated: Bool) {
|
|
self.listView.forEachItemNode { itemNode in
|
|
if let itemNode = itemNode as? HorizontalPeerItemNode {
|
|
itemNode.updateSelection(animated: animated)
|
|
}
|
|
}
|
|
}
|
|
}
|