This commit is contained in:
Isaac 2025-12-26 20:29:30 +08:00
parent 7ed08c0141
commit 4a13c3830a
234 changed files with 1442 additions and 1764 deletions

View file

@ -4856,12 +4856,9 @@ Sorry for the inconvenience.";
"Conversation.SendMessage.SetReminder" = "Set a Reminder";
"Conversation.SelectedMessages_1" = "%@ Selected";
"Conversation.SelectedMessages_2" = "%@ Selected";
"Conversation.SelectedMessages_3_10" = "%@ Selected";
"Conversation.SelectedMessages_any" = "%@ Selected";
"Conversation.SelectedMessages_many" = "%@ Selected";
"Conversation.SelectedMessages_0" = "%@ Selected";
"Conversation.SelectedMessagesFormat_1" = "{} Selected";
"Conversation.SelectedMessagesFormat_any" = "{} Selected";
"AccentColor.Title" = "Accent Color";

View file

@ -114,7 +114,7 @@ class BotCheckoutHeaderItemNode: ListViewItemNode {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.imageNode)

View file

@ -113,7 +113,7 @@ class BotCheckoutPriceItemNode: ListViewItemNode {
self.maskNode = ASImageNode()
self.maskNode.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.titleNode)

View file

@ -509,7 +509,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
self.maskNode = ASImageNode()
self.maskNode.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.backgroundNode)

View file

@ -243,7 +243,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
self.accessibilityArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.containerNode)

View file

@ -103,7 +103,7 @@ public final class CallListController: TelegramBaseController {
self.segmentedTitleView = ItemListControllerSegmentedTitleView(theme: self.presentationData.theme, segments: [self.presentationData.strings.Calls_All, self.presentationData.strings.Calls_Missed], selectedIndex: 0)
super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass), mediaAccessoryPanelVisibility: .none, locationBroadcastPanelSource: .none, groupCallPanelSource: .none)
super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self.tabBarItemContextActionType = .always
@ -423,10 +423,15 @@ public final class CallListController: TelegramBaseController {
self.displayNodeDidLoad()
}
override public var navigationEdgeEffectExtension: CGFloat {
return self.controllerNode.navigationEdgeEffectExtension
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
let navigationLayout = self.navigationLayout(layout: layout)
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: navigationLayout.navigationFrame.maxY, transition: transition)
}
@objc func callPressed() {

View file

@ -235,6 +235,10 @@ final class CallListControllerNode: ASDisplayNode {
private let openGroupCallDisposable = MetaDisposable()
var navigationEdgeEffectExtension: CGFloat {
return max(0.0, self.listNode.edgeEffectExtension)
}
private var previousContentOffset: ListViewVisibleContentOffset?
init(controller: CallListController, context: AccountContext, mode: CallListControllerMode, presentationData: PresentationData, call: @escaping (EngineMessage) -> Void, joinGroupCall: @escaping (EnginePeer.Id, EngineGroupCallDescription) -> Void, openInfo: @escaping (EnginePeer.Id, [EngineMessage]) -> Void, emptyStateUpdated: @escaping (Bool) -> Void, openNewCall: @escaping () -> Void) {
@ -682,6 +686,13 @@ final class CallListControllerNode: ASDisplayNode {
}
}
}
self.listNode.onEdgeEffectExtensionUpdated = { [weak self] transition in
guard let self else {
return
}
self.controller?.updateNavigationEdgeEffectExtension(transition: transition)
}
}
deinit {
@ -959,5 +970,7 @@ final class CallListControllerNode: ASDisplayNode {
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - edgeEffectHeight), size: CGSize(width: layout.size.width, height: edgeEffectHeight))
transition.updateFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
self.edgeEffectView.update(content: self.presentationData.theme.list.plainBackgroundColor, rect: edgeEffectFrame, edge: .bottom, edgeSize: edgeEffectFrame.height, transition: ComponentTransition(transition))
self.controller?.updateNavigationEdgeEffectExtension(transition: transition)
}
}

View file

@ -208,7 +208,7 @@ class CallListGroupCallItemNode: ItemListRevealOptionsItemNode {
self.accessibilityArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.indicatorNode)

View file

@ -70,7 +70,7 @@ class CallListHoleItemNode: ListViewItemNode {
self.labelNode = TextNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.separatorNode)
self.addSubnode(self.labelNode)

View file

@ -86,7 +86,7 @@ class ChatListFilterSettingsHeaderItemNode: ListViewItemNode {
self.animationNode = DefaultAnimatedStickerNodeImpl()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.animationNode)

View file

@ -10,9 +10,12 @@ swift_library(
"-warnings-as-errors",
],
deps = [
"//submodules/Display:Display",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/ListSectionHeaderNode:ListSectionHeaderNode",
"//submodules/Display",
"//submodules/TelegramPresentationData",
"//submodules/ListSectionHeaderNode",
"//submodules/ComponentFlow",
"//submodules/Components/ComponentDisplayAdapters",
"//submodules/TelegramUI/Components/EdgeEffect",
],
visibility = [
"//visibility:public",

View file

@ -4,6 +4,9 @@ import AsyncDisplayKit
import Display
import TelegramPresentationData
import ListSectionHeaderNode
import EdgeEffect
import ComponentFlow
import ComponentDisplayAdapters
public enum ChatListSearchItemHeaderType {
case localPeers
@ -250,6 +253,7 @@ public final class ChatListSearchItemHeaderNode: ListViewItemHeaderNode {
private var validLayout: (size: CGSize, leftInset: CGFloat, rightInset: CGFloat)?
private var edgeEffectView: EdgeEffectView?
private let sectionHeaderNode: ListSectionHeaderNode
public init(type: ChatListSearchItemHeaderType, theme: PresentationTheme, strings: PresentationStrings, actionTitle: String?, action: ((ASDisplayNode) -> Void)?) {
@ -263,6 +267,8 @@ public final class ChatListSearchItemHeaderNode: ListViewItemHeaderNode {
super.init()
//self.contributesToEdgeEffect = true
self.sectionHeaderNode.title = type.title(strings: strings).uppercased()
self.sectionHeaderNode.action = actionTitle
self.sectionHeaderNode.activateAction = action

View file

@ -169,7 +169,7 @@ public class ChatListAdditionalCategoryItemNode: ItemListRevealOptionsItemNode {
self.titleNode = TextNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -60,6 +60,7 @@ import ChatListFilterTabContainerNode
import HeaderPanelContainerComponent
import HorizontalTabsComponent
import GlobalControlPanelsContext
import ChatListFilterTabContainerNode
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
let controller: ViewController
@ -248,18 +249,17 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.animationCache = context.animationCache
self.animationRenderer = context.animationRenderer
let groupCallPanelSource: GroupCallPanelSource
var groupCallPanelSource: EnginePeer.Id?
var chatListNotices = false
switch self.location {
case let .chatList(groupId):
groupCallPanelSource = .all
if case .root = groupId {
chatListNotices = true
}
case let .forum(peerId):
groupCallPanelSource = .peer(peerId)
groupCallPanelSource = peerId
case .savedMessagesChats:
groupCallPanelSource = .none
break
}
self.tabsNode = SparseNode()
@ -274,7 +274,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
chatListNotices: chatListNotices
)
super.init(context: context, navigationBarPresentationData: nil, mediaAccessoryPanelVisibility: .none, locationBroadcastPanelSource: .none, groupCallPanelSource: .none)
super.init(context: context, navigationBarPresentationData: nil)
self.accessoryPanelContainer = ASDisplayNode()
@ -3660,10 +3660,35 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return id
}
}
let _ = defaultFilterIds
var reorderedFilterIdsValue: [Int32]?
if let reorderedFilterIds = self.tabContainerNode.reorderedFilterIds, reorderedFilterIds != defaultFilterIds {
reorderedFilterIdsValue = reorderedFilterIds
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View, let headerPanelsView = navigationBarView.headerPanels as? HeaderPanelContainerComponent.View, let tabsView = headerPanelsView.tabs as? HorizontalTabsComponent.View, let reorderedItemIds = tabsView.reorderedItemIds {
reorderedFilterIdsValue = reorderedItemIds.compactMap { item -> Int32? in
guard let value = item.base as? Int32 else {
return nil
}
if value == Int32.min {
return 0
}
return value
}
}
if let reorderedFilterIdsValue, let tabContainerData = self.tabContainerData {
var entries: [ChatListFilterTabEntry] = []
for id in reorderedFilterIdsValue {
let mappedId: ChatListFilterTabEntryId
if id == 0 {
mappedId = .all
} else {
mappedId = .filter(id)
}
if let entry = tabContainerData.0.first(where: { $0.id == mappedId }) {
entries.append(entry)
}
}
self.tabContainerData?.0 = entries
}
let completion = { [weak self] in
@ -7259,7 +7284,7 @@ private final class ChatListLocationContext {
dateTimeFormat: presentationData.dateTimeFormat,
nameDisplayOrder: presentationData.nameDisplayOrder,
displayBackground: false,
content: .custom(presentationData.strings.ChatList_SelectedTopics(Int32(stateAndFilterId.state.selectedThreadIds.count)), nil, false),
content: .custom(title: [ChatTitleContent.TitleTextItem(id: AnyHashable(0), content: .text(presentationData.strings.ChatList_SelectedTopics(Int32(stateAndFilterId.state.selectedThreadIds.count))))], subtitle: nil, isEnabled: false),
activities: nil,
networkState: nil,
tapped: {

View file

@ -21,13 +21,13 @@ import ChatFolderLinkPreviewScreen
import ChatListHeaderComponent
import StoryPeerListComponent
import TelegramNotices
import ChatListFilterTabContainerNode
import HeaderPanelContainerComponent
import HorizontalTabsComponent
import PremiumUI
import MediaPlaybackHeaderPanelComponent
import LiveLocationHeaderPanelComponent
import ChatListHeaderNoticeComponent
import ChatListFilterTabContainerNode
public enum ChatListContainerNodeFilter: Equatable {
case all

View file

@ -148,7 +148,7 @@ class ChatListFilterPresetCategoryItemNode: ItemListRevealOptionsItemNode, ItemL
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -201,7 +201,7 @@ final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemNode {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.containerNode)
self.containerNode.addSubnode(self.titleNode.textNode)

View file

@ -132,7 +132,7 @@ public class ChatListFilterPresetListSuggestedItemNode: ListViewItemNode, ItemLi
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.labelNode)

View file

@ -113,7 +113,7 @@ public class ChatListFilterTagSectionHeaderItemNode: ListViewItemNode {
self.activateArea = AccessibilityAreaNode()
self.activateArea.accessibilityTraits = [.staticText, .header]
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.accessoryTextNode)

View file

@ -79,7 +79,7 @@ class ChatListRecentPeersListItemNode: ListViewItemNode {
self.separatorNode = ASDisplayNode()
self.separatorNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)

View file

@ -5035,7 +5035,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
transition.updateFrame(node: self.mediaAccessoryPanelContainer, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: MediaNavigationAccessoryHeaderNode.minimizedHeight)))
let topInset: CGFloat = topInset + topPanelHeight
let overflowInset: CGFloat = 20.0
let overflowInset: CGFloat = 0.0
let insets = UIEdgeInsets(top: topInset + topPanelHeight, left: sideInset, bottom: bottomInset, right: sideInset)
self.shimmerNode.frame = CGRect(origin: CGPoint(x: overflowInset, y: topInset), size: CGSize(width: size.width - overflowInset * 2.0, height: size.height))

View file

@ -126,7 +126,7 @@ public class ItemListFilterTitleInputItemNode: ListViewItemNode, UITextFieldDele
self.maskNode = ASImageNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
}
override public func didLoad() {

View file

@ -172,7 +172,7 @@ class ChatListArchiveInfoItemNode: ListViewItemNode, ASScrollViewDelegate {
self.infoPageNodes = (0 ..< 3).map({ _ in InfoPageNode() })
self.pageControlNode.pagesCount = self.infoPageNodes.count
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.scrollNode)
self.infoPageNodes.forEach(self.scrollNode.addSubnode)

View file

@ -55,7 +55,7 @@ class ChatListEmptyHeaderItemNode: ListViewItemNode {
private var item: ChatListEmptyHeaderItem?
required init() {
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
}
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {

View file

@ -92,7 +92,7 @@ class ChatListEmptyInfoItemNode: ListViewItemNode {
self.animationNode = DefaultAnimatedStickerNodeImpl()
self.textNode = TextNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.animationNode)
self.addSubnode(self.textNode)
@ -207,7 +207,7 @@ class ChatListSectionHeaderNode: ListViewItemNode {
private var headerNode: ListSectionHeaderNode?
required init() {
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.zPosition = 1.0
}

View file

@ -56,7 +56,7 @@ class ChatListHoleItemNode: ListViewItemNode {
var relativePosition: (first: Bool, last: Bool) = (false, false)
required init() {
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
}
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
@ -153,7 +153,7 @@ class ChatListSearchEmptyFooterItemNode: ListViewItemNode {
self.searchAllMessagesTitle = TextNode()
self.searchAllMessagesTitle.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.contentNode)
self.contentNode.addSubnode(self.titleNode)

View file

@ -1655,7 +1655,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
self.separatorNode = ASDisplayNode()
self.separatorNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -129,7 +129,7 @@ class ContactsAddItemNode: ListViewItemNode {
self.iconNode = ASImageNode()
self.titleNode = TextNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)

View file

@ -181,7 +181,7 @@ class ContactListActionItemNode: ListViewItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.iconNode)
self.addSubnode(self.titleNode)

View file

@ -1234,7 +1234,6 @@ public final class ContactListNode: ASDisplayNode {
self.presentationData = presentationData
self.listNode = ListView()
self.listNode.dynamicBounceEnabled = false
self.listNode.accessibilityPageScrolledString = { row, count in
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
}
@ -2098,8 +2097,6 @@ public final class ContactListNode: ASDisplayNode {
strongSelf.authorizationNode.isHidden = authorizationPreviousHidden
strongSelf.addSubnode(strongSelf.authorizationNode)
strongSelf.listNode.dynamicBounceEnabled = false
strongSelf.listNode.forEachAccessoryItemNode({ accessoryItemNode in
if let accessoryItemNode = accessoryItemNode as? ContactsSectionHeaderAccessoryItemNode {
accessoryItemNode.updateTheme(theme: presentationData.theme)

View file

@ -103,7 +103,7 @@ public class LimitedPermissionItemNode: ListViewItemNode {
self.actionButtonTitleNode = TextNode()
self.actionButtonTitleNode.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.textNode)
self.addSubnode(self.activateArea)

View file

@ -584,7 +584,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
self.titleNode = TextNode()
self.statusNode = TextNodeWithEntities()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -210,7 +210,6 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
private final var displayLink: CADisplayLink!
private final var needsAnimations = false
public final var dynamicBounceEnabled = true
public final var rotated = false
public final var experimentalSnapScrollToItem = false
public final var useMainQueueTransactions = false
@ -265,6 +264,9 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
public final var addContentOffset: ((CGFloat, ListViewItemNode?) -> Void)?
public final var shouldStopScrolling: ((CGFloat) -> Bool)?
public final var onContentsUpdated: ((ContainedViewLayoutTransition) -> Void)?
public private(set) final var edgeEffectExtension: CGFloat = 0.0
public final var onEdgeEffectExtensionUpdated: ((ContainedViewLayoutTransition) -> Void)?
public final var updateScrollingIndicator: ((ScrollingIndicatorState?, ContainedViewLayoutTransition) -> Void)?
@ -1044,41 +1046,10 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
self.enqueueUpdateVisibleItems(synchronous: false)
}
var useScrollDynamics = false
let anchor: CGFloat
if self.isTracking {
anchor = self.touchesPosition.y
} else if deltaY < 0.0 {
anchor = self.visibleSize.height
} else {
anchor = 0.0
}
self.didScrollWithOffset?(deltaY, .immediate, nil, self.isTrackingOrDecelerating)
for itemNode in self.itemNodes {
itemNode.updateFrame(itemNode.frame.offsetBy(dx: 0.0, dy: -deltaY), within: self.visibleSize)
if self.dynamicBounceEnabled && itemNode.wantsScrollDynamics {
useScrollDynamics = true
var distance: CGFloat
let itemFrame = itemNode.apparentFrame
if anchor < itemFrame.origin.y {
distance = abs(itemFrame.origin.y - anchor)
} else if anchor > itemFrame.origin.y + itemFrame.size.height {
distance = abs(anchor - (itemFrame.origin.y + itemFrame.size.height))
} else {
distance = 0.0
}
let factor: CGFloat = max(0.08, abs(distance) / self.visibleSize.height)
let resistance: CGFloat = testSpringFreeResistance
itemNode.addScrollingOffset(deltaY * factor * resistance)
}
}
if !self.snapToBounds(snapTopItem: false, stackFromBottom: self.stackFromBottom, insetDeltaOffsetFix: 0.0).offset.isZero {
@ -1088,38 +1059,10 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
self.updateItemHeaders(leftInset: self.insets.left, rightInset: self.insets.right, synchronousLoad: false)
for (_, headerNode) in self.itemHeaderNodes {
if self.dynamicBounceEnabled && headerNode.wantsScrollDynamics {
useScrollDynamics = true
var distance: CGFloat
let itemFrame = headerNode.frame
if anchor < itemFrame.origin.y {
distance = abs(itemFrame.origin.y - anchor)
} else if anchor > itemFrame.origin.y + itemFrame.size.height {
distance = abs(anchor - (itemFrame.origin.y + itemFrame.size.height))
} else {
distance = 0.0
}
let factor: CGFloat = max(0.08, abs(distance) / self.visibleSize.height)
let resistance: CGFloat = testSpringFreeResistance
headerNode.addScrollingOffset(deltaY * factor * resistance)
}
}
if useScrollDynamics {
self.setNeedsAnimations()
}
self.updateVisibleContentOffset()
self.updateVisibleItemRange()
self.updateItemNodesVisibilities(onlyPositive: false)
self.onContentsUpdated?(.immediate)
//CATransaction.commit()
}
private func calculateAdditionalTopInverseInset() -> CGFloat {
@ -3914,6 +3857,8 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
let flashing = self.headerItemsAreFlashing()
var maxEdgeEffectExtension: CGFloat = 0.0
func addHeader(id: VisibleHeaderNodeId, upperBound: CGFloat, upperIndex: Int, upperBoundEdge: CGFloat, lowerBound: CGFloat, lowerIndex: Int, item: ListViewItemHeader, hasValidNodes: Bool) {
let itemHeaderHeight: CGFloat = item.height
@ -4096,6 +4041,11 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
}
headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, distance: stickLocationDistance, transition: .immediate)
}
if headerNode.contributesToEdgeEffect && stickLocationDistance > 0.0 {
maxEdgeEffectExtension = max(maxEdgeEffectExtension, upperDisplayBound + headerFrame.height + 8.0)
}
headerNode.offsetByHeaderNodeId = offsetByHeaderNodeId
headerNode.naturalOriginY = naturalY
var maxIntersectionHeight: (CGFloat, Int)?
@ -4228,6 +4178,11 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
}
}
}
if self.edgeEffectExtension != maxEdgeEffectExtension {
self.edgeEffectExtension = maxEdgeEffectExtension
self.onEdgeEffectExtensionUpdated?(transition.0)
}
}
private func updateItemNodesVisibilities(onlyPositive: Bool) {

View file

@ -22,13 +22,12 @@ public protocol ListViewItemHeader: AnyObject {
}
open class ListViewItemHeaderNode: ASDisplayNode {
private final var spring: ListViewItemSpring?
let wantsScrollDynamics: Bool
let isRotated: Bool
final private(set) var internalStickLocationDistanceFactor: CGFloat = 0.0
final var internalStickLocationDistance: CGFloat = 0.0
private var isFlashingOnScrolling = false
weak var attachedToItemNode: ListViewItemNode?
public var contributesToEdgeEffect: Bool = false
var offsetByHeaderNodeId: ListViewItemNode.HeaderId?
var naturalOriginY: CGFloat?
@ -53,12 +52,8 @@ open class ListViewItemHeaderNode: ASDisplayNode {
return self.alpha
}
public init(layerBacked: Bool = false, dynamicBounce: Bool = false, isRotated: Bool = false, seeThrough: Bool = false) {
self.wantsScrollDynamics = dynamicBounce
public init(layerBacked: Bool = false, isRotated: Bool = false, seeThrough: Bool = false) {
self.isRotated = isRotated
if dynamicBounce {
self.spring = ListViewItemSpring(stiffness: -280.0, damping: -24.0, mass: 0.85)
}
super.init()
@ -69,54 +64,10 @@ open class ListViewItemHeaderNode: ASDisplayNode {
}
final func addScrollingOffset(_ scrollingOffset: CGFloat) {
if self.spring != nil && internalStickLocationDistanceFactor.isZero {
let bounds = self.bounds
self.bounds = CGRect(origin: CGPoint(x: 0.0, y: bounds.origin.y + scrollingOffset), size: bounds.size)
}
}
public func animate(_ timestamp: Double) -> Bool {
var continueAnimations = false
if let _ = self.spring {
let bounds = self.bounds
var offset = bounds.origin.y
let currentOffset = offset
let frictionConstant: CGFloat = testSpringFriction
let springConstant: CGFloat = testSpringConstant
let time: CGFloat = 1.0 / 60.0
// friction force = velocity * friction constant
let frictionForce = self.spring!.velocity * frictionConstant
// spring force = (target point - current position) * spring constant
let springForce = -currentOffset * springConstant
// force = spring force - friction force
let force = springForce - frictionForce
// velocity = current velocity + force * time / mass
self.spring!.velocity = self.spring!.velocity + force * time
// position = current position + velocity * time
offset = currentOffset + self.spring!.velocity * time
offset = offset.isNaN ? 0.0 : offset
let epsilon: CGFloat = 0.1
if abs(offset) < epsilon && abs(self.spring!.velocity) < epsilon {
offset = 0.0
self.spring!.velocity = 0.0
} else {
continueAnimations = true
}
if abs(offset) > 250.0 {
offset = offset < 0.0 ? -250.0 : 250.0
}
self.bounds = CGRect(origin: CGPoint(x: 0.0, y: offset), size: bounds.size)
}
return continueAnimations
return false
}
open func animateRemoved(duration: Double) {

View file

@ -129,7 +129,6 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
return nil
}
private final var spring: ListViewItemSpring?
private final var animations: [(String, ListViewAnimation)] = []
private final var pendingControlledTransitions: [ControlledTransition] = []
private final var controlledTransitions: [ControlledTransitionContext] = []
@ -142,8 +141,6 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
open func attachedHeaderNodesUpdated() {
}
final let wantsScrollDynamics: Bool
open var preferredAnimationCurve: (CGFloat) -> CGFloat {
return listViewAnimationCurveSystem
}
@ -236,12 +233,7 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
return .complete()
}
public init(layerBacked: Bool, dynamicBounce: Bool = true, rotated: Bool = false, seeThrough: Bool = false) {
if dynamicBounce {
self.spring = ListViewItemSpring(stiffness: -280.0, damping: -24.0, mass: 0.85)
}
self.wantsScrollDynamics = dynamicBounce
public init(layerBacked: Bool, rotated: Bool = false, seeThrough: Bool = false) {
self.rotated = rotated
super.init()
@ -338,56 +330,14 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
}
final func addScrollingOffset(_ scrollingOffset: CGFloat) {
if self.spring != nil {
self.contentOffset += scrollingOffset
}
}
func initializeDynamicsFromSibling(_ itemView: ListViewItemNode, additionalOffset: CGFloat) {
if let itemViewSpring = itemView.spring {
self.contentOffset = itemView.contentOffset + additionalOffset
self.spring?.velocity = itemViewSpring.velocity
}
}
public func animate(timestamp: Double, invertOffsetDirection: inout Bool) -> Bool {
var continueAnimations = false
if let _ = self.spring {
var offset = self.contentOffset
let frictionConstant: CGFloat = testSpringFriction
let springConstant: CGFloat = testSpringConstant
let time: CGFloat = 1.0 / 60.0
// friction force = velocity * friction constant
let frictionForce = self.spring!.velocity * frictionConstant
// spring force = (target point - current position) * spring constant
let springForce = -self.contentOffset * springConstant
// force = spring force - friction force
let force = springForce - frictionForce
// velocity = current velocity + force * time / mass
self.spring!.velocity = self.spring!.velocity + force * time
// position = current position + velocity * time
offset = self.contentOffset + self.spring!.velocity * time
offset = offset.isNaN ? 0.0 : offset
let epsilon: CGFloat = 0.1
if abs(offset) < epsilon && abs(self.spring!.velocity) < epsilon {
offset = 0.0
self.spring!.velocity = 0.0
} else {
continueAnimations = true
}
if abs(offset) > 250.0 {
offset = offset < 0.0 ? -250.0 : 250.0
}
self.contentOffset = offset
}
var i = 0
var animationCount = self.animations.count
while i < animationCount {

View file

@ -190,6 +190,8 @@ public protocol NavigationBar: ASDisplayNode {
var requestContainerLayout: ((ContainedViewLayoutTransition) -> Void)? { get set }
func updateLayout(size: CGSize, defaultHeight: CGFloat, additionalTopHeight: CGFloat, additionalContentHeight: CGFloat, additionalBackgroundHeight: CGFloat, additionalCutout: CGSize?, leftInset: CGFloat, rightInset: CGFloat, appearsHidden: Bool, isLandscape: Bool, transition: ContainedViewLayoutTransition)
func updateEdgeEffectExtension(value: CGFloat, transition: ContainedViewLayoutTransition)
}
public var defaultNavigationBarImpl: ((NavigationBarPresentationData) -> NavigationBar)?

View file

@ -249,6 +249,16 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
open var interactiveNavivationGestureEdgeWidth: InteractiveTransitionGestureRecognizerEdgeWidth? {
return nil
}
open var navigationEdgeEffectExtension: CGFloat {
return 0.0
}
public func updateNavigationEdgeEffectExtension(transition: ContainedViewLayoutTransition) {
if let navigationBar = self.navigationBar {
navigationBar.updateEdgeEffectExtension(value: max(0.0, self.navigationEdgeEffectExtension - navigationBar.frame.maxY), transition: transition)
}
}
open func navigationLayout(layout: ContainerViewLayout) -> NavigationLayout {
let statusBarHeight: CGFloat = layout.statusBarHeight ?? 0.0

View file

@ -59,7 +59,7 @@ public final class HashtagSearchController: TelegramBaseController {
}
self.presentationData = presentationData
super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass), mediaAccessoryPanelVisibility: .specific(size: .compact), locationBroadcastPanelSource: .none, groupCallPanelSource: .none)
super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style

View file

@ -200,7 +200,7 @@ final class HashtagSearchRecentQueryItemNode: ItemListRevealOptionsItemNode {
self.iconNode = ASImageNode()
self.iconNode.displaysAsynchronously = false
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)

View file

@ -138,7 +138,7 @@ public final class HorizontalPeerItemNode: ListViewItemNode {
self.onlineNode = PeerOnlineMarkerNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.peerNode)
self.addSubnode(self.badgeBackgroundNode)

View file

@ -170,7 +170,7 @@ public class AdditionalLinkItemNode: ListViewItemNode, ItemListItemNode {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -94,7 +94,7 @@ class InviteLinkHeaderItemNode: ListViewItemNode {
self.animationNode = DefaultAnimatedStickerNodeImpl()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode.textNode)

View file

@ -86,7 +86,7 @@ class InviteLinkInviteHeaderItemNode: ListViewItemNode {
self.iconNode.displaysAsynchronously = false
self.iconNode.displayWithoutProcessing = true
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)

View file

@ -74,7 +74,7 @@ class InviteLinkInviteManageItemNode: ListViewItemNode {
self.backgroundNode = ASDisplayNode()
self.buttonNode = HighlightableButtonNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.buttonNode)

View file

@ -203,7 +203,7 @@ public class ItemListFolderInviteLinkItemNode: ListViewItemNode, ItemListItemNod
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.fieldNode)
self.addSubnode(self.addressNode)

View file

@ -210,7 +210,7 @@ public class ItemListFolderInviteLinkListItemNode: ItemListRevealOptionsItemNode
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -170,7 +170,7 @@ private final class ItemListInviteLinkTimeLimitItemNode: ListViewItemNode {
self.customTextNode.isUserInteractionEnabled = false
self.customTextNode.displaysAsynchronously = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.lowTextNode)
self.addSubnode(self.mediumTextNode)

View file

@ -235,7 +235,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -186,7 +186,7 @@ private final class ItemListInviteLinkUsageLimitItemNode: ListViewItemNode {
self.customTextNode.isUserInteractionEnabled = false
self.customTextNode.displaysAsynchronously = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.lowTextNode)
self.addSubnode(self.mediumTextNode)

View file

@ -223,7 +223,7 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
self.contentWrapperNode = ASDisplayNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -210,7 +210,7 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.fieldNode)
self.addSubnode(self.addressNode)

View file

@ -142,7 +142,7 @@ public class ItemListAddressItemNode: ListViewItemNode {
self.iconNode = ASImageNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.labelNode)
self.addSubnode(self.textNode)

View file

@ -327,7 +327,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
self.callButton = HighlightableButtonNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.isAccessibilityElement = true

View file

@ -160,7 +160,7 @@ public final class ItemListPeerActionItemNode: ListViewItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.iconNode)
self.addSubnode(self.titleNode)
@ -262,7 +262,9 @@ public final class ItemListPeerActionItemNode: ListViewItemNode {
case .plain:
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
if !item.alwaysPlain {
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
}
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
}
}

View file

@ -855,7 +855,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -263,7 +263,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.containerNode)

View file

@ -104,7 +104,7 @@ public final class ItemListControllerSegmentedTitleView: UIView {
layout: .fit
)),
environment: {},
containerSize: CGSize(width: size.width, height: 40.0)
containerSize: CGSize(width: size.width, height: 44.0)
)
let tabSelectorFrame = CGRect(origin: CGPoint(x: floor((size.width - tabSelectorSize.width) / 2.0), y: floor((size.height - tabSelectorSize.height) / 2.0)), size: tabSelectorSize)

View file

@ -125,7 +125,7 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)

View file

@ -85,7 +85,7 @@ public class ItemListActivityTextItemNode: ListViewItemNode {
self.activityIndicator = ActivityIndicator(type: ActivityIndicatorType.custom(.black, 16.0, 2.0, false))
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.activityIndicator)

View file

@ -168,7 +168,7 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.contentParentNode)
self.contentParentNode.addSubnode(self.contentContainerNode)

View file

@ -254,7 +254,7 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode.textNode)
self.addSubnode(self.labelNode)

View file

@ -83,8 +83,8 @@ open class ItemListRevealOptionsItemNode: ListViewItemNode, ASGestureRecognizerD
return !self.isDisplayingRevealedOptions
}
override public init(layerBacked: Bool, dynamicBounce: Bool, rotated: Bool, seeThrough: Bool) {
super.init(layerBacked: layerBacked, dynamicBounce: dynamicBounce, rotated: rotated, seeThrough: seeThrough)
override public init(layerBacked: Bool, rotated: Bool, seeThrough: Bool) {
super.init(layerBacked: layerBacked, rotated: rotated, seeThrough: seeThrough)
}
open var controlsContainer: ASDisplayNode {

View file

@ -267,7 +267,7 @@ public class ItemListExpandableSwitchItemNode: ListViewItemNode, ItemListItemNod
self.subItemContainer = ASDisplayNode()
self.subItemContainer.clipsToBounds = true
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.titleValueNode)

View file

@ -181,7 +181,7 @@ public class InfoItemNode: ListViewItemNode {
self.closeButton.hitTestSlop = UIEdgeInsets(top: -8.0, left: -8.0, bottom: -8.0, right: -8.0)
self.closeButton.displaysAsynchronously = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.badgeNode)
self.addSubnode(self.labelNode)

View file

@ -152,7 +152,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
self.limitTextNode = TextNode()
self.limitTextNode.displaysAsynchronously = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.textClippingNode.addSubnode(self.textNode)
self.addSubnode(self.textClippingNode)

View file

@ -127,7 +127,7 @@ public class ItemListMultilineTextItemNode: ListViewItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.textNode)
self.addSubnode(self.activateArea)

View file

@ -93,7 +93,7 @@ public class ItemListPlaceholderItemNode: ListViewItemNode, ItemListItemNode {
self.textNode = TextNode()
self.textNode.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.textNode)
}

View file

@ -139,7 +139,7 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
self.activateArea = AccessibilityAreaNode()
self.activateArea.accessibilityTraits = [.staticText, .header]
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.accessoryTextNode)

View file

@ -177,7 +177,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
self.labelNode = TextNode()
self.labelNode.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode.textNode)
self.addSubnode(self.textNode)

View file

@ -207,7 +207,7 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.switchNode)

View file

@ -132,7 +132,7 @@ public class ItemListTextItemNode: ListViewItemNode, ItemListItemNode {
self.activateArea = AccessibilityAreaNode()
self.activateArea.accessibilityTraits = .staticText
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.textNode.textNode)
self.addSubnode(self.activateArea)

View file

@ -134,7 +134,7 @@ public class ItemListTextWithLabelItemNode: ListViewItemNode {
self.textNode.contentMode = .left
self.textNode.contentsScale = UIScreen.main.scale
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.isAccessibilityElement = true

View file

@ -171,7 +171,7 @@ public class ItemListVenueItemNode: ListViewItemNode, ItemListItemNode {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.isAccessibilityElement = true

View file

@ -66,7 +66,7 @@ final class ListMessageHoleItemNode: ListViewItemNode {
private var activityIndicator: UIActivityIndicatorView?
init() {
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
}
override func didLoad() {

View file

@ -10,7 +10,7 @@ public class ListMessageNode: ListViewItemNode {
var interaction: ListMessageItemInteraction?
required init() {
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
}
func setupItem(_ item: ListMessageItem) {

View file

@ -10,9 +10,10 @@ swift_library(
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/TelegramPresentationData",
"//submodules/ImageBlur",
],
visibility = [
"//visibility:public",

View file

@ -3,6 +3,7 @@ import UIKit
import AsyncDisplayKit
import Display
import TelegramPresentationData
import ImageBlur
private let titleFont = Font.regular(13.0)
private let actionFont = Font.regular(13.0)
@ -15,6 +16,7 @@ public enum ListSectionHeaderActionType {
public final class ListSectionHeaderNode: ASDisplayNode {
private let backgroundLayer: SimpleLayer
private let label: ImmediateTextNode
private let labelBackgroundView: UIImageView
private var actionButtonLabel: ImmediateTextNode?
private var actionButton: HighlightableButtonNode?
private var theme: PresentationTheme
@ -89,13 +91,16 @@ public final class ListSectionHeaderNode: ASDisplayNode {
self.label.isAccessibilityElement = true
self.label.displaysAsynchronously = false
self.labelBackgroundView = UIImageView()
super.init()
self.layer.addSublayer(self.backgroundLayer)
self.view.addSubview(self.labelBackgroundView)
self.addSubnode(self.label)
self.backgroundLayer.backgroundColor = theme.chatList.sectionHeaderFillColor.cgColor
//self.backgroundLayer.backgroundColor = theme.chatList.sectionHeaderFillColor.cgColor
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
@ -135,7 +140,7 @@ public final class ListSectionHeaderNode: ASDisplayNode {
if self.theme !== theme {
self.theme = theme
self.backgroundLayer.backgroundColor = theme.chatList.sectionHeaderFillColor.cgColor
//self.backgroundLayer.backgroundColor = theme.chatList.sectionHeaderFillColor.cgColor
self.label.attributedText = NSAttributedString(string: self.title ?? "", font: titleFont, textColor: self.theme.chatList.sectionHeaderTextColor)
@ -150,7 +155,23 @@ public final class ListSectionHeaderNode: ASDisplayNode {
public func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, showBackground: Bool = true) {
self.validLayout = (size, leftInset, rightInset)
let labelSize = self.label.updateLayout(CGSize(width: max(0.0, size.width - leftInset - rightInset - 18.0), height: size.height))
self.label.frame = CGRect(origin: CGPoint(x: leftInset + 16.0, y: 6.0 + UIScreenPixel), size: CGSize(width: labelSize.width, height: size.height))
let labelFrame = CGRect(origin: CGPoint(x: leftInset + 16.0, y: 6.0 + UIScreenPixel), size: CGSize(width: labelSize.width, height: labelSize.height))
self.label.frame = labelFrame
let labelBackgroundSize: CGFloat = labelSize.height
let labelBackgroundInnerInset: CGFloat = 6.0
let labelBackgroundInset: CGFloat = 10.0 + labelBackgroundInnerInset
if self.labelBackgroundView.image?.size.width != labelBackgroundSize + labelBackgroundInset * 2.0 {
self.labelBackgroundView.image = blurredImage(generateImage(CGSize(width: labelBackgroundSize + labelBackgroundInset * 2.0, height: labelBackgroundSize + labelBackgroundInset * 2.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(UIColor.white.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(x: labelBackgroundInset - labelBackgroundInnerInset, y: labelBackgroundInset - labelBackgroundInnerInset), size: CGSize(width: labelBackgroundSize + labelBackgroundInnerInset * 2.0, height: labelBackgroundSize + labelBackgroundInnerInset * 2.0)))
})!, radius: 19, iterations: 3)?.stretchableImage(withLeftCapWidth: Int(labelBackgroundInset + labelBackgroundSize * 0.5), topCapHeight: Int(labelBackgroundInset + labelBackgroundSize * 0.5)).withRenderingMode(.alwaysTemplate)
}
self.labelBackgroundView.tintColor = self.theme.list.plainBackgroundColor.withAlphaComponent(0.5)
//self.labelBackgroundView.tintColor = UIColor.blue.withMultipliedAlpha(0.8)
self.labelBackgroundView.frame = labelFrame.insetBy(dx: -labelBackgroundInset - 4.0, dy: -labelBackgroundInset)
if let actionButton = self.actionButton, let actionButtonLabel = self.actionButtonLabel {
let buttonSize = actionButtonLabel.updateLayout(CGSize(width: size.width, height: size.height))

View file

@ -224,7 +224,7 @@ final class LocationActionListItemNode: ListViewItemNode {
self.venueIconNode = TransformImageNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)

View file

@ -65,7 +65,7 @@ private class LocationAttributionItemNode: ListViewItemNode {
self.imageNode.displaysAsynchronously = false
self.imageNode.displayWithoutProcessing = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.imageNode)
}

View file

@ -98,7 +98,7 @@ public final class LocationInfoListItemNode: ListViewItemNode {
self.venueIconNode = TransformImageNode()
self.venueIconNode.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.buttonNode)

View file

@ -119,7 +119,7 @@ final class LocationLiveListItemNode: ListViewItemNode {
self.avatarNode = AvatarNode(font: avatarFont)
self.avatarNode.isLayerBacked = !smartInvertColorsEnabled()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)

View file

@ -58,7 +58,7 @@ private class LocationSectionHeaderItemNode: ListViewItemNode {
private var layoutParams: ListViewItemLayoutParams?
required init() {
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
}
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {

View file

@ -130,7 +130,7 @@ private final class MediaGroupsGridAlbumItemNode : ListViewItemNode {
self.countNode = TextNode()
self.countNode.isUserInteractionEnabled = false
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.containerNode)
self.containerNode.addSubnode(self.imageNode)
@ -283,7 +283,7 @@ private class MediaGroupsAlbumGridItemNode: ListViewItemNode {
self.listNode = ListView()
self.listNode.transform = CATransform3DMakeRotation(-CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.listNode)
}

View file

@ -172,7 +172,7 @@ class MediaGroupsAlbumItemNode: ListViewItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.iconNode)
self.addSubnode(self.titleNode)

View file

@ -59,7 +59,7 @@ private class MediaGroupsHeaderItemNode: ListViewItemNode {
init() {
self.titleNode = TextNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.titleNode)
}

View file

@ -754,7 +754,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
self.galleryNode.setControlsHidden(true, animated: false)
if let centralItemNode = self.galleryNode.pager.centralItemNode(), let itemSize = centralItemNode.contentSize() {
self.preferredContentSize = itemSize.aspectFitted(self.view.bounds.size)
self.containerLayoutUpdated(ContainerViewLayout(size: self.preferredContentSize, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
self.containerLayoutUpdated(ContainerViewLayout(size: self.preferredContentSize, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
centralItemNode.activateAsInitial()
}
}

View file

@ -90,7 +90,7 @@ class ChannelDiscussionGroupSetupHeaderItemNode: ListViewItemNode {
self.labelNode.contentMode = .left
self.labelNode.contentsScale = UIScreen.main.scale
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.imageNode)
self.addSubnode(self.titleNode)

View file

@ -95,7 +95,7 @@ class ChatSlowmodeItemNode: ListViewItemNode {
return textNode
}
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.textNodes.forEach(self.addSubnode)
}

View file

@ -103,7 +103,7 @@ class ChatUnrestrictBoostersItemNode: ListViewItemNode {
return textNode
}
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.iconNodes.forEach(self.addSubnode)
self.textNodes.forEach(self.addSubnode)

View file

@ -174,7 +174,7 @@ public class ItemListCallListItemNode: ListViewItemNode {
self.accessibilityArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.accessibilityArea)

View file

@ -168,7 +168,7 @@ public class ItemListReactionItemNode: ListViewItemNode, ItemListItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.switchNode)

View file

@ -123,7 +123,7 @@ class ItemListSecretChatKeyItemNode: ListViewItemNode {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.keyNode)

View file

@ -125,7 +125,7 @@ class PeerRemoveTimeoutItemNode: ListViewItemNode, ItemListItemNode {
return TextNode()
}
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.titleNodes.forEach(self.addSubnode)

View file

@ -100,7 +100,7 @@ class UserInfoEditingPhoneActionItemNode: ListViewItemNode {
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.iconNode)
self.addSubnode(self.titleNode)

View file

@ -131,7 +131,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
self.clearButton.displaysAsynchronously = false
self.clearButton.isHidden = true
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.editableControlNode)
self.addSubnode(self.labelNode)

View file

@ -76,7 +76,7 @@ class PeersNearbyHeaderItemNode: ListViewItemNode {
self.animationNode = DefaultAnimatedStickerNodeImpl()
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.animationNode)

View file

@ -212,7 +212,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
super.init(layerBacked: false, rotated: false, seeThrough: false)
self.addSubnode(self.containerNode)

View file

@ -99,7 +99,7 @@ class IncreaseLimitHeaderItemNode: ListViewItemNode {
self.textNode.contentMode = .left
self.textNode.contentsScale = UIScreen.main.scale
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)

View file

@ -91,7 +91,7 @@ private final class SubscriptionsCountItemNode: ListViewItemNode {
return textNode
}
super.init(layerBacked: false, dynamicBounce: false)
super.init(layerBacked: false)
self.textNodes.forEach(self.addSubnode)
}

View file

@ -304,7 +304,9 @@ public final class SearchBarPlaceholderContentView: UIView {
}
ComponentTransition(transition).setAlpha(view: glassBackgroundView, alpha: backgroundAlpha)
let isDark = params.backgroundColor.hsb.b < 0.5
glassBackgroundView.update(size: backgroundFrame.size, cornerRadius: backgroundFrame.height * 0.5, isDark: isDark, tintColor: .init(kind: .panel, color: UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.6)), isInteractive: true, transition: ComponentTransition(transition))
if params.isActive {
glassBackgroundView.update(size: backgroundFrame.size, cornerRadius: backgroundFrame.height * 0.5, isDark: isDark, tintColor: .init(kind: .panel, color: UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.6)), isInteractive: true, transition: ComponentTransition(transition))
}
if params.isActive {
let transition = ComponentTransition(transition)

Some files were not shown because too many files have changed in this diff Show more