This commit is contained in:
Isaac 2025-12-12 23:58:00 +08:00
parent 3982aa3f9e
commit a63c90aa00
41 changed files with 550 additions and 503 deletions

View file

@ -34,6 +34,9 @@ swift_library(
"//submodules/InviteLinksUI", "//submodules/InviteLinksUI",
"//submodules/UndoUI", "//submodules/UndoUI",
"//submodules/TelegramCallsUI", "//submodules/TelegramCallsUI",
"//submodules/TelegramUI/Components/EdgeEffect",
"//submodules/ComponentFlow",
"//submodules/Components/ComponentDisplayAdapters",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View file

@ -361,10 +361,10 @@ public final class CallListController: TelegramBaseController {
if empty { if empty {
switch strongSelf.mode { switch strongSelf.mode {
case .tab: case .tab:
strongSelf.navigationItem.setLeftBarButton(nil, animated: true) strongSelf.navigationItem.setLeftBarButton(nil, animated: strongSelf.controllerNode.didSetReady)
strongSelf.navigationItem.setRightBarButton(nil, animated: true) strongSelf.navigationItem.setRightBarButton(nil, animated: strongSelf.controllerNode.didSetReady)
case .navigation: case .navigation:
strongSelf.navigationItem.setRightBarButton(nil, animated: true) strongSelf.navigationItem.setRightBarButton(nil, animated: strongSelf.controllerNode.didSetReady)
} }
} else { } else {
var pressedImpl: (() -> Void)? var pressedImpl: (() -> Void)?
@ -381,25 +381,24 @@ public final class CallListController: TelegramBaseController {
switch strongSelf.mode { switch strongSelf.mode {
case .tab: case .tab:
if strongSelf.editingMode { if strongSelf.editingMode {
strongSelf.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.donePressed)), animated: true) strongSelf.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.donePressed)), animated: strongSelf.controllerNode.didSetReady)
strongSelf.navigationItem.setRightBarButton(UIBarButtonItem(customDisplayNode: buttonNode), animated: true) strongSelf.navigationItem.setRightBarButton(UIBarButtonItem(customDisplayNode: buttonNode), animated: strongSelf.controllerNode.didSetReady)
strongSelf.navigationItem.rightBarButtonItem?.setCustomAction({ strongSelf.navigationItem.rightBarButtonItem?.setCustomAction({
pressedImpl?() pressedImpl?()
}) })
} else { } else {
strongSelf.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: strongSelf, action: #selector(strongSelf.editPressed)), animated: true) strongSelf.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: strongSelf, action: #selector(strongSelf.editPressed)), animated: strongSelf.controllerNode.didSetReady)
//strongSelf.navigationItem.setRightBarButton(UIBarButtonItem(image: PresentationResourcesRootController.navigationCallIcon(strongSelf.presentationData.theme), style: .plain, target: self, action: #selector(strongSelf.callPressed)), animated: true) strongSelf.navigationItem.setRightBarButton(nil, animated: strongSelf.controllerNode.didSetReady)
strongSelf.navigationItem.setRightBarButton(nil, animated: true)
} }
case .navigation: case .navigation:
if strongSelf.editingMode { if strongSelf.editingMode {
strongSelf.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: buttonNode), animated: true) strongSelf.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: buttonNode), animated: strongSelf.controllerNode.didSetReady)
strongSelf.navigationItem.leftBarButtonItem?.setCustomAction({ strongSelf.navigationItem.leftBarButtonItem?.setCustomAction({
pressedImpl?() pressedImpl?()
}) })
strongSelf.navigationItem.setRightBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.donePressed)), animated: true) strongSelf.navigationItem.setRightBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.donePressed)), animated: strongSelf.controllerNode.didSetReady)
} else { } else {
strongSelf.navigationItem.setRightBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: strongSelf, action: #selector(strongSelf.editPressed)), animated: true) strongSelf.navigationItem.setRightBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: strongSelf, action: #selector(strongSelf.editPressed)), animated: strongSelf.controllerNode.didSetReady)
} }
} }
} }

View file

@ -15,6 +15,9 @@ import AnimatedStickerNode
import TelegramAnimatedStickerNode import TelegramAnimatedStickerNode
import AppBundle import AppBundle
import ItemListPeerActionItem import ItemListPeerActionItem
import EdgeEffect
import ComponentFlow
import ComponentDisplayAdapters
private struct CallListNodeListViewTransition { private struct CallListNodeListViewTransition {
let callListView: CallListNodeView let callListView: CallListNodeView
@ -185,7 +188,7 @@ final class CallListControllerNode: ASDisplayNode {
private var containerLayout: (ContainerViewLayout, CGFloat)? private var containerLayout: (ContainerViewLayout, CGFloat)?
private let _ready = ValuePromise<Bool>() private let _ready = ValuePromise<Bool>()
private var didSetReady = false private(set) var didSetReady = false
var ready: Signal<Bool, NoError> { var ready: Signal<Bool, NoError> {
return _ready.get() return _ready.get()
} }
@ -220,6 +223,8 @@ final class CallListControllerNode: ASDisplayNode {
private let emptyButtonIconNode: ASImageNode private let emptyButtonIconNode: ASImageNode
private let emptyButtonTextNode: ImmediateTextNode private let emptyButtonTextNode: ImmediateTextNode
private let edgeEffectView: EdgeEffectView
private let call: (EngineMessage) -> Void private let call: (EngineMessage) -> Void
private let joinGroupCall: (EnginePeer.Id, EngineGroupCallDescription) -> Void private let joinGroupCall: (EnginePeer.Id, EngineGroupCallDescription) -> Void
private let openNewCall: () -> Void private let openNewCall: () -> Void
@ -277,6 +282,8 @@ final class CallListControllerNode: ASDisplayNode {
self.emptyButtonIconNode.displaysAsynchronously = false self.emptyButtonIconNode.displaysAsynchronously = false
self.emptyButtonIconNode.isUserInteractionEnabled = false self.emptyButtonIconNode.isUserInteractionEnabled = false
self.edgeEffectView = EdgeEffectView()
super.init() super.init()
self.setViewBlock({ self.setViewBlock({
@ -289,6 +296,8 @@ final class CallListControllerNode: ASDisplayNode {
self.addSubnode(self.emptyButtonTextNode) self.addSubnode(self.emptyButtonTextNode)
self.addSubnode(self.emptyButtonIconNode) self.addSubnode(self.emptyButtonIconNode)
self.addSubnode(self.emptyButtonNode) self.addSubnode(self.emptyButtonNode)
self.view.addSubview(self.edgeEffectView)
switch self.mode { switch self.mode {
case .tab: case .tab:
@ -945,5 +954,10 @@ final class CallListControllerNode: ASDisplayNode {
self.dequeuedInitialTransitionOnLayout = true self.dequeuedInitialTransitionOnLayout = true
self.dequeueTransition() self.dequeueTransition()
} }
let edgeEffectHeight: CGFloat = layout.intrinsicInsets.bottom
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))
} }
} }

View file

@ -2102,9 +2102,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
let effectiveBackgroundColor: UIColor let effectiveBackgroundColor: UIColor
if item.isPinned { if item.isPinned {
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned, voiceChat: self.onlineIsVoiceChat) onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned, voiceChat: self.onlineIsVoiceChat)
//TODO:localize effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
} else { } else {
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .regular, voiceChat: self.onlineIsVoiceChat) onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .regular, voiceChat: self.onlineIsVoiceChat)
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
@ -2118,9 +2116,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
if let avatarLiveBadge = self.avatarLiveBadge { if let avatarLiveBadge = self.avatarLiveBadge {
let effectiveBackgroundColor: UIColor let effectiveBackgroundColor: UIColor
if item.isPinned { if item.isPinned {
//TODO:localize effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
} else { } else {
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
} }
@ -4133,9 +4129,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
let effectiveBackgroundColor: UIColor let effectiveBackgroundColor: UIColor
if item.isPinned { if item.isPinned {
//TODO:localize effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
} else { } else {
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
} }
@ -4156,9 +4150,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
effectiveBackgroundColor = item.presentationData.theme.chatList.itemHighlightedBackgroundColor effectiveBackgroundColor = item.presentationData.theme.chatList.itemHighlightedBackgroundColor
} else if case let .chatList(index) = item.index, index.pinningIndex != nil { } else if case let .chatList(index) = item.index, index.pinningIndex != nil {
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned, voiceChat: onlineIsVoiceChat) onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned, voiceChat: onlineIsVoiceChat)
//TODO:localize effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
} else { } else {
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .regular, voiceChat: onlineIsVoiceChat) onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .regular, voiceChat: onlineIsVoiceChat)
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
@ -5070,9 +5062,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
backgroundColor = theme.itemBackgroundColor backgroundColor = theme.itemBackgroundColor
highlightedBackgroundColor = theme.itemHighlightedBackgroundColor highlightedBackgroundColor = theme.itemHighlightedBackgroundColor
} else { } else {
//TODO:localize backgroundColor = theme.pinnedItemBackgroundColor
backgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
//backgroundColor = theme.pinnedItemBackgroundColor
highlightedBackgroundColor = theme.pinnedItemHighlightedBackgroundColor highlightedBackgroundColor = theme.pinnedItemHighlightedBackgroundColor
} }
} else { } else {

View file

@ -3251,8 +3251,10 @@ public final class ChatListNode: ListView {
if entryCount - 1 - i < 0 { if entryCount - 1 - i < 0 {
continue continue
} }
if case .PeerEntry = transition.chatListView.filteredEntries[entryCount - 1 - i] { switch transition.chatListView.filteredEntries[entryCount - 1 - i] {
} else { case .PeerEntry, .GroupReferenceEntry:
break
default:
continue continue
} }
if case let .index(index) = transition.chatListView.filteredEntries[entryCount - 1 - i].sortIndex, case let .chatList(chatListIndex) = index, chatListIndex.pinningIndex != nil { if case let .index(index) = transition.chatListView.filteredEntries[entryCount - 1 - i].sortIndex, case let .chatList(chatListIndex) = index, chatListIndex.pinningIndex != nil {

View file

@ -142,7 +142,7 @@ private final class AuthorizationSequenceCountrySelectionNavigationContentNode:
self.cancel = cancel self.cancel = cancel
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme), strings: strings, fieldStyle: .modern) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme), presentationTheme: theme, strings: strings, fieldStyle: .modern)
let placeholderText = strings.Common_Search let placeholderText = strings.Common_Search
let searchBarFont = Font.regular(17.0) let searchBarFont = Font.regular(17.0)

View file

@ -980,7 +980,7 @@ private final class SearchNavigationContentNode: NavigationBarContentNode {
self.cancel = cancel self.cancel = cancel
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme), strings: strings, fieldStyle: .modern, cancelText: strings.Common_Done) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme), presentationTheme: theme, strings: strings, fieldStyle: .modern, cancelText: strings.Common_Done)
let placeholderText = placeholder?(strings) ?? strings.Common_Search let placeholderText = placeholder?(strings) ?? strings.Common_Search
let searchBarFont = Font.regular(17.0) let searchBarFont = Font.regular(17.0)
@ -1004,7 +1004,7 @@ private final class SearchNavigationContentNode: NavigationBarContentNode {
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: theme), strings: strings) self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: theme), presentationTheme: theme, strings: strings)
} }
func setQueryUpdated(_ f: @escaping (String, String?) -> Void) { func setQueryUpdated(_ f: @escaping (String, String?) -> Void) {

View file

@ -59,7 +59,7 @@ public final class HashtagSearchController: TelegramBaseController {
} }
self.presentationData = presentationData self.presentationData = presentationData
super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData), mediaAccessoryPanelVisibility: .specific(size: .compact), locationBroadcastPanelSource: .none, groupCallPanelSource: .none) super.init(context: context, navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass), mediaAccessoryPanelVisibility: .specific(size: .compact), locationBroadcastPanelSource: .none, groupCallPanelSource: .none)
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@ -87,7 +87,7 @@ public final class HashtagSearchController: TelegramBaseController {
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings { if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate) self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData, style: .glass), transition: .immediate)
self.controllerNode.updatePresentationData(self.presentationData) self.controllerNode.updatePresentationData(self.presentationData)
} }
} }

View file

@ -79,7 +79,7 @@ final class HashtagSearchNavigationContentNode: NavigationBarContentNode {
var initialQuery = initialQuery var initialQuery = initialQuery
initialQuery.removeFirst() initialQuery.removeFirst()
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), strings: strings, fieldStyle: .modern, icon: icon, displayBackground: false) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), presentationTheme: theme, strings: strings, fieldStyle: .modern, icon: icon, displayBackground: false)
self.searchBar.text = initialQuery self.searchBar.text = initialQuery
self.searchBar.placeholderString = NSAttributedString(string: strings.HashtagSearch_SearchPlaceholder, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor) self.searchBar.placeholderString = NSAttributedString(string: strings.HashtagSearch_SearchPlaceholder, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor)
@ -111,7 +111,7 @@ final class HashtagSearchNavigationContentNode: NavigationBarContentNode {
func updateTheme(_ theme: PresentationTheme) { func updateTheme(_ theme: PresentationTheme) {
self.theme = theme self.theme = theme
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), strings: self.strings) self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), presentationTheme: theme, strings: self.strings)
} }
func setQueryUpdated(_ f: @escaping (String) -> Void) { func setQueryUpdated(_ f: @escaping (String) -> Void) {

View file

@ -38,7 +38,7 @@ final class SearchNavigationContentNode: NavigationBarContentNode, ItemListContr
self.cancel = cancel self.cancel = cancel
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), strings: strings, fieldStyle: .modern, displayBackground: false) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), presentationTheme: theme, strings: strings, fieldStyle: .modern, displayBackground: false)
super.init() super.init()
@ -66,7 +66,7 @@ final class SearchNavigationContentNode: NavigationBarContentNode, ItemListContr
func updateTheme(_ theme: PresentationTheme) { func updateTheme(_ theme: PresentationTheme) {
self.theme = theme self.theme = theme
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: self.theme), strings: self.strings) self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: self.theme), presentationTheme: self.theme, strings: self.strings)
self.updatePlaceholder() self.updatePlaceholder()
} }

View file

@ -18,7 +18,7 @@ final class LocationSearchNavigationContentNode: NavigationBarContentNode {
self.presentationData = presentationData self.presentationData = presentationData
self.interaction = interaction self.interaction = interaction
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings, fieldStyle: .modern) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), presentationTheme: presentationData.theme, strings: presentationData.strings, fieldStyle: .modern)
self.searchBar.placeholderString = NSAttributedString(string: presentationData.strings.Map_Search, font: searchBarFont, textColor: presentationData.theme.rootController.navigationSearchBar.inputPlaceholderTextColor) self.searchBar.placeholderString = NSAttributedString(string: presentationData.strings.Map_Search, font: searchBarFont, textColor: presentationData.theme.rootController.navigationSearchBar.inputPlaceholderTextColor)
super.init() super.init()
@ -58,6 +58,6 @@ final class LocationSearchNavigationContentNode: NavigationBarContentNode {
func updatePresentationData(_ presentationData: PresentationData) { func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData self.presentationData = presentationData
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings) self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), presentationTheme: presentationData.theme, strings: presentationData.strings)
} }
} }

View file

@ -168,6 +168,7 @@ private final class ChannelDiscussionSearchNavigationContentNode: NavigationBarC
accent: theme.chat.inputPanel.panelControlAccentColor, accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor keyboard: theme.rootController.keyboardColor
), ),
presentationTheme: theme,
strings: strings, strings: strings,
fieldStyle: .inlineNavigation, fieldStyle: .inlineNavigation,
forceSeparator: false, forceSeparator: false,

View file

@ -83,6 +83,7 @@ final class GroupInfoSearchNavigationContentNode: NavigationBarContentNode, Item
accent: theme.chat.inputPanel.panelControlAccentColor, accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor keyboard: theme.rootController.keyboardColor
), ),
presentationTheme: theme,
strings: strings, strings: strings,
fieldStyle: .inlineNavigation, fieldStyle: .inlineNavigation,
forceSeparator: false, forceSeparator: false,

View file

@ -894,6 +894,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
public var tokensUpdated: (([SearchBarToken]) -> Void)? public var tokensUpdated: (([SearchBarToken]) -> Void)?
private let inlineSearchPlaceholder: SearchBarPlaceholderNode
private var inlineSearchPlaceholderContentsView: SearchBarPlaceholderContentView?
private let backgroundNode: NavigationBackgroundNode private let backgroundNode: NavigationBackgroundNode
private let separatorNode: ASDisplayNode private let separatorNode: ASDisplayNode
private let textBackgroundNode: ASDisplayNode private let textBackgroundNode: ASDisplayNode
@ -972,6 +975,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView { if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
takenSearchPlaceholderContentView.updateSearchIconVisibility(isVisible: !self.activity) takenSearchPlaceholderContentView.updateSearchIconVisibility(isVisible: !self.activity)
} }
if let inlineSearchPlaceholderContentsView = self.inlineSearchPlaceholderContentsView {
inlineSearchPlaceholderContentsView.updateSearchIconVisibility(isVisible: !self.activity)
}
} }
} }
} }
@ -999,14 +1005,21 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
public let fieldStyle: SearchBarStyle public let fieldStyle: SearchBarStyle
private let forceSeparator: Bool private let forceSeparator: Bool
private var theme: SearchBarNodeTheme? private var theme: SearchBarNodeTheme?
private var presentationTheme: PresentationTheme
private var strings: PresentationStrings? private var strings: PresentationStrings?
private let cancelText: String? private let cancelText: String?
public init(theme: SearchBarNodeTheme, strings: PresentationStrings, fieldStyle: SearchBarStyle = .legacy, icon: Icon = .loupe, forceSeparator: Bool = false, displayBackground: Bool = true, cancelText: String? = nil) { private var isAnimatingOut: Bool = false
public init(theme: SearchBarNodeTheme, presentationTheme: PresentationTheme, strings: PresentationStrings, fieldStyle: SearchBarStyle = .legacy, icon: Icon = .loupe, forceSeparator: Bool = false, displayBackground: Bool = true, cancelText: String? = nil) {
self.presentationTheme = presentationTheme
self.fieldStyle = fieldStyle self.fieldStyle = fieldStyle
self.forceSeparator = forceSeparator self.forceSeparator = forceSeparator
self.cancelText = cancelText self.cancelText = cancelText
self.icon = icon self.icon = icon
self.inlineSearchPlaceholder = SearchBarPlaceholderNode(fieldStyle: .glass)
self.backgroundNode = NavigationBackgroundNode(color: theme.background) self.backgroundNode = NavigationBackgroundNode(color: theme.background)
self.backgroundNode.isUserInteractionEnabled = false self.backgroundNode.isUserInteractionEnabled = false
@ -1043,7 +1056,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
super.init() super.init()
switch self.fieldStyle { switch self.fieldStyle {
case .glass, .inlineNavigation: case .glass:
break
case .inlineNavigation:
break break
case .legacy, .modern: case .legacy, .modern:
self.addSubnode(self.backgroundNode) self.addSubnode(self.backgroundNode)
@ -1085,11 +1100,11 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside) self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
self.clearButton.addTarget(self, action: #selector(self.clearPressed), forControlEvents: .touchUpInside) self.clearButton.addTarget(self, action: #selector(self.clearPressed), forControlEvents: .touchUpInside)
self.updateThemeAndStrings(theme: theme, strings: strings) self.updateThemeAndStrings(theme: theme, presentationTheme: presentationTheme, strings: strings)
self.updateIsEmpty(animated: false) self.updateIsEmpty(animated: false)
} }
public func updateThemeAndStrings(theme: SearchBarNodeTheme, strings: PresentationStrings) { public func updateThemeAndStrings(theme: SearchBarNodeTheme, presentationTheme: PresentationTheme, strings: PresentationStrings) {
if self.theme != theme || self.strings !== strings { if self.theme != theme || self.strings !== strings {
self.clearButton.accessibilityLabel = strings.WebSearch_RecentSectionClear self.clearButton.accessibilityLabel = strings.WebSearch_RecentSectionClear
self.cancelButton.accessibilityLabel = self.cancelText ?? strings.Common_Cancel self.cancelButton.accessibilityLabel = self.cancelText ?? strings.Common_Cancel
@ -1122,6 +1137,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
} }
self.theme = theme self.theme = theme
self.presentationTheme = presentationTheme
self.strings = strings self.strings = strings
if let (boundingSize, leftInset, rightInset) = self.validLayout { if let (boundingSize, leftInset, rightInset) = self.validLayout {
self.updateLayout(boundingSize: boundingSize, leftInset: leftInset, rightInset: rightInset, transition: .immediate) self.updateLayout(boundingSize: boundingSize, leftInset: leftInset, rightInset: rightInset, transition: .immediate)
@ -1184,6 +1200,45 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
transition.updateFrame(node: self.clearButton, frame: CGRect(origin: CGPoint(x: textBackgroundFrame.maxX - 6.0 - clearSize.width, y: textBackgroundFrame.minY + floor((textBackgroundFrame.size.height - clearSize.height) / 2.0)), size: clearSize)) transition.updateFrame(node: self.clearButton, frame: CGRect(origin: CGPoint(x: textBackgroundFrame.maxX - 6.0 - clearSize.width, y: textBackgroundFrame.minY + floor((textBackgroundFrame.size.height - clearSize.height) / 2.0)), size: clearSize))
self.textField.frame = textFrame self.textField.frame = textFrame
let searchPlaceholderFrame = CGRect(origin: CGPoint(x: 16.0, y: 0.0), size: CGSize(width: max(0.0, boundingSize.width - 16.0 * 2.0), height: 44.0))
if case .glass = self.fieldStyle, self.takenSearchPlaceholderContentView == nil {
transition.updateFrame(node: self.inlineSearchPlaceholder, frame: searchPlaceholderFrame)
if let theme = self.theme {
let _ = self.inlineSearchPlaceholder.updateLayout(
placeholderString: self.placeholderString,
compactPlaceholderString: self.placeholderString,
constrainedSize: searchPlaceholderFrame.size,
expansionProgress: 1.0,
iconColor: theme.inputIcon,
foregroundColor: self.presentationTheme.chat.inputPanel.panelControlColor,
backgroundColor: self.presentationTheme.rootController.navigationBar.opaqueBackgroundColor,
controlColor: self.presentationTheme.chat.inputPanel.panelControlColor,
transition: transition
)
if self.inlineSearchPlaceholderContentsView == nil {
let inlineSearchPlaceholderContentsView = self.inlineSearchPlaceholder.takeContents()
inlineSearchPlaceholderContentsView.onCancel = { [weak self] in
guard let self else {
return
}
self.cancel?()
}
self.inlineSearchPlaceholderContentsView = inlineSearchPlaceholderContentsView
self.view.insertSubview(inlineSearchPlaceholderContentsView, at: 0)
}
}
if let inlineSearchPlaceholderContentsView = self.inlineSearchPlaceholderContentsView {
inlineSearchPlaceholderContentsView.update(size: searchPlaceholderFrame.size, isActive: true, transition: transition)
transition.updateFrame(view: inlineSearchPlaceholderContentsView, frame: searchPlaceholderFrame)
}
}
if !self.isAnimatingOut, let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
transition.updateFrame(view: takenSearchPlaceholderContentView, frame: searchPlaceholderFrame)
takenSearchPlaceholderContentView.update(size: searchPlaceholderFrame.size, isActive: true, transition: transition)
}
} }
@objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) {
@ -1201,6 +1256,8 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
} }
public func animateIn(from node: SearchBarPlaceholderNode, duration: Double, timingFunction: String) { public func animateIn(from node: SearchBarPlaceholderNode, duration: Double, timingFunction: String) {
self.inlineSearchPlaceholder.isHidden = true
let takenSearchPlaceholderContentView = node.takeContents() let takenSearchPlaceholderContentView = node.takeContents()
takenSearchPlaceholderContentView.onCancel = { [weak self] in takenSearchPlaceholderContentView.onCancel = { [weak self] in
guard let self else { guard let self else {
@ -1210,6 +1267,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
} }
self.takenSearchPlaceholderContentView = takenSearchPlaceholderContentView self.takenSearchPlaceholderContentView = takenSearchPlaceholderContentView
self.view.insertSubview(takenSearchPlaceholderContentView, at: 0) self.view.insertSubview(takenSearchPlaceholderContentView, at: 0)
if let inlineSearchPlaceholderContentsView = self.inlineSearchPlaceholderContentsView {
inlineSearchPlaceholderContentsView.removeFromSuperview()
}
let sourceFrame = node.view.convert(node.bounds, to: self.view) let sourceFrame = node.view.convert(node.bounds, to: self.view)
let targetFrame = CGRect(origin: CGPoint(x: 16.0, y: 0.0), size: CGSize(width: max(0.0, self.bounds.width - 16.0 * 2.0), height: 44.0)) let targetFrame = CGRect(origin: CGPoint(x: 16.0, y: 0.0), size: CGSize(width: max(0.0, self.bounds.width - 16.0 * 2.0), height: 44.0))
@ -1271,6 +1331,8 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
} }
public func transitionOut(to node: SearchBarPlaceholderNode, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) { public func transitionOut(to node: SearchBarPlaceholderNode, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) {
self.isAnimatingOut = true
/*let targetTextBackgroundFrame = node.view.convert(node.backgroundView.frame, to: self.view) /*let targetTextBackgroundFrame = node.view.convert(node.backgroundView.frame, to: self.view)
let duration: Double = transition.isAnimated ? 0.5 : 0.0 let duration: Double = transition.isAnimated ? 0.5 : 0.0
@ -1531,6 +1593,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView { if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
takenSearchPlaceholderContentView.updatePlaceholderVisibility(isVisible: isEmpty) takenSearchPlaceholderContentView.updatePlaceholderVisibility(isVisible: isEmpty)
} }
self.inlineSearchPlaceholderContentsView?.updatePlaceholderVisibility(isVisible: isEmpty)
let clearIsHidden = (textIsEmpty && tokensEmpty) && self.prefixString == nil let clearIsHidden = (textIsEmpty && tokensEmpty) && self.prefixString == nil
transition.updateAlpha(node: self.clearButton.imageNode, alpha: clearIsHidden ? 0.0 : 1.0) transition.updateAlpha(node: self.clearButton.imageNode, alpha: clearIsHidden ? 0.0 : 1.0)

View file

@ -49,13 +49,15 @@ public final class SearchBarPlaceholderContentView: UIView {
} }
let fieldStyle: SearchBarStyle let fieldStyle: SearchBarStyle
let backgroundNode: ASDisplayNode? let plainBackgroundView: UIImageView
let glassBackgroundView: GlassBackgroundView? let glassBackgroundView: GlassBackgroundView?
private var fillBackgroundColor: UIColor private var fillBackgroundColor: UIColor
private var foregroundColor: UIColor private var foregroundColor: UIColor
private var iconColor: UIColor private var iconColor: UIColor
let iconNode: ASImageNode let iconNode: ASImageNode
let labelNode: TextNode let labelNode: TextNode
let plainIconNode: ASImageNode
let plainLabelNode: TextNode
private var close: (background: GlassBackgroundView, icon: UIImageView)? private var close: (background: GlassBackgroundView, icon: UIImageView)?
@ -72,20 +74,13 @@ public final class SearchBarPlaceholderContentView: UIView {
self.foregroundColor = UIColor(rgb: 0xededed) self.foregroundColor = UIColor(rgb: 0xededed)
self.iconColor = UIColor(rgb: 0x000000, alpha: 0.0) self.iconColor = UIColor(rgb: 0x000000, alpha: 0.0)
self.plainBackgroundView = UIImageView()
switch fieldStyle { switch fieldStyle {
case .legacy, .modern: case .legacy, .modern:
let backgroundNode = ASDisplayNode()
backgroundNode.isLayerBacked = false
backgroundNode.displaysAsynchronously = false
backgroundNode.backgroundColor = self.foregroundColor
backgroundNode.cornerRadius = self.fieldStyle.cornerDiameter / 2.0
self.backgroundNode = backgroundNode
self.glassBackgroundView = nil self.glassBackgroundView = nil
case .inlineNavigation, .glass: case .inlineNavigation, .glass:
self.glassBackgroundView = GlassBackgroundView() self.glassBackgroundView = GlassBackgroundView()
self.backgroundNode = nil
} }
self.iconNode = ASImageNode() self.iconNode = ASImageNode()
@ -96,20 +91,27 @@ public final class SearchBarPlaceholderContentView: UIView {
self.labelNode.isOpaque = false self.labelNode.isOpaque = false
self.labelNode.isUserInteractionEnabled = false self.labelNode.isUserInteractionEnabled = false
self.plainIconNode = ASImageNode()
self.plainIconNode.displaysAsynchronously = false
self.plainIconNode.displayWithoutProcessing = true
self.plainLabelNode = TextNode()
self.plainLabelNode.isOpaque = false
self.plainLabelNode.isUserInteractionEnabled = false
super.init(frame: CGRect()) super.init(frame: CGRect())
if let backgroundNode = self.backgroundNode { self.plainBackgroundView.isUserInteractionEnabled = true
backgroundNode.isUserInteractionEnabled = true self.addSubview(self.plainBackgroundView)
self.addSubview(backgroundNode.view)
} self.plainBackgroundView.addSubview(self.plainIconNode.view)
self.plainBackgroundView.addSubview(self.plainLabelNode.view)
if let glassBackgroundView = self.glassBackgroundView { if let glassBackgroundView = self.glassBackgroundView {
self.addSubview(glassBackgroundView) self.addSubview(glassBackgroundView)
glassBackgroundView.contentView.addSubview(self.iconNode.view) glassBackgroundView.contentView.addSubview(self.iconNode.view)
glassBackgroundView.contentView.addSubview(self.labelNode.view) glassBackgroundView.contentView.addSubview(self.labelNode.view)
} else {
self.addSubview(self.iconNode.view)
self.addSubview(self.labelNode.view)
} }
} }
@ -161,6 +163,7 @@ public final class SearchBarPlaceholderContentView: UIView {
private func updateLayout(params: Params, transition: ContainedViewLayoutTransition) -> CGFloat { private func updateLayout(params: Params, transition: ContainedViewLayoutTransition) -> CGFloat {
let labelLayout = TextNode.asyncLayout(self.labelNode) let labelLayout = TextNode.asyncLayout(self.labelNode)
let plainLabelLayout = TextNode.asyncLayout(self.plainLabelNode)
let currentForegroundColor = self.foregroundColor let currentForegroundColor = self.foregroundColor
let currentIconColor = self.iconColor let currentIconColor = self.iconColor
@ -172,6 +175,7 @@ public final class SearchBarPlaceholderContentView: UIView {
} }
let (labelLayoutResult, labelApply) = labelLayout(TextNodeLayoutArguments(attributedString: placeholderString, backgroundColor: .clear, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: params.constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (labelLayoutResult, labelApply) = labelLayout(TextNodeLayoutArguments(attributedString: placeholderString, backgroundColor: .clear, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: params.constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (_, plainLabelApply) = plainLabelLayout(TextNodeLayoutArguments(attributedString: placeholderString, backgroundColor: .clear, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: params.constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var updatedColor: UIColor? var updatedColor: UIColor?
var updatedIconImage: UIImage? var updatedIconImage: UIImage?
@ -185,19 +189,19 @@ public final class SearchBarPlaceholderContentView: UIView {
let height = params.constrainedSize.height * params.expansionProgress let height = params.constrainedSize.height * params.expansionProgress
let _ = labelApply() let _ = labelApply()
let _ = plainLabelApply()
self.fillBackgroundColor = params.backgroundColor self.fillBackgroundColor = params.backgroundColor
self.foregroundColor = params.foregroundColor self.foregroundColor = params.foregroundColor
self.iconColor = params.iconColor self.iconColor = params.iconColor
if let backgroundNode = self.backgroundNode { self.plainBackgroundView.isUserInteractionEnabled = params.expansionProgress > 0.9999
backgroundNode.isUserInteractionEnabled = params.expansionProgress > 0.9999
}
if let updatedColor, let backgroundNode = self.backgroundNode { if let updatedColor {
backgroundNode.backgroundColor = updatedColor self.plainBackgroundView.backgroundColor = updatedColor
} }
if let updatedIconImage { if let updatedIconImage {
self.iconNode.image = updatedIconImage self.iconNode.image = updatedIconImage
self.plainIconNode.image = updatedIconImage
} }
self.placeholderString = placeholderString self.placeholderString = placeholderString
@ -220,6 +224,7 @@ public final class SearchBarPlaceholderContentView: UIView {
iconX = floor((params.constrainedSize.width - totalWidth) / 2.0) iconX = floor((params.constrainedSize.width - totalWidth) / 2.0)
} }
transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: iconX, y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize)) transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: iconX, y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize))
transition.updateFrame(node: self.plainIconNode, frame: CGRect(origin: CGPoint(x: iconX, y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize))
} else { } else {
iconX = 12.0 iconX = 12.0
} }
@ -230,6 +235,7 @@ public final class SearchBarPlaceholderContentView: UIView {
let labelX: CGFloat = iconX + iconSize.width + spacing let labelX: CGFloat = iconX + iconSize.width + spacing
let labelFrame = CGRect(origin: CGPoint(x: labelX, y: floorToScreenPixels((height - labelLayoutResult.size.height) / 2.0) + textOffset), size: labelLayoutResult.size) let labelFrame = CGRect(origin: CGPoint(x: labelX, y: floorToScreenPixels((height - labelLayoutResult.size.height) / 2.0) + textOffset), size: labelLayoutResult.size)
transition.updateFrame(node: self.labelNode, frame: labelFrame) transition.updateFrame(node: self.labelNode, frame: labelFrame)
transition.updateFrame(node: self.plainLabelNode, frame: labelFrame)
var innerAlpha = max(0.0, params.expansionProgress - 0.77) / 0.23 var innerAlpha = max(0.0, params.expansionProgress - 0.77) / 0.23
if innerAlpha > 0.9999 { if innerAlpha > 0.9999 {
@ -241,27 +247,36 @@ public final class SearchBarPlaceholderContentView: UIView {
if !transition.isAnimated { if !transition.isAnimated {
self.labelNode.layer.removeAnimation(forKey: "opacity") self.labelNode.layer.removeAnimation(forKey: "opacity")
self.iconNode.layer.removeAnimation(forKey: "opacity") self.iconNode.layer.removeAnimation(forKey: "opacity")
self.plainLabelNode.layer.removeAnimation(forKey: "opacity")
self.plainIconNode.layer.removeAnimation(forKey: "opacity")
} }
transition.updateAlpha(node: self.labelNode, alpha: innerAlpha) transition.updateAlpha(node: self.labelNode, alpha: innerAlpha)
transition.updateAlpha(node: self.iconNode, alpha: innerAlpha) transition.updateAlpha(node: self.iconNode, alpha: innerAlpha)
transition.updateAlpha(node: self.plainLabelNode, alpha: innerAlpha)
transition.updateAlpha(node: self.plainIconNode, alpha: innerAlpha)
} }
let outerAlpha = min(0.3, params.expansionProgress) / 0.3 let outerAlpha = min(0.3, params.expansionProgress) / 0.3
let cornerRadius = min(self.fieldStyle.cornerDiameter / 2.0, height / 2.0) let cornerRadius = height * 0.5
if let backgroundNode = self.backgroundNode, backgroundNode.cornerRadius != cornerRadius { if self.plainBackgroundView.layer.cornerRadius != cornerRadius {
if !transition.isAnimated { if !transition.isAnimated {
backgroundNode.layer.removeAnimation(forKey: "cornerRadius") self.plainBackgroundView.layer.removeAnimation(forKey: "cornerRadius")
} }
transition.updateCornerRadius(node: backgroundNode, cornerRadius: cornerRadius) transition.updateCornerRadius(layer: self.plainBackgroundView.layer, cornerRadius: cornerRadius)
} }
if let backgroundNode = self.backgroundNode, backgroundNode.alpha != outerAlpha { var plainBackgroundAlpha = outerAlpha
if params.isActive {
plainBackgroundAlpha = 0.0
}
if self.plainBackgroundView.alpha != plainBackgroundAlpha {
if !transition.isAnimated { if !transition.isAnimated {
backgroundNode.layer.removeAnimation(forKey: "opacity") self.plainBackgroundView.layer.removeAnimation(forKey: "opacity")
} }
transition.updateAlpha(node: backgroundNode, alpha: outerAlpha) transition.updateAlpha(layer: self.plainBackgroundView.layer, alpha: plainBackgroundAlpha)
} }
var backgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: params.constrainedSize.width, height: height)) var backgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: params.constrainedSize.width, height: height))
@ -269,12 +284,12 @@ public final class SearchBarPlaceholderContentView: UIView {
backgroundFrame.size.width -= 44.0 + 8.0 backgroundFrame.size.width -= 44.0 + 8.0
} }
if let backgroundNode = self.backgroundNode, backgroundNode.frame != backgroundFrame { if self.plainBackgroundView.frame != backgroundFrame {
if !transition.isAnimated { if !transition.isAnimated {
backgroundNode.layer.removeAnimation(forKey: "position") self.plainBackgroundView.layer.removeAnimation(forKey: "position")
backgroundNode.layer.removeAnimation(forKey: "bounds") self.plainBackgroundView.layer.removeAnimation(forKey: "bounds")
} }
transition.updateFrame(node: backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: params.constrainedSize.width, height: height))) transition.updateFrame(view: self.plainBackgroundView, frame: CGRect(origin: CGPoint(), size: CGSize(width: params.constrainedSize.width, height: height)))
} }
if let glassBackgroundView = self.glassBackgroundView { if let glassBackgroundView = self.glassBackgroundView {
@ -284,6 +299,9 @@ public final class SearchBarPlaceholderContentView: UIView {
if backgroundFrame.height < 16.0 { if backgroundFrame.height < 16.0 {
backgroundAlpha = max(0.0, min(1.0, backgroundFrame.height / 16.0)) backgroundAlpha = max(0.0, min(1.0, backgroundFrame.height / 16.0))
} }
if !params.isActive {
backgroundAlpha = 0.0
}
ComponentTransition(transition).setAlpha(view: glassBackgroundView, alpha: backgroundAlpha) ComponentTransition(transition).setAlpha(view: glassBackgroundView, alpha: backgroundAlpha)
let isDark = params.backgroundColor.hsb.b < 0.5 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)) 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))
@ -372,10 +390,12 @@ public final class SearchBarPlaceholderContentView: UIView {
public func updatePlaceholderVisibility(isVisible: Bool) { public func updatePlaceholderVisibility(isVisible: Bool) {
self.labelNode.isHidden = !isVisible self.labelNode.isHidden = !isVisible
self.plainLabelNode.isHidden = !isVisible
} }
public func updateSearchIconVisibility(isVisible: Bool) { public func updateSearchIconVisibility(isVisible: Bool) {
self.iconNode.isHidden = !isVisible self.iconNode.isHidden = !isVisible
self.plainIconNode.isHidden = !isVisible
} }
} }
@ -408,12 +428,10 @@ public class SearchBarPlaceholderNode: ASDisplayNode {
private let contentView: SearchBarPlaceholderContentView private let contentView: SearchBarPlaceholderContentView
public var backgroundView: UIView { public var backgroundView: UIView {
if let backgroundNode = self.contentView.backgroundNode { if let glassBackgroundView = self.contentView.glassBackgroundView {
return backgroundNode.view
} else if let glassBackgroundView = self.contentView.glassBackgroundView {
return glassBackgroundView return glassBackgroundView
} else { } else {
preconditionFailure() return self.contentView.plainBackgroundView
} }
} }

View file

@ -57,7 +57,7 @@ public final class SearchDisplayController {
self.searchBarIsExternal = searchBarIsExternal self.searchBarIsExternal = searchBarIsExternal
if !searchBarIsExternal { if !searchBarIsExternal {
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: presentationData.theme, hasBackground: hasBackground, hasSeparator: hasSeparator, inline: inline), strings: presentationData.strings, fieldStyle: fieldStyle, forceSeparator: hasSeparator, displayBackground: hasBackground) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: presentationData.theme, hasBackground: hasBackground, hasSeparator: hasSeparator, inline: inline), presentationTheme: presentationData.theme, strings: presentationData.strings, fieldStyle: fieldStyle, forceSeparator: hasSeparator, displayBackground: hasBackground)
} }
self.backgroundNode = BackgroundNode() self.backgroundNode = BackgroundNode()
self.backgroundNode.allowsGroupOpacity = true self.backgroundNode.allowsGroupOpacity = true
@ -143,7 +143,7 @@ public final class SearchDisplayController {
public func updatePresentationData(_ presentationData: PresentationData) { public func updatePresentationData(_ presentationData: PresentationData) {
if !self.searchBarIsExternal { if !self.searchBarIsExternal {
self.searchBar?.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: self.hasSeparator, inline: self.inline), strings: presentationData.strings) self.searchBar?.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: self.hasSeparator, inline: self.inline), presentationTheme: presentationData.theme, strings: presentationData.strings)
} }
self.contentNode.updatePresentationData(presentationData) self.contentNode.updatePresentationData(presentationData)

View file

@ -988,7 +988,7 @@ extension StoreMessage {
} }
} }
if (flags & (1 << 17)) != 0 { if (flags & (1 << 19)) != 0 {
attributes.append(ContentRequiresValidationMessageAttribute()) attributes.append(ContentRequiresValidationMessageAttribute())
} }
@ -1174,7 +1174,7 @@ extension StoreMessage {
threadId = 1 threadId = 1
} }
if (flags & (1 << 17)) != 0 { if (flags & (1 << 19)) != 0 {
attributes.append(ContentRequiresValidationMessageAttribute()) attributes.append(ContentRequiresValidationMessageAttribute())
} }

View file

@ -62,7 +62,8 @@ public struct TelegramChatAdminRightsFlags: OptionSet, Hashable {
.canPostStories, .canPostStories,
.canEditStories, .canEditStories,
.canDeleteStories, .canDeleteStories,
.canManageDirect .canManageDirect,
.canBanUsers
] ]
public static func peerSpecific(peer: EnginePeer) -> TelegramChatAdminRightsFlags { public static func peerSpecific(peer: EnginePeer) -> TelegramChatAdminRightsFlags {

View file

@ -504,7 +504,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati
pinnedBadgeColor: UIColor(rgb: 0x767677), pinnedBadgeColor: UIColor(rgb: 0x767677),
pinnedSearchBarColor: UIColor(rgb: 0x272728), pinnedSearchBarColor: UIColor(rgb: 0x272728),
regularSearchBarColor: UIColor(rgb: 0x272728), regularSearchBarColor: UIColor(rgb: 0x272728),
sectionHeaderFillColor: UIColor(rgb: 0x1c1c1d), sectionHeaderFillColor: .black,
sectionHeaderTextColor: UIColor(rgb: 0xffffff), sectionHeaderTextColor: UIColor(rgb: 0xffffff),
verifiedIconFillColor: UIColor(rgb: 0xffffff), verifiedIconFillColor: UIColor(rgb: 0xffffff),
verifiedIconForegroundColor: UIColor(rgb: 0x000000), verifiedIconForegroundColor: UIColor(rgb: 0x000000),

View file

@ -714,7 +714,7 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres
pinnedBadgeColor: mainSecondaryTextColor.withAlphaComponent(0.5), pinnedBadgeColor: mainSecondaryTextColor.withAlphaComponent(0.5),
pinnedSearchBarColor: accentColor.withMultiplied(hue: 1.029, saturation: 0.609, brightness: 0.12), pinnedSearchBarColor: accentColor.withMultiplied(hue: 1.029, saturation: 0.609, brightness: 0.12),
regularSearchBarColor: accentColor.withMultiplied(hue: 1.029, saturation: 0.609, brightness: 0.12), regularSearchBarColor: accentColor.withMultiplied(hue: 1.029, saturation: 0.609, brightness: 0.12),
sectionHeaderFillColor: mainBackgroundColor, sectionHeaderFillColor: .black,
sectionHeaderTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), sectionHeaderTextColor: mainSecondaryTextColor.withAlphaComponent(0.5),
verifiedIconFillColor: accentColor, verifiedIconFillColor: accentColor,
verifiedIconForegroundColor: .white, verifiedIconForegroundColor: .white,

View file

@ -565,8 +565,8 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio
pinnedBadgeColor: UIColor(rgb: 0xb6b6bb), pinnedBadgeColor: UIColor(rgb: 0xb6b6bb),
pinnedSearchBarColor: UIColor(rgb: 0xe5e5e5), pinnedSearchBarColor: UIColor(rgb: 0xe5e5e5),
regularSearchBarColor: UIColor(rgb: 0xe9e9e9), regularSearchBarColor: UIColor(rgb: 0xe9e9e9),
sectionHeaderFillColor: UIColor(rgb: 0xf7f7f7), sectionHeaderFillColor: .white,
sectionHeaderTextColor: UIColor(rgb: 0x8e8e93), sectionHeaderTextColor: .black,
verifiedIconFillColor: defaultDayAccentColor, verifiedIconFillColor: defaultDayAccentColor,
verifiedIconForegroundColor: UIColor(rgb: 0xffffff), verifiedIconForegroundColor: UIColor(rgb: 0xffffff),
secretIconColor: UIColor(rgb: 0x00b12c), secretIconColor: UIColor(rgb: 0x00b12c),

View file

@ -25,7 +25,7 @@ final class ChatRecentActionsSearchNavigationContentNode: NavigationBarContentNo
self.cancel = cancel self.cancel = cancel
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), strings: strings, fieldStyle: .modern, displayBackground: false) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), presentationTheme: theme, strings: strings, fieldStyle: .modern, displayBackground: false)
let placeholderText = strings.Common_Search let placeholderText = strings.Common_Search
self.searchBar.placeholderString = NSAttributedString(string: placeholderText, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor) self.searchBar.placeholderString = NSAttributedString(string: placeholderText, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor)

View file

@ -64,6 +64,7 @@ public final class ChatSearchNavigationContentNode: NavigationBarContentNode {
accent: theme.chat.inputPanel.panelControlAccentColor, accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor keyboard: theme.rootController.keyboardColor
), ),
presentationTheme: theme,
strings: strings, strings: strings,
fieldStyle: .inlineNavigation, fieldStyle: .inlineNavigation,
forceSeparator: false, forceSeparator: false,
@ -246,6 +247,7 @@ public final class ChatSearchNavigationContentNode: NavigationBarContentNode {
accent: presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor, accent: presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor,
keyboard: presentationInterfaceState.theme.rootController.keyboardColor keyboard: presentationInterfaceState.theme.rootController.keyboardColor
), ),
presentationTheme: presentationInterfaceState.theme,
strings: presentationInterfaceState.strings strings: presentationInterfaceState.strings
) )

View file

@ -359,6 +359,9 @@ public final class ChatListNavigationBar: Component {
let searchOffsetFraction = clippedSearchOffset / searchOffsetDistance let searchOffsetFraction = clippedSearchOffset / searchOffsetDistance
searchContentNode.expansionProgress = 1.0 - searchOffsetFraction searchContentNode.expansionProgress = 1.0 - searchOffsetFraction
embeddedSearchBarExpansionHeight = 60.0 - floorToScreenPixels((1.0 - searchOffsetFraction) * searchSize.height) embeddedSearchBarExpansionHeight = 60.0 - floorToScreenPixels((1.0 - searchOffsetFraction) * searchSize.height)
if searchOffsetFraction > 0.0 {
searchFrame.origin.y -= (60.0 - 44.0) * 0.5 * searchOffsetFraction
}
searchFrameValue = searchFrame searchFrameValue = searchFrame
transition.setFrameWithAdditivePosition(view: searchContentNode.view, frame: searchFrame) transition.setFrameWithAdditivePosition(view: searchContentNode.view, frame: searchFrame)
@ -479,7 +482,7 @@ public final class ChatListNavigationBar: Component {
if component.statusBarHeight < 1.0 { if component.statusBarHeight < 1.0 {
headerContentY = 0.0 headerContentY = 0.0
} else { } else {
headerContentY = component.statusBarHeight + 5.0 headerContentY = component.statusBarHeight + 10.0
} }
} }
let headerContentFrame = CGRect(origin: CGPoint(x: 0.0, y: headerContentY), size: headerContentSize) let headerContentFrame = CGRect(origin: CGPoint(x: 0.0, y: headerContentY), size: headerContentSize)
@ -683,7 +686,7 @@ public final class ChatListNavigationBar: Component {
} }
} else { } else {
contentHeight += 44.0 contentHeight += 44.0
contentHeight += 8.0 contentHeight += 7.0
if component.search != nil { if component.search != nil {
contentHeight += navigationBarSearchContentHeight contentHeight += navigationBarSearchContentHeight
@ -696,8 +699,6 @@ public final class ChatListNavigationBar: Component {
transition.setFrame(view: disappearingHeaderPanelsView, frame: headerPanelsFrame) transition.setFrame(view: disappearingHeaderPanelsView, frame: headerPanelsFrame)
} }
if let headerPanels = component.headerPanels { if let headerPanels = component.headerPanels {
headersContentHeight += 4.0
let headerPanelsView: ComponentView<Empty> let headerPanelsView: ComponentView<Empty>
var headerPanelsTransition = transition var headerPanelsTransition = transition
if let current = self.headerPanelsView { if let current = self.headerPanelsView {

View file

@ -116,7 +116,7 @@ public final class NavigationButtonComponent: Component {
switch component.content { switch component.content {
case let .text(title, isBold): case let .text(title, isBold):
textString = NSAttributedString(string: title, font: isBold ? Font.bold(17.0) : Font.regular(17.0), textColor: theme.chat.inputPanel.panelControlColor) textString = NSAttributedString(string: title, font: isBold ? Font.bold(17.0) : Font.medium(17.0), textColor: theme.chat.inputPanel.panelControlColor)
case .more: case .more:
isMore = true isMore = true
case let .icon(imageNameValue): case let .icon(imageNameValue):
@ -140,7 +140,7 @@ public final class NavigationButtonComponent: Component {
textView.attributedText = textString textView.attributedText = textString
let textSize = textView.updateLayout(availableSize) let textSize = textView.updateLayout(availableSize)
let textInset: CGFloat = 10.0 let textInset: CGFloat = 12.0
size.width = max(44.0, textSize.width + textInset * 2.0) size.width = max(44.0, textSize.width + textInset * 2.0)
textView.frame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: floor((availableSize.height - textSize.height) / 2.0)), size: textSize) textView.frame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: floor((availableSize.height - textSize.height) / 2.0)), size: textSize)

View file

@ -1010,13 +1010,7 @@ public final class ChatTitleComponent: Component {
let containerSize = CGSize(width: contentSize.width + containerSideInset * 2.0, height: 44.0) let containerSize = CGSize(width: contentSize.width + containerSideInset * 2.0, height: 44.0)
let containerFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - containerSize.width) * 0.5), y: floorToScreenPixels((availableSize.height - containerSize.height) * 0.5)), size: containerSize) let containerFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - containerSize.width) * 0.5), y: floorToScreenPixels((availableSize.height - containerSize.height) * 0.5)), size: containerSize)
var titleFrame = CGRect(origin: CGPoint(x: floor((containerFrame.width - titleSize.width) * 0.5), y: floor((containerFrame.height - contentSize.height) * 0.5)), size: titleSize) let titleFrame = CGRect(origin: CGPoint(x: titleLeftIconsWidth + floor((containerFrame.width - titleSize.width - titleLeftIconsWidth - titleRightIconsWidth) * 0.5), y: floor((containerFrame.height - contentSize.height) * 0.5)), size: titleSize)
if titleFrame.origin.x + titleFrame.width + titleRightIconsWidth > containerFrame.width - containerSideInset {
titleFrame.origin.x = containerFrame.width - containerSideInset - titleFrame.width - titleRightIconsWidth
}
if titleFrame.origin.x - titleLeftIconsWidth < containerSideInset {
titleFrame.origin.x = containerSideInset + titleLeftIconsWidth
}
if let titleView = self.title.view { if let titleView = self.title.view {
if titleView.superview == nil { if titleView.superview == nil {
titleView.isUserInteractionEnabled = false titleView.isUserInteractionEnabled = false
@ -1130,6 +1124,8 @@ public final class ChatTitleComponent: Component {
if let backgroundView = self.backgroundView { if let backgroundView = self.backgroundView {
self.backgroundView = nil self.backgroundView = nil
backgroundView.removeFromSuperview() backgroundView.removeFromSuperview()
}
if self.contentContainer.superview !== self {
self.addSubview(self.contentContainer) self.addSubview(self.contentContainer)
} }
transition.setFrame(view: self.contentContainer, frame: containerFrame) transition.setFrame(view: self.contentContainer, frame: containerFrame)

View file

@ -77,33 +77,33 @@ public class EdgeEffectView: UIView {
} }
if blur { if blur {
let gradientMaskLayer = SimpleGradientLayer()
let baseGradientAlpha: CGFloat = 1.0
let numSteps = 8
let firstStep = 1
let firstLocation = 0.8
gradientMaskLayer.colors = (0 ..< numSteps).map { i in
if i < firstStep {
return UIColor(white: 1.0, alpha: 1.0).cgColor
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
let value: CGFloat = 1.0 - bezierPoint(0.42, 0.0, 0.58, 1.0, step)
return UIColor(white: 1.0, alpha: baseGradientAlpha * value).cgColor
}
}
gradientMaskLayer.locations = (0 ..< numSteps).map { i -> NSNumber in
if i < firstStep {
return 0.0 as NSNumber
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
return (firstLocation + (1.0 - firstLocation) * step) as NSNumber
}
}
let blurView: VariableBlurView let blurView: VariableBlurView
if let current = self.blurView { if let current = self.blurView {
blurView = current blurView = current
} else { } else {
let gradientMaskLayer = SimpleGradientLayer()
let baseGradientAlpha: CGFloat = 1.0
let numSteps = 8
let firstStep = 1
let firstLocation = 0.8
gradientMaskLayer.colors = (0 ..< numSteps).map { i in
if i < firstStep {
return UIColor(white: 1.0, alpha: 1.0).cgColor
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
let value: CGFloat = 1.0 - bezierPoint(0.42, 0.0, 0.58, 1.0, step)
return UIColor(white: 1.0, alpha: baseGradientAlpha * value).cgColor
}
}
gradientMaskLayer.locations = (0 ..< numSteps).map { i -> NSNumber in
if i < firstStep {
return 0.0 as NSNumber
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
return (firstLocation + (1.0 - firstLocation) * step) as NSNumber
}
}
blurView = VariableBlurView(gradientMask: self.contentMaskView.image ?? UIImage(), maxBlurRadius: 8.0) blurView = VariableBlurView(gradientMask: self.contentMaskView.image ?? UIImage(), maxBlurRadius: 8.0)
blurView.layer.mask = gradientMaskLayer blurView.layer.mask = gradientMaskLayer
self.insertSubview(blurView, at: 0) self.insertSubview(blurView, at: 0)

View file

@ -535,9 +535,12 @@ public class GlassBackgroundView: UIView {
if transition.animation.isImmediate { if transition.animation.isImmediate {
nativeView.effect = glassEffect nativeView.effect = glassEffect
} else { } else {
UIView.animate(withDuration: 0.2, animations: { if let glassEffect, let currentEffect = nativeView.effect as? UIGlassEffect, currentEffect.tintColor == glassEffect.tintColor, currentEffect.isInteractive == glassEffect.isInteractive {
nativeView.effect = glassEffect } else {
}) UIView.animate(withDuration: 0.15, animations: {
nativeView.effect = glassEffect
})
}
} }
} }

View file

@ -81,6 +81,7 @@ final class GroupStickerSearchNavigationContentNode: NavigationBarContentNode, I
accent: theme.chat.inputPanel.panelControlAccentColor, accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor keyboard: theme.rootController.keyboardColor
), ),
presentationTheme: theme,
strings: strings, strings: strings,
fieldStyle: .inlineNavigation, fieldStyle: .inlineNavigation,
forceSeparator: false, forceSeparator: false,
@ -127,7 +128,7 @@ final class GroupStickerSearchNavigationContentNode: NavigationBarContentNode, I
func updateTheme(_ theme: PresentationTheme) { func updateTheme(_ theme: PresentationTheme) {
self.theme = theme self.theme = theme
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: self.theme), strings: self.strings) self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: self.theme), presentationTheme: self.theme, strings: self.strings)
self.updatePlaceholder() self.updatePlaceholder()
} }

View file

@ -460,6 +460,7 @@ final class MiniAppListScreenComponent: Component {
let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false) let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false)
searchBarNode = SearchBarNode( searchBarNode = SearchBarNode(
theme: searchBarTheme, theme: searchBarTheme,
presentationTheme: environment.theme,
strings: environment.strings, strings: environment.strings,
fieldStyle: .modern, fieldStyle: .modern,
displayBackground: false displayBackground: false

View file

@ -151,7 +151,7 @@ private final class ItemComponent: Component {
if case let .item(item) = component.content, case .done = item.style { if case let .item(item) = component.content, case .done = item.style {
titleFont = Font.bold(17.0) titleFont = Font.bold(17.0)
} else { } else {
titleFont = Font.regular(17.0) titleFont = Font.medium(17.0)
} }
let title: ComponentView<Empty> let title: ComponentView<Empty>
@ -204,7 +204,7 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
private let isGlass: Bool private let isGlass: Bool
private func fontForCurrentState() -> UIFont { private func fontForCurrentState() -> UIFont {
return self.bold ? UIFont.boldSystemFont(ofSize: 17.0) : UIFont.systemFont(ofSize: 17.0) return self.bold ? Font.semibold(17.0) : Font.medium(17.0)
} }
private func attributesForCurrentState() -> [NSAttributedString.Key: AnyObject] { private func attributesForCurrentState() -> [NSAttributedString.Key: AnyObject] {
@ -711,7 +711,7 @@ public final class NavigationButtonNodeImpl: ContextControllerSourceNode, Naviga
var nodeInset: CGFloat = 0.0 var nodeInset: CGFloat = 0.0
if self.isGlass { if self.isGlass {
if node.image == nil && node.node == nil { if node.image == nil && node.node == nil {
nodeInset += 10.0 nodeInset += 12.0
} }
if nodeSize.width + nodeInset * 2.0 < 44.0 { if nodeSize.width + nodeInset * 2.0 < 44.0 {
nodeInset = floorToScreenPixels((44.0 - nodeSize.width) * 0.5) nodeInset = floorToScreenPixels((44.0 - nodeSize.width) * 0.5)

View file

@ -168,6 +168,7 @@ swift_library(
"//submodules/TelegramUI/Components/MediaManager/PeerMessagesMediaPlaylist", "//submodules/TelegramUI/Components/MediaManager/PeerMessagesMediaPlaylist",
"//submodules/TelegramUI/Components/TextFieldComponent", "//submodules/TelegramUI/Components/TextFieldComponent",
"//submodules/TelegramUI/Components/EdgeEffect", "//submodules/TelegramUI/Components/EdgeEffect",
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View file

@ -13,6 +13,23 @@ private enum MoreIconNodeState: Equatable {
case moreToSearch(Float) case moreToSearch(Float)
} }
private let glassBackArrowImage: UIImage? = {
let imageSize = CGSize(width: 44.0, height: 44.0)
let topRightPoint = CGPoint(x: 24.6, y: 14.0)
let centerPoint = CGPoint(x: 17.0, y: imageSize.height * 0.5)
return generateImage(imageSize, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setStrokeColor(UIColor.white.cgColor)
context.setLineWidth(2.0)
context.setLineCap(.round)
context.setLineJoin(.round)
context.move(to: topRightPoint)
context.addLine(to: centerPoint)
context.addLine(to: CGPoint(x: topRightPoint.x, y: size.height - topRightPoint.y))
context.strokePath()
})?.withRenderingMode(.alwaysTemplate)
}()
private final class MoreIconNode: ManagedAnimationNode { private final class MoreIconNode: ManagedAnimationNode {
private let duration: Double = 0.21 private let duration: Double = 0.21
private var iconState: MoreIconNodeState = .more private var iconState: MoreIconNodeState = .more
@ -124,14 +141,11 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
let contextSourceNode: ContextReferenceContentNode let contextSourceNode: ContextReferenceContentNode
private let textNode: ImmediateTextNode private let textNode: ImmediateTextNode
private let iconNode: ASImageNode private let iconNode: ASImageNode
private let backIconLayer: SimpleShapeLayer
private var animationNode: MoreIconNode? private var animationNode: MoreIconNode?
private let backgroundNode: NavigationBackgroundNode
private var key: PeerInfoHeaderNavigationButtonKey? private var key: PeerInfoHeaderNavigationButtonKey?
private var contentsColor: UIColor = .white private var contentsColor: UIColor = .white
private var canBeExpanded: Bool = false
var action: ((ASDisplayNode, ContextGesture?) -> Void)? var action: ((ASDisplayNode, ContextGesture?) -> Void)?
@ -146,27 +160,14 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
self.iconNode.displaysAsynchronously = false self.iconNode.displaysAsynchronously = false
self.iconNode.displayWithoutProcessing = true self.iconNode.displayWithoutProcessing = true
self.backIconLayer = SimpleShapeLayer() super.init(pointerStyle: .insetRectangle(0.0, 0.0))
self.backIconLayer.lineWidth = 3.0
self.backIconLayer.lineCap = .round
self.backIconLayer.lineJoin = .round
self.backIconLayer.strokeColor = UIColor.white.cgColor
self.backIconLayer.fillColor = nil
self.backIconLayer.isHidden = true
self.backIconLayer.path = try? convertSvgPath("M10.5,2 L1.5,11 L10.5,20 ")
self.backgroundNode = NavigationBackgroundNode(color: .clear, enableBlur: true)
super.init(pointerStyle: .insetRectangle(-8.0, 2.0))
self.isAccessibilityElement = true self.isAccessibilityElement = true
self.accessibilityTraits = .button self.accessibilityTraits = .button
self.containerNode.addSubnode(self.contextSourceNode) self.containerNode.addSubnode(self.contextSourceNode)
self.contextSourceNode.addSubnode(self.backgroundNode)
self.contextSourceNode.addSubnode(self.textNode) self.contextSourceNode.addSubnode(self.textNode)
self.contextSourceNode.addSubnode(self.iconNode) self.contextSourceNode.addSubnode(self.iconNode)
self.contextSourceNode.layer.addSublayer(self.backIconLayer)
self.addSubnode(self.containerNode) self.addSubnode(self.containerNode)
@ -178,10 +179,6 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
} }
self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside) self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside)
if isReduceTransparencyEnabled() {
self.backgroundNode.isHidden = true
}
} }
@objc private func pressed() { @objc private func pressed() {
@ -190,11 +187,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
} }
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
var boundingRect = self.bounds let boundingRect = self.bounds
if self.textNode.alpha != 0.0 {
boundingRect = boundingRect.union(self.textNode.frame)
}
boundingRect = boundingRect.insetBy(dx: -8.0, dy: -4.0)
if boundingRect.contains(point) { if boundingRect.contains(point) {
return super.hitTest(self.bounds.center, with: event) return super.hitTest(self.bounds.center, with: event)
} else { } else {
@ -202,31 +195,11 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
} }
} }
func updateContentsColor(backgroundColor: UIColor, contentsColor: UIColor, canBeExpanded: Bool, transition: ContainedViewLayoutTransition) { func updateContentsColor(contentsColor: UIColor, transition: ContainedViewLayoutTransition) {
self.contentsColor = contentsColor self.contentsColor = contentsColor
self.canBeExpanded = canBeExpanded
self.backgroundNode.updateColor(color: backgroundColor, transition: transition)
transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor) transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor)
transition.updateTintColor(view: self.iconNode.view, color: self.contentsColor) transition.updateTintColor(view: self.iconNode.view, color: self.contentsColor)
transition.updateStrokeColor(layer: self.backIconLayer, strokeColor: self.contentsColor)
switch self.key {
case .back:
transition.updateAlpha(layer: self.textNode.layer, alpha: canBeExpanded ? 1.0 : 0.0)
transition.updateTransformScale(node: self.textNode, scale: canBeExpanded ? 1.0 : 0.001)
var iconTransform = CATransform3DIdentity
iconTransform = CATransform3DScale(iconTransform, canBeExpanded ? 1.0 : 0.8, canBeExpanded ? 1.0 : 0.8, 1.0)
iconTransform = CATransform3DTranslate(iconTransform, canBeExpanded ? -7.0 : 0.0, 0.0, 0.0)
transition.updateTransform(node: self.iconNode, transform: CATransform3DGetAffineTransform(iconTransform))
transition.updateTransform(layer: self.backIconLayer, transform: CATransform3DGetAffineTransform(iconTransform))
transition.updateLineWidth(layer: self.backIconLayer, lineWidth: canBeExpanded ? 3.0 : 2.075)
default:
break
}
if let animationNode = self.animationNode { if let animationNode = self.animationNode {
transition.updateTintColor(layer: animationNode.imageNode.layer, color: self.contentsColor) transition.updateTintColor(layer: animationNode.imageNode.layer, color: self.contentsColor)
@ -239,7 +212,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
var iconOffset = CGPoint() var iconOffset = CGPoint()
switch key { switch key {
case .back: case .back:
iconOffset = CGPoint(x: -1.0, y: 0.0) iconOffset = CGPoint(x: 0.0, y: 0.0)
default: default:
break break
} }
@ -258,9 +231,9 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
var animationState: MoreIconNodeState = .more var animationState: MoreIconNodeState = .more
switch key { switch key {
case .back: case .back:
text = presentationData.strings.Common_Back text = ""
accessibilityText = presentationData.strings.Common_Back accessibilityText = presentationData.strings.Common_Back
icon = navigationBarBackArrowImage(color: .white) icon = glassBackArrowImage
case .edit: case .edit:
text = presentationData.strings.Common_Edit text = presentationData.strings.Common_Edit
accessibilityText = text accessibilityText = text
@ -323,7 +296,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
self.accessibilityLabel = accessibilityText self.accessibilityLabel = accessibilityText
self.containerNode.isGestureEnabled = isGestureEnabled self.containerNode.isGestureEnabled = isGestureEnabled
let font: UIFont = isBold ? Font.semibold(17.0) : Font.regular(17.0) let font: UIFont = isBold ? Font.semibold(17.0) : Font.medium(17.0)
self.textNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white) self.textNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white)
transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor) transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor)
@ -357,70 +330,39 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
textSize = self.textNode.bounds.size textSize = self.textNode.bounds.size
} }
let inset: CGFloat = 0.0 let textInset: CGFloat = 12.0
var textInset: CGFloat = 0.0
switch key {
case .back:
textInset += 11.0
default:
break
}
let resultSize: CGSize let resultSize: CGSize
let textFrame = CGRect(origin: CGPoint(x: inset + textInset, y: floor((height - textSize.height) / 2.0)), size: textSize) let textFrame = CGRect(origin: CGPoint(x: textInset, y: floor((height - textSize.height) / 2.0)), size: textSize)
self.textNode.position = textFrame.center self.textNode.position = textFrame.center
self.textNode.bounds = CGRect(origin: CGPoint(), size: textFrame.size) self.textNode.bounds = CGRect(origin: CGPoint(), size: textFrame.size)
if let animationNode = self.animationNode { if let animationNode = self.animationNode {
let animationSize = CGSize(width: 30.0, height: 30.0) let animationSize = CGSize(width: 30.0, height: 30.0)
animationNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - animationSize.height) / 2.0)), size: animationSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y) animationNode.frame = CGRect(origin: CGPoint(x: floor((height - animationSize.width) * 0.5), y: floor((height - animationSize.height) / 2.0)), size: animationSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y)
let size = CGSize(width: animationSize.width + inset * 2.0, height: height) let size = CGSize(width: height, height: height)
self.containerNode.frame = CGRect(origin: CGPoint(), size: size) self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size) self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size)
resultSize = size resultSize = size
} else if let image = self.iconNode.image { } else if let image = self.iconNode.image {
let iconFrame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size).offsetBy(dx: iconOffset.x, dy: iconOffset.y) let iconFrame = CGRect(origin: CGPoint(x: floor((height - image.size.width) * 0.5), y: floor((height - image.size.height) / 2.0)), size: image.size).offsetBy(dx: iconOffset.x, dy: iconOffset.y)
self.iconNode.position = iconFrame.center self.iconNode.position = iconFrame.center
self.iconNode.bounds = CGRect(origin: CGPoint(), size: iconFrame.size) self.iconNode.bounds = CGRect(origin: CGPoint(), size: iconFrame.size)
if case .back = key { let size = CGSize(width: height, height: height)
self.backIconLayer.position = iconFrame.center
self.backIconLayer.bounds = CGRect(origin: CGPoint(), size: iconFrame.size)
self.iconNode.isHidden = true
self.backIconLayer.isHidden = false
} else {
self.iconNode.isHidden = false
self.backIconLayer.isHidden = true
}
let size = CGSize(width: image.size.width + inset * 2.0, height: height)
self.containerNode.frame = CGRect(origin: CGPoint(), size: size) self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size) self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size)
resultSize = size resultSize = size
} else { } else {
let size = CGSize(width: textSize.width + inset * 2.0, height: height) let size = CGSize(width: textSize.width + textInset * 2.0, height: height)
self.containerNode.frame = CGRect(origin: CGPoint(), size: size) self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size) self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size)
resultSize = size resultSize = size
} }
let diameter: CGFloat = 32.0
let backgroundWidth: CGFloat
if self.iconNode.image != nil || self.animationNode != nil {
backgroundWidth = diameter
} else {
backgroundWidth = max(diameter, resultSize.width + 12.0 * 2.0)
}
let backgroundFrame = CGRect(origin: CGPoint(x: floor((resultSize.width - backgroundWidth) * 0.5), y: floor((resultSize.height - diameter) * 0.5)), size: CGSize(width: backgroundWidth, height: diameter))
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
self.backgroundNode.update(size: backgroundFrame.size, cornerRadius: diameter * 0.5, transition: transition)
self.hitTestSlop = UIEdgeInsets(top: -2.0, left: -12.0, bottom: -2.0, right: -12.0)
return resultSize return resultSize
} }
} }

View file

@ -4,6 +4,9 @@ import AsyncDisplayKit
import ContextUI import ContextUI
import TelegramPresentationData import TelegramPresentationData
import Display import Display
import ComponentFlow
import ComponentDisplayAdapters
import GlassBackgroundComponent
enum PeerInfoHeaderNavigationButtonKey { enum PeerInfoHeaderNavigationButtonKey {
case back case back
@ -24,101 +27,125 @@ enum PeerInfoHeaderNavigationButtonKey {
case postStory case postStory
} }
struct PeerInfoHeaderNavigationButtonSpec: Equatable { struct PeerInfoHeaderNavigationButtonSpec: Hashable {
let key: PeerInfoHeaderNavigationButtonKey let key: PeerInfoHeaderNavigationButtonKey
let isForExpandedView: Bool let isForExpandedView: Bool
} }
final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
private var presentationData: PresentationData? private var presentationData: PresentationData?
private(set) var leftButtonNodes: [PeerInfoHeaderNavigationButtonKey: PeerInfoHeaderNavigationButton] = [:]
private(set) var rightButtonNodes: [PeerInfoHeaderNavigationButtonKey: PeerInfoHeaderNavigationButton] = [:] private let backgroundContainer: GlassBackgroundContainerView
private let leftButtonsBackground: GlassBackgroundView
private let rightButtonsBackground: GlassBackgroundView
private let leftButtonsContainer: UIView
private let rightButtonsContainer: UIView
private(set) var leftButtonNodes: [PeerInfoHeaderNavigationButtonSpec: PeerInfoHeaderNavigationButton] = [:]
private(set) var rightButtonNodes: [PeerInfoHeaderNavigationButtonSpec: PeerInfoHeaderNavigationButton] = [:]
private var currentLeftButtons: [PeerInfoHeaderNavigationButtonSpec] = [] private var currentLeftButtons: [PeerInfoHeaderNavigationButtonSpec] = []
private var currentRightButtons: [PeerInfoHeaderNavigationButtonSpec] = [] private var currentRightButtons: [PeerInfoHeaderNavigationButtonSpec] = []
private var backgroundContentColor: UIColor = .clear private var backgroundContentColor: UIColor = .clear
private var isOverColoredContents: Bool = false
private var contentsColor: UIColor = .white private var contentsColor: UIColor = .white
private var canBeExpanded: Bool = false
var performAction: ((PeerInfoHeaderNavigationButtonKey, ContextReferenceContentNode?, ContextGesture?) -> Void)? var performAction: ((PeerInfoHeaderNavigationButtonKey, ContextReferenceContentNode?, ContextGesture?) -> Void)?
func updateContentsColor(backgroundContentColor: UIColor, contentsColor: UIColor, canBeExpanded: Bool, transition: ContainedViewLayoutTransition) { override init() {
self.backgroundContentColor = backgroundContentColor self.backgroundContainer = GlassBackgroundContainerView()
self.contentsColor = contentsColor self.leftButtonsBackground = GlassBackgroundView()
self.canBeExpanded = canBeExpanded self.rightButtonsBackground = GlassBackgroundView()
for (_, button) in self.leftButtonNodes { self.leftButtonsContainer = UIView()
button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition) self.leftButtonsContainer.clipsToBounds = true
transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: canBeExpanded ? -8.0 : 0.0, y: 0.0)) self.rightButtonsContainer = UIView()
self.rightButtonsContainer.clipsToBounds = true
super.init()
self.view.addSubview(self.backgroundContainer)
self.backgroundContainer.contentView.addSubview(self.leftButtonsBackground)
self.backgroundContainer.contentView.addSubview(self.rightButtonsBackground)
self.leftButtonsBackground.contentView.addSubview(self.leftButtonsContainer)
self.rightButtonsBackground.contentView.addSubview(self.rightButtonsContainer)
}
func updateContentsColor(backgroundContentColor: UIColor, contentsColor: UIColor, isOverColoredContents: Bool, transition: ContainedViewLayoutTransition) {
self.backgroundContentColor = backgroundContentColor
self.isOverColoredContents = isOverColoredContents
self.contentsColor = contentsColor
guard let presentationData = self.presentationData else {
return
}
let normalButtonContentsColor: UIColor = self.isOverColoredContents ? .white : presentationData.theme.chat.inputPanel.panelControlColor
let expandedButtonContentsColor: UIColor = presentationData.theme.chat.inputPanel.panelControlColor
for (spec, button) in self.leftButtonNodes {
button.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: transition)
} }
var accumulatedRightButtonOffset: CGFloat = canBeExpanded ? 16.0 : 0.0
for spec in self.currentRightButtons.reversed() { for spec in self.currentRightButtons.reversed() {
guard let button = self.rightButtonNodes[spec.key] else { guard let button = self.rightButtonNodes[spec] else {
continue continue
} }
button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition) button.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: transition)
if !spec.isForExpandedView { }
transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: accumulatedRightButtonOffset, y: 0.0)) for (spec, button) in self.rightButtonNodes {
if self.backgroundContentColor.alpha != 0.0 { if !self.currentRightButtons.contains(where: { $0 == spec }) {
accumulatedRightButtonOffset -= 6.0 button.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: transition)
}
}
}
for (key, button) in self.rightButtonNodes {
if !self.currentRightButtons.contains(where: { $0.key == key }) {
button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition)
transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: 0.0, y: 0.0))
} }
} }
self.updateBackgroundColors(transition: ComponentTransition(transition))
} }
func update(size: CGSize, presentationData: PresentationData, leftButtons: [PeerInfoHeaderNavigationButtonSpec], rightButtons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, shouldAnimateIn: Bool, transition: ContainedViewLayoutTransition) { func update(size: CGSize, presentationData: PresentationData, leftButtons: [PeerInfoHeaderNavigationButtonSpec], rightButtons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, shouldAnimateIn: Bool, transition: ContainedViewLayoutTransition) {
let sideInset: CGFloat = 24.0 transition.updateFrame(view: self.backgroundContainer, frame: CGRect(origin: CGPoint(), size: size))
let expandedSideInset: CGFloat = 16.0
let maximumExpandOffset: CGFloat = 14.0 let buttonHeight: CGFloat = 44.0
let expandOffset: CGFloat = -expandFraction * maximumExpandOffset
let sideInset: CGFloat = 16.0
var normalLeftButtonsWidth: CGFloat = 0.0
var expandedLeftButtonsWidth: CGFloat = 0.0
let maxBlur: CGFloat = 5.0
let normalButtonContentsColor: UIColor = self.isOverColoredContents ? .white : presentationData.theme.chat.inputPanel.panelControlColor
let expandedButtonContentsColor: UIColor = presentationData.theme.chat.inputPanel.panelControlColor
if self.currentLeftButtons != leftButtons || presentationData.strings !== self.presentationData?.strings { if self.currentLeftButtons != leftButtons || presentationData.strings !== self.presentationData?.strings {
self.currentLeftButtons = leftButtons self.currentLeftButtons = leftButtons
var nextRegularButtonOrigin = sideInset
var nextExpandedButtonOrigin = sideInset
for spec in leftButtons.reversed() { for spec in leftButtons.reversed() {
let buttonNode: PeerInfoHeaderNavigationButton let buttonNode: PeerInfoHeaderNavigationButton
var wasAdded = false var wasAdded = false
if let current = self.leftButtonNodes[spec.key] { if let current = self.leftButtonNodes[spec] {
buttonNode = current buttonNode = current
} else { } else {
wasAdded = true wasAdded = true
buttonNode = PeerInfoHeaderNavigationButton() buttonNode = PeerInfoHeaderNavigationButton()
self.leftButtonNodes[spec.key] = buttonNode self.leftButtonNodes[spec] = buttonNode
self.addSubnode(buttonNode) self.leftButtonsContainer.addSubview(buttonNode.view)
buttonNode.action = { [weak self] _, gesture in buttonNode.action = { [weak self] _, gesture in
guard let strongSelf = self, let buttonNode = strongSelf.leftButtonNodes[spec.key] else { guard let strongSelf = self, let buttonNode = strongSelf.leftButtonNodes[spec] else {
return return
} }
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture) strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
} }
} }
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: size.height) let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: buttonHeight)
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin let buttonFrame = CGRect(origin: CGPoint(x: spec.isForExpandedView ? expandedLeftButtonsWidth : normalLeftButtonsWidth, y: 0.0), size: buttonSize)
let buttonY: CGFloat
if case .back = spec.key {
buttonY = 0.0
} else {
buttonY = expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)
}
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin, y: buttonY), size: buttonSize)
nextButtonOrigin += buttonSize.width + 4.0
if spec.isForExpandedView { if spec.isForExpandedView {
nextExpandedButtonOrigin = nextButtonOrigin expandedLeftButtonsWidth += buttonSize.width
} else { } else {
nextRegularButtonOrigin = nextButtonOrigin normalLeftButtonsWidth += buttonSize.width
} }
let alphaFactor: CGFloat let alphaFactor: CGFloat
if case .back = spec.key { if case .back = spec.key {
@ -126,48 +153,40 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
} else { } else {
alphaFactor = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) alphaFactor = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
} }
if wasAdded { if wasAdded {
buttonNode.frame = buttonFrame buttonNode.frame = buttonFrame
buttonNode.alpha = 0.0 buttonNode.alpha = 0.0
ComponentTransition.immediate.setBlur(layer: buttonNode.layer, radius: maxBlur)
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: self.canBeExpanded, transition: .immediate) ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: 0.0)
buttonNode.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: .immediate)
transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: CGPoint(x: canBeExpanded ? -8.0 : 0.0, y: 0.0))
} else { } else {
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
} }
} }
var removeKeys: [PeerInfoHeaderNavigationButtonKey] = [] var removeKeys: [PeerInfoHeaderNavigationButtonSpec] = []
for (key, _) in self.leftButtonNodes { for (spec, _) in self.leftButtonNodes {
if !leftButtons.contains(where: { $0.key == key }) { if !leftButtons.contains(where: { $0 == spec }) {
removeKeys.append(key) removeKeys.append(spec)
} }
} }
for key in removeKeys { for spec in removeKeys {
if let buttonNode = self.leftButtonNodes.removeValue(forKey: key) { if let buttonNode = self.leftButtonNodes.removeValue(forKey: spec) {
buttonNode.removeFromSupernode() buttonNode.view.removeFromSuperview()
} }
} }
} else { } else {
var nextRegularButtonOrigin = sideInset
var nextExpandedButtonOrigin = sideInset
for spec in leftButtons.reversed() { for spec in leftButtons.reversed() {
if let buttonNode = self.leftButtonNodes[spec.key] { if let buttonNode = self.leftButtonNodes[spec] {
let buttonSize = buttonNode.bounds.size let buttonSize = buttonNode.bounds.size
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin let buttonFrame = CGRect(origin: CGPoint(x: spec.isForExpandedView ? expandedLeftButtonsWidth : normalLeftButtonsWidth, y: 0.0), size: buttonSize)
let buttonY: CGFloat
if case .back = spec.key {
buttonY = 0.0
} else {
buttonY = expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)
}
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin, y: buttonY), size: buttonSize)
nextButtonOrigin += buttonSize.width + 4.0
if spec.isForExpandedView { if spec.isForExpandedView {
nextExpandedButtonOrigin = nextButtonOrigin expandedLeftButtonsWidth += buttonSize.width
} else { } else {
nextRegularButtonOrigin = nextButtonOrigin normalLeftButtonsWidth += buttonSize.width
} }
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
let alphaFactor: CGFloat let alphaFactor: CGFloat
@ -182,16 +201,17 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
buttonTransition = .animated(duration: duration * 0.25, curve: curve) buttonTransition = .animated(duration: duration * 0.25, curve: curve)
} }
buttonTransition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) buttonTransition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
ComponentTransition(buttonTransition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
} }
} }
} }
var accumulatedRightButtonOffset: CGFloat = self.canBeExpanded ? 16.0 : 0.0 var normalRightButtonsWidth: CGFloat = 0.0
var expandedRightButtonsWidth: CGFloat = 0.0
if self.currentRightButtons != rightButtons || presentationData.strings !== self.presentationData?.strings { if self.currentRightButtons != rightButtons || presentationData.strings !== self.presentationData?.strings {
self.currentRightButtons = rightButtons self.currentRightButtons = rightButtons
var nextRegularButtonOrigin = size.width - sideInset - 8.0
var nextExpandedButtonOrigin = size.width - expandedSideInset
for spec in rightButtons.reversed() { for spec in rightButtons.reversed() {
let buttonNode: PeerInfoHeaderNavigationButton let buttonNode: PeerInfoHeaderNavigationButton
var wasAdded = false var wasAdded = false
@ -201,32 +221,30 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
key = .moreSearchSort key = .moreSearchSort
} }
if let current = self.rightButtonNodes[key] { if let current = self.rightButtonNodes[spec] {
buttonNode = current buttonNode = current
} else { } else {
wasAdded = true wasAdded = true
buttonNode = PeerInfoHeaderNavigationButton() buttonNode = PeerInfoHeaderNavigationButton()
self.rightButtonNodes[key] = buttonNode self.rightButtonNodes[spec] = buttonNode
self.addSubnode(buttonNode) self.rightButtonsContainer.addSubview(buttonNode.view)
} }
buttonNode.action = { [weak self] _, gesture in buttonNode.action = { [weak self] _, gesture in
guard let strongSelf = self, let buttonNode = strongSelf.rightButtonNodes[key] else { guard let strongSelf = self, let buttonNode = strongSelf.rightButtonNodes[spec] else {
return return
} }
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture) strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
} }
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: size.height) let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: buttonHeight)
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin let buttonFrame = CGRect(origin: CGPoint(x: spec.isForExpandedView ? expandedRightButtonsWidth : normalRightButtonsWidth, y: 0.0), size: buttonSize)
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize)
nextButtonOrigin -= buttonSize.width + 15.0
if spec.isForExpandedView { if spec.isForExpandedView {
nextExpandedButtonOrigin = nextButtonOrigin expandedRightButtonsWidth += buttonSize.width
} else { } else {
nextRegularButtonOrigin = nextButtonOrigin normalRightButtonsWidth += buttonSize.width
} }
let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
if wasAdded { if wasAdded {
buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: self.canBeExpanded, transition: .immediate) buttonNode.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: .immediate)
if shouldAnimateIn { if shouldAnimateIn {
if key == .moreSearchSort || key == .searchWithTags || key == .standaloneSearch { if key == .moreSearchSort || key == .searchWithTags || key == .standaloneSearch {
@ -236,62 +254,51 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
buttonNode.frame = buttonFrame buttonNode.frame = buttonFrame
buttonNode.alpha = 0.0 buttonNode.alpha = 0.0
ComponentTransition.immediate.setBlur(layer: buttonNode.layer, radius: maxBlur)
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
if !spec.isForExpandedView {
transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: CGPoint(x: accumulatedRightButtonOffset, y: 0.0))
if self.backgroundContentColor.alpha != 0.0 {
accumulatedRightButtonOffset -= 6.0
}
} else {
transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: .zero)
}
} else { } else {
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
} }
} }
var removeKeys: [PeerInfoHeaderNavigationButtonKey] = [] var removeKeys: [PeerInfoHeaderNavigationButtonSpec] = []
for (key, _) in self.rightButtonNodes { for (spec, _) in self.rightButtonNodes {
if key == .moreSearchSort { if spec.key == .moreSearchSort {
if !rightButtons.contains(where: { $0.key == .more || $0.key == .search || $0.key == .sort }) { if !rightButtons.contains(where: { $0.key == .more || $0.key == .search || $0.key == .sort }) {
removeKeys.append(key) removeKeys.append(spec)
} }
} else if !rightButtons.contains(where: { $0.key == key }) { } else if !rightButtons.contains(where: { $0 == spec }) {
removeKeys.append(key) removeKeys.append(spec)
} }
} }
for key in removeKeys { for spec in removeKeys {
if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) { if let buttonNode = self.rightButtonNodes.removeValue(forKey: spec) {
if key == .moreSearchSort || key == .searchWithTags || key == .standaloneSearch { if spec.key == .moreSearchSort || spec.key == .searchWithTags || spec.key == .standaloneSearch {
buttonNode.layer.animateAlpha(from: buttonNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonNode] _ in buttonNode.layer.animateAlpha(from: buttonNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonNode] _ in
buttonNode?.removeFromSupernode() buttonNode?.view.removeFromSuperview()
}) })
buttonNode.layer.animateScale(from: 1.0, to: 0.001, duration: 0.2, removeOnCompletion: false) buttonNode.layer.animateScale(from: 1.0, to: 0.001, duration: 0.2, removeOnCompletion: false)
} else { } else {
buttonNode.removeFromSupernode() buttonNode.view.removeFromSuperview()
} }
} }
} }
} else { } else {
var nextRegularButtonOrigin = size.width - sideInset - 8.0
var nextExpandedButtonOrigin = size.width - expandedSideInset
for spec in rightButtons.reversed() { for spec in rightButtons.reversed() {
var key = spec.key var key = spec.key
if key == .more || key == .search || key == .sort { if key == .more || key == .search || key == .sort {
key = .moreSearchSort key = .moreSearchSort
} }
if let buttonNode = self.rightButtonNodes[key] { if let buttonNode = self.rightButtonNodes[spec] {
let buttonSize = buttonNode.bounds.size let buttonSize = buttonNode.bounds.size
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin let buttonFrame = CGRect(origin: CGPoint(x: spec.isForExpandedView ? expandedRightButtonsWidth : normalRightButtonsWidth, y: 0.0), size: buttonSize)
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize)
nextButtonOrigin -= buttonSize.width + 15.0
if spec.isForExpandedView { if spec.isForExpandedView {
nextExpandedButtonOrigin = nextButtonOrigin expandedRightButtonsWidth += buttonSize.width
} else { } else {
nextRegularButtonOrigin = nextButtonOrigin normalRightButtonsWidth += buttonSize.width
} }
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
@ -301,9 +308,60 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
buttonTransition = .animated(duration: duration * 0.25, curve: curve) buttonTransition = .animated(duration: duration * 0.25, curve: curve)
} }
buttonTransition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) buttonTransition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
} }
} }
} }
self.presentationData = presentationData self.presentationData = presentationData
let buttonsY: CGFloat = floor((size.height - buttonHeight) * 0.5) + 2.0
let leftButtonsWidth = (1.0 - expandFraction) * normalLeftButtonsWidth + expandFraction * expandedLeftButtonsWidth
let rightButtonsWidth = (1.0 - expandFraction) * normalRightButtonsWidth + expandFraction * expandedRightButtonsWidth
var leftButtonsFrame = CGRect(origin: CGPoint(x: sideInset, y: buttonsY), size: CGSize(width: max(44.0, leftButtonsWidth), height: buttonHeight))
if leftButtonsWidth < 44.0 {
let leftFraction = leftButtonsWidth / 44.0
leftButtonsFrame.origin.x = floorToScreenPixels(leftFraction * sideInset + (1.0 - leftFraction) * (-44.0))
}
var rightButtonsFrame = CGRect(origin: CGPoint(x: size.width - sideInset - rightButtonsWidth, y: buttonsY), size: CGSize(width: max(44.0, rightButtonsWidth), height: buttonHeight))
if rightButtonsWidth < 44.0 {
let rightFraction = rightButtonsWidth / 44.0
rightButtonsFrame.origin.x = floorToScreenPixels(rightFraction * (size.width - sideInset - 44.0) + (1.0 - rightFraction) * size.width)
}
transition.updateFrame(view: self.leftButtonsBackground, frame: leftButtonsFrame)
transition.updateFrame(view: self.leftButtonsContainer, frame: CGRect(origin: CGPoint(), size: leftButtonsFrame.size))
self.leftButtonsContainer.layer.cornerRadius = leftButtonsFrame.height * 0.5
transition.updateFrame(view: self.rightButtonsBackground, frame: rightButtonsFrame)
transition.updateFrame(view: self.rightButtonsContainer, frame: CGRect(origin: CGPoint(), size: rightButtonsFrame.size))
self.rightButtonsContainer.layer.cornerRadius = rightButtonsFrame.height * 0.5
self.updateBackgroundColors(transition: ComponentTransition(transition))
}
private func updateBackgroundColors(transition: ComponentTransition) {
guard let presentationData = self.presentationData else {
return
}
let leftButtonsSize = self.leftButtonsBackground.bounds.size
let rightButtonsSize = self.rightButtonsBackground.bounds.size
let tintColor: GlassBackgroundView.TintColor
let tintIsDark: Bool
if self.isOverColoredContents {
tintColor = .init(kind: .custom, color: self.backgroundContentColor)
tintIsDark = presentationData.theme.overallDarkAppearance
} else {
tintColor = .init(kind: .panel, color: UIColor(white: presentationData.theme.overallDarkAppearance ? 0.0 : 1.0, alpha: 0.6))
tintIsDark = presentationData.theme.overallDarkAppearance
}
self.backgroundContainer.update(size: self.backgroundContainer.bounds.size, isDark: tintIsDark, transition: transition)
self.rightButtonsBackground.update(size: rightButtonsSize, cornerRadius: rightButtonsSize.height * 0.5, isDark: tintIsDark, tintColor: tintColor, isInteractive: true, transition: transition)
self.leftButtonsBackground.update(size: leftButtonsSize, cornerRadius: leftButtonsSize.height * 0.5, isDark: tintIsDark, tintColor: tintColor, isInteractive: true, transition: transition)
} }
} }

View file

@ -44,6 +44,7 @@ import ProfileLevelInfoScreen
import PlainButtonComponent import PlainButtonComponent
import BundleIconComponent import BundleIconComponent
import MarqueeComponent import MarqueeComponent
import EdgeEffect
final class PeerInfoHeaderNavigationTransition { final class PeerInfoHeaderNavigationTransition {
let sourceNavigationBar: NavigationBar let sourceNavigationBar: NavigationBar
@ -63,7 +64,7 @@ final class PeerInfoHeaderNavigationTransition {
} }
} }
final class PeerInfoHeaderRegularContentNode: ASDisplayNode { final class PeerInfoHeaderRegularContentNode: SparseNode {
} }
enum PeerInfoHeaderTextFieldNodeKey: Equatable { enum PeerInfoHeaderTextFieldNodeKey: Equatable {
@ -90,6 +91,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
private var state: PeerInfoState? private var state: PeerInfoState?
private var peer: Peer? private var peer: Peer?
private var threadData: MessageHistoryThreadData? private var threadData: MessageHistoryThreadData?
private var isSearching: Bool = false
private var avatarSize: CGFloat? private var avatarSize: CGFloat?
private let isOpenedFromChat: Bool private let isOpenedFromChat: Bool
@ -151,17 +153,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let usernameNode: MultiScaleTextNode let usernameNode: MultiScaleTextNode
var actionButtonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderActionButtonNode] = [:] var actionButtonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderActionButtonNode] = [:]
var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:] var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:]
let backgroundNode: NavigationBackgroundNode let panelsExpansionBackgroundView: UIView
let expandedBackgroundNode: NavigationBackgroundNode let headerEdgeEffectView: EdgeEffectView
let separatorNode: ASDisplayNode
let navigationBackgroundNode: ASDisplayNode
let navigationBackgroundBackgroundNode: ASDisplayNode
var navigationTitle: String? var navigationTitle: String?
let navigationTitleNode: ImmediateTextNode
let navigationSeparatorNode: ASDisplayNode
let navigationButtonContainer: PeerInfoHeaderNavigationButtonContainerNode let navigationButtonContainer: PeerInfoHeaderNavigationButtonContainerNode
let editingNavigationBackgroundNode: NavigationBackgroundNode let searchContainer: ASDisplayNode
let editingNavigationBackgroundSeparator: ASDisplayNode let searchBarContainer: SparseNode
let editingEdgeEffectView: EdgeEffectView
var musicBackground: UIView? var musicBackground: UIView?
var music: ComponentView<Empty>? var music: ComponentView<Empty>?
@ -286,30 +284,16 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.avatarOverlayNode = PeerInfoEditingAvatarOverlayNode(context: context) self.avatarOverlayNode = PeerInfoEditingAvatarOverlayNode(context: context)
self.avatarOverlayNode.isUserInteractionEnabled = false self.avatarOverlayNode.isUserInteractionEnabled = false
self.navigationBackgroundNode = ASDisplayNode()
self.navigationBackgroundNode.isHidden = true
self.navigationBackgroundNode.isUserInteractionEnabled = false
self.navigationBackgroundBackgroundNode = ASDisplayNode()
self.navigationBackgroundBackgroundNode.isUserInteractionEnabled = false
self.navigationTitleNode = ImmediateTextNode()
self.navigationSeparatorNode = ASDisplayNode()
self.navigationButtonContainer = PeerInfoHeaderNavigationButtonContainerNode() self.navigationButtonContainer = PeerInfoHeaderNavigationButtonContainerNode()
self.editingNavigationBackgroundNode = NavigationBackgroundNode(color: .clear, enableBlur: true) self.searchBarContainer = SparseNode()
self.editingNavigationBackgroundSeparator = ASDisplayNode() self.searchContainer = ASDisplayNode()
self.backgroundNode = NavigationBackgroundNode(color: .clear) self.panelsExpansionBackgroundView = UIView()
self.backgroundNode.isHidden = true self.headerEdgeEffectView = EdgeEffectView()
self.backgroundNode.isUserInteractionEnabled = false self.headerEdgeEffectView.isUserInteractionEnabled = false
self.expandedBackgroundNode = NavigationBackgroundNode(color: .clear)
self.expandedBackgroundNode.isHidden = false
self.expandedBackgroundNode.isUserInteractionEnabled = false
self.separatorNode = ASDisplayNode() self.editingEdgeEffectView = EdgeEffectView()
self.separatorNode.isLayerBacked = true self.editingEdgeEffectView.isUserInteractionEnabled = false
self.animationCache = context.animationCache self.animationCache = context.animationCache
self.animationRenderer = context.animationRenderer self.animationRenderer = context.animationRenderer
@ -320,8 +304,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self?.requestUpdateLayout?(false) self?.requestUpdateLayout?(false)
} }
self.addSubnode(self.backgroundNode) self.view.addSubview(self.panelsExpansionBackgroundView)
self.addSubnode(self.expandedBackgroundNode) self.addSubnode(self.searchContainer)
self.view.addSubview(self.headerEdgeEffectView)
self.view.addSubview(self.backgroundBannerView) self.view.addSubview(self.backgroundBannerView)
self.titleNodeContainer.addSubnode(self.titleNode) self.titleNodeContainer.addSubnode(self.titleNode)
self.subtitleNodeContainer.addSubnode(self.subtitleNode) self.subtitleNodeContainer.addSubnode(self.subtitleNode)
@ -346,14 +331,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.addSubnode(self.editingContentNode) self.addSubnode(self.editingContentNode)
self.addSubnode(self.avatarOverlayNode) self.addSubnode(self.avatarOverlayNode)
self.addSubnode(self.navigationBackgroundNode) self.view.addSubview(self.editingEdgeEffectView)
self.navigationBackgroundNode.addSubnode(self.navigationBackgroundBackgroundNode)
self.navigationBackgroundNode.addSubnode(self.navigationTitleNode)
self.navigationBackgroundNode.addSubnode(self.navigationSeparatorNode)
self.addSubnode(self.editingNavigationBackgroundNode)
self.addSubnode(self.editingNavigationBackgroundSeparator)
self.addSubnode(self.navigationButtonContainer) self.addSubnode(self.navigationButtonContainer)
self.addSubnode(self.separatorNode) self.addSubnode(self.searchBarContainer)
self.avatarListNode.avatarContainerNode.tapped = { [weak self] in self.avatarListNode.avatarContainerNode.tapped = { [weak self] in
self?.initiateAvatarExpansion(gallery: false, first: false) self?.initiateAvatarExpansion(gallery: false, first: false)
@ -509,7 +489,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
private var currentStatusIcon: CredibilityIcon? private var currentStatusIcon: CredibilityIcon?
private var currentPanelStatusData: PeerInfoStatusData? private var currentPanelStatusData: PeerInfoStatusData?
func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, paneContainerY: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, threadData: MessageHistoryThreadData?, peerNotificationSettings: TelegramPeerNotificationSettings?, threadNotificationSettings: TelegramPeerNotificationSettings?, globalNotificationSettings: EngineGlobalNotificationSettings?, statusData: PeerInfoStatusData?, panelStatusData: (PeerInfoStatusData?, PeerInfoStatusData?, CGFloat?), isSecretChat: Bool, isContact: Bool, isSettings: Bool, state: PeerInfoState, profileGiftsContext: ProfileGiftsContext?, screenData: PeerInfoScreenData?, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition, additive: Bool, animateHeader: Bool) -> CGFloat { func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, paneContainerY: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, threadData: MessageHistoryThreadData?, peerNotificationSettings: TelegramPeerNotificationSettings?, threadNotificationSettings: TelegramPeerNotificationSettings?, globalNotificationSettings: EngineGlobalNotificationSettings?, statusData: PeerInfoStatusData?, panelStatusData: (PeerInfoStatusData?, PeerInfoStatusData?, CGFloat?), isSecretChat: Bool, isContact: Bool, isSettings: Bool, state: PeerInfoState, profileGiftsContext: ProfileGiftsContext?, screenData: PeerInfoScreenData?, isSearching: Bool, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition, additive: Bool, animateHeader: Bool) -> CGFloat {
if self.appliedCustomNavigationContentNode !== self.customNavigationContentNode { if self.appliedCustomNavigationContentNode !== self.customNavigationContentNode {
if let previous = self.appliedCustomNavigationContentNode { if let previous = self.appliedCustomNavigationContentNode {
transition.updateAlpha(node: previous, alpha: 0.0, completion: { [weak previous] _ in transition.updateAlpha(node: previous, alpha: 0.0, completion: { [weak previous] _ in
@ -536,11 +516,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.state = state self.state = state
self.peer = peer self.peer = peer
self.threadData = threadData self.threadData = threadData
self.isSearching = isSearching
self.avatarListNode.listContainerNode.peer = peer.flatMap(EnginePeer.init) self.avatarListNode.listContainerNode.peer = peer.flatMap(EnginePeer.init)
let isFirstTime = self.validLayout == nil let isFirstTime = self.validLayout == nil
self.validLayout = (width, statusBarHeight, deviceMetrics) self.validLayout = (width, statusBarHeight, deviceMetrics)
self.searchBarContainer.isUserInteractionEnabled = isSearching
self.searchContainer.isUserInteractionEnabled = isSearching
let previousPanelStatusData = self.currentPanelStatusData let previousPanelStatusData = self.currentPanelStatusData
self.currentPanelStatusData = panelStatusData.0 self.currentPanelStatusData = panelStatusData.0
@ -637,7 +621,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
transition.updateAlpha(node: self.regularContentNode, alpha: (state.isEditing || self.customNavigationContentNode != nil) ? 0.0 : 1.0) transition.updateAlpha(node: self.regularContentNode, alpha: (state.isEditing || self.customNavigationContentNode != nil) ? 0.0 : 1.0)
if self.navigationTransition == nil { if self.navigationTransition == nil {
transition.updateAlpha(node: self.navigationButtonContainer, alpha: self.customNavigationContentNode != nil ? 0.0 : 1.0) transition.updateAlpha(node: self.navigationButtonContainer, alpha: (self.customNavigationContentNode != nil || isSearching) ? 0.0 : 1.0)
} }
self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0
@ -656,10 +640,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 22.0), size: CGSize(width: avatarSize, height: avatarSize)) let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 22.0), size: CGSize(width: avatarSize, height: avatarSize))
self.backgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
let headerBackgroundColor: UIColor = presentationData.theme.list.blocksBackgroundColor
let regularNavigationContentsAccentColor: UIColor = peer?.effectiveProfileColor != nil ? .white : presentationData.theme.list.itemAccentColor let regularNavigationContentsAccentColor: UIColor = peer?.effectiveProfileColor != nil ? .white : presentationData.theme.list.itemAccentColor
let collapsedHeaderNavigationContentsAccentColor = presentationData.theme.list.itemAccentColor let collapsedHeaderNavigationContentsAccentColor = presentationData.theme.list.itemAccentColor
let expandedAvatarNavigationContentsAccentColor: UIColor = .white let expandedAvatarNavigationContentsAccentColor: UIColor = .white
@ -674,7 +654,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let regularHeaderButtonBackgroundColor: UIColor let regularHeaderButtonBackgroundColor: UIColor
let collapsedHeaderButtonBackgroundColor: UIColor = .clear let collapsedHeaderButtonBackgroundColor: UIColor = .clear
let expandedAvatarHeaderButtonBackgroundColor: UIColor = UIColor(white: 1.0, alpha: 0.1) let expandedAvatarHeaderButtonBackgroundColor: UIColor = UIColor(white: 0.0, alpha: 0.5)
let regularContentButtonForegroundColor: UIColor = peer?.effectiveProfileColor != nil ? UIColor.white : presentationData.theme.list.itemAccentColor let regularContentButtonForegroundColor: UIColor = peer?.effectiveProfileColor != nil ? UIColor.white : presentationData.theme.list.itemAccentColor
let collapsedHeaderContentButtonForegroundColor = presentationData.theme.list.itemAccentColor let collapsedHeaderContentButtonForegroundColor = presentationData.theme.list.itemAccentColor
@ -745,61 +725,21 @@ final class PeerInfoHeaderNode: ASDisplayNode {
navigationTransition = animateHeader ? .animated(duration: 0.2, curve: .easeInOut) : .immediate navigationTransition = animateHeader ? .animated(duration: 0.2, curve: .easeInOut) : .immediate
} }
let editingEdgeEffectHeight: CGFloat = 40.0
let editingEdgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: navigationHeight + 10.0))
transition.updateFrame(view: self.editingEdgeEffectView, frame: editingEdgeEffectFrame)
self.editingEdgeEffectView.update(content: presentationData.theme.list.blocksBackgroundColor, blur: true, rect: editingEdgeEffectFrame, edge: .top, edgeSize: editingEdgeEffectHeight, transition: ComponentTransition(transition))
let editingBackgroundAlpha: CGFloat let editingBackgroundAlpha: CGFloat
if state.isEditing { if state.isEditing {
editingBackgroundAlpha = max(0.0, min(1.0, contentOffset / 20.0)) editingBackgroundAlpha = max(0.0, min(1.0, contentOffset / 20.0))
} else { } else {
editingBackgroundAlpha = 0.0 editingBackgroundAlpha = 0.0
} }
ComponentTransition(transition).setAlpha(view: self.editingEdgeEffectView, alpha: editingBackgroundAlpha)
self.editingNavigationBackgroundSeparator.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
self.editingNavigationBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
let editingNavigationBackgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: navigationHeight))
transition.updateFrame(node: self.editingNavigationBackgroundNode, frame: editingNavigationBackgroundFrame)
self.editingNavigationBackgroundNode.update(size: editingNavigationBackgroundFrame.size, transition: transition)
transition.updateFrame(node: self.editingNavigationBackgroundSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: editingNavigationBackgroundFrame.maxY), size: CGSize(width: width, height: UIScreenPixel)))
transition.updateAlpha(node: self.editingNavigationBackgroundNode, alpha: editingBackgroundAlpha)
transition.updateAlpha(node: self.editingNavigationBackgroundSeparator, alpha: editingBackgroundAlpha)
let backgroundBannerAlpha: CGFloat let backgroundBannerAlpha: CGFloat
var effectiveSeparatorAlpha: CGFloat do {
/*if let navigationTransition = self.navigationTransition {
transitionSourceHeight = navigationTransition.sourceNavigationBar.backgroundNode.bounds.height
transitionFraction = navigationTransition.fraction
innerBackgroundTransitionFraction = 0.0
backgroundBannerAlpha = 1.0
if let avatarNavigationNode = navigationTransition.sourceNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode {
if let statusView = avatarNavigationNode.statusView.view {
transitionSourceAvatarFrame = statusView.convert(statusView.bounds, to: navigationTransition.sourceNavigationBar.view)
} else {
transitionSourceAvatarFrame = avatarNavigationNode.avatarNode.view.convert(avatarNavigationNode.avatarNode.view.bounds, to: navigationTransition.sourceNavigationBar.view)
}
transition.updateAlpha(node: self.avatarListNode.avatarContainerNode.avatarNode, alpha: 1.0 - transitionFraction)
} else {
if deviceMetrics.hasDynamicIsland && statusBarHeight > 0.0 && !isLandscape {
transitionSourceAvatarFrame = CGRect(origin: CGPoint(x: avatarFrame.minX, y: -20.0), size: avatarFrame.size).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4)
} else {
transitionSourceAvatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: -avatarFrame.maxY).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4)
}
}
transitionSourceTitleFrame = navigationTransition.sourceTitleFrame
transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame
transition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: 1.0 - transitionFraction)
self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - transitionFraction), forceKeepBlur: true, transition: transition)
effectiveSeparatorAlpha = transitionFraction
if self.isAvatarExpanded, case .animated = transition, transitionFraction == 1.0 {
self.avatarListNode.animateAvatarCollapse(transition: transition)
}
self.avatarClippingNode.clipsToBounds = false
} else*/ do {
let backgroundTransitionStepDistance: CGFloat = 50.0 let backgroundTransitionStepDistance: CGFloat = 50.0
var backgroundTransitionDistance: CGFloat = navigationHeight + panelWithAvatarHeight - backgroundTransitionStepDistance var backgroundTransitionDistance: CGFloat = navigationHeight + panelWithAvatarHeight - backgroundTransitionStepDistance
if self.isSettings || self.isMyProfile { if self.isSettings || self.isMyProfile {
@ -812,9 +752,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
innerBackgroundTransitionFraction = max(0.0, min(1.0, contentOffset / backgroundTransitionStepDistance)) innerBackgroundTransitionFraction = max(0.0, min(1.0, contentOffset / backgroundTransitionStepDistance))
} }
self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - innerBackgroundTransitionFraction), forceKeepBlur: true, transition: transition)
navigationTransition.updateAlpha(node: self.expandedBackgroundNode, alpha: state.isEditing ? 0.0 : 1.0)
if state.isEditing { if state.isEditing {
backgroundBannerAlpha = 0.0 backgroundBannerAlpha = 0.0
} else { } else {
@ -826,8 +763,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} }
navigationTransition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: backgroundBannerAlpha) navigationTransition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: backgroundBannerAlpha)
effectiveSeparatorAlpha = innerBackgroundTransitionFraction
self.avatarClippingNode.clipsToBounds = true self.avatarClippingNode.clipsToBounds = true
} }
@ -1161,7 +1096,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.titleExpandedVerifiedIconSize = expandedIconSize self.titleExpandedVerifiedIconSize = expandedIconSize
} }
self.navigationButtonContainer.updateContentsColor(backgroundContentColor: headerButtonBackgroundColor, contentsColor: navigationContentsAccentColor, canBeExpanded: navigationContentsCanBeExpanded, transition: navigationTransition) var actualNavigationContentsColor = navigationContentsAccentColor
actualNavigationContentsColor = presentationData.theme.chat.inputPanel.panelControlColor
self.navigationButtonContainer.updateContentsColor(backgroundContentColor: headerButtonBackgroundColor, contentsColor: actualNavigationContentsColor, isOverColoredContents: !navigationContentsCanBeExpanded, transition: navigationTransition)
self.titleNode.updateTintColor(color: navigationContentsPrimaryColor, transition: navigationTransition) self.titleNode.updateTintColor(color: navigationContentsPrimaryColor, transition: navigationTransition)
self.subtitleNode.updateTintColor(color: navigationContentsSecondaryColor, transition: navigationTransition) self.subtitleNode.updateTintColor(color: navigationContentsSecondaryColor, transition: navigationTransition)
@ -1189,25 +1127,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.avatarListNode.listContainerNode.currentItemNode?.updateTransitionFraction(transitionFraction, transition: transition) self.avatarListNode.listContainerNode.currentItemNode?.updateTransitionFraction(transitionFraction, transition: transition)
self.avatarOverlayNode.updateTransitionFraction(transitionFraction, transition: transition) self.avatarOverlayNode.updateTransitionFraction(transitionFraction, transition: transition)
if self.navigationTitle != presentationData.strings.EditProfile_Title || themeUpdated {
self.navigationTitleNode.attributedText = NSAttributedString(string: presentationData.strings.EditProfile_Title, font: Font.semibold(17.0), textColor: .white)
}
let navigationTitleSize = self.navigationTitleNode.updateLayout(CGSize(width: width, height: navigationHeight))
self.navigationTitleNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - navigationTitleSize.width) / 2.0), y: navigationHeight - 44.0 + floorToScreenPixels((44.0 - navigationTitleSize.height) / 2.0)), size: navigationTitleSize)
self.navigationBackgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: navigationHeight))
self.navigationBackgroundBackgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: navigationHeight))
self.navigationSeparatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: navigationHeight), size: CGSize(width: width, height: UIScreenPixel))
self.navigationBackgroundBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.opaqueBackgroundColor
self.navigationSeparatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
let navigationSeparatorAlpha: CGFloat = 0.0
transition.updateAlpha(node: self.navigationBackgroundBackgroundNode, alpha: 1.0 - navigationSeparatorAlpha)
transition.updateAlpha(node: self.navigationSeparatorNode, alpha: navigationSeparatorAlpha)
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
let expandedAvatarControlsHeight: CGFloat = 61.0 let expandedAvatarControlsHeight: CGFloat = 61.0
var expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight) var expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight)
if self.isSettings || self.isMyProfile { if self.isSettings || self.isMyProfile {
@ -1638,7 +1557,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let singleTitleLockOffset: CGFloat = ((peer?.id == self.context.account.peerId && !self.isMyProfile) || subtitleSize.height.isZero) ? 8.0 : 0.0 let singleTitleLockOffset: CGFloat = ((peer?.id == self.context.account.peerId && !self.isMyProfile) || subtitleSize.height.isZero) ? 8.0 : 0.0
let titleLockOffset: CGFloat = 7.0 + singleTitleLockOffset let titleLockOffset: CGFloat = 16.0 + singleTitleLockOffset
let titleMaxLockOffset: CGFloat = 7.0 let titleMaxLockOffset: CGFloat = 7.0
let titleOffset: CGFloat let titleOffset: CGFloat
let titleCollapseFraction: CGFloat let titleCollapseFraction: CGFloat
@ -1697,38 +1616,37 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let paneAreaExpansionDistance: CGFloat = 32.0 let paneAreaExpansionDistance: CGFloat = 32.0
let effectiveAreaExpansionFraction: CGFloat let effectiveAreaExpansionFraction: CGFloat
let realAreaExpansionFraction: CGFloat
if state.isEditing { if state.isEditing {
effectiveAreaExpansionFraction = 0.0 effectiveAreaExpansionFraction = 0.0
realAreaExpansionFraction = effectiveAreaExpansionFraction
} else if isSettings || isMyProfile { } else if isSettings || isMyProfile {
var paneAreaExpansionDelta = (self.frame.maxY - navigationHeight) - contentOffset var paneAreaExpansionDelta = (self.frame.maxY - navigationHeight) - contentOffset
paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance))
effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
do {
var paneAreaExpansionDelta = (paneContainerY - navigationHeight) - contentOffset
paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance))
realAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
}
} else { } else {
var paneAreaExpansionDelta = (paneContainerY - navigationHeight) - contentOffset var paneAreaExpansionDelta = (paneContainerY - navigationHeight) - contentOffset
paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance))
effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
realAreaExpansionFraction = effectiveAreaExpansionFraction
} }
let secondarySeparatorAlpha = 1.0 - effectiveAreaExpansionFraction
if self.navigationTransition == nil && !self.isSettings && effectiveSeparatorAlpha == 1.0 && secondarySeparatorAlpha < 1.0 {
effectiveSeparatorAlpha = secondarySeparatorAlpha
}
if self.customNavigationContentNode != nil {
effectiveSeparatorAlpha = 0.0
}
if state.isEditing {
effectiveSeparatorAlpha = 0.0
}
transition.updateAlpha(node: self.separatorNode, alpha: effectiveSeparatorAlpha)
self.titleNode.update(stateFractions: [ self.titleNode.update(stateFractions: [
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0, TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0 TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
], transition: transition) ], transition: transition)
let subtitleAlpha: CGFloat transition.updateAlpha(node: self.titleNode, alpha: isSearching ? 0.0 : 1.0)
var subtitleAlpha: CGFloat
var subtitleOffset: CGFloat = 0.0 var subtitleOffset: CGFloat = 0.0
let panelSubtitleAlpha: CGFloat var panelSubtitleAlpha: CGFloat
var panelSubtitleOffset: CGFloat = 0.0 var panelSubtitleOffset: CGFloat = 0.0
if self.isSettings { if self.isSettings {
subtitleAlpha = 1.0 - titleCollapseFraction subtitleAlpha = 1.0 - titleCollapseFraction
@ -1755,6 +1673,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} }
} }
} }
if isSearching {
subtitleAlpha = 0.0
panelSubtitleAlpha = 0.0
}
self.subtitleNode.update(stateFractions: [ self.subtitleNode.update(stateFractions: [
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0, TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0 TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
@ -2465,18 +2389,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} }
let backgroundFrame: CGRect let backgroundFrame: CGRect
let separatorFrame: CGRect
var resolvedHeight: CGFloat var resolvedHeight: CGFloat
if state.isEditing { if state.isEditing {
resolvedHeight = editingContentHeight resolvedHeight = editingContentHeight
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + max(navigationHeight, resolvedHeight - contentOffset)), size: CGSize(width: width, height: 2000.0)) backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + max(navigationHeight, resolvedHeight - contentOffset)), size: CGSize(width: width, height: 2000.0))
separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: max(navigationHeight, resolvedHeight - contentOffset)), size: CGSize(width: width, height: UIScreenPixel))
} else { } else {
resolvedHeight = resolvedRegularHeight resolvedHeight = resolvedRegularHeight
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + apparentHeight), size: CGSize(width: width, height: 2000.0)) backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + apparentHeight), size: CGSize(width: width, height: 2000.0))
separatorFrame = CGRect(origin: CGPoint(x: 0.0, y: apparentHeight), size: CGSize(width: width, height: UIScreenPixel))
} }
transition.updateFrame(node: self.regularContentNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: resolvedHeight))) transition.updateFrame(node: self.regularContentNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: resolvedHeight)))
@ -2582,20 +2503,29 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} }
} }
let edgeEffectHeight: CGFloat = 40.0
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: backgroundFrame.width, height: navigationHeight + 10.0))
let panelsExpansionBackgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + paneContainerY - contentOffset), size: CGSize(width: width, height: 2000.0))
if additive { if additive {
transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame) transition.updateFrameAdditive(layer: self.headerEdgeEffectView.layer, frame: edgeEffectFrame)
self.backgroundNode.update(size: self.backgroundNode.bounds.size, transition: transition) transition.updateFrameAdditive(view: self.panelsExpansionBackgroundView, frame: panelsExpansionBackgroundFrame)
transition.updateFrameAdditive(node: self.expandedBackgroundNode, frame: backgroundFrame)
self.expandedBackgroundNode.update(size: self.expandedBackgroundNode.bounds.size, transition: transition)
transition.updateFrameAdditive(node: self.separatorNode, frame: separatorFrame)
} else { } else {
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) transition.updateFrame(view: self.headerEdgeEffectView, frame: edgeEffectFrame)
self.backgroundNode.update(size: self.backgroundNode.bounds.size, transition: transition) transition.updateFrame(view: self.panelsExpansionBackgroundView, frame: panelsExpansionBackgroundFrame)
transition.updateFrame(node: self.expandedBackgroundNode, frame: backgroundFrame)
self.expandedBackgroundNode.update(size: self.expandedBackgroundNode.bounds.size, transition: transition)
transition.updateFrame(node: self.separatorNode, frame: separatorFrame)
} }
self.panelsExpansionBackgroundView.backgroundColor = presentationData.theme.rootController.navigationBar.opaqueBackgroundColor
transition.updateAlpha(layer: self.panelsExpansionBackgroundView.layer, alpha: realAreaExpansionFraction)
if isSettings {
self.panelsExpansionBackgroundView.isHidden = true
}
self.headerEdgeEffectView.update(content: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor, blur: true, rect: edgeEffectFrame, edge: .top, edgeSize: edgeEffectHeight, transition: ComponentTransition(transition))
navigationTransition.updateAlpha(layer: self.headerEdgeEffectView.layer, alpha: state.isEditing ? 0.0 : 1.0)
if !state.isEditing { if !state.isEditing {
if !isSettings && !isMyProfile { if !isSettings && !isMyProfile {
if self.isAvatarExpanded { if self.isAvatarExpanded {
@ -2775,8 +2705,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
guard let result = super.hitTest(point, with: event) else { guard let result = super.hitTest(point, with: event) else {
return nil return nil
} }
if !self.backgroundNode.frame.contains(point) {
return nil if self.isSearching {
if !result.isDescendant(of: self.searchBarContainer.view) && !result.isDescendant(of: self.searchContainer.view) {
return self.view
}
return result
} }
if let customNavigationContentNode = self.customNavigationContentNode { if let customNavigationContentNode = self.customNavigationContentNode {

View file

@ -10622,7 +10622,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
switch status { switch status {
case .available: case .available:
var cameraTransitionIn: StoryCameraTransitionIn? var cameraTransitionIn: StoryCameraTransitionIn?
if let rightButton = self.headerNode.navigationButtonContainer.rightButtonNodes[.postStory] { if let rightButton = self.headerNode.navigationButtonContainer.rightButtonNodes.first(where: { $0.key.key == .postStory })?.value {
cameraTransitionIn = StoryCameraTransitionIn( cameraTransitionIn = StoryCameraTransitionIn(
sourceView: rightButton.view, sourceView: rightButton.view,
sourceRect: rightButton.view.bounds, sourceRect: rightButton.view.bounds,
@ -11452,7 +11452,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
if self.isSettings { if self.isSettings {
if let settings = self.data?.globalSettings { if let settings = self.data?.globalSettings {
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Settings_Search, hasBackground: true, hasSeparator: true, contentNode: SettingsSearchContainerNode(context: self.context, openResult: { [weak self] result in self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .navigation, placeholder: self.presentationData.strings.Settings_Search, hasBackground: true, hasSeparator: true, contentNode: SettingsSearchContainerNode(context: self.context, openResult: { [weak self] result in
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
result.present(strongSelf.context, navigationController, { [weak self] mode, controller in result.present(strongSelf.context, navigationController, { [weak self] mode, controller in
if let strongSelf = self { if let strongSelf = self {
@ -11482,7 +11482,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, searchBarIsExternal: true) }, searchBarIsExternal: true)
} }
} else if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .members = currentPaneKey { } else if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .members = currentPaneKey {
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, hasBackground: true, hasSeparator: true, contentNode: ChannelMembersSearchContainerNode(context: self.context, forceTheme: nil, peerId: self.peerId, mode: .searchMembers, filters: [], searchContext: self.groupMembersSearchContext, openPeer: { [weak self] peer, participant in self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .navigation, placeholder: self.presentationData.strings.Common_Search, hasBackground: true, hasSeparator: true, contentNode: ChannelMembersSearchContainerNode(context: self.context, forceTheme: nil, peerId: self.peerId, mode: .searchMembers, filters: [], searchContext: self.groupMembersSearchContext, openPeer: { [weak self] peer, participant in
self?.openPeer(peerId: peer.id, navigation: .info(nil)) self?.openPeer(peerId: peer.id, navigation: .info(nil))
}, updateActivity: { _ in }, updateActivity: { _ in
}, pushController: { [weak self] c in }, pushController: { [weak self] c in
@ -11583,9 +11583,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
} }
} }
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, hasBackground: true, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.peerId, threadId: self.chatLocation.threadId, tagMask: tagMask, interfaceInteraction: self.chatInterfaceInteraction), cancel: { [weak self] in self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .navigation, placeholder: self.presentationData.strings.Common_Search, hasBackground: false, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.peerId, threadId: self.chatLocation.threadId, tagMask: tagMask, interfaceInteraction: self.chatInterfaceInteraction), cancel: { [weak self] in
self?.deactivateSearch() self?.deactivateSearch()
}) }, fieldStyle: .glass)
} }
let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut) let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut)
@ -11595,8 +11595,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
self.searchDisplayController?.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate) self.searchDisplayController?.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self] subnode, isSearchBar in self.searchDisplayController?.activate(insertSubnode: { [weak self] subnode, isSearchBar in
if let strongSelf = self, let navigationBar = strongSelf.controller?.navigationBar { guard let self else {
strongSelf.insertSubnode(subnode, belowSubnode: navigationBar) return
}
if isSearchBar {
self.headerNode.searchBarContainer.addSubnode(subnode)
} else {
self.headerNode.searchContainer.addSubnode(subnode)
} }
}, placeholder: nil) }, placeholder: nil)
@ -11627,12 +11632,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
if let navigationBar = self.controller?.navigationBar { if let navigationBar = self.controller?.navigationBar {
transition.updateAlpha(node: navigationBar, alpha: 1.0) transition.updateAlpha(node: navigationBar, alpha: 1.0)
} }
if let (layout, navigationHeight) = self.validLayout {
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.4, curve: .spring), additive: false)
}
} }
private weak var mediaGalleryContextMenu: ContextController? private weak var mediaGalleryContextMenu: ContextController?
func displaySharedMediaFastScrollingTooltip() { func displaySharedMediaFastScrollingTooltip() {
guard let buttonNode = self.headerNode.navigationButtonContainer.rightButtonNodes[.more] else { guard let buttonNode = self.headerNode.navigationButtonContainer.rightButtonNodes.first(where: { $0.key.key == .more })?.value else {
return return
} }
guard let controller = self.controller else { guard let controller = self.controller else {
@ -12582,8 +12590,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
} }
let headerInset = sectionInset let headerInset = sectionInset
let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : self.scrollNode.view.contentOffset.y, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, profileGiftsContext: self.data?.profileGiftsContext, screenData: self.data, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: self.headerNode.navigationTransition == nil ? transition : .immediate, additive: additive, animateHeader: transition.isAnimated && self.headerNode.navigationTransition == nil) let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : self.scrollNode.view.contentOffset.y, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, profileGiftsContext: self.data?.profileGiftsContext, screenData: self.data, isSearching: self.searchDisplayController != nil, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: self.headerNode.navigationTransition == nil ? transition : .immediate, additive: additive, animateHeader: transition.isAnimated && self.headerNode.navigationTransition == nil)
let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight)) let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: layout.size.height))
if additive { if additive {
transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame) transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame)
} else { } else {
@ -12967,7 +12975,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
} }
let headerInset = sectionInset let headerInset = sectionInset
let _ = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : offsetY, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, profileGiftsContext: self.data?.profileGiftsContext, screenData: self.data, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: self.headerNode.navigationTransition == nil ? transition : .immediate, additive: additive, animateHeader: animateHeader && self.headerNode.navigationTransition == nil) let _ = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : offsetY, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.savedMessagesPeer ?? self.data?.peer, cachedData: self.data?.cachedData, threadData: self.data?.threadData, peerNotificationSettings: self.data?.peerNotificationSettings, threadNotificationSettings: self.data?.threadNotificationSettings, globalNotificationSettings: self.data?.globalNotificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, profileGiftsContext: self.data?.profileGiftsContext, screenData: self.data, isSearching: self.searchDisplayController != nil, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: self.headerNode.navigationTransition == nil ? transition : .immediate, additive: additive, animateHeader: animateHeader && self.headerNode.navigationTransition == nil)
} }
let paneAreaExpansionDistance: CGFloat = 32.0 let paneAreaExpansionDistance: CGFloat = 32.0
@ -12996,11 +13004,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
disableTabSwitching = true disableTabSwitching = true
} }
let navigationBarHeight: CGFloat = !self.isSettings && layout.isModalOverlay ? 56.0 : 44.0 let navigationBarHeight: CGFloat = !self.isSettings && layout.isModalOverlay ? 68.0 : 60.0
self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, deviceMetrics: layout.deviceMetrics, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, areTabsHidden: self.headerNode.customNavigationContentNode != nil, disableTabSwitching: disableTabSwitching, navigationHeight: navigationHeight, transition: transition) self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, deviceMetrics: layout.deviceMetrics, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, areTabsHidden: self.headerNode.customNavigationContentNode != nil, disableTabSwitching: disableTabSwitching, navigationHeight: navigationHeight, transition: transition)
transition.updateFrame(node: self.headerNode.navigationButtonContainer, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight))) transition.updateFrame(node: self.headerNode.navigationButtonContainer, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight)))
var searchBarContainerY: CGFloat = layout.statusBarHeight ?? 0.0
searchBarContainerY += floor((navigationBarHeight - 44.0) * 0.5) + 2.0
transition.updateFrame(node: self.headerNode.searchBarContainer, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left, y: searchBarContainerY), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight)))
transition.updateFrame(node: self.headerNode.searchContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
var leftNavigationButtons: [PeerInfoHeaderNavigationButtonSpec] = [] var leftNavigationButtons: [PeerInfoHeaderNavigationButtonSpec] = []
var rightNavigationButtons: [PeerInfoHeaderNavigationButtonSpec] = [] var rightNavigationButtons: [PeerInfoHeaderNavigationButtonSpec] = []
@ -13074,6 +13085,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
switch previousItem { switch previousItem {
case .close, .item: case .close, .item:
leftNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .back, isForExpandedView: false)) leftNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .back, isForExpandedView: false))
leftNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .back, isForExpandedView: true))
} }
} }
self.headerNode.navigationButtonContainer.update(size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight), presentationData: self.presentationData, leftButtons: leftNavigationButtons, rightButtons: rightNavigationButtons, expandFraction: effectiveAreaExpansionFraction, shouldAnimateIn: animateHeader, transition: transition) self.headerNode.navigationButtonContainer.update(size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight), presentationData: self.presentationData, leftButtons: leftNavigationButtons, rightButtons: rightNavigationButtons, expandFraction: effectiveAreaExpansionFraction, shouldAnimateIn: animateHeader, transition: transition)
@ -14597,7 +14609,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
} }
let headerInset = sectionInset let headerInset = sectionInset
topHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, isModalOverlay: layout.isModalOverlay, isMediaOnly: false, contentOffset: 0.0, paneContainerY: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.savedMessagesPeer ?? self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, threadData: self.screenNode.data?.threadData, peerNotificationSettings: self.screenNode.data?.peerNotificationSettings, threadNotificationSettings: self.screenNode.data?.threadNotificationSettings, globalNotificationSettings: self.screenNode.data?.globalNotificationSettings, statusData: self.screenNode.data?.status, panelStatusData: (nil, nil, nil), isSecretChat: self.screenNode.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.screenNode.data?.isContact ?? false, isSettings: self.screenNode.isSettings, state: self.screenNode.state, profileGiftsContext: self.screenNode.data?.profileGiftsContext, screenData: self.screenNode.data, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: transition, additive: false, animateHeader: false) topHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, isModalOverlay: layout.isModalOverlay, isMediaOnly: false, contentOffset: 0.0, paneContainerY: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.savedMessagesPeer ?? self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, threadData: self.screenNode.data?.threadData, peerNotificationSettings: self.screenNode.data?.peerNotificationSettings, threadNotificationSettings: self.screenNode.data?.threadNotificationSettings, globalNotificationSettings: self.screenNode.data?.globalNotificationSettings, statusData: self.screenNode.data?.status, panelStatusData: (nil, nil, nil), isSecretChat: self.screenNode.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.screenNode.data?.isContact ?? false, isSettings: self.screenNode.isSettings, state: self.screenNode.state, profileGiftsContext: self.screenNode.data?.profileGiftsContext, screenData: self.screenNode.data, isSearching: false, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, transition: transition, additive: false, animateHeader: false)
} }
let titleScale = (fraction * previousTitleNode.view.bounds.height + (1.0 - fraction) * self.headerNode.titleNodeRawContainer.bounds.height) / previousTitleNode.view.bounds.height let titleScale = (fraction * previousTitleNode.view.bounds.height + (1.0 - fraction) * self.headerNode.titleNodeRawContainer.bounds.height) / previousTitleNode.view.bounds.height

View file

@ -1020,6 +1020,7 @@ final class QuickReplySetupScreenComponent: Component {
let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false) let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false)
searchBarNode = SearchBarNode( searchBarNode = SearchBarNode(
theme: searchBarTheme, theme: searchBarTheme,
presentationTheme: environment.theme,
strings: environment.strings, strings: environment.strings,
fieldStyle: .modern, fieldStyle: .modern,
displayBackground: false displayBackground: false

View file

@ -478,6 +478,7 @@ final class PeerSelectionScreenComponent: Component {
let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false) let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false)
searchBarNode = SearchBarNode( searchBarNode = SearchBarNode(
theme: searchBarTheme, theme: searchBarTheme,
presentationTheme: environment.theme,
strings: environment.strings, strings: environment.strings,
fieldStyle: .modern, fieldStyle: .modern,
displayBackground: false displayBackground: false

View file

@ -206,6 +206,7 @@ public final class NavigationSearchView: UIView {
accent: params.theme.chat.inputPanel.panelControlAccentColor, accent: params.theme.chat.inputPanel.panelControlAccentColor,
keyboard: params.theme.rootController.keyboardColor keyboard: params.theme.rootController.keyboardColor
), ),
presentationTheme: params.theme,
strings: params.strings, strings: params.strings,
fieldStyle: .inlineNavigation, fieldStyle: .inlineNavigation,
icon: .loupe, icon: .loupe,

View file

@ -573,7 +573,7 @@ final class ContactsSearchNavigationContentNode: NavigationBarContentNode {
init(presentationData: PresentationData, dismissSearch: @escaping () -> Void, updateSearchQuery: @escaping (String) -> Void) { init(presentationData: PresentationData, dismissSearch: @escaping () -> Void, updateSearchQuery: @escaping (String) -> Void) {
self.presentationData = presentationData self.presentationData = presentationData
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings, fieldStyle: .modern) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), presentationTheme: presentationData.theme, strings: presentationData.strings, fieldStyle: .modern)
self.searchBar.placeholderString = NSAttributedString(string: presentationData.strings.Common_Search, font: searchBarFont, textColor: presentationData.theme.rootController.navigationSearchBar.inputPlaceholderTextColor) self.searchBar.placeholderString = NSAttributedString(string: presentationData.strings.Common_Search, font: searchBarFont, textColor: presentationData.theme.rootController.navigationSearchBar.inputPlaceholderTextColor)
super.init() super.init()
@ -617,7 +617,7 @@ final class ContactsSearchNavigationContentNode: NavigationBarContentNode {
func updatePresentationData(_ presentationData: PresentationData) { func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData self.presentationData = presentationData
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), strings: presentationData.strings) self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationData.theme, hasSeparator: false), presentationTheme: presentationData.theme, strings: presentationData.strings)
} }
} }

View file

@ -22,7 +22,7 @@ final class WebSearchNavigationContentNode: NavigationBarContentNode {
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), strings: strings, fieldStyle: .modern, displayBackground: !attachment) self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasSeparator: false), presentationTheme: theme, strings: strings, fieldStyle: .modern, displayBackground: !attachment)
self.searchBar.hasCancelButton = attachment self.searchBar.hasCancelButton = attachment
self.searchBar.placeholderString = NSAttributedString(string: attachment ? strings.Attachment_SearchWeb : strings.Common_Search, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor) self.searchBar.placeholderString = NSAttributedString(string: attachment ? strings.Attachment_SearchWeb : strings.Common_Search, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor)