mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Glass
This commit is contained in:
parent
3982aa3f9e
commit
a63c90aa00
41 changed files with 550 additions and 503 deletions
|
|
@ -34,6 +34,9 @@ swift_library(
|
|||
"//submodules/InviteLinksUI",
|
||||
"//submodules/UndoUI",
|
||||
"//submodules/TelegramCallsUI",
|
||||
"//submodules/TelegramUI/Components/EdgeEffect",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
|
|
|||
|
|
@ -361,10 +361,10 @@ public final class CallListController: TelegramBaseController {
|
|||
if empty {
|
||||
switch strongSelf.mode {
|
||||
case .tab:
|
||||
strongSelf.navigationItem.setLeftBarButton(nil, animated: true)
|
||||
strongSelf.navigationItem.setRightBarButton(nil, animated: true)
|
||||
strongSelf.navigationItem.setLeftBarButton(nil, animated: strongSelf.controllerNode.didSetReady)
|
||||
strongSelf.navigationItem.setRightBarButton(nil, animated: strongSelf.controllerNode.didSetReady)
|
||||
case .navigation:
|
||||
strongSelf.navigationItem.setRightBarButton(nil, animated: true)
|
||||
strongSelf.navigationItem.setRightBarButton(nil, animated: strongSelf.controllerNode.didSetReady)
|
||||
}
|
||||
} else {
|
||||
var pressedImpl: (() -> Void)?
|
||||
|
|
@ -381,25 +381,24 @@ public final class CallListController: TelegramBaseController {
|
|||
switch strongSelf.mode {
|
||||
case .tab:
|
||||
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.setRightBarButton(UIBarButtonItem(customDisplayNode: buttonNode), 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: strongSelf.controllerNode.didSetReady)
|
||||
strongSelf.navigationItem.rightBarButtonItem?.setCustomAction({
|
||||
pressedImpl?()
|
||||
})
|
||||
} else {
|
||||
strongSelf.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: strongSelf, action: #selector(strongSelf.editPressed)), animated: true)
|
||||
//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: 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(nil, animated: strongSelf.controllerNode.didSetReady)
|
||||
}
|
||||
case .navigation:
|
||||
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({
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ import AnimatedStickerNode
|
|||
import TelegramAnimatedStickerNode
|
||||
import AppBundle
|
||||
import ItemListPeerActionItem
|
||||
import EdgeEffect
|
||||
import ComponentFlow
|
||||
import ComponentDisplayAdapters
|
||||
|
||||
private struct CallListNodeListViewTransition {
|
||||
let callListView: CallListNodeView
|
||||
|
|
@ -185,7 +188,7 @@ final class CallListControllerNode: ASDisplayNode {
|
|||
private var containerLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
private let _ready = ValuePromise<Bool>()
|
||||
private var didSetReady = false
|
||||
private(set) var didSetReady = false
|
||||
var ready: Signal<Bool, NoError> {
|
||||
return _ready.get()
|
||||
}
|
||||
|
|
@ -220,6 +223,8 @@ final class CallListControllerNode: ASDisplayNode {
|
|||
private let emptyButtonIconNode: ASImageNode
|
||||
private let emptyButtonTextNode: ImmediateTextNode
|
||||
|
||||
private let edgeEffectView: EdgeEffectView
|
||||
|
||||
private let call: (EngineMessage) -> Void
|
||||
private let joinGroupCall: (EnginePeer.Id, EngineGroupCallDescription) -> Void
|
||||
private let openNewCall: () -> Void
|
||||
|
|
@ -277,6 +282,8 @@ final class CallListControllerNode: ASDisplayNode {
|
|||
self.emptyButtonIconNode.displaysAsynchronously = false
|
||||
self.emptyButtonIconNode.isUserInteractionEnabled = false
|
||||
|
||||
self.edgeEffectView = EdgeEffectView()
|
||||
|
||||
super.init()
|
||||
|
||||
self.setViewBlock({
|
||||
|
|
@ -289,6 +296,8 @@ final class CallListControllerNode: ASDisplayNode {
|
|||
self.addSubnode(self.emptyButtonTextNode)
|
||||
self.addSubnode(self.emptyButtonIconNode)
|
||||
self.addSubnode(self.emptyButtonNode)
|
||||
|
||||
self.view.addSubview(self.edgeEffectView)
|
||||
|
||||
switch self.mode {
|
||||
case .tab:
|
||||
|
|
@ -945,5 +954,10 @@ final class CallListControllerNode: ASDisplayNode {
|
|||
self.dequeuedInitialTransitionOnLayout = true
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2102,9 +2102,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
let effectiveBackgroundColor: UIColor
|
||||
if item.isPinned {
|
||||
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned, voiceChat: self.onlineIsVoiceChat)
|
||||
//TODO:localize
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
} else {
|
||||
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .regular, voiceChat: self.onlineIsVoiceChat)
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
|
|
@ -2118,9 +2116,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
if let avatarLiveBadge = self.avatarLiveBadge {
|
||||
let effectiveBackgroundColor: UIColor
|
||||
if item.isPinned {
|
||||
//TODO:localize
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
} else {
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
}
|
||||
|
|
@ -4133,9 +4129,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
|
||||
let effectiveBackgroundColor: UIColor
|
||||
if item.isPinned {
|
||||
//TODO:localize
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
} else {
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
}
|
||||
|
|
@ -4156,9 +4150,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemHighlightedBackgroundColor
|
||||
} else if case let .chatList(index) = item.index, index.pinningIndex != nil {
|
||||
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned, voiceChat: onlineIsVoiceChat)
|
||||
//TODO:localize
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
//effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.pinnedItemBackgroundColor
|
||||
} else {
|
||||
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .regular, voiceChat: onlineIsVoiceChat)
|
||||
effectiveBackgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
|
|
@ -5070,9 +5062,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
backgroundColor = theme.itemBackgroundColor
|
||||
highlightedBackgroundColor = theme.itemHighlightedBackgroundColor
|
||||
} else {
|
||||
//TODO:localize
|
||||
backgroundColor = item.presentationData.theme.chatList.itemBackgroundColor
|
||||
//backgroundColor = theme.pinnedItemBackgroundColor
|
||||
backgroundColor = theme.pinnedItemBackgroundColor
|
||||
highlightedBackgroundColor = theme.pinnedItemHighlightedBackgroundColor
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3251,8 +3251,10 @@ public final class ChatListNode: ListView {
|
|||
if entryCount - 1 - i < 0 {
|
||||
continue
|
||||
}
|
||||
if case .PeerEntry = transition.chatListView.filteredEntries[entryCount - 1 - i] {
|
||||
} else {
|
||||
switch transition.chatListView.filteredEntries[entryCount - 1 - i] {
|
||||
case .PeerEntry, .GroupReferenceEntry:
|
||||
break
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if case let .index(index) = transition.chatListView.filteredEntries[entryCount - 1 - i].sortIndex, case let .chatList(chatListIndex) = index, chatListIndex.pinningIndex != nil {
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ private final class AuthorizationSequenceCountrySelectionNavigationContentNode:
|
|||
|
||||
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 searchBarFont = Font.regular(17.0)
|
||||
|
||||
|
|
|
|||
|
|
@ -980,7 +980,7 @@ private final class SearchNavigationContentNode: NavigationBarContentNode {
|
|||
|
||||
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 searchBarFont = Font.regular(17.0)
|
||||
|
||||
|
|
@ -1004,7 +1004,7 @@ private final class SearchNavigationContentNode: NavigationBarContentNode {
|
|||
self.theme = theme
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
|||
}
|
||||
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
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
|||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ final class HashtagSearchNavigationContentNode: NavigationBarContentNode {
|
|||
var initialQuery = initialQuery
|
||||
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.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) {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ final class SearchNavigationContentNode: NavigationBarContentNode, ItemListContr
|
|||
|
||||
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()
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ final class SearchNavigationContentNode: NavigationBarContentNode, ItemListContr
|
|||
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ final class LocationSearchNavigationContentNode: NavigationBarContentNode {
|
|||
self.presentationData = presentationData
|
||||
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)
|
||||
|
||||
super.init()
|
||||
|
|
@ -58,6 +58,6 @@ final class LocationSearchNavigationContentNode: NavigationBarContentNode {
|
|||
|
||||
func updatePresentationData(_ 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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ private final class ChannelDiscussionSearchNavigationContentNode: NavigationBarC
|
|||
accent: theme.chat.inputPanel.panelControlAccentColor,
|
||||
keyboard: theme.rootController.keyboardColor
|
||||
),
|
||||
presentationTheme: theme,
|
||||
strings: strings,
|
||||
fieldStyle: .inlineNavigation,
|
||||
forceSeparator: false,
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ final class GroupInfoSearchNavigationContentNode: NavigationBarContentNode, Item
|
|||
accent: theme.chat.inputPanel.panelControlAccentColor,
|
||||
keyboard: theme.rootController.keyboardColor
|
||||
),
|
||||
presentationTheme: theme,
|
||||
strings: strings,
|
||||
fieldStyle: .inlineNavigation,
|
||||
forceSeparator: false,
|
||||
|
|
|
|||
|
|
@ -894,6 +894,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
|
||||
public var tokensUpdated: (([SearchBarToken]) -> Void)?
|
||||
|
||||
private let inlineSearchPlaceholder: SearchBarPlaceholderNode
|
||||
private var inlineSearchPlaceholderContentsView: SearchBarPlaceholderContentView?
|
||||
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let textBackgroundNode: ASDisplayNode
|
||||
|
|
@ -972,6 +975,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
|
||||
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
|
||||
private let forceSeparator: Bool
|
||||
private var theme: SearchBarNodeTheme?
|
||||
private var presentationTheme: PresentationTheme
|
||||
private var strings: PresentationStrings?
|
||||
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.forceSeparator = forceSeparator
|
||||
self.cancelText = cancelText
|
||||
self.icon = icon
|
||||
|
||||
self.inlineSearchPlaceholder = SearchBarPlaceholderNode(fieldStyle: .glass)
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: theme.background)
|
||||
self.backgroundNode.isUserInteractionEnabled = false
|
||||
|
|
@ -1043,7 +1056,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
super.init()
|
||||
|
||||
switch self.fieldStyle {
|
||||
case .glass, .inlineNavigation:
|
||||
case .glass:
|
||||
break
|
||||
case .inlineNavigation:
|
||||
break
|
||||
case .legacy, .modern:
|
||||
self.addSubnode(self.backgroundNode)
|
||||
|
|
@ -1085,11 +1100,11 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), 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)
|
||||
}
|
||||
|
||||
public func updateThemeAndStrings(theme: SearchBarNodeTheme, strings: PresentationStrings) {
|
||||
public func updateThemeAndStrings(theme: SearchBarNodeTheme, presentationTheme: PresentationTheme, strings: PresentationStrings) {
|
||||
if self.theme != theme || self.strings !== strings {
|
||||
self.clearButton.accessibilityLabel = strings.WebSearch_RecentSectionClear
|
||||
self.cancelButton.accessibilityLabel = self.cancelText ?? strings.Common_Cancel
|
||||
|
|
@ -1122,6 +1137,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
}
|
||||
|
||||
self.theme = theme
|
||||
self.presentationTheme = presentationTheme
|
||||
self.strings = strings
|
||||
if let (boundingSize, leftInset, rightInset) = self.validLayout {
|
||||
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))
|
||||
|
||||
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) {
|
||||
|
|
@ -1201,6 +1256,8 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
}
|
||||
|
||||
public func animateIn(from node: SearchBarPlaceholderNode, duration: Double, timingFunction: String) {
|
||||
self.inlineSearchPlaceholder.isHidden = true
|
||||
|
||||
let takenSearchPlaceholderContentView = node.takeContents()
|
||||
takenSearchPlaceholderContentView.onCancel = { [weak self] in
|
||||
guard let self else {
|
||||
|
|
@ -1210,6 +1267,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
}
|
||||
self.takenSearchPlaceholderContentView = takenSearchPlaceholderContentView
|
||||
self.view.insertSubview(takenSearchPlaceholderContentView, at: 0)
|
||||
if let inlineSearchPlaceholderContentsView = self.inlineSearchPlaceholderContentsView {
|
||||
inlineSearchPlaceholderContentsView.removeFromSuperview()
|
||||
}
|
||||
|
||||
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))
|
||||
|
|
@ -1271,6 +1331,8 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
}
|
||||
|
||||
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 duration: Double = transition.isAnimated ? 0.5 : 0.0
|
||||
|
|
@ -1531,6 +1593,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
|||
if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
|
||||
takenSearchPlaceholderContentView.updatePlaceholderVisibility(isVisible: isEmpty)
|
||||
}
|
||||
self.inlineSearchPlaceholderContentsView?.updatePlaceholderVisibility(isVisible: isEmpty)
|
||||
|
||||
let clearIsHidden = (textIsEmpty && tokensEmpty) && self.prefixString == nil
|
||||
transition.updateAlpha(node: self.clearButton.imageNode, alpha: clearIsHidden ? 0.0 : 1.0)
|
||||
|
|
|
|||
|
|
@ -49,13 +49,15 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
}
|
||||
|
||||
let fieldStyle: SearchBarStyle
|
||||
let backgroundNode: ASDisplayNode?
|
||||
let plainBackgroundView: UIImageView
|
||||
let glassBackgroundView: GlassBackgroundView?
|
||||
private var fillBackgroundColor: UIColor
|
||||
private var foregroundColor: UIColor
|
||||
private var iconColor: UIColor
|
||||
let iconNode: ASImageNode
|
||||
let labelNode: TextNode
|
||||
let plainIconNode: ASImageNode
|
||||
let plainLabelNode: TextNode
|
||||
|
||||
private var close: (background: GlassBackgroundView, icon: UIImageView)?
|
||||
|
||||
|
|
@ -72,20 +74,13 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
self.foregroundColor = UIColor(rgb: 0xededed)
|
||||
self.iconColor = UIColor(rgb: 0x000000, alpha: 0.0)
|
||||
|
||||
self.plainBackgroundView = UIImageView()
|
||||
|
||||
switch fieldStyle {
|
||||
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
|
||||
case .inlineNavigation, .glass:
|
||||
self.glassBackgroundView = GlassBackgroundView()
|
||||
|
||||
self.backgroundNode = nil
|
||||
}
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
|
|
@ -96,20 +91,27 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
self.labelNode.isOpaque = 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())
|
||||
|
||||
if let backgroundNode = self.backgroundNode {
|
||||
backgroundNode.isUserInteractionEnabled = true
|
||||
self.addSubview(backgroundNode.view)
|
||||
}
|
||||
self.plainBackgroundView.isUserInteractionEnabled = true
|
||||
self.addSubview(self.plainBackgroundView)
|
||||
|
||||
self.plainBackgroundView.addSubview(self.plainIconNode.view)
|
||||
self.plainBackgroundView.addSubview(self.plainLabelNode.view)
|
||||
|
||||
if let glassBackgroundView = self.glassBackgroundView {
|
||||
self.addSubview(glassBackgroundView)
|
||||
|
||||
glassBackgroundView.contentView.addSubview(self.iconNode.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 {
|
||||
let labelLayout = TextNode.asyncLayout(self.labelNode)
|
||||
let plainLabelLayout = TextNode.asyncLayout(self.plainLabelNode)
|
||||
let currentForegroundColor = self.foregroundColor
|
||||
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 (_, plainLabelApply) = plainLabelLayout(TextNodeLayoutArguments(attributedString: placeholderString, backgroundColor: .clear, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: params.constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
var updatedColor: UIColor?
|
||||
var updatedIconImage: UIImage?
|
||||
|
|
@ -185,19 +189,19 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
let height = params.constrainedSize.height * params.expansionProgress
|
||||
|
||||
let _ = labelApply()
|
||||
let _ = plainLabelApply()
|
||||
|
||||
self.fillBackgroundColor = params.backgroundColor
|
||||
self.foregroundColor = params.foregroundColor
|
||||
self.iconColor = params.iconColor
|
||||
if let backgroundNode = self.backgroundNode {
|
||||
backgroundNode.isUserInteractionEnabled = params.expansionProgress > 0.9999
|
||||
}
|
||||
self.plainBackgroundView.isUserInteractionEnabled = params.expansionProgress > 0.9999
|
||||
|
||||
if let updatedColor, let backgroundNode = self.backgroundNode {
|
||||
backgroundNode.backgroundColor = updatedColor
|
||||
if let updatedColor {
|
||||
self.plainBackgroundView.backgroundColor = updatedColor
|
||||
}
|
||||
if let updatedIconImage {
|
||||
self.iconNode.image = updatedIconImage
|
||||
self.plainIconNode.image = updatedIconImage
|
||||
}
|
||||
|
||||
self.placeholderString = placeholderString
|
||||
|
|
@ -220,6 +224,7 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
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.plainIconNode, frame: CGRect(origin: CGPoint(x: iconX, y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize))
|
||||
} else {
|
||||
iconX = 12.0
|
||||
}
|
||||
|
|
@ -230,6 +235,7 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
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)
|
||||
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
|
||||
if innerAlpha > 0.9999 {
|
||||
|
|
@ -241,27 +247,36 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
if !transition.isAnimated {
|
||||
self.labelNode.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.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 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 {
|
||||
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 {
|
||||
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))
|
||||
|
|
@ -269,12 +284,12 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
backgroundFrame.size.width -= 44.0 + 8.0
|
||||
}
|
||||
|
||||
if let backgroundNode = self.backgroundNode, backgroundNode.frame != backgroundFrame {
|
||||
if self.plainBackgroundView.frame != backgroundFrame {
|
||||
if !transition.isAnimated {
|
||||
backgroundNode.layer.removeAnimation(forKey: "position")
|
||||
backgroundNode.layer.removeAnimation(forKey: "bounds")
|
||||
self.plainBackgroundView.layer.removeAnimation(forKey: "position")
|
||||
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 {
|
||||
|
|
@ -284,6 +299,9 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
if 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)
|
||||
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))
|
||||
|
|
@ -372,10 +390,12 @@ public final class SearchBarPlaceholderContentView: UIView {
|
|||
|
||||
public func updatePlaceholderVisibility(isVisible: Bool) {
|
||||
self.labelNode.isHidden = !isVisible
|
||||
self.plainLabelNode.isHidden = !isVisible
|
||||
}
|
||||
|
||||
public func updateSearchIconVisibility(isVisible: Bool) {
|
||||
self.iconNode.isHidden = !isVisible
|
||||
self.plainIconNode.isHidden = !isVisible
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,12 +428,10 @@ public class SearchBarPlaceholderNode: ASDisplayNode {
|
|||
private let contentView: SearchBarPlaceholderContentView
|
||||
|
||||
public var backgroundView: UIView {
|
||||
if let backgroundNode = self.contentView.backgroundNode {
|
||||
return backgroundNode.view
|
||||
} else if let glassBackgroundView = self.contentView.glassBackgroundView {
|
||||
if let glassBackgroundView = self.contentView.glassBackgroundView {
|
||||
return glassBackgroundView
|
||||
} else {
|
||||
preconditionFailure()
|
||||
return self.contentView.plainBackgroundView
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public final class SearchDisplayController {
|
|||
self.searchBarIsExternal = 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.allowsGroupOpacity = true
|
||||
|
|
@ -143,7 +143,7 @@ public final class SearchDisplayController {
|
|||
|
||||
public func updatePresentationData(_ presentationData: PresentationData) {
|
||||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ extension StoreMessage {
|
|||
}
|
||||
}
|
||||
|
||||
if (flags & (1 << 17)) != 0 {
|
||||
if (flags & (1 << 19)) != 0 {
|
||||
attributes.append(ContentRequiresValidationMessageAttribute())
|
||||
}
|
||||
|
||||
|
|
@ -1174,7 +1174,7 @@ extension StoreMessage {
|
|||
threadId = 1
|
||||
}
|
||||
|
||||
if (flags & (1 << 17)) != 0 {
|
||||
if (flags & (1 << 19)) != 0 {
|
||||
attributes.append(ContentRequiresValidationMessageAttribute())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ public struct TelegramChatAdminRightsFlags: OptionSet, Hashable {
|
|||
.canPostStories,
|
||||
.canEditStories,
|
||||
.canDeleteStories,
|
||||
.canManageDirect
|
||||
.canManageDirect,
|
||||
.canBanUsers
|
||||
]
|
||||
|
||||
public static func peerSpecific(peer: EnginePeer) -> TelegramChatAdminRightsFlags {
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati
|
|||
pinnedBadgeColor: UIColor(rgb: 0x767677),
|
||||
pinnedSearchBarColor: UIColor(rgb: 0x272728),
|
||||
regularSearchBarColor: UIColor(rgb: 0x272728),
|
||||
sectionHeaderFillColor: UIColor(rgb: 0x1c1c1d),
|
||||
sectionHeaderFillColor: .black,
|
||||
sectionHeaderTextColor: UIColor(rgb: 0xffffff),
|
||||
verifiedIconFillColor: UIColor(rgb: 0xffffff),
|
||||
verifiedIconForegroundColor: UIColor(rgb: 0x000000),
|
||||
|
|
|
|||
|
|
@ -714,7 +714,7 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres
|
|||
pinnedBadgeColor: mainSecondaryTextColor.withAlphaComponent(0.5),
|
||||
pinnedSearchBarColor: 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),
|
||||
verifiedIconFillColor: accentColor,
|
||||
verifiedIconForegroundColor: .white,
|
||||
|
|
|
|||
|
|
@ -565,8 +565,8 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio
|
|||
pinnedBadgeColor: UIColor(rgb: 0xb6b6bb),
|
||||
pinnedSearchBarColor: UIColor(rgb: 0xe5e5e5),
|
||||
regularSearchBarColor: UIColor(rgb: 0xe9e9e9),
|
||||
sectionHeaderFillColor: UIColor(rgb: 0xf7f7f7),
|
||||
sectionHeaderTextColor: UIColor(rgb: 0x8e8e93),
|
||||
sectionHeaderFillColor: .white,
|
||||
sectionHeaderTextColor: .black,
|
||||
verifiedIconFillColor: defaultDayAccentColor,
|
||||
verifiedIconForegroundColor: UIColor(rgb: 0xffffff),
|
||||
secretIconColor: UIColor(rgb: 0x00b12c),
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ final class ChatRecentActionsSearchNavigationContentNode: NavigationBarContentNo
|
|||
|
||||
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
|
||||
self.searchBar.placeholderString = NSAttributedString(string: placeholderText, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor)
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ public final class ChatSearchNavigationContentNode: NavigationBarContentNode {
|
|||
accent: theme.chat.inputPanel.panelControlAccentColor,
|
||||
keyboard: theme.rootController.keyboardColor
|
||||
),
|
||||
presentationTheme: theme,
|
||||
strings: strings,
|
||||
fieldStyle: .inlineNavigation,
|
||||
forceSeparator: false,
|
||||
|
|
@ -246,6 +247,7 @@ public final class ChatSearchNavigationContentNode: NavigationBarContentNode {
|
|||
accent: presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor,
|
||||
keyboard: presentationInterfaceState.theme.rootController.keyboardColor
|
||||
),
|
||||
presentationTheme: presentationInterfaceState.theme,
|
||||
strings: presentationInterfaceState.strings
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -359,6 +359,9 @@ public final class ChatListNavigationBar: Component {
|
|||
let searchOffsetFraction = clippedSearchOffset / searchOffsetDistance
|
||||
searchContentNode.expansionProgress = 1.0 - searchOffsetFraction
|
||||
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
|
||||
transition.setFrameWithAdditivePosition(view: searchContentNode.view, frame: searchFrame)
|
||||
|
|
@ -479,7 +482,7 @@ public final class ChatListNavigationBar: Component {
|
|||
if component.statusBarHeight < 1.0 {
|
||||
headerContentY = 0.0
|
||||
} else {
|
||||
headerContentY = component.statusBarHeight + 5.0
|
||||
headerContentY = component.statusBarHeight + 10.0
|
||||
}
|
||||
}
|
||||
let headerContentFrame = CGRect(origin: CGPoint(x: 0.0, y: headerContentY), size: headerContentSize)
|
||||
|
|
@ -683,7 +686,7 @@ public final class ChatListNavigationBar: Component {
|
|||
}
|
||||
} else {
|
||||
contentHeight += 44.0
|
||||
contentHeight += 8.0
|
||||
contentHeight += 7.0
|
||||
|
||||
if component.search != nil {
|
||||
contentHeight += navigationBarSearchContentHeight
|
||||
|
|
@ -696,8 +699,6 @@ public final class ChatListNavigationBar: Component {
|
|||
transition.setFrame(view: disappearingHeaderPanelsView, frame: headerPanelsFrame)
|
||||
}
|
||||
if let headerPanels = component.headerPanels {
|
||||
headersContentHeight += 4.0
|
||||
|
||||
let headerPanelsView: ComponentView<Empty>
|
||||
var headerPanelsTransition = transition
|
||||
if let current = self.headerPanelsView {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ public final class NavigationButtonComponent: Component {
|
|||
|
||||
switch component.content {
|
||||
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:
|
||||
isMore = true
|
||||
case let .icon(imageNameValue):
|
||||
|
|
@ -140,7 +140,7 @@ public final class NavigationButtonComponent: Component {
|
|||
|
||||
textView.attributedText = textString
|
||||
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)
|
||||
|
||||
textView.frame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: floor((availableSize.height - textSize.height) / 2.0)), size: textSize)
|
||||
|
|
|
|||
|
|
@ -1010,13 +1010,7 @@ public final class ChatTitleComponent: Component {
|
|||
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)
|
||||
|
||||
var titleFrame = CGRect(origin: CGPoint(x: floor((containerFrame.width - titleSize.width) * 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
|
||||
}
|
||||
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 let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
titleView.isUserInteractionEnabled = false
|
||||
|
|
@ -1130,6 +1124,8 @@ public final class ChatTitleComponent: Component {
|
|||
if let backgroundView = self.backgroundView {
|
||||
self.backgroundView = nil
|
||||
backgroundView.removeFromSuperview()
|
||||
}
|
||||
if self.contentContainer.superview !== self {
|
||||
self.addSubview(self.contentContainer)
|
||||
}
|
||||
transition.setFrame(view: self.contentContainer, frame: containerFrame)
|
||||
|
|
|
|||
|
|
@ -77,33 +77,33 @@ public class EdgeEffectView: UIView {
|
|||
}
|
||||
|
||||
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
|
||||
if let current = self.blurView {
|
||||
blurView = current
|
||||
} 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.layer.mask = gradientMaskLayer
|
||||
self.insertSubview(blurView, at: 0)
|
||||
|
|
|
|||
|
|
@ -535,9 +535,12 @@ public class GlassBackgroundView: UIView {
|
|||
if transition.animation.isImmediate {
|
||||
nativeView.effect = glassEffect
|
||||
} else {
|
||||
UIView.animate(withDuration: 0.2, animations: {
|
||||
nativeView.effect = glassEffect
|
||||
})
|
||||
if let glassEffect, let currentEffect = nativeView.effect as? UIGlassEffect, currentEffect.tintColor == glassEffect.tintColor, currentEffect.isInteractive == glassEffect.isInteractive {
|
||||
} else {
|
||||
UIView.animate(withDuration: 0.15, animations: {
|
||||
nativeView.effect = glassEffect
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ final class GroupStickerSearchNavigationContentNode: NavigationBarContentNode, I
|
|||
accent: theme.chat.inputPanel.panelControlAccentColor,
|
||||
keyboard: theme.rootController.keyboardColor
|
||||
),
|
||||
presentationTheme: theme,
|
||||
strings: strings,
|
||||
fieldStyle: .inlineNavigation,
|
||||
forceSeparator: false,
|
||||
|
|
@ -127,7 +128,7 @@ final class GroupStickerSearchNavigationContentNode: NavigationBarContentNode, I
|
|||
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -460,6 +460,7 @@ final class MiniAppListScreenComponent: Component {
|
|||
let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false)
|
||||
searchBarNode = SearchBarNode(
|
||||
theme: searchBarTheme,
|
||||
presentationTheme: environment.theme,
|
||||
strings: environment.strings,
|
||||
fieldStyle: .modern,
|
||||
displayBackground: false
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ private final class ItemComponent: Component {
|
|||
if case let .item(item) = component.content, case .done = item.style {
|
||||
titleFont = Font.bold(17.0)
|
||||
} else {
|
||||
titleFont = Font.regular(17.0)
|
||||
titleFont = Font.medium(17.0)
|
||||
}
|
||||
|
||||
let title: ComponentView<Empty>
|
||||
|
|
@ -204,7 +204,7 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
|
|||
private let isGlass: Bool
|
||||
|
||||
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] {
|
||||
|
|
@ -711,7 +711,7 @@ public final class NavigationButtonNodeImpl: ContextControllerSourceNode, Naviga
|
|||
var nodeInset: CGFloat = 0.0
|
||||
if self.isGlass {
|
||||
if node.image == nil && node.node == nil {
|
||||
nodeInset += 10.0
|
||||
nodeInset += 12.0
|
||||
}
|
||||
if nodeSize.width + nodeInset * 2.0 < 44.0 {
|
||||
nodeInset = floorToScreenPixels((44.0 - nodeSize.width) * 0.5)
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ swift_library(
|
|||
"//submodules/TelegramUI/Components/MediaManager/PeerMessagesMediaPlaylist",
|
||||
"//submodules/TelegramUI/Components/TextFieldComponent",
|
||||
"//submodules/TelegramUI/Components/EdgeEffect",
|
||||
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,23 @@ private enum MoreIconNodeState: Equatable {
|
|||
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 let duration: Double = 0.21
|
||||
private var iconState: MoreIconNodeState = .more
|
||||
|
|
@ -124,14 +141,11 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
let contextSourceNode: ContextReferenceContentNode
|
||||
private let textNode: ImmediateTextNode
|
||||
private let iconNode: ASImageNode
|
||||
private let backIconLayer: SimpleShapeLayer
|
||||
private var animationNode: MoreIconNode?
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
|
||||
private var key: PeerInfoHeaderNavigationButtonKey?
|
||||
|
||||
private var contentsColor: UIColor = .white
|
||||
private var canBeExpanded: Bool = false
|
||||
|
||||
var action: ((ASDisplayNode, ContextGesture?) -> Void)?
|
||||
|
||||
|
|
@ -146,27 +160,14 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
self.iconNode.displaysAsynchronously = false
|
||||
self.iconNode.displayWithoutProcessing = true
|
||||
|
||||
self.backIconLayer = SimpleShapeLayer()
|
||||
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))
|
||||
super.init(pointerStyle: .insetRectangle(0.0, 0.0))
|
||||
|
||||
self.isAccessibilityElement = true
|
||||
self.accessibilityTraits = .button
|
||||
|
||||
self.containerNode.addSubnode(self.contextSourceNode)
|
||||
self.contextSourceNode.addSubnode(self.backgroundNode)
|
||||
self.contextSourceNode.addSubnode(self.textNode)
|
||||
self.contextSourceNode.addSubnode(self.iconNode)
|
||||
self.contextSourceNode.layer.addSublayer(self.backIconLayer)
|
||||
|
||||
self.addSubnode(self.containerNode)
|
||||
|
||||
|
|
@ -178,10 +179,6 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
}
|
||||
|
||||
self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside)
|
||||
|
||||
if isReduceTransparencyEnabled() {
|
||||
self.backgroundNode.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func pressed() {
|
||||
|
|
@ -190,11 +187,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
var boundingRect = self.bounds
|
||||
if self.textNode.alpha != 0.0 {
|
||||
boundingRect = boundingRect.union(self.textNode.frame)
|
||||
}
|
||||
boundingRect = boundingRect.insetBy(dx: -8.0, dy: -4.0)
|
||||
let boundingRect = self.bounds
|
||||
if boundingRect.contains(point) {
|
||||
return super.hitTest(self.bounds.center, with: event)
|
||||
} 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.canBeExpanded = canBeExpanded
|
||||
|
||||
self.backgroundNode.updateColor(color: backgroundColor, transition: transition)
|
||||
|
||||
transition.updateTintColor(layer: self.textNode.layer, 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 {
|
||||
transition.updateTintColor(layer: animationNode.imageNode.layer, color: self.contentsColor)
|
||||
|
|
@ -239,7 +212,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
var iconOffset = CGPoint()
|
||||
switch key {
|
||||
case .back:
|
||||
iconOffset = CGPoint(x: -1.0, y: 0.0)
|
||||
iconOffset = CGPoint(x: 0.0, y: 0.0)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
|
@ -258,9 +231,9 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
var animationState: MoreIconNodeState = .more
|
||||
switch key {
|
||||
case .back:
|
||||
text = presentationData.strings.Common_Back
|
||||
text = ""
|
||||
accessibilityText = presentationData.strings.Common_Back
|
||||
icon = navigationBarBackArrowImage(color: .white)
|
||||
icon = glassBackArrowImage
|
||||
case .edit:
|
||||
text = presentationData.strings.Common_Edit
|
||||
accessibilityText = text
|
||||
|
|
@ -323,7 +296,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
self.accessibilityLabel = accessibilityText
|
||||
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)
|
||||
transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor)
|
||||
|
|
@ -357,70 +330,39 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||
textSize = self.textNode.bounds.size
|
||||
}
|
||||
|
||||
let inset: CGFloat = 0.0
|
||||
var textInset: CGFloat = 0.0
|
||||
switch key {
|
||||
case .back:
|
||||
textInset += 11.0
|
||||
default:
|
||||
break
|
||||
}
|
||||
let textInset: CGFloat = 12.0
|
||||
|
||||
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.bounds = CGRect(origin: CGPoint(), size: textFrame.size)
|
||||
|
||||
if let animationNode = self.animationNode {
|
||||
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.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
resultSize = size
|
||||
} 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.bounds = CGRect(origin: CGPoint(), size: iconFrame.size)
|
||||
|
||||
if case .back = key {
|
||||
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)
|
||||
let size = CGSize(width: height, height: height)
|
||||
self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
resultSize = size
|
||||
} 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.contextSourceNode.frame = CGRect(origin: CGPoint(), size: 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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import AsyncDisplayKit
|
|||
import ContextUI
|
||||
import TelegramPresentationData
|
||||
import Display
|
||||
import ComponentFlow
|
||||
import ComponentDisplayAdapters
|
||||
import GlassBackgroundComponent
|
||||
|
||||
enum PeerInfoHeaderNavigationButtonKey {
|
||||
case back
|
||||
|
|
@ -24,101 +27,125 @@ enum PeerInfoHeaderNavigationButtonKey {
|
|||
case postStory
|
||||
}
|
||||
|
||||
struct PeerInfoHeaderNavigationButtonSpec: Equatable {
|
||||
struct PeerInfoHeaderNavigationButtonSpec: Hashable {
|
||||
let key: PeerInfoHeaderNavigationButtonKey
|
||||
let isForExpandedView: Bool
|
||||
}
|
||||
|
||||
final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
||||
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 currentRightButtons: [PeerInfoHeaderNavigationButtonSpec] = []
|
||||
|
||||
private var backgroundContentColor: UIColor = .clear
|
||||
private var isOverColoredContents: Bool = false
|
||||
private var contentsColor: UIColor = .white
|
||||
private var canBeExpanded: Bool = false
|
||||
|
||||
var performAction: ((PeerInfoHeaderNavigationButtonKey, ContextReferenceContentNode?, ContextGesture?) -> Void)?
|
||||
|
||||
func updateContentsColor(backgroundContentColor: UIColor, contentsColor: UIColor, canBeExpanded: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.backgroundContentColor = backgroundContentColor
|
||||
self.contentsColor = contentsColor
|
||||
self.canBeExpanded = canBeExpanded
|
||||
override init() {
|
||||
self.backgroundContainer = GlassBackgroundContainerView()
|
||||
self.leftButtonsBackground = GlassBackgroundView()
|
||||
self.rightButtonsBackground = GlassBackgroundView()
|
||||
|
||||
for (_, button) in self.leftButtonNodes {
|
||||
button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition)
|
||||
transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: canBeExpanded ? -8.0 : 0.0, y: 0.0))
|
||||
self.leftButtonsContainer = UIView()
|
||||
self.leftButtonsContainer.clipsToBounds = true
|
||||
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() {
|
||||
guard let button = self.rightButtonNodes[spec.key] else {
|
||||
guard let button = self.rightButtonNodes[spec] else {
|
||||
continue
|
||||
}
|
||||
button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition)
|
||||
if !spec.isForExpandedView {
|
||||
transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: accumulatedRightButtonOffset, y: 0.0))
|
||||
if self.backgroundContentColor.alpha != 0.0 {
|
||||
accumulatedRightButtonOffset -= 6.0
|
||||
}
|
||||
}
|
||||
}
|
||||
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))
|
||||
button.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: transition)
|
||||
}
|
||||
for (spec, button) in self.rightButtonNodes {
|
||||
if !self.currentRightButtons.contains(where: { $0 == spec }) {
|
||||
button.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
self.updateBackgroundColors(transition: ComponentTransition(transition))
|
||||
}
|
||||
|
||||
func update(size: CGSize, presentationData: PresentationData, leftButtons: [PeerInfoHeaderNavigationButtonSpec], rightButtons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, shouldAnimateIn: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let sideInset: CGFloat = 24.0
|
||||
let expandedSideInset: CGFloat = 16.0
|
||||
transition.updateFrame(view: self.backgroundContainer, frame: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
let maximumExpandOffset: CGFloat = 14.0
|
||||
let expandOffset: CGFloat = -expandFraction * maximumExpandOffset
|
||||
let buttonHeight: CGFloat = 44.0
|
||||
|
||||
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 {
|
||||
self.currentLeftButtons = leftButtons
|
||||
|
||||
var nextRegularButtonOrigin = sideInset
|
||||
var nextExpandedButtonOrigin = sideInset
|
||||
for spec in leftButtons.reversed() {
|
||||
let buttonNode: PeerInfoHeaderNavigationButton
|
||||
var wasAdded = false
|
||||
if let current = self.leftButtonNodes[spec.key] {
|
||||
if let current = self.leftButtonNodes[spec] {
|
||||
buttonNode = current
|
||||
} else {
|
||||
wasAdded = true
|
||||
buttonNode = PeerInfoHeaderNavigationButton()
|
||||
self.leftButtonNodes[spec.key] = buttonNode
|
||||
self.addSubnode(buttonNode)
|
||||
self.leftButtonNodes[spec] = buttonNode
|
||||
self.leftButtonsContainer.addSubview(buttonNode.view)
|
||||
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
|
||||
}
|
||||
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
|
||||
}
|
||||
}
|
||||
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: size.height)
|
||||
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
|
||||
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: buttonHeight)
|
||||
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 {
|
||||
nextExpandedButtonOrigin = nextButtonOrigin
|
||||
expandedLeftButtonsWidth += buttonSize.width
|
||||
} else {
|
||||
nextRegularButtonOrigin = nextButtonOrigin
|
||||
normalLeftButtonsWidth += buttonSize.width
|
||||
}
|
||||
let alphaFactor: CGFloat
|
||||
if case .back = spec.key {
|
||||
|
|
@ -126,48 +153,40 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||
} else {
|
||||
alphaFactor = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
|
||||
}
|
||||
|
||||
if wasAdded {
|
||||
buttonNode.frame = buttonFrame
|
||||
buttonNode.alpha = 0.0
|
||||
ComponentTransition.immediate.setBlur(layer: buttonNode.layer, radius: maxBlur)
|
||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: self.canBeExpanded, transition: .immediate)
|
||||
|
||||
transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: CGPoint(x: canBeExpanded ? -8.0 : 0.0, y: 0.0))
|
||||
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: 0.0)
|
||||
buttonNode.updateContentsColor(contentsColor: spec.isForExpandedView ? expandedButtonContentsColor : normalButtonContentsColor, transition: .immediate)
|
||||
} else {
|
||||
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
|
||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
|
||||
}
|
||||
}
|
||||
var removeKeys: [PeerInfoHeaderNavigationButtonKey] = []
|
||||
for (key, _) in self.leftButtonNodes {
|
||||
if !leftButtons.contains(where: { $0.key == key }) {
|
||||
removeKeys.append(key)
|
||||
var removeKeys: [PeerInfoHeaderNavigationButtonSpec] = []
|
||||
for (spec, _) in self.leftButtonNodes {
|
||||
if !leftButtons.contains(where: { $0 == spec }) {
|
||||
removeKeys.append(spec)
|
||||
}
|
||||
}
|
||||
for key in removeKeys {
|
||||
if let buttonNode = self.leftButtonNodes.removeValue(forKey: key) {
|
||||
buttonNode.removeFromSupernode()
|
||||
for spec in removeKeys {
|
||||
if let buttonNode = self.leftButtonNodes.removeValue(forKey: spec) {
|
||||
buttonNode.view.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var nextRegularButtonOrigin = sideInset
|
||||
var nextExpandedButtonOrigin = sideInset
|
||||
for spec in leftButtons.reversed() {
|
||||
if let buttonNode = self.leftButtonNodes[spec.key] {
|
||||
if let buttonNode = self.leftButtonNodes[spec] {
|
||||
let buttonSize = buttonNode.bounds.size
|
||||
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
|
||||
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
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: spec.isForExpandedView ? expandedLeftButtonsWidth : normalLeftButtonsWidth, y: 0.0), size: buttonSize)
|
||||
if spec.isForExpandedView {
|
||||
nextExpandedButtonOrigin = nextButtonOrigin
|
||||
expandedLeftButtonsWidth += buttonSize.width
|
||||
} else {
|
||||
nextRegularButtonOrigin = nextButtonOrigin
|
||||
normalLeftButtonsWidth += buttonSize.width
|
||||
}
|
||||
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
|
||||
let alphaFactor: CGFloat
|
||||
|
|
@ -182,16 +201,17 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||
buttonTransition = .animated(duration: duration * 0.25, curve: curve)
|
||||
}
|
||||
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 {
|
||||
self.currentRightButtons = rightButtons
|
||||
|
||||
var nextRegularButtonOrigin = size.width - sideInset - 8.0
|
||||
var nextExpandedButtonOrigin = size.width - expandedSideInset
|
||||
for spec in rightButtons.reversed() {
|
||||
let buttonNode: PeerInfoHeaderNavigationButton
|
||||
var wasAdded = false
|
||||
|
|
@ -201,32 +221,30 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||
key = .moreSearchSort
|
||||
}
|
||||
|
||||
if let current = self.rightButtonNodes[key] {
|
||||
if let current = self.rightButtonNodes[spec] {
|
||||
buttonNode = current
|
||||
} else {
|
||||
wasAdded = true
|
||||
buttonNode = PeerInfoHeaderNavigationButton()
|
||||
self.rightButtonNodes[key] = buttonNode
|
||||
self.addSubnode(buttonNode)
|
||||
self.rightButtonNodes[spec] = buttonNode
|
||||
self.rightButtonsContainer.addSubview(buttonNode.view)
|
||||
}
|
||||
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
|
||||
}
|
||||
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
|
||||
}
|
||||
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: size.height)
|
||||
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize)
|
||||
nextButtonOrigin -= buttonSize.width + 15.0
|
||||
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: buttonHeight)
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: spec.isForExpandedView ? expandedRightButtonsWidth : normalRightButtonsWidth, y: 0.0), size: buttonSize)
|
||||
if spec.isForExpandedView {
|
||||
nextExpandedButtonOrigin = nextButtonOrigin
|
||||
expandedRightButtonsWidth += buttonSize.width
|
||||
} else {
|
||||
nextRegularButtonOrigin = nextButtonOrigin
|
||||
normalRightButtonsWidth += buttonSize.width
|
||||
}
|
||||
let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
|
||||
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 key == .moreSearchSort || key == .searchWithTags || key == .standaloneSearch {
|
||||
|
|
@ -236,62 +254,51 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||
|
||||
buttonNode.frame = buttonFrame
|
||||
buttonNode.alpha = 0.0
|
||||
ComponentTransition.immediate.setBlur(layer: buttonNode.layer, radius: maxBlur)
|
||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
|
||||
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)
|
||||
}
|
||||
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
|
||||
} else {
|
||||
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
|
||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
|
||||
}
|
||||
}
|
||||
var removeKeys: [PeerInfoHeaderNavigationButtonKey] = []
|
||||
for (key, _) in self.rightButtonNodes {
|
||||
if key == .moreSearchSort {
|
||||
var removeKeys: [PeerInfoHeaderNavigationButtonSpec] = []
|
||||
for (spec, _) in self.rightButtonNodes {
|
||||
if spec.key == .moreSearchSort {
|
||||
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 }) {
|
||||
removeKeys.append(key)
|
||||
} else if !rightButtons.contains(where: { $0 == spec }) {
|
||||
removeKeys.append(spec)
|
||||
}
|
||||
}
|
||||
for key in removeKeys {
|
||||
if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) {
|
||||
if key == .moreSearchSort || key == .searchWithTags || key == .standaloneSearch {
|
||||
for spec in removeKeys {
|
||||
if let buttonNode = self.rightButtonNodes.removeValue(forKey: spec) {
|
||||
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?.removeFromSupernode()
|
||||
buttonNode?.view.removeFromSuperview()
|
||||
})
|
||||
buttonNode.layer.animateScale(from: 1.0, to: 0.001, duration: 0.2, removeOnCompletion: false)
|
||||
} else {
|
||||
buttonNode.removeFromSupernode()
|
||||
buttonNode.view.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var nextRegularButtonOrigin = size.width - sideInset - 8.0
|
||||
var nextExpandedButtonOrigin = size.width - expandedSideInset
|
||||
|
||||
for spec in rightButtons.reversed() {
|
||||
var key = spec.key
|
||||
if key == .more || key == .search || key == .sort {
|
||||
key = .moreSearchSort
|
||||
}
|
||||
|
||||
if let buttonNode = self.rightButtonNodes[key] {
|
||||
if let buttonNode = self.rightButtonNodes[spec] {
|
||||
let buttonSize = buttonNode.bounds.size
|
||||
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize)
|
||||
nextButtonOrigin -= buttonSize.width + 15.0
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: spec.isForExpandedView ? expandedRightButtonsWidth : normalRightButtonsWidth, y: 0.0), size: buttonSize)
|
||||
if spec.isForExpandedView {
|
||||
nextExpandedButtonOrigin = nextButtonOrigin
|
||||
expandedRightButtonsWidth += buttonSize.width
|
||||
} else {
|
||||
nextRegularButtonOrigin = nextButtonOrigin
|
||||
normalRightButtonsWidth += buttonSize.width
|
||||
}
|
||||
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
|
||||
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.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
ComponentTransition(transition).setBlur(layer: buttonNode.layer, radius: (1.0 - alphaFactor * alphaFactor) * maxBlur)
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import ProfileLevelInfoScreen
|
|||
import PlainButtonComponent
|
||||
import BundleIconComponent
|
||||
import MarqueeComponent
|
||||
import EdgeEffect
|
||||
|
||||
final class PeerInfoHeaderNavigationTransition {
|
||||
let sourceNavigationBar: NavigationBar
|
||||
|
|
@ -63,7 +64,7 @@ final class PeerInfoHeaderNavigationTransition {
|
|||
}
|
||||
}
|
||||
|
||||
final class PeerInfoHeaderRegularContentNode: ASDisplayNode {
|
||||
final class PeerInfoHeaderRegularContentNode: SparseNode {
|
||||
}
|
||||
|
||||
enum PeerInfoHeaderTextFieldNodeKey: Equatable {
|
||||
|
|
@ -90,6 +91,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
private var state: PeerInfoState?
|
||||
private var peer: Peer?
|
||||
private var threadData: MessageHistoryThreadData?
|
||||
private var isSearching: Bool = false
|
||||
private var avatarSize: CGFloat?
|
||||
|
||||
private let isOpenedFromChat: Bool
|
||||
|
|
@ -151,17 +153,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
let usernameNode: MultiScaleTextNode
|
||||
var actionButtonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderActionButtonNode] = [:]
|
||||
var buttonNodes: [PeerInfoHeaderButtonKey: PeerInfoHeaderButtonNode] = [:]
|
||||
let backgroundNode: NavigationBackgroundNode
|
||||
let expandedBackgroundNode: NavigationBackgroundNode
|
||||
let separatorNode: ASDisplayNode
|
||||
let navigationBackgroundNode: ASDisplayNode
|
||||
let navigationBackgroundBackgroundNode: ASDisplayNode
|
||||
let panelsExpansionBackgroundView: UIView
|
||||
let headerEdgeEffectView: EdgeEffectView
|
||||
var navigationTitle: String?
|
||||
let navigationTitleNode: ImmediateTextNode
|
||||
let navigationSeparatorNode: ASDisplayNode
|
||||
let navigationButtonContainer: PeerInfoHeaderNavigationButtonContainerNode
|
||||
let editingNavigationBackgroundNode: NavigationBackgroundNode
|
||||
let editingNavigationBackgroundSeparator: ASDisplayNode
|
||||
let searchContainer: ASDisplayNode
|
||||
let searchBarContainer: SparseNode
|
||||
let editingEdgeEffectView: EdgeEffectView
|
||||
|
||||
var musicBackground: UIView?
|
||||
var music: ComponentView<Empty>?
|
||||
|
|
@ -286,30 +284,16 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
self.avatarOverlayNode = PeerInfoEditingAvatarOverlayNode(context: context)
|
||||
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.editingNavigationBackgroundNode = NavigationBackgroundNode(color: .clear, enableBlur: true)
|
||||
self.editingNavigationBackgroundSeparator = ASDisplayNode()
|
||||
self.searchBarContainer = SparseNode()
|
||||
self.searchContainer = ASDisplayNode()
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: .clear)
|
||||
self.backgroundNode.isHidden = true
|
||||
self.backgroundNode.isUserInteractionEnabled = false
|
||||
self.expandedBackgroundNode = NavigationBackgroundNode(color: .clear)
|
||||
self.expandedBackgroundNode.isHidden = false
|
||||
self.expandedBackgroundNode.isUserInteractionEnabled = false
|
||||
self.panelsExpansionBackgroundView = UIView()
|
||||
self.headerEdgeEffectView = EdgeEffectView()
|
||||
self.headerEdgeEffectView.isUserInteractionEnabled = false
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.separatorNode.isLayerBacked = true
|
||||
self.editingEdgeEffectView = EdgeEffectView()
|
||||
self.editingEdgeEffectView.isUserInteractionEnabled = false
|
||||
|
||||
self.animationCache = context.animationCache
|
||||
self.animationRenderer = context.animationRenderer
|
||||
|
|
@ -320,8 +304,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
self?.requestUpdateLayout?(false)
|
||||
}
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.expandedBackgroundNode)
|
||||
self.view.addSubview(self.panelsExpansionBackgroundView)
|
||||
self.addSubnode(self.searchContainer)
|
||||
self.view.addSubview(self.headerEdgeEffectView)
|
||||
self.view.addSubview(self.backgroundBannerView)
|
||||
self.titleNodeContainer.addSubnode(self.titleNode)
|
||||
self.subtitleNodeContainer.addSubnode(self.subtitleNode)
|
||||
|
|
@ -346,14 +331,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
|
||||
self.addSubnode(self.editingContentNode)
|
||||
self.addSubnode(self.avatarOverlayNode)
|
||||
self.addSubnode(self.navigationBackgroundNode)
|
||||
self.navigationBackgroundNode.addSubnode(self.navigationBackgroundBackgroundNode)
|
||||
self.navigationBackgroundNode.addSubnode(self.navigationTitleNode)
|
||||
self.navigationBackgroundNode.addSubnode(self.navigationSeparatorNode)
|
||||
self.addSubnode(self.editingNavigationBackgroundNode)
|
||||
self.addSubnode(self.editingNavigationBackgroundSeparator)
|
||||
self.view.addSubview(self.editingEdgeEffectView)
|
||||
self.addSubnode(self.navigationButtonContainer)
|
||||
self.addSubnode(self.separatorNode)
|
||||
self.addSubnode(self.searchBarContainer)
|
||||
|
||||
self.avatarListNode.avatarContainerNode.tapped = { [weak self] in
|
||||
self?.initiateAvatarExpansion(gallery: false, first: false)
|
||||
|
|
@ -509,7 +489,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
private var currentStatusIcon: CredibilityIcon?
|
||||
|
||||
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 let previous = self.appliedCustomNavigationContentNode {
|
||||
transition.updateAlpha(node: previous, alpha: 0.0, completion: { [weak previous] _ in
|
||||
|
|
@ -536,11 +516,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
self.state = state
|
||||
self.peer = peer
|
||||
self.threadData = threadData
|
||||
self.isSearching = isSearching
|
||||
self.avatarListNode.listContainerNode.peer = peer.flatMap(EnginePeer.init)
|
||||
|
||||
let isFirstTime = self.validLayout == nil
|
||||
self.validLayout = (width, statusBarHeight, deviceMetrics)
|
||||
|
||||
self.searchBarContainer.isUserInteractionEnabled = isSearching
|
||||
self.searchContainer.isUserInteractionEnabled = isSearching
|
||||
|
||||
let previousPanelStatusData = self.currentPanelStatusData
|
||||
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)
|
||||
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
|
||||
|
|
@ -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))
|
||||
|
||||
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 collapsedHeaderNavigationContentsAccentColor = presentationData.theme.list.itemAccentColor
|
||||
let expandedAvatarNavigationContentsAccentColor: UIColor = .white
|
||||
|
|
@ -674,7 +654,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
|
||||
let regularHeaderButtonBackgroundColor: UIColor
|
||||
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 collapsedHeaderContentButtonForegroundColor = presentationData.theme.list.itemAccentColor
|
||||
|
|
@ -745,61 +725,21 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
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
|
||||
if state.isEditing {
|
||||
editingBackgroundAlpha = max(0.0, min(1.0, contentOffset / 20.0))
|
||||
} else {
|
||||
editingBackgroundAlpha = 0.0
|
||||
}
|
||||
|
||||
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)
|
||||
ComponentTransition(transition).setAlpha(view: self.editingEdgeEffectView, alpha: editingBackgroundAlpha)
|
||||
|
||||
let backgroundBannerAlpha: CGFloat
|
||||
|
||||
var effectiveSeparatorAlpha: CGFloat
|
||||
/*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 {
|
||||
do {
|
||||
let backgroundTransitionStepDistance: CGFloat = 50.0
|
||||
var backgroundTransitionDistance: CGFloat = navigationHeight + panelWithAvatarHeight - backgroundTransitionStepDistance
|
||||
if self.isSettings || self.isMyProfile {
|
||||
|
|
@ -812,9 +752,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
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 {
|
||||
backgroundBannerAlpha = 0.0
|
||||
} else {
|
||||
|
|
@ -826,8 +763,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
}
|
||||
navigationTransition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: backgroundBannerAlpha)
|
||||
|
||||
effectiveSeparatorAlpha = innerBackgroundTransitionFraction
|
||||
|
||||
self.avatarClippingNode.clipsToBounds = true
|
||||
}
|
||||
|
||||
|
|
@ -1161,7 +1096,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
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.subtitleNode.updateTintColor(color: navigationContentsSecondaryColor, transition: navigationTransition)
|
||||
|
|
@ -1189,25 +1127,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
self.avatarListNode.listContainerNode.currentItemNode?.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
|
||||
var expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight)
|
||||
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 titleLockOffset: CGFloat = 7.0 + singleTitleLockOffset
|
||||
let titleLockOffset: CGFloat = 16.0 + singleTitleLockOffset
|
||||
let titleMaxLockOffset: CGFloat = 7.0
|
||||
let titleOffset: CGFloat
|
||||
let titleCollapseFraction: CGFloat
|
||||
|
|
@ -1697,38 +1616,37 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
|
||||
let paneAreaExpansionDistance: CGFloat = 32.0
|
||||
let effectiveAreaExpansionFraction: CGFloat
|
||||
let realAreaExpansionFraction: CGFloat
|
||||
if state.isEditing {
|
||||
effectiveAreaExpansionFraction = 0.0
|
||||
realAreaExpansionFraction = effectiveAreaExpansionFraction
|
||||
} else if isSettings || isMyProfile {
|
||||
var paneAreaExpansionDelta = (self.frame.maxY - navigationHeight) - contentOffset
|
||||
paneAreaExpansionDelta = max(0.0, min(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 {
|
||||
var paneAreaExpansionDelta = (paneContainerY - navigationHeight) - contentOffset
|
||||
paneAreaExpansionDelta = max(0.0, min(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: [
|
||||
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
|
||||
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
|
||||
], transition: transition)
|
||||
|
||||
let subtitleAlpha: CGFloat
|
||||
transition.updateAlpha(node: self.titleNode, alpha: isSearching ? 0.0 : 1.0)
|
||||
|
||||
var subtitleAlpha: CGFloat
|
||||
var subtitleOffset: CGFloat = 0.0
|
||||
let panelSubtitleAlpha: CGFloat
|
||||
var panelSubtitleAlpha: CGFloat
|
||||
var panelSubtitleOffset: CGFloat = 0.0
|
||||
if self.isSettings {
|
||||
subtitleAlpha = 1.0 - titleCollapseFraction
|
||||
|
|
@ -1755,6 +1673,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isSearching {
|
||||
subtitleAlpha = 0.0
|
||||
panelSubtitleAlpha = 0.0
|
||||
}
|
||||
|
||||
self.subtitleNode.update(stateFractions: [
|
||||
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
|
||||
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
|
||||
|
|
@ -2465,18 +2389,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
let backgroundFrame: CGRect
|
||||
let separatorFrame: CGRect
|
||||
|
||||
var resolvedHeight: CGFloat
|
||||
|
||||
if state.isEditing {
|
||||
resolvedHeight = editingContentHeight
|
||||
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 {
|
||||
resolvedHeight = resolvedRegularHeight
|
||||
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)))
|
||||
|
|
@ -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 {
|
||||
transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame)
|
||||
self.backgroundNode.update(size: self.backgroundNode.bounds.size, transition: transition)
|
||||
transition.updateFrameAdditive(node: self.expandedBackgroundNode, frame: backgroundFrame)
|
||||
self.expandedBackgroundNode.update(size: self.expandedBackgroundNode.bounds.size, transition: transition)
|
||||
transition.updateFrameAdditive(node: self.separatorNode, frame: separatorFrame)
|
||||
transition.updateFrameAdditive(layer: self.headerEdgeEffectView.layer, frame: edgeEffectFrame)
|
||||
transition.updateFrameAdditive(view: self.panelsExpansionBackgroundView, frame: panelsExpansionBackgroundFrame)
|
||||
} else {
|
||||
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
|
||||
self.backgroundNode.update(size: self.backgroundNode.bounds.size, transition: transition)
|
||||
transition.updateFrame(node: self.expandedBackgroundNode, frame: backgroundFrame)
|
||||
self.expandedBackgroundNode.update(size: self.expandedBackgroundNode.bounds.size, transition: transition)
|
||||
transition.updateFrame(node: self.separatorNode, frame: separatorFrame)
|
||||
transition.updateFrame(view: self.headerEdgeEffectView, frame: edgeEffectFrame)
|
||||
transition.updateFrame(view: self.panelsExpansionBackgroundView, frame: panelsExpansionBackgroundFrame)
|
||||
}
|
||||
|
||||
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 !isSettings && !isMyProfile {
|
||||
if self.isAvatarExpanded {
|
||||
|
|
@ -2775,8 +2705,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
guard let result = super.hitTest(point, with: event) else {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -10622,7 +10622,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
switch status {
|
||||
case .available:
|
||||
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(
|
||||
sourceView: rightButton.view,
|
||||
sourceRect: rightButton.view.bounds,
|
||||
|
|
@ -11452,7 +11452,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
|
||||
if self.isSettings {
|
||||
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 {
|
||||
result.present(strongSelf.context, navigationController, { [weak self] mode, controller in
|
||||
if let strongSelf = self {
|
||||
|
|
@ -11482,7 +11482,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
}, searchBarIsExternal: true)
|
||||
}
|
||||
} 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))
|
||||
}, updateActivity: { _ 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()
|
||||
})
|
||||
}, fieldStyle: .glass)
|
||||
}
|
||||
|
||||
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?.activate(insertSubnode: { [weak self] subnode, isSearchBar in
|
||||
if let strongSelf = self, let navigationBar = strongSelf.controller?.navigationBar {
|
||||
strongSelf.insertSubnode(subnode, belowSubnode: navigationBar)
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if isSearchBar {
|
||||
self.headerNode.searchBarContainer.addSubnode(subnode)
|
||||
} else {
|
||||
self.headerNode.searchContainer.addSubnode(subnode)
|
||||
}
|
||||
}, placeholder: nil)
|
||||
|
||||
|
|
@ -11627,12 +11632,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
if let navigationBar = self.controller?.navigationBar {
|
||||
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?
|
||||
|
||||
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
|
||||
}
|
||||
guard let controller = self.controller else {
|
||||
|
|
@ -12582,8 +12590,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
}
|
||||
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 headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight))
|
||||
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: layout.size.height))
|
||||
if additive {
|
||||
transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame)
|
||||
} else {
|
||||
|
|
@ -12967,7 +12975,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
}
|
||||
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
|
||||
|
|
@ -12996,11 +13004,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
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)
|
||||
|
||||
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 rightNavigationButtons: [PeerInfoHeaderNavigationButtonSpec] = []
|
||||
|
|
@ -13074,6 +13085,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
switch previousItem {
|
||||
case .close, .item:
|
||||
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)
|
||||
|
|
@ -14597,7 +14609,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
|
|||
}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1020,6 +1020,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||
let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false)
|
||||
searchBarNode = SearchBarNode(
|
||||
theme: searchBarTheme,
|
||||
presentationTheme: environment.theme,
|
||||
strings: environment.strings,
|
||||
fieldStyle: .modern,
|
||||
displayBackground: false
|
||||
|
|
|
|||
|
|
@ -478,6 +478,7 @@ final class PeerSelectionScreenComponent: Component {
|
|||
let searchBarTheme = SearchBarNodeTheme(theme: environment.theme, hasSeparator: false)
|
||||
searchBarNode = SearchBarNode(
|
||||
theme: searchBarTheme,
|
||||
presentationTheme: environment.theme,
|
||||
strings: environment.strings,
|
||||
fieldStyle: .modern,
|
||||
displayBackground: false
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ public final class NavigationSearchView: UIView {
|
|||
accent: params.theme.chat.inputPanel.panelControlAccentColor,
|
||||
keyboard: params.theme.rootController.keyboardColor
|
||||
),
|
||||
presentationTheme: params.theme,
|
||||
strings: params.strings,
|
||||
fieldStyle: .inlineNavigation,
|
||||
icon: .loupe,
|
||||
|
|
|
|||
|
|
@ -573,7 +573,7 @@ final class ContactsSearchNavigationContentNode: NavigationBarContentNode {
|
|||
init(presentationData: PresentationData, dismissSearch: @escaping () -> Void, updateSearchQuery: @escaping (String) -> Void) {
|
||||
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)
|
||||
|
||||
super.init()
|
||||
|
|
@ -617,7 +617,7 @@ final class ContactsSearchNavigationContentNode: NavigationBarContentNode {
|
|||
|
||||
func updatePresentationData(_ 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ final class WebSearchNavigationContentNode: NavigationBarContentNode {
|
|||
self.theme = theme
|
||||
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.placeholderString = NSAttributedString(string: attachment ? strings.Attachment_SearchWeb : strings.Common_Search, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputPlaceholderTextColor)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue