This commit is contained in:
Isaac 2025-12-10 00:16:36 +08:00
parent dca1f06e91
commit 0c3530d8a8
105 changed files with 1034 additions and 880 deletions

View file

@ -440,21 +440,57 @@ class TargetBuilder {
}
}
// Add SDK frameworks
// Collect SDK frameworks from this module and all transitive dependencies
var allSdkFrameworks: Set<String> = []
if let sdkFrameworks = module.sdkFrameworks {
for framework in sdkFrameworks {
let fileRef = PBXFileReference(
sourceTree: .sdkRoot,
name: "\(framework).framework",
lastKnownFileType: "wrapper.framework",
path: "System/Library/Frameworks/\(framework).framework"
)
pbxproj.add(object: fileRef)
let buildFile = PBXBuildFile(file: fileRef)
pbxproj.add(object: buildFile)
frameworksPhase.files?.append(buildFile)
allSdkFrameworks.formUnion(sdkFrameworks)
}
for depName in allDeps {
if let depModule = modules[depName], let depFrameworks = depModule.sdkFrameworks {
allSdkFrameworks.formUnion(depFrameworks)
}
}
// Add SDK frameworks
for framework in allSdkFrameworks {
let fileRef = PBXFileReference(
sourceTree: .sdkRoot,
name: "\(framework).framework",
lastKnownFileType: "wrapper.framework",
path: "System/Library/Frameworks/\(framework).framework"
)
pbxproj.add(object: fileRef)
let buildFile = PBXBuildFile(file: fileRef)
pbxproj.add(object: buildFile)
frameworksPhase.files?.append(buildFile)
}
// Collect SDK dylibs from this module and all transitive dependencies
var allSdkDylibs: Set<String> = []
if let sdkDylibs = module.sdkDylibs {
allSdkDylibs.formUnion(sdkDylibs)
}
for depName in allDeps {
if let depModule = modules[depName], let depDylibs = depModule.sdkDylibs {
allSdkDylibs.formUnion(depDylibs)
}
}
// Add SDK dylibs (system libraries like libz, libiconv, etc.)
for dylib in allSdkDylibs {
// Clean up the library name - remove 'lib' prefix if present
let libName = dylib.hasPrefix("lib") ? String(dylib.dropFirst(3)) : dylib
let fileRef = PBXFileReference(
sourceTree: .sdkRoot,
name: "lib\(libName).tbd",
lastKnownFileType: "sourcecode.text-based-dylib-definition",
path: "usr/lib/lib\(libName).tbd"
)
pbxproj.add(object: fileRef)
let buildFile = PBXBuildFile(file: fileRef)
pbxproj.add(object: buildFile)
frameworksPhase.files?.append(buildFile)
}
}
}

View file

@ -1216,7 +1216,7 @@ public enum ChatHistoryListDisplayHeaders {
public enum ChatHistoryListMode: Equatable {
case bubbles
case list(search: Bool, reversed: Bool, reverseGroups: Bool, displayHeaders: ChatHistoryListDisplayHeaders, hintLinks: Bool, isGlobalSearch: Bool)
case list(reversed: Bool, reverseGroups: Bool, displayHeaders: ChatHistoryListDisplayHeaders, hintLinks: Bool, isGlobalSearch: Bool)
}
public protocol ChatControllerInteractionProtocol: AnyObject {

View file

@ -196,7 +196,6 @@ public final class BrowserBookmarksScreen: ViewController {
controllerInteraction: self.controllerInteraction,
selectedMessages: .single(nil),
mode: .list(
search: false,
reversed: false,
reverseGroups: false,
displayHeaders: .none,
@ -287,9 +286,9 @@ public final class BrowserBookmarksScreen: ViewController {
}
let tagMask: MessageTags = .webPage
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, hasBackground: true, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.context.account.peerId, threadId: nil, tagMask: tagMask, interfaceInteraction: self.controllerInteraction), cancel: { [weak self] in
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .navigation, placeholder: self.presentationData.strings.Common_Search, hasBackground: true, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.context.account.peerId, threadId: nil, tagMask: tagMask, interfaceInteraction: self.controllerInteraction), cancel: { [weak self] in
self?.controller?.deactivateSearch()
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in
@ -372,7 +371,9 @@ public final class BrowserBookmarksScreen: ViewController {
self.openUrl = openUrl
self.addBookmark = addBookmark
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.navigationPresentation = .modal
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
@ -435,7 +436,7 @@ public final class BrowserBookmarksScreen: ViewController {
private func updateThemeAndStrings() {
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.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
}

View file

@ -1,22 +0,0 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ChatListSearchItemNode",
module_name = "ChatListSearchItemNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/SearchBarNode:SearchBarNode",
],
visibility = [
"//visibility:public",
],
)

View file

@ -1,168 +0,0 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import TelegramPresentationData
import SearchBarNode
private let searchBarFont = Font.regular(17.0)
public protocol ChatListSearchItemNeighbour: ListViewItem {
var isPinned: Bool { get }
}
public class ChatListSearchItem: ListViewItem {
public let selectable: Bool = false
public let theme: PresentationTheme
public let isEnabled: Bool
private let placeholder: String
private let activate: () -> Void
public init(theme: PresentationTheme, isEnabled: Bool = true, placeholder: String, activate: @escaping () -> Void) {
self.theme = theme
self.isEnabled = isEnabled
self.placeholder = placeholder
self.activate = activate
}
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
async {
let node = ChatListSearchItemNode()
node.placeholder = self.placeholder
let makeLayout = node.asyncLayout()
var nextIsPinned = false
if let nextItem = nextItem as? ChatListSearchItemNeighbour, nextItem.isPinned {
nextIsPinned = true
}
let (layout, apply) = makeLayout(self, params, nextIsPinned, self.isEnabled)
node.contentSize = layout.contentSize
node.insets = layout.insets
node.activate = self.activate
Queue.mainQueue().async {
completion(node, {
return (nil, { _ in
apply(false)
})
})
}
}
}
public func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
Queue.mainQueue().async {
if let nodeValue = node() as? ChatListSearchItemNode {
nodeValue.placeholder = self.placeholder
let layout = nodeValue.asyncLayout()
async {
var nextIsPinned = false
if let nextItem = nextItem as? ChatListSearchItemNeighbour, nextItem.isPinned {
nextIsPinned = true
}
let (nodeLayout, apply) = layout(self, params, nextIsPinned, self.isEnabled)
Queue.mainQueue().async {
completion(nodeLayout, { _ in
apply(animation.isAnimated)
})
}
}
}
}
}
}
public class ChatListSearchItemNode: ListViewItemNode {
public let searchBarNode: SearchBarPlaceholderNode
private var disabledOverlay: ASDisplayNode?
public var placeholder: String?
fileprivate var activate: (() -> Void)? {
didSet {
self.searchBarNode.activate = self.activate
}
}
required public init() {
self.searchBarNode = SearchBarPlaceholderNode(fieldStyle: .modern)
super.init(layerBacked: false, dynamicBounce: false)
self.addSubnode(self.searchBarNode)
}
override public func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
let makeLayout = self.asyncLayout()
var nextIsPinned = false
if let nextItem = nextItem as? ChatListSearchItemNeighbour, nextItem.isPinned {
nextIsPinned = true
}
let (layout, apply) = makeLayout(item as! ChatListSearchItem, params, nextIsPinned, (item as! ChatListSearchItem).isEnabled)
apply(false)
self.contentSize = layout.contentSize
self.insets = layout.insets
}
public func asyncLayout() -> (_ item: ChatListSearchItem, _ params: ListViewItemLayoutParams, _ nextIsPinned: Bool, _ isEnabled: Bool) -> (ListViewItemNodeLayout, (Bool) -> Void) {
let searchBarNodeLayout = self.searchBarNode.asyncLayout()
let placeholder = self.placeholder
return { [weak self] item, params, nextIsPinned, isEnabled in
let baseWidth = params.width - params.leftInset - params.rightInset
let backgroundColor = nextIsPinned ? item.theme.chatList.pinnedItemBackgroundColor : item.theme.chatList.itemBackgroundColor
let placeholderColor = item.theme.list.itemSecondaryTextColor
let placeholderString = NSAttributedString(string: placeholder ?? "", font: searchBarFont, textColor: placeholderColor)
let (_, searchBarApply) = searchBarNodeLayout(placeholderString, placeholderString, CGSize(width: baseWidth - 20.0, height: 36.0), 1.0, placeholderColor, nextIsPinned ? item.theme.chatList.pinnedSearchBarColor : item.theme.chatList.regularSearchBarColor, backgroundColor, .immediate)
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 54.0), insets: UIEdgeInsets())
return (layout, { animated in
if let strongSelf = self {
let transition: ContainedViewLayoutTransition
if animated {
transition = .animated(duration: 0.3, curve: .easeInOut)
} else {
transition = .immediate
}
let searchBarFrame = CGRect(origin: CGPoint(x: params.leftInset + 10.0, y: 8.0), size: CGSize(width: baseWidth - 20.0, height: 36.0))
strongSelf.searchBarNode.frame = searchBarFrame
searchBarApply()
strongSelf.searchBarNode.bounds = CGRect(origin: CGPoint(), size: CGSize(width: baseWidth - 20.0, height: 36.0))
if !item.isEnabled {
if strongSelf.disabledOverlay == nil {
let disabledOverlay = ASDisplayNode()
strongSelf.addSubnode(disabledOverlay)
strongSelf.disabledOverlay = disabledOverlay
if animated {
disabledOverlay.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
}
}
if let disabledOverlay = strongSelf.disabledOverlay {
disabledOverlay.backgroundColor = backgroundColor.withAlphaComponent(0.4)
disabledOverlay.frame = searchBarFrame
}
} else if let disabledOverlay = strongSelf.disabledOverlay {
strongSelf.disabledOverlay = nil
if animated {
disabledOverlay.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak disabledOverlay] _ in
disabledOverlay?.removeFromSupernode()
})
} else {
disabledOverlay.removeFromSupernode()
}
}
transition.updateBackgroundColor(node: strongSelf, color: backgroundColor)
}
})
}
}
}

View file

@ -29,7 +29,6 @@ swift_library(
"//submodules/ActivityIndicator:ActivityIndicator",
"//submodules/SearchBarNode:SearchBarNode",
"//submodules/ChatListSearchRecentPeersNode:ChatListSearchRecentPeersNode",
"//submodules/ChatListSearchItemNode:ChatListSearchItemNode",
"//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
"//submodules/TemporaryCachedPeerDataManager:TemporaryCachedPeerDataManager",
"//submodules/PeerPresenceStatusManager:PeerPresenceStatusManager",

View file

@ -2946,6 +2946,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return
}
#if DEBUG
if "".isEmpty {
(self.navigationController as? NavigationController)?.pushViewController(oldChannelsController(context: self.context, intent: .join, completed: { value in
}))
return
}
#endif
var reachedCountLimit = false
var premiumNeeded = false
var hasActiveCall = false
@ -4668,8 +4676,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
public private(set) var isSearchActive: Bool = false
public func activateSearch(filter: ChatListSearchFilter, query: String? = nil) {
self.activateSearchInternal(isFromTabBar: false, filter: filter, query: query)
}
public func activateSearchInternal(isFromTabBar: Bool, filter: ChatListSearchFilter, query: String? = nil) {
var searchContentNode: NavigationBarSearchContentNode?
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View {
if !isFromTabBar, let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View {
searchContentNode = navigationBarView.searchContentNode
}
@ -4714,7 +4726,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
do {
let displaySearchFilters = true
if let filterContainerNodeAndActivate = await self.chatListDisplayNode.activateSearch(placeholderNode: searchContentNode?.placeholderNode, displaySearchFilters: displaySearchFilters, hasDownloads: self.hasDownloads, initialFilter: filter, navigationController: self.navigationController as? NavigationController, searchBarIsExternal: true) {
if let filterContainerNodeAndActivate = await self.chatListDisplayNode.activateSearch(placeholderNode: searchContentNode?.placeholderNode, displaySearchFilters: displaySearchFilters, hasDownloads: self.hasDownloads, initialFilter: filter, navigationController: self.navigationController as? NavigationController, searchBarIsExternal: searchContentNode == nil) {
let activate = filterContainerNodeAndActivate
activate(filter != .downloads)
@ -4726,10 +4738,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let transition: ContainedViewLayoutTransition = .animated(duration: 0.4, curve: .spring)
self.setDisplayNavigationBar(false, transition: transition)
self.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: true), transition: transition)
if let searchBarNode = self.currentTabBarSearchNode?() as? SearchBarNode {
self.chatListDisplayNode.searchDisplayController?.setSearchBar(searchBarNode)
searchBarNode.activate()
if searchContentNode == nil {
self.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: true), transition: transition)
if let searchBarNode = self.currentTabBarSearchNode?() as? SearchBarNode {
self.chatListDisplayNode.searchDisplayController?.setSearchBar(searchBarNode)
searchBarNode.activate()
}
} else {
(self.parent as? TabBarController)?.updateIsTabBarHidden(true, transition: transition)
}
self.isSearchActive = true
@ -4791,6 +4808,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
completion?()
self.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: false), transition: transition)
(self.parent as? TabBarController)?.updateIsTabBarHidden(false, transition: transition)
self.isSearchActive = false
if let navigationController = self.navigationController as? NavigationController {
@ -4814,14 +4832,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return
}
#if DEBUG
if "".isEmpty {
(self.navigationController as? NavigationController)?.pushViewController(oldChannelsController(context: self.context, intent: .join, completed: { value in
}))
return
}
#endif
guard let navigationController = self.navigationController as? NavigationController else {
return
}
@ -6256,7 +6266,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
override public func tabBarActivateSearch() {
self.activateSearch()
self.activateSearchInternal(isFromTabBar: true, filter: .chats, query: nil)
}
override public func tabBarDeactivateSearch() {

View file

@ -1098,7 +1098,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
private var toolbarNode: ToolbarNode?
var toolbarActionSelected: ((ToolbarActionOption) -> Void)?
private var isSearchDisplayControllerActive: Bool = false
private var isSearchDisplayControllerActive: ChatListNavigationBar.ActiveSearch?
private var skipSearchDisplayControllerLayout: Bool = false
private(set) var searchDisplayController: SearchDisplayController?
private var disappearingSearchDisplayController: SearchDisplayController?
@ -1556,8 +1556,8 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
strings: self.presentationData.strings,
statusBarHeight: layout.statusBarHeight ?? 0.0,
sideInset: layout.safeInsets.left,
search: nil, //ChatListNavigationBar.Search(isEnabled: true),
isSearchActive: self.isSearchDisplayControllerActive,
search: ChatListNavigationBar.Search(isEnabled: true),
activeSearch: self.isSearchDisplayControllerActive,
primaryContent: headerContent?.primaryContent,
secondaryContent: headerContent?.secondaryContent,
secondaryTransition: self.inlineStackContainerTransitionFraction,
@ -1654,7 +1654,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
}
var offset = resultingOffset
if self.isSearchDisplayControllerActive {
if self.isSearchDisplayControllerActive != nil {
offset = 0.0
}
@ -1715,8 +1715,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
var storiesInset = storiesInset
let navigationBarLayout = self.updateNavigationBar(layout: layout, deferScrollApplication: true, transition: ComponentTransition(transition))
//self.mainContainerNode.initialScrollingOffset = ChatListNavigationBar.searchScrollHeight + navigationBarLayout.storiesInset
self.mainContainerNode.initialScrollingOffset = navigationBarLayout.storiesInset
self.mainContainerNode.initialScrollingOffset = ChatListNavigationBar.searchScrollHeight + navigationBarLayout.storiesInset
navigationBarHeight = navigationBarLayout.navigationHeight
visualNavigationHeight = navigationBarLayout.navigationHeight
@ -1891,7 +1890,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
}, searchBarIsExternal: searchBarIsExternal)
}, fieldStyle: placeholderNode?.fieldStyle ?? .modern, searchBarIsExternal: searchBarIsExternal)
self.mainContainerNode.accessibilityElementsHidden = true
self.inlineStackContainerNode?.accessibilityElementsHidden = true
@ -1900,7 +1899,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
return
}
strongSelf.isSearchDisplayControllerActive = true
strongSelf.isSearchDisplayControllerActive = ChatListNavigationBar.ActiveSearch(isExternal: placeholderNode == nil)
strongSelf.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: cleanNavigationBarHeight, transition: .immediate)
strongSelf.searchDisplayController?.activate(insertSubnode: { [weak self] subnode, isSearchBar in
@ -1910,7 +1909,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
if isSearchBar {
if let navigationBarComponentView = self.navigationBarView.view as? ChatListNavigationBar.View {
navigationBarComponentView.addSubnode(subnode)
navigationBarComponentView.searchContentNode?.addSubnode(subnode)
}
} else {
self.insertSubnode(subnode, aboveSubnode: self.debugListView)
@ -1923,7 +1922,7 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
func deactivateSearch(placeholderNode: SearchBarPlaceholderNode?, animated: Bool) -> (() -> Void)? {
if let searchDisplayController = self.searchDisplayController {
self.isSearchDisplayControllerActive = false
self.isSearchDisplayControllerActive = nil
self.searchDisplayController = nil
self.disappearingSearchDisplayController = searchDisplayController
self.mainContainerNode.accessibilityElementsHidden = false

View file

@ -768,12 +768,15 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
filters = defaultAvailableSearchPanes(isForum: isForum, hasDownloads: self.hasDownloads, hasPublicPosts: self.showPublicPostsTab).map(\.filter)
}
var filtersSideInset: CGFloat = 12.0
if layout.insets(options: [.input]).bottom <= 84.0 {
filtersSideInset = 20.0
var filtersInsets = UIEdgeInsets(top: 0.0, left: 12.0, bottom: layout.insets(options: [.input]).bottom + 34.0, right: 12.0)
if layout.insets(options: [.input]).bottom <= 30.0 {
filtersInsets = ContainerViewLayout.concentricInsets(bottomInset: layout.insets(options: [.input]).bottom, innerDiameter: 40.0, sideInset: 32.0)
} else if layout.insets(options: [.input]).bottom <= 84.0 {
filtersInsets.left = 20.0
filtersInsets.right = filtersInsets.left
}
self.filterContainerNode.update(size: CGSize(width: layout.size.width - (layout.safeInsets.left + filtersSideInset) * 2.0, height: 40.0), sideInset: 0.0, filters: filters.map { .filter($0) }, displayGlobalPostsNewBadge: self.displayGlobalPostsNewBadge, selectedFilter: self.selectedFilter?.id, transitionFraction: self.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
self.filterContainerNode.update(size: CGSize(width: layout.size.width - (layout.safeInsets.left + filtersInsets.left) * 2.0, height: 40.0), sideInset: 0.0, filters: filters.map { .filter($0) }, displayGlobalPostsNewBadge: self.displayGlobalPostsNewBadge, selectedFilter: self.selectedFilter?.id, transitionFraction: self.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
@ -784,12 +787,20 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
let topInset = navigationBarHeight
var filtersSideInset: CGFloat = 12.0
if layout.insets(options: [.input]).bottom <= 84.0 {
filtersSideInset = 20.0
var filtersInsets = UIEdgeInsets(top: 0.0, left: 12.0, bottom: layout.insets(options: [.input]).bottom, right: 12.0)
if layout.insets(options: [.input]).bottom <= 30.0 {
filtersInsets = ContainerViewLayout.concentricInsets(bottomInset: layout.insets(options: [.input]).bottom, innerDiameter: 40.0, sideInset: 32.0)
} else if layout.insets(options: [.input]).bottom <= 84.0 {
filtersInsets.left = 20.0
filtersInsets.right = filtersInsets.left
} else {
if let inputHeight = layout.inputHeight, filtersInsets.bottom == inputHeight {
filtersInsets.bottom += 8.0
}
filtersInsets.bottom = max(8.0, filtersInsets.bottom)
}
transition.updateFrame(node: self.filterContainerNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + filtersSideInset, y: layout.size.height - layout.insets(options: [.input]).bottom - 40.0 + 6.0), size: CGSize(width: layout.size.width - (layout.safeInsets.left + filtersSideInset) * 2.0, height: 40.0)))
transition.updateFrame(node: self.filterContainerNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + filtersInsets.left, y: layout.size.height - filtersInsets.bottom - 40.0), size: CGSize(width: layout.size.width - (layout.safeInsets.left + filtersInsets.left) * 2.0, height: 40.0)))
self.updateFilterContainerNode(layout: layout, transition: transition)
if isFirstTime {

View file

@ -15,7 +15,6 @@ import PeerOnlineMarkerNode
import LocalizedPeerData
import PeerPresenceStatusManager
import PhotoResources
import ChatListSearchItemNode
import ContextUI
import ChatInterfaceState
import TextFormat
@ -454,7 +453,7 @@ private final class ChatListItemTagListComponent: Component {
}
}
public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
public class ChatListItem: ListViewItem {
public enum EnabledContextActions {
public struct Actions: OptionSet {
public var rawValue: Int32

View file

@ -489,7 +489,25 @@ public struct ComponentTransition {
}
public func setAlpha(view: UIView, alpha: CGFloat, delay: Double = 0.0, completion: ((Bool) -> Void)? = nil) {
self.setAlpha(layer: view.layer, alpha: alpha, delay: delay, completion: completion)
if view.alpha == alpha {
completion?(true)
return
}
switch self.animation {
case .none:
view.alpha = alpha
view.layer.removeAnimation(forKey: "opacity")
completion?(true)
case .curve:
let previousAlpha: Float
if view.layer.animation(forKey: "opacity") != nil {
previousAlpha = view.layer.presentation()?.opacity ?? Float(view.alpha)
} else {
previousAlpha = Float(view.alpha)
}
view.alpha = alpha
self.animateAlpha(layer: view.layer, from: CGFloat(previousAlpha), to: alpha, delay: delay, completion: completion)
}
}
public func setAlpha(layer: CALayer, alpha: CGFloat, delay: Double = 0.0, completion: ((Bool) -> Void)? = nil) {

View file

@ -1664,7 +1664,7 @@ final class ComposePollScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -22,7 +22,6 @@ swift_library(
"//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
"//submodules/ItemListPeerItem:ItemListPeerItem",
"//submodules/ContactsPeerItem:ContactsPeerItem",
"//submodules/ChatListSearchItemNode:ChatListSearchItemNode",
"//submodules/TelegramPermissionsUI:TelegramPermissionsUI",
"//submodules/TelegramNotices:TelegramNotices",
"//submodules/AlertUI:AlertUI",

View file

@ -16,7 +16,6 @@ import AccountContext
import TelegramPermissions
import TelegramNotices
import ContactsPeerItem
import ChatListSearchItemNode
import ChatListSearchItemHeader
import SearchUI
import TelegramPermissionsUI
@ -96,7 +95,6 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
var hasUnseenCloseFriends: Bool
}
case search(PresentationTheme, PresentationStrings)
case sort(PresentationTheme, PresentationStrings, ContactsSortOrder)
case permissionInfo(PresentationTheme, String, String, Bool)
case permissionEnable(PresentationTheme, String)
@ -107,8 +105,6 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
var stableId: ContactListNodeEntryId {
switch self {
case .search:
return .search
case .sort:
return .sort
case .permissionInfo:
@ -133,10 +129,6 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
func item(context: AccountContext, presentationData: PresentationData, interaction: ContactListNodeInteraction, isSearch: Bool, listStyle: ItemListStyle) -> ListViewItem {
switch self {
case let .search(theme, strings):
return ChatListSearchItem(theme: theme, placeholder: strings.Contacts_SearchLabel, activate: {
interaction.activateSearch()
})
case let .sort(_, strings, sortOrder):
var text = strings.Contacts_SortedByName
if case .presence = sortOrder {
@ -270,12 +262,6 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
static func ==(lhs: ContactListNodeEntry, rhs: ContactListNodeEntry) -> Bool {
switch lhs {
case let .search(lhsTheme, lhsStrings):
if case let .search(rhsTheme, rhsStrings) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings {
return true
} else {
return false
}
case let .sort(lhsTheme, lhsStrings, lhsSortOrder):
if case let .sort(rhsTheme, rhsStrings, rhsSortOrder) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsSortOrder == rhsSortOrder {
return true
@ -376,39 +362,35 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
static func <(lhs: ContactListNodeEntry, rhs: ContactListNodeEntry) -> Bool {
switch lhs {
case .search:
return true
case .sort:
switch rhs {
case .search:
return false
default:
return true
}
case .permissionInfo:
switch rhs {
case .search, .sort:
case .sort:
return false
default:
return true
}
case .permissionEnable:
switch rhs {
case .search, .sort, .permissionInfo:
case .sort, .permissionInfo:
return false
default:
return true
}
case .permissionLimited:
switch rhs {
case .search, .sort, .permissionInfo, .permissionEnable:
case .sort, .permissionInfo, .permissionEnable:
return false
default:
return true
}
case let .option(lhsIndex, _, _, _, _):
switch rhs {
case .search, .sort, .permissionInfo, .permissionEnable, .permissionLimited:
case .sort, .permissionInfo, .permissionEnable, .permissionLimited:
return false
case let .option(rhsIndex, _, _, _, _):
return lhsIndex < rhsIndex
@ -417,14 +399,14 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
}
case let .header(lhsIndex, _):
switch rhs {
case .search, .sort, .permissionInfo, .permissionEnable, .permissionLimited, .option:
case .sort, .permissionInfo, .permissionEnable, .permissionLimited, .option:
return false
case let .header(rhsIndex, _), let .peer(rhsIndex, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
return lhsIndex < rhsIndex
}
case let .peer(lhsIndex, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
switch rhs {
case .search, .sort, .permissionInfo, .permissionEnable, .permissionLimited, .option:
case .sort, .permissionInfo, .permissionEnable, .permissionLimited, .option:
return false
case let .peer(rhsIndex, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _), let .header(rhsIndex, _):
// if (lhsStoryData == nil) != (rhsStoryData == nil) {
@ -901,9 +883,6 @@ private func preparedContactListNodeTransition(context: AccountContext, presenta
switch entry {
case .sort:
shouldFixScroll = true
case .search:
//indexSections.apend(CollectionIndexNode.searchIndex)
break
case let .peer(_, _, _, header, _, _, _, _, _, _, _, _, _, _, _, _):
if let header = header as? ContactListNameIndexHeader {
if !existingSections.contains(header.letter) {
@ -1419,11 +1398,6 @@ public final class ContactListNode: ASDisplayNode {
var peerIndex = 0
loop: for entry in entries {
switch entry {
case .search:
if section == CollectionIndexNode.searchIndex {
strongSelf.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.PreferSynchronousDrawing, .PreferSynchronousResourceLoading], scrollToItem: ListViewScrollToItem(index: index, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: nil), directionHint: .Down), additionalScrollDistance: 0.0, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
break loop
}
case let .peer(_, _, _, header, _, _, _, _, _, _, _, _, _, _, _, _):
if let header = header as? ContactListNameIndexHeader {
if let scalar = UnicodeScalar(header.letter) {

View file

@ -342,7 +342,7 @@ public class ContactsController: ViewController {
}
self.contactsNode.contactListNode.activateSearch = { [weak self] in
self?.activateSearch()
self?.activateSearch(isFromTabBar: false)
}
self.contactsNode.contactListNode.openPeer = { [weak self] peer, _, _, _ in
@ -579,12 +579,17 @@ public class ContactsController: ViewController {
self.sortButton.contextAction?(self.sortButton.containerNode, nil)
}
private func activateSearch() {
self.contactsNode.activateSearch(placeholderNode: self.searchContentNode()?.placeholderNode)
self.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: true), transition: .animated(duration: 0.5, curve: .spring))
if let searchBarNode = self.currentTabBarSearchNode?() as? SearchBarNode {
self.contactsNode.searchDisplayController?.setSearchBar(searchBarNode)
searchBarNode.activate()
private func activateSearch(isFromTabBar: Bool) {
let placeholderNode = isFromTabBar ? nil : self.searchContentNode()?.placeholderNode
self.contactsNode.activateSearch(placeholderNode: placeholderNode)
if placeholderNode != nil {
(self.parent as? TabBarController)?.updateIsTabBarHidden(true, transition: .animated(duration: 0.5, curve: .spring))
} else {
self.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: true), transition: .animated(duration: 0.5, curve: .spring))
if let searchBarNode = self.currentTabBarSearchNode?() as? SearchBarNode {
self.contactsNode.searchDisplayController?.setSearchBar(searchBarNode)
searchBarNode.activate()
}
}
self.requestLayout(transition: .animated(duration: 0.5, curve: .spring))
}
@ -592,6 +597,7 @@ public class ContactsController: ViewController {
private func deactivateSearch(animated: Bool) {
self.contactsNode.deactivateSearch(placeholderNode: self.searchContentNode()?.placeholderNode, animated: animated)
self.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: false), transition: .animated(duration: 0.5, curve: .spring))
(self.parent as? TabBarController)?.updateIsTabBarHidden(false, transition: .animated(duration: 0.5, curve: .spring))
self.requestLayout(transition: .animated(duration: 0.5, curve: .spring))
}
@ -799,7 +805,7 @@ public class ContactsController: ViewController {
}
override public func tabBarActivateSearch() {
self.activateSearch()
self.activateSearch(isFromTabBar: true)
}
override public func tabBarDeactivateSearch() {

View file

@ -53,7 +53,7 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
private let context: AccountContext
private(set) var searchDisplayController: SearchDisplayController?
private var isSearchDisplayControllerActive: Bool = false
private var isSearchDisplayControllerActive: ChatListNavigationBar.ActiveSearch?
private var storiesUnlocked: Bool = false
private var containerLayout: (ContainerViewLayout, CGFloat)?
@ -360,8 +360,8 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
strings: self.presentationData.strings,
statusBarHeight: layout.statusBarHeight ?? 0.0,
sideInset: layout.safeInsets.left,
search: nil,//ChatListNavigationBar.Search(isEnabled: true),
isSearchActive: self.isSearchDisplayControllerActive,
search: ChatListNavigationBar.Search(isEnabled: true),
activeSearch: self.isSearchDisplayControllerActive,
primaryContent: primaryContent,
secondaryContent: nil,
secondaryTransition: 0.0,
@ -415,7 +415,7 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
private func updateNavigationScrolling(transition: ContainedViewLayoutTransition) {
var offset = self.getEffectiveNavigationScrollingOffset()
if self.isSearchDisplayControllerActive {
if self.isSearchDisplayControllerActive != nil {
offset = 0.0
}
@ -482,10 +482,10 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
return
}
self.isSearchDisplayControllerActive = true
self.isSearchDisplayControllerActive = ChatListNavigationBar.ActiveSearch(isExternal: placeholderNode == nil)
self.storiesUnlocked = false
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, contentNode: ContactsSearchContainerNode(context: self.context, glass: true, externalSearchBar: true, onlyWriteable: false, categories: [.cloudContacts, .global, .deviceContacts], addContact: { [weak self] phoneNumber in
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .navigation, contentNode: ContactsSearchContainerNode(context: self.context, glass: true, externalSearchBar: true, onlyWriteable: false, categories: [.cloudContacts, .global, .deviceContacts], addContact: { [weak self] phoneNumber in
if let requestAddContact = self?.requestAddContact {
requestAddContact(phoneNumber)
}
@ -503,14 +503,14 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
}, searchBarIsExternal: placeholderNode == nil)
}, fieldStyle: placeholderNode?.fieldStyle ?? .modern, searchBarIsExternal: placeholderNode == nil)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self] subnode, isSearchBar in
if let strongSelf = self {
if isSearchBar {
if let navigationBarComponentView = strongSelf.navigationBarView.view as? ChatListNavigationBar.View {
navigationBarComponentView.addSubnode(subnode)
navigationBarComponentView.searchContentNode?.addSubnode(subnode)
}
} else {
strongSelf.insertSubnode(subnode, aboveSubnode: strongSelf.contactListNode)
@ -520,21 +520,10 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
}
func deactivateSearch(placeholderNode: SearchBarPlaceholderNode?, animated: Bool) {
self.isSearchDisplayControllerActive = false
self.isSearchDisplayControllerActive = nil
if let searchDisplayController = self.searchDisplayController {
var previousFrame: CGRect?
if let placeholderNode {
let previousFrameValue = placeholderNode.frame
previousFrame = previousFrameValue
placeholderNode.frame = previousFrameValue.offsetBy(dx: 0.0, dy: 54.0)
}
searchDisplayController.deactivate(placeholder: placeholderNode, animated: animated)
self.searchDisplayController = nil
if let placeholderNode, let previousFrame {
placeholderNode.frame = previousFrame
}
}
}
}

View file

@ -293,7 +293,7 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings))
self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = glass ? .clear : UIColor.black.withAlphaComponent(0.5)
self.dimNode.backgroundColor = .clear
self.backgroundNode = ASDisplayNode()
self.backgroundNode.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
@ -693,8 +693,22 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
self.backgroundNode.frame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: navigationBarHeight))
self.listNode.frame = CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight), size: CGSize(width: layout.size.width, height: layout.size.height - topInset))
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right), duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
self.listNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: layout.size.height))
let listDuration: Double
let listCurve: ListViewAnimationCurve
switch transition {
case .immediate:
listDuration = 0.0
listCurve = .Default(duration: nil)
case let .animated(duration, curve):
listDuration = duration
if case .spring = curve {
listCurve = .Spring(duration: duration)
} else {
listCurve = .Default(duration: nil)
}
}
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: UIEdgeInsets(top: topInset, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right), duration: listDuration, curve: listCurve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
let size = layout.size
let sideInset = layout.safeInsets.left
@ -797,14 +811,14 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
}
let containerTransition = ContainedViewLayoutTransition.animated(duration: 0.3, curve: .easeInOut)
containerTransition.updateAlpha(node: strongSelf.listNode, alpha: isSearching ? 1.0 : 0.0)
containerTransition.updateAlpha(node: strongSelf.backgroundNode, alpha: isSearching ? 1.0 : 0.0)
//let containerTransition = ContainedViewLayoutTransition.animated(duration: 0.3, curve: .easeInOut)
ContainedViewLayoutTransition.immediate.updateAlpha(node: strongSelf.listNode, alpha: isSearching ? 1.0 : 0.0)
ContainedViewLayoutTransition.immediate.updateAlpha(node: strongSelf.backgroundNode, alpha: isSearching ? 1.0 : 0.0)
strongSelf.dimNode.isHidden = isSearching
containerTransition.updateAlpha(node: strongSelf.emptyResultsAnimationNode, alpha: emptyResults ? 1.0 : 0.0)
containerTransition.updateAlpha(node: strongSelf.emptyResultsTitleNode, alpha: emptyResults ? 1.0 : 0.0)
containerTransition.updateAlpha(node: strongSelf.emptyResultsTextNode, alpha: emptyResults ? 1.0 : 0.0)
ContainedViewLayoutTransition.immediate.updateAlpha(node: strongSelf.emptyResultsAnimationNode, alpha: emptyResults ? 1.0 : 0.0)
ContainedViewLayoutTransition.immediate.updateAlpha(node: strongSelf.emptyResultsTitleNode, alpha: emptyResults ? 1.0 : 0.0)
ContainedViewLayoutTransition.immediate.updateAlpha(node: strongSelf.emptyResultsTextNode, alpha: emptyResults ? 1.0 : 0.0)
strongSelf.emptyResultsAnimationNode.visibility = emptyResults
})
}

View file

@ -36,8 +36,9 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.navigationPresentation = .modal
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@ -86,7 +87,7 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr
private func updateThemeAndStrings() {
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.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.presentationData.strings.Contacts_InviteFriends
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View file

@ -518,7 +518,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -398,7 +398,7 @@ public final class AuthorizationSequenceCountrySelectionController: ViewControll
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: self.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in
@ -419,7 +419,7 @@ public final class AuthorizationSequenceCountrySelectionController: ViewControll
component: AnyComponentWithIdentity(id: "search", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Search",
tintColor: self.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -254,9 +254,7 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
let statusBarHeight: CGFloat = layout.statusBarHeight ?? 0.0
var defaultNavigationBarHeight: CGFloat
if self._presentedInModal && self._hasGlassStyle {
defaultNavigationBarHeight = 66.0
} else if self._presentedInModal && layout.orientation == .portrait {
defaultNavigationBarHeight = 60.0
defaultNavigationBarHeight = 68.0
} else {
defaultNavigationBarHeight = 60.0
}
@ -459,14 +457,29 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
}
if let navigationBar = self.navigationBar {
if let contentNode = navigationBar.contentNode, case .expansion = contentNode.mode, !self.displayNavigationBar {
navigationBarFrame.origin.y -= navigationLayout.defaultContentHeight
navigationBarFrame.size.height += contentNode.height + navigationLayout.defaultContentHeight + statusBarHeight
navigationBarFrame.origin.y -= navigationLayout.defaultContentHeight + statusBarHeight
navigationBarFrame.size.height += contentNode.height + navigationLayout.defaultContentHeight + statusBarHeight * 2.0
if self._presentedInModal && self._hasGlassStyle {
navigationBarFrame.size.height += 8.0
}
}
//navigationBar.backgroundColor = .blue
if let _ = navigationBar.contentNode, let _ = navigationBar.secondaryContentNode, !self.displayNavigationBar {
navigationBarFrame.size.height += navigationBar.secondaryContentHeight
}
navigationBar.updateLayout(size: navigationBarFrame.size, defaultHeight: navigationLayout.defaultContentHeight, additionalTopHeight: statusBarHeight, additionalContentHeight: self.additionalNavigationBarHeight, additionalBackgroundHeight: additionalBackgroundHeight, additionalCutout: additionalCutout, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, appearsHidden: !self.displayNavigationBar, isLandscape: isLandscape, transition: transition)
var additionalTopHeight = statusBarHeight
if !self.displayNavigationBar {
additionalTopHeight -= statusBarHeight
if statusBarHeight != 0.0 {
additionalTopHeight += 6.0
}
}
if self._presentedInModal && self._hasGlassStyle {
additionalTopHeight += 8.0
}
navigationBar.updateLayout(size: navigationBarFrame.size, defaultHeight: navigationLayout.defaultContentHeight, additionalTopHeight: additionalTopHeight, additionalContentHeight: self.additionalNavigationBarHeight, additionalBackgroundHeight: additionalBackgroundHeight, additionalCutout: additionalCutout, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, appearsHidden: !self.displayNavigationBar, isLandscape: isLandscape, transition: transition)
if !transition.isAnimated {
navigationBar.layer.removeAnimation(forKey: "bounds")
navigationBar.layer.removeAnimation(forKey: "position")

View file

@ -1393,7 +1393,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
component: AnyComponentWithIdentity(id: isPickingLocation ? "back" : "close", component: AnyComponent(
BundleIconComponent(
name: isPickingLocation ? "Navigation/Back" : "Navigation/Close",
tintColor: self.presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in
@ -1428,7 +1428,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
component: AnyComponentWithIdentity(id: "search", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Search",
tintColor: self.presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -2586,7 +2586,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
component: AnyComponentWithIdentity(id: isBack ? "back" : "close", component: AnyComponent(
BundleIconComponent(
name: isBack ? "Navigation/Back" : "Navigation/Close",
tintColor: self.presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in
@ -2619,7 +2619,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
content: LottieComponent.AppBundleContent(
name: "anim_morewide"
),
color: self.presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor,
color: self.presentationData.theme.chat.inputPanel.panelControlColor,
size: CGSize(width: 34.0, height: 34.0),
playOnce: self.moreButtonPlayOnce
)

View file

@ -242,7 +242,7 @@ private final class CreateExternalMediaStreamScreenComponent: CombinedComponent
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -164,7 +164,7 @@ private final class ChannelDiscussionSearchNavigationContentNode: NavigationBarC
primaryText: theme.chat.inputPanel.panelControlColor,
placeholder: theme.chat.inputPanel.inputPlaceholderColor,
inputIcon: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.panelControlColor,
accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor
),

View file

@ -685,7 +685,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -79,7 +79,7 @@ final class GroupInfoSearchNavigationContentNode: NavigationBarContentNode, Item
primaryText: theme.chat.inputPanel.panelControlColor,
placeholder: theme.chat.inputPanel.inputPlaceholderColor,
inputIcon: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.panelControlColor,
accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor
),

View file

@ -163,7 +163,7 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -864,7 +864,7 @@ private final class LimitSheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -170,7 +170,7 @@ private final class SheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -21,6 +21,8 @@ swift_library(
"//submodules/AvatarNode:AvatarNode",
"//submodules/AccountContext:AccountContext",
"//submodules/TelegramUI/Components/EmojiStatusComponent",
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
"//submodules/Components/ComponentDisplayAdapters",
],
visibility = [
"//visibility:public",

View file

@ -11,6 +11,7 @@ import AvatarNode
import AccountContext
import ComponentFlow
import EmojiStatusComponent
import ComponentDisplayAdapters
private func generateLoupeIcon(color: UIColor) -> UIImage? {
return generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Loupe"), color: color)
@ -549,7 +550,10 @@ private class SearchBarTextField: UITextField, UIScrollViewDelegate {
super.init(frame: CGRect())
self.addSubnode(self.placeholderLabel)
if case .glass = style {
} else {
self.addSubnode(self.placeholderLabel)
}
self.addSubnode(self.prefixLabel)
self.addSubnode(self.clippingNode)
self.clippingNode.addSubnode(self.tokenContainerNode)
@ -685,8 +689,11 @@ private class SearchBarTextField: UITextField, UIScrollViewDelegate {
let textRect = self.textRect(forBounds: bounds)
let labelSize = self.placeholderLabel.updateLayout(textRect.size)
if case .inlineNavigation = self.style {
placeholderYOffset += 0.0//(bounds.height - labelSize.height) * 0.5
switch self.style {
case .glass, .inlineNavigation:
placeholderYOffset += 0.0
case .legacy, .modern:
break
}
self.placeholderLabel.frame = CGRect(origin: CGPoint(x: textRect.minX + placeholderXOffset, y: floorToScreenPixels(bounds.height - labelSize.height) * 0.5), size: labelSize)
@ -821,10 +828,11 @@ public enum SearchBarStyle {
case modern
case legacy
case inlineNavigation
case glass
var font: UIFont {
switch self {
case .modern, .inlineNavigation:
case .modern, .inlineNavigation, .glass:
return Font.regular(17.0)
case .legacy:
return Font.regular(14.0)
@ -835,6 +843,8 @@ public enum SearchBarStyle {
switch self {
case .modern, .inlineNavigation:
return 21.0
case .glass:
return 22.0
case .legacy:
return 14.0
}
@ -844,6 +854,8 @@ public enum SearchBarStyle {
switch self {
case .inlineNavigation:
return 48.0
case .glass:
return 44.0
case .modern:
return 36.0
case .legacy:
@ -855,6 +867,8 @@ public enum SearchBarStyle {
switch self {
case .inlineNavigation:
return 0.0
case .glass:
return 20.0
case .modern:
return 10.0
case .legacy:
@ -889,6 +903,8 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
private let clearButton: HighlightableButtonNode
private let cancelButton: HighlightableButtonNode
private var takenSearchPlaceholderContentView: SearchBarPlaceholderContentView?
public var placeholderString: NSAttributedString? {
get {
return self.textField.placeholderString
@ -953,6 +969,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
activityIndicator.removeFromSupernode()
}
self.iconNode.isHidden = self.activity
if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
takenSearchPlaceholderContentView.updateSearchIconVisibility(isVisible: !self.activity)
}
}
}
}
@ -977,7 +996,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
private var validLayout: (CGSize, CGFloat, CGFloat)?
private let fieldStyle: SearchBarStyle
public let fieldStyle: SearchBarStyle
private let forceSeparator: Bool
private var theme: SearchBarNodeTheme?
private var strings: PresentationStrings?
@ -1023,16 +1042,20 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
super.init()
if case .inlineNavigation = self.fieldStyle {
} else {
switch self.fieldStyle {
case .glass, .inlineNavigation:
break
case .legacy, .modern:
self.addSubnode(self.backgroundNode)
self.addSubnode(self.separatorNode)
self.addSubnode(self.textBackgroundNode)
}
self.view.addSubview(self.textField)
if case .inlineNavigation = self.fieldStyle {
} else {
switch self.fieldStyle {
case .glass, .inlineNavigation:
break
case .legacy, .modern:
self.addSubnode(self.iconNode)
self.addSubnode(self.cancelButton)
}
@ -1121,16 +1144,22 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
textBackgroundHeight = self.fieldStyle.height
}
let verticalOffset: CGFloat
if case .inlineNavigation = self.fieldStyle {
switch self.fieldStyle {
case .inlineNavigation, .glass:
verticalOffset = -textBackgroundHeight
} else {
case .legacy, .modern:
verticalOffset = boundingSize.height - 82.0
}
let cancelButtonSize = self.cancelButton.measure(CGSize(width: 100.0, height: CGFloat.infinity))
transition.updateFrame(node: self.cancelButton, frame: CGRect(origin: CGPoint(x: contentFrame.maxX - 10.0 - cancelButtonSize.width, y: verticalOffset + textBackgroundHeight + floorToScreenPixels((textBackgroundHeight - cancelButtonSize.height) / 2.0)), size: cancelButtonSize))
let padding = self.fieldStyle.padding
var textBackgroundFrame = CGRect(origin: CGPoint(x: contentFrame.minX + padding, y: verticalOffset + textBackgroundHeight), size: CGSize(width: contentFrame.width - padding * 2.0 - (self.hasCancelButton ? cancelButtonSize.width + 11.0 : 0.0), height: textBackgroundHeight))
var textBackgroundFrame = CGRect(origin: CGPoint(x: contentFrame.minX + padding, y: verticalOffset + textBackgroundHeight), size: CGSize(width: contentFrame.width - padding - (self.hasCancelButton ? cancelButtonSize.width + 11.0 : 0.0), height: textBackgroundHeight))
if case .glass = self.fieldStyle {
textBackgroundFrame.size.width -= 8.0
} else {
textBackgroundFrame.size.width -= padding
}
transition.updateFrame(node: self.textBackgroundNode, frame: textBackgroundFrame)
var textFrame = CGRect(origin: CGPoint(x: 0.0, y: textBackgroundFrame.minY), size: CGSize(width: max(1.0, textBackgroundFrame.size.width - 24.0 - 27.0), height: textBackgroundFrame.size.height))
@ -1172,7 +1201,24 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
}
public func animateIn(from node: SearchBarPlaceholderNode, duration: Double, timingFunction: String) {
let initialTextBackgroundFrame = node.view.convert(node.backgroundNode.frame, to: self.view)
let takenSearchPlaceholderContentView = node.takeContents()
takenSearchPlaceholderContentView.onCancel = { [weak self] in
guard let self else {
return
}
self.cancel?()
}
self.takenSearchPlaceholderContentView = takenSearchPlaceholderContentView
self.view.insertSubview(takenSearchPlaceholderContentView, at: 0)
let sourceFrame = node.view.convert(node.bounds, to: self.view)
let targetFrame = CGRect(origin: CGPoint(x: 16.0, y: 0.0), size: CGSize(width: max(0.0, self.bounds.width - 16.0 * 2.0), height: 44.0))
let transition: ContainedViewLayoutTransition = .animated(duration: duration, curve: timingFunction == kCAMediaTimingFunctionSpring ? .spring : .easeInOut)
takenSearchPlaceholderContentView.frame = sourceFrame
transition.updateFrame(view: takenSearchPlaceholderContentView, frame: targetFrame)
takenSearchPlaceholderContentView.update(size: targetFrame.size, isActive: true, transition: transition)
/*let initialTextBackgroundFrame = node.view.convert(node.backgroundView.frame, to: self.view)
let initialBackgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: self.bounds.size.width, height: max(0.0, initialTextBackgroundFrame.maxY + 8.0)))
if let fromBackgroundColor = node.backgroundColor, let toBackgroundColor = self.backgroundNode.backgroundColor {
@ -1186,7 +1232,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.separatorNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
self.separatorNode.layer.animateFrame(from: initialSeparatorFrame, to: self.separatorNode.frame, duration: duration, timingFunction: timingFunction)
if let fromTextBackgroundColor = node.backgroundNode.backgroundColor, let toTextBackgroundColor = self.textBackgroundNode.backgroundColor {
if let fromTextBackgroundColor = node.backgroundView.backgroundColor, let toTextBackgroundColor = self.textBackgroundNode.backgroundColor {
self.textBackgroundNode.layer.animate(from: fromTextBackgroundColor.cgColor, to: toTextBackgroundColor.cgColor, keyPath: "backgroundColor", timingFunction: timingFunction, duration: duration * 1.0)
}
self.textBackgroundNode.layer.animateFrame(from: initialTextBackgroundFrame, to: self.textBackgroundNode.frame, duration: duration, timingFunction: timingFunction)
@ -1211,7 +1257,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
let cancelButtonFrame = self.cancelButton.frame
self.cancelButton.layer.animatePosition(from: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: initialTextBackgroundFrame.midY), to: self.cancelButton.layer.position, duration: duration, timingFunction: timingFunction)
node.isHidden = true
node.isHidden = true*/
}
public func deactivate(clear: Bool = true) {
@ -1225,7 +1271,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
}
public func transitionOut(to node: SearchBarPlaceholderNode, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) {
let targetTextBackgroundFrame = node.view.convert(node.backgroundNode.frame, to: self.view)
/*let targetTextBackgroundFrame = node.view.convert(node.backgroundView.frame, to: self.view)
let duration: Double = transition.isAnimated ? 0.5 : 0.0
let timingFunction = kCAMediaTimingFunctionSpring
@ -1341,8 +1387,8 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
let transitionBackgroundNode = ASDisplayNode()
transitionBackgroundNode.isLayerBacked = true
transitionBackgroundNode.displaysAsynchronously = false
transitionBackgroundNode.backgroundColor = node.backgroundNode.backgroundColor
transitionBackgroundNode.cornerRadius = node.backgroundNode.cornerRadius
transitionBackgroundNode.backgroundColor = node.backgroundView.backgroundColor
transitionBackgroundNode.cornerRadius = node.backgroundView.layer.cornerRadius
self.insertSubnode(transitionBackgroundNode, aboveSubnode: self.textBackgroundNode)
transitionBackgroundNode.layer.animateFrame(from: self.textBackgroundNode.frame, to: targetTextBackgroundFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
@ -1365,7 +1411,52 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.iconNode.layer.animateFrame(from: self.iconNode.frame, to: targetIconFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
let cancelButtonFrame = self.cancelButton.frame
self.cancelButton.layer.animatePosition(from: self.cancelButton.layer.position, to: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: targetTextBackgroundFrame.midY), duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
self.cancelButton.layer.animatePosition(from: self.cancelButton.layer.position, to: CGPoint(x: self.bounds.size.width + cancelButtonFrame.size.width / 2.0, y: targetTextBackgroundFrame.midY), duration: duration, timingFunction: timingFunction, removeOnCompletion: false)*/
if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
let transition = ComponentTransition(transition)
let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.2)
let sourceFrame = node.view.convert(node.bounds, to: self.view)
takenSearchPlaceholderContentView.update(size: sourceFrame.size, isActive: false, transition: transition.containedViewLayoutTransition)
takenSearchPlaceholderContentView.updatePlaceholderVisibility(isVisible: true)
takenSearchPlaceholderContentView.updateSearchIconVisibility(isVisible: true)
transition.setFrame(view: takenSearchPlaceholderContentView, frame: sourceFrame, completion: { [weak node] _ in
node?.putBackContents()
completion()
})
let textBackgroundHeight: CGFloat
if case .inlineNavigation = self.fieldStyle {
textBackgroundHeight = sourceFrame.height
} else {
textBackgroundHeight = self.fieldStyle.height
}
let padding = self.fieldStyle.padding
var textBackgroundFrame = CGRect(origin: CGPoint(x: sourceFrame.minX + padding, y: sourceFrame.minY), size: CGSize(width: sourceFrame.width - padding, height: textBackgroundHeight))
if case .glass = self.fieldStyle {
textBackgroundFrame.size.width -= 8.0
} else {
textBackgroundFrame.size.width -= padding
}
var textFrame = CGRect(origin: CGPoint(x: 0.0, y: textBackgroundFrame.minY), size: CGSize(width: max(1.0, textBackgroundFrame.size.width - 24.0 - 27.0), height: textBackgroundFrame.size.height))
if case .inlineNavigation = self.fieldStyle {
textFrame.size.width = sourceFrame.width - 27.0
textBackgroundFrame.size.width = sourceFrame.width
} else {
textFrame.origin.x = textBackgroundFrame.minX + 24.0
}
transition.setFrame(view: self.textField, frame: textFrame)
//alphaTransition.setAlpha(view: self.textField, alpha: 0.0)
self.textField.isHidden = true
let clearSize = self.clearButton.bounds.size
alphaTransition.setAlpha(view: self.clearButton.view, alpha: 0.0)
transition.setFrame(view: self.clearButton.view, frame: CGRect(origin: CGPoint(x: textBackgroundFrame.maxX - 6.0 - clearSize.width, y: textBackgroundFrame.minY + floor((textBackgroundFrame.size.height - clearSize.height) / 2.0)), size: clearSize))
}
}
public func textFieldDidBeginEditing(_ textField: UITextField) {
@ -1437,6 +1528,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .spring) : .immediate
let placeholderTransition = !isEmpty ? .immediate : transition
placeholderTransition.updateAlpha(node: self.textField.placeholderLabel, alpha: isEmpty ? 1.0 : 0.0)
if let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
takenSearchPlaceholderContentView.updatePlaceholderVisibility(isVisible: isEmpty)
}
let clearIsHidden = (textIsEmpty && tokensEmpty) && self.prefixString == nil
transition.updateAlpha(node: self.clearButton.imageNode, alpha: clearIsHidden ? 0.0 : 1.0)

View file

@ -5,6 +5,8 @@ import AsyncDisplayKit
import Display
import AppBundle
import ComponentFlow
import GlassBackgroundComponent
import ComponentDisplayAdapters
private let templateLoupeIcon = UIImage(bundleImageName: "Components/Search Bar/Loupe")
@ -21,44 +23,72 @@ private class SearchBarPlaceholderNodeView: UIView {
}
}
public class SearchBarPlaceholderNode: ASDisplayNode {
public var activate: (() -> Void)?
public final class SearchBarPlaceholderContentView: UIView {
private struct Params {
var placeholderString: NSAttributedString?
var compactPlaceholderString: NSAttributedString?
var constrainedSize: CGSize
var expansionProgress: CGFloat
var iconColor: UIColor
var foregroundColor: UIColor
var backgroundColor: UIColor
var controlColor: UIColor
var isActive: Bool
init(placeholderString: NSAttributedString?, compactPlaceholderString: NSAttributedString?, constrainedSize: CGSize, expansionProgress: CGFloat, iconColor: UIColor, foregroundColor: UIColor, backgroundColor: UIColor, controlColor: UIColor, isActive: Bool) {
self.placeholderString = placeholderString
self.compactPlaceholderString = compactPlaceholderString
self.constrainedSize = constrainedSize
self.expansionProgress = expansionProgress
self.iconColor = iconColor
self.foregroundColor = foregroundColor
self.backgroundColor = backgroundColor
self.controlColor = controlColor
self.isActive = isActive
}
}
private let fieldStyle: SearchBarStyle
public let backgroundNode: ASDisplayNode
let fieldStyle: SearchBarStyle
let backgroundNode: ASDisplayNode?
let glassBackgroundView: GlassBackgroundView?
private var fillBackgroundColor: UIColor
private var foregroundColor: UIColor
private var iconColor: UIColor
public let iconNode: ASImageNode
public let labelNode: TextNode
let iconNode: ASImageNode
let labelNode: TextNode
var pointerInteraction: PointerInteraction?
private var close: (background: GlassBackgroundView, icon: UIImageView)?
public private(set) var placeholderString: NSAttributedString?
private(set) var placeholderString: NSAttributedString?
private(set) var accessoryComponentContainer: UIView?
private(set) var accessoryComponentView: ComponentHostView<Empty>?
private var params: Params?
convenience public override init() {
self.init(fieldStyle: .legacy)
}
public var onCancel: (() -> Void)?
public init(fieldStyle: SearchBarStyle = .legacy) {
init(fieldStyle: SearchBarStyle) {
self.fieldStyle = fieldStyle
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isLayerBacked = false
self.backgroundNode.displaysAsynchronously = false
self.fillBackgroundColor = UIColor.white
self.foregroundColor = UIColor(rgb: 0xededed)
self.iconColor = UIColor(rgb: 0x000000, alpha: 0.0)
self.backgroundNode.backgroundColor = self.foregroundColor
self.backgroundNode.cornerRadius = self.fieldStyle.cornerDiameter / 2.0
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()
self.iconNode.isLayerBacked = true
self.iconNode.displaysAsynchronously = false
self.iconNode.displayWithoutProcessing = true
@ -66,51 +96,404 @@ public class SearchBarPlaceholderNode: ASDisplayNode {
self.labelNode.isOpaque = false
self.labelNode.isUserInteractionEnabled = false
super.init(frame: CGRect())
if let backgroundNode = self.backgroundNode {
backgroundNode.isUserInteractionEnabled = true
self.addSubview(backgroundNode.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)
}
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func onCloseTapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
self.onCancel?()
}
}
func updateLayout(
placeholderString: NSAttributedString?,
compactPlaceholderString: NSAttributedString?,
constrainedSize: CGSize,
expansionProgress: CGFloat,
iconColor: UIColor,
foregroundColor: UIColor,
backgroundColor: UIColor,
controlColor: UIColor,
transition: ContainedViewLayoutTransition
) -> CGFloat {
let params = Params(
placeholderString: placeholderString,
compactPlaceholderString: compactPlaceholderString,
constrainedSize: constrainedSize,
expansionProgress: expansionProgress,
iconColor: iconColor,
foregroundColor: foregroundColor,
backgroundColor: backgroundColor,
controlColor: controlColor,
isActive: false
)
self.params = params
return self.updateLayout(params: params, transition: transition)
}
public func update(size: CGSize, isActive: Bool, transition: ContainedViewLayoutTransition) {
guard var params = self.params else {
return
}
params.constrainedSize = size
params.expansionProgress = 1.0
params.isActive = isActive
let _ = self.updateLayout(params: params, transition: transition)
}
private func updateLayout(params: Params, transition: ContainedViewLayoutTransition) -> CGFloat {
let labelLayout = TextNode.asyncLayout(self.labelNode)
let currentForegroundColor = self.foregroundColor
let currentIconColor = self.iconColor
let placeholderString: NSAttributedString?
if params.constrainedSize.width < 350.0 {
placeholderString = params.compactPlaceholderString
} else {
placeholderString = params.placeholderString
}
let (labelLayoutResult, labelApply) = labelLayout(TextNodeLayoutArguments(attributedString: placeholderString, backgroundColor: .clear, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: params.constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var updatedColor: UIColor?
var updatedIconImage: UIImage?
if !currentForegroundColor.isEqual(params.foregroundColor) {
updatedColor = params.foregroundColor
}
if !currentIconColor.isEqual(params.iconColor) {
updatedIconImage = generateLoupeIcon(color: params.iconColor)
}
let height = params.constrainedSize.height * params.expansionProgress
let _ = labelApply()
self.fillBackgroundColor = params.backgroundColor
self.foregroundColor = params.foregroundColor
self.iconColor = params.iconColor
if let backgroundNode = self.backgroundNode {
backgroundNode.isUserInteractionEnabled = params.expansionProgress > 0.9999
}
if let updatedColor, let backgroundNode = self.backgroundNode {
backgroundNode.backgroundColor = updatedColor
}
if let updatedIconImage {
self.iconNode.image = updatedIconImage
}
self.placeholderString = placeholderString
var iconSize = CGSize()
var totalWidth = labelLayoutResult.size.width
var spacing: CGFloat = 4.0
if params.isActive {
spacing = 2.0
}
let iconX: CGFloat
if let iconImage = self.iconNode.image {
iconSize = iconImage.size
totalWidth += iconSize.width + spacing
if params.isActive {
iconX = 8.0
} else {
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))
} else {
iconX = 12.0
}
var textOffset: CGFloat = 0.0
if params.constrainedSize.height >= 36.0 {
textOffset += 1.0
}
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)
var innerAlpha = max(0.0, params.expansionProgress - 0.77) / 0.23
if innerAlpha > 0.9999 {
innerAlpha = 1.0
} else if innerAlpha < 0.0001 {
innerAlpha = 0.0
}
if self.labelNode.alpha != innerAlpha {
if !transition.isAnimated {
self.labelNode.layer.removeAnimation(forKey: "opacity")
self.iconNode.layer.removeAnimation(forKey: "opacity")
}
transition.updateAlpha(node: self.labelNode, alpha: innerAlpha)
transition.updateAlpha(node: self.iconNode, alpha: innerAlpha)
}
let outerAlpha = min(0.3, params.expansionProgress) / 0.3
let cornerRadius = min(self.fieldStyle.cornerDiameter / 2.0, height / 2.0)
if let backgroundNode = self.backgroundNode, backgroundNode.cornerRadius != cornerRadius {
if !transition.isAnimated {
backgroundNode.layer.removeAnimation(forKey: "cornerRadius")
}
transition.updateCornerRadius(node: backgroundNode, cornerRadius: cornerRadius)
}
if let backgroundNode = self.backgroundNode, backgroundNode.alpha != outerAlpha {
if !transition.isAnimated {
backgroundNode.layer.removeAnimation(forKey: "opacity")
}
transition.updateAlpha(node: backgroundNode, alpha: outerAlpha)
}
var backgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: params.constrainedSize.width, height: height))
if params.isActive {
backgroundFrame.size.width -= 44.0 + 8.0
}
if let backgroundNode = self.backgroundNode, backgroundNode.frame != backgroundFrame {
if !transition.isAnimated {
backgroundNode.layer.removeAnimation(forKey: "position")
backgroundNode.layer.removeAnimation(forKey: "bounds")
}
transition.updateFrame(node: backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: params.constrainedSize.width, height: height)))
}
if let glassBackgroundView = self.glassBackgroundView {
transition.updatePosition(layer: glassBackgroundView.layer, position: backgroundFrame.center)
transition.updateBounds(layer: glassBackgroundView.layer, bounds: CGRect(origin: CGPoint(), size: backgroundFrame.size))
var backgroundAlpha: CGFloat = 1.0
if backgroundFrame.height < 16.0 {
backgroundAlpha = max(0.0, min(1.0, backgroundFrame.height / 16.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))
if params.isActive {
let transition = ComponentTransition(transition)
let closeFrame = CGRect(origin: CGPoint(x: params.constrainedSize.width - 44.0, y: 0.0), size: CGSize(width: 44.0, height: 44.0))
let close: (background: GlassBackgroundView, icon: UIImageView)
var closeTransition = transition
if let current = self.close {
close = current
} else {
closeTransition = closeTransition.withAnimation(.none)
close = (GlassBackgroundView(), UIImageView())
self.close = close
close.icon.image = generateImage(CGSize(width: 40.0, height: 40.0), contextGenerator: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setLineWidth(2.0)
context.setLineCap(.round)
context.setStrokeColor(UIColor.white.cgColor)
context.beginPath()
context.move(to: CGPoint(x: 12.0, y: 12.0))
context.addLine(to: CGPoint(x: size.width - 12.0, y: size.height - 12.0))
context.move(to: CGPoint(x: size.width - 12.0, y: 12.0))
context.addLine(to: CGPoint(x: 12.0, y: size.height - 12.0))
context.strokePath()
})?.withRenderingMode(.alwaysTemplate)
close.background.contentView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.onCloseTapGesture(_:))))
close.background.contentView.addSubview(close.icon)
self.insertSubview(close.background, at: 0)
if let image = close.icon.image {
close.icon.frame = image.size.centered(in: CGRect(origin: CGPoint(), size: closeFrame.size))
}
close.background.frame = closeFrame.offsetBy(dx: closeFrame.width + 40.0, dy: 0.0)
let isDark = params.backgroundColor.hsb.b < 0.5
close.background.update(size: close.background.bounds.size, cornerRadius: close.background.bounds.height * 0.5, isDark: isDark, tintColor: .init(kind: .panel, color: UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.6)), isInteractive: true, transition: .immediate)
ComponentTransition.immediate.setScale(view: close.background, scale: 0.001)
}
close.icon.tintColor = params.controlColor
transition.setPosition(view: close.background, position: closeFrame.center)
transition.setBounds(view: close.background, bounds: CGRect(origin: CGPoint(), size: closeFrame.size))
transition.setScale(view: close.background, scale: 1.0)
if let image = close.icon.image {
transition.setFrame(view: close.icon, frame: image.size.centered(in: CGRect(origin: CGPoint(), size: closeFrame.size)))
}
let isDark = params.backgroundColor.hsb.b < 0.5
close.background.update(size: closeFrame.size, cornerRadius: closeFrame.height * 0.5, isDark: isDark, tintColor: .init(kind: .panel, color: UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.6)), isInteractive: true, transition: closeTransition)
} else {
let transition = ComponentTransition(transition)
if let close = self.close {
self.close = nil
let closeBackground = close.background
let closeFrame = CGRect(origin: CGPoint(x: params.constrainedSize.width - 44.0, y: 0.0), size: CGSize(width: 44.0, height: 44.0)).offsetBy(dx: 44.0 + 40.0, dy: 0.0)
transition.setPosition(view: closeBackground, position: closeFrame.center)
transition.setBounds(view: closeBackground, bounds: CGRect(origin: CGPoint(), size: closeFrame.size))
let isDark = params.backgroundColor.hsb.b < 0.5
closeBackground.update(size: closeFrame.size, cornerRadius: closeFrame.height * 0.5, isDark: isDark, tintColor: .init(kind: .panel, color: UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.6)), isInteractive: true, transition: transition)
transition.setScale(view: closeBackground, scale: 0.001, completion: { [weak closeBackground] _ in
closeBackground?.removeFromSuperview()
})
}
}
}
/*if let accessoryComponentContainer = self.accessoryComponentContainer {
accessoryComponentContainer.frame = CGRect(origin: CGPoint(x: constrainedSize.width - accessoryComponentContainer.bounds.width - 4.0, y: floor((constrainedSize.height * expansionProgress - accessoryComponentContainer.bounds.height) / 2.0)), size: accessoryComponentContainer.bounds.size)
transition.updateAlpha(layer: accessoryComponentContainer.layer, alpha: innerAlpha)
}*/
return height
}
public func updatePlaceholderVisibility(isVisible: Bool) {
self.labelNode.isHidden = !isVisible
}
public func updateSearchIconVisibility(isVisible: Bool) {
self.iconNode.isHidden = !isVisible
}
}
public class SearchBarPlaceholderNode: ASDisplayNode {
private struct Params {
var placeholderString: NSAttributedString?
var compactPlaceholderString: NSAttributedString?
var constrainedSize: CGSize
var expansionProgress: CGFloat
var iconColor: UIColor
var foregroundColor: UIColor
var backgroundColor: UIColor
var controlColor: UIColor
init(placeholderString: NSAttributedString?, compactPlaceholderString: NSAttributedString?, constrainedSize: CGSize, expansionProgress: CGFloat, iconColor: UIColor, foregroundColor: UIColor, backgroundColor: UIColor, controlColor: UIColor) {
self.placeholderString = placeholderString
self.compactPlaceholderString = compactPlaceholderString
self.constrainedSize = constrainedSize
self.expansionProgress = expansionProgress
self.iconColor = iconColor
self.foregroundColor = foregroundColor
self.backgroundColor = backgroundColor
self.controlColor = controlColor
}
}
public var activate: (() -> Void)?
private let containerView: UIView
private let contentView: SearchBarPlaceholderContentView
public var backgroundView: UIView {
if let backgroundNode = self.contentView.backgroundNode {
return backgroundNode.view
} else if let glassBackgroundView = self.contentView.glassBackgroundView {
return glassBackgroundView
} else {
preconditionFailure()
}
}
public var iconNode: ASImageNode {
return self.contentView.iconNode
}
public var labelNode: TextNode {
return self.contentView.labelNode
}
public var fieldStyle: SearchBarStyle {
return self.contentView.fieldStyle
}
var pointerInteraction: PointerInteraction?
public var placeholderString: NSAttributedString? {
return self.contentView.placeholderString
}
private(set) var accessoryComponentContainer: UIView?
private(set) var accessoryComponentView: ComponentHostView<Empty>?
private var params: Params?
private var currentLayoutHeight: CGFloat?
private var isTakenOut: Bool = false
public init(fieldStyle: SearchBarStyle = .legacy) {
self.containerView = UIView()
self.contentView = SearchBarPlaceholderContentView(fieldStyle: fieldStyle)
super.init()
self.addSubnode(self.backgroundNode)
self.addSubnode(self.iconNode)
self.addSubnode(self.labelNode)
self.backgroundNode.isUserInteractionEnabled = true
self.view.addSubview(self.containerView)
self.containerView.addSubview(self.contentView)
}
override public func didLoad() {
super.didLoad()
let gestureRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.backgroundTap(_:)))
gestureRecognizer.highlight = { [weak self] point in
/*gestureRecognizer.highlight = { [weak self] point in
guard let strongSelf = self else {
return
}
if let _ = point {
strongSelf.backgroundNode.layer.animate(from: (strongSelf.backgroundNode.backgroundColor ?? strongSelf.foregroundColor).cgColor, to: strongSelf.foregroundColor.withMultipliedBrightnessBy(0.9).cgColor, keyPath: "backgroundColor", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.2)
strongSelf.backgroundNode.backgroundColor = strongSelf.foregroundColor.withMultipliedBrightnessBy(0.9)
} else {
strongSelf.backgroundNode.layer.animate(from: (strongSelf.backgroundNode.backgroundColor ?? strongSelf.foregroundColor).cgColor, to: strongSelf.foregroundColor.cgColor, keyPath: "backgroundColor", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.4)
strongSelf.backgroundNode.backgroundColor = strongSelf.foregroundColor
if let backgroundNode = strongSelf.contentView.backgroundNode {
if let _ = point {
backgroundNode.layer.animate(from: (backgroundNode.backgroundColor ?? strongSelf.foregroundColor).cgColor, to: strongSelf.foregroundColor.withMultipliedBrightnessBy(0.9).cgColor, keyPath: "backgroundColor", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.2)
backgroundNode.backgroundColor = strongSelf.foregroundColor.withMultipliedBrightnessBy(0.9)
} else {
backgroundNode.layer.animate(from: (backgroundNode.backgroundColor ?? strongSelf.foregroundColor).cgColor, to: strongSelf.foregroundColor.cgColor, keyPath: "backgroundColor", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.4)
backgroundNode.backgroundColor = strongSelf.foregroundColor
}
}
}
}*/
gestureRecognizer.tapActionAtPoint = { _ in
return .waitForSingleTap
}
self.backgroundNode.view.addGestureRecognizer(gestureRecognizer)
self.containerView.addGestureRecognizer(gestureRecognizer)
self.pointerInteraction = PointerInteraction(node: self, style: .caret, willEnter: { [weak self] in
/*self.pointerInteraction = PointerInteraction(node: self, style: .caret, willEnter: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.backgroundNode.backgroundColor = strongSelf.foregroundColor.withMultipliedBrightnessBy(0.95)
if let backgroundNode = strongSelf.contentView.backgroundNode {
backgroundNode.backgroundColor = strongSelf.foregroundColor.withMultipliedBrightnessBy(0.95)
}
}, willExit: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.backgroundNode.backgroundColor = strongSelf.foregroundColor
})
if let backgroundNode = strongSelf.contentView.backgroundNode {
backgroundNode.backgroundColor = strongSelf.foregroundColor
}
})*/
}
public func setAccessoryComponent(component: AnyComponent<Empty>?) {
if let component = component {
/*if let component = component {
let accessoryComponentContainer: UIView
if let current = self.accessoryComponentContainer {
accessoryComponentContainer = current
@ -142,119 +525,43 @@ public class SearchBarPlaceholderNode: ASDisplayNode {
accessoryComponentView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak accessoryComponentView] _ in
accessoryComponentView?.removeFromSuperview()
})
}*/
}
public func takeContents() -> SearchBarPlaceholderContentView {
self.isTakenOut = true
return self.contentView
}
public func putBackContents() {
self.isTakenOut = false
self.containerView.addSubview(self.contentView)
if let params = self.params {
let _ = self.update(params: params, transition: .immediate)
}
}
public func asyncLayout() -> (_ placeholderString: NSAttributedString?, _ compactPlaceholderString: NSAttributedString?, _ constrainedSize: CGSize, _ expansionProgress: CGFloat, _ iconColor: UIColor, _ foregroundColor: UIColor, _ backgroundColor: UIColor, _ transition: ContainedViewLayoutTransition) -> (CGFloat, () -> Void) {
let labelLayout = TextNode.asyncLayout(self.labelNode)
let currentForegroundColor = self.foregroundColor
let currentIconColor = self.iconColor
public func updateLayout(placeholderString: NSAttributedString?, compactPlaceholderString: NSAttributedString?, constrainedSize: CGSize, expansionProgress: CGFloat, iconColor: UIColor, foregroundColor: UIColor, backgroundColor: UIColor, controlColor: UIColor, transition: ContainedViewLayoutTransition) -> CGFloat {
let params = Params(placeholderString: placeholderString, compactPlaceholderString: compactPlaceholderString, constrainedSize: constrainedSize, expansionProgress: expansionProgress, iconColor: iconColor, foregroundColor: foregroundColor, backgroundColor: backgroundColor, controlColor: controlColor)
self.params = params
return { fullPlaceholderString, compactPlaceholderString, constrainedSize, expansionProgress, iconColor, foregroundColor, backgroundColor, transition in
let placeholderString: NSAttributedString?
if constrainedSize.width < 350.0 {
placeholderString = compactPlaceholderString
} else {
placeholderString = fullPlaceholderString
}
let (labelLayoutResult, labelApply) = labelLayout(TextNodeLayoutArguments(attributedString: placeholderString, backgroundColor: .clear, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: constrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var updatedColor: UIColor?
var updatedIconImage: UIImage?
if !currentForegroundColor.isEqual(foregroundColor) {
updatedColor = foregroundColor
}
if !currentIconColor.isEqual(iconColor) {
updatedIconImage = generateLoupeIcon(color: iconColor)
}
let height = constrainedSize.height * expansionProgress
return (height, { [weak self] in
if let strongSelf = self {
let _ = labelApply()
strongSelf.fillBackgroundColor = backgroundColor
strongSelf.foregroundColor = foregroundColor
strongSelf.iconColor = iconColor
strongSelf.backgroundNode.isUserInteractionEnabled = expansionProgress > 0.9999
if let updatedColor = updatedColor {
strongSelf.backgroundNode.backgroundColor = updatedColor
}
if let updatedIconImage = updatedIconImage {
strongSelf.iconNode.image = updatedIconImage
}
strongSelf.placeholderString = placeholderString
var iconSize = CGSize()
var totalWidth = labelLayoutResult.size.width
let spacing: CGFloat = 6.0
if let iconImage = strongSelf.iconNode.image {
iconSize = iconImage.size
totalWidth += iconSize.width + spacing
transition.updateFrame(node: strongSelf.iconNode, frame: CGRect(origin: CGPoint(x: floor((constrainedSize.width - totalWidth) / 2.0), y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize))
}
var textOffset: CGFloat = 0.0
if constrainedSize.height >= 36.0 {
textOffset += 1.0
}
let labelFrame = CGRect(origin: CGPoint(x: floor((constrainedSize.width - totalWidth) / 2.0) + iconSize.width + spacing, y: floorToScreenPixels((height - labelLayoutResult.size.height) / 2.0) + textOffset), size: labelLayoutResult.size)
transition.updateFrame(node: strongSelf.labelNode, frame: labelFrame)
var innerAlpha = max(0.0, expansionProgress - 0.77) / 0.23
if innerAlpha > 0.9999 {
innerAlpha = 1.0
} else if innerAlpha < 0.0001 {
innerAlpha = 0.0
}
if strongSelf.labelNode.alpha != innerAlpha {
if !transition.isAnimated {
strongSelf.labelNode.layer.removeAnimation(forKey: "opacity")
strongSelf.iconNode.layer.removeAnimation(forKey: "opacity")
}
transition.updateAlpha(node: strongSelf.labelNode, alpha: innerAlpha)
transition.updateAlpha(node: strongSelf.iconNode, alpha: innerAlpha)
}
let outerAlpha = min(0.3, expansionProgress) / 0.3
let cornerRadius = min(strongSelf.fieldStyle.cornerDiameter / 2.0, height / 2.0)
if strongSelf.backgroundNode.cornerRadius != cornerRadius {
if !transition.isAnimated {
strongSelf.backgroundNode.layer.removeAnimation(forKey: "cornerRadius")
}
transition.updateCornerRadius(node: strongSelf.backgroundNode, cornerRadius: cornerRadius)
}
if strongSelf.backgroundNode.alpha != outerAlpha {
if !transition.isAnimated {
strongSelf.backgroundNode.layer.removeAnimation(forKey: "opacity")
}
transition.updateAlpha(node: strongSelf.backgroundNode, alpha: outerAlpha)
}
if strongSelf.backgroundNode.frame != CGRect(origin: CGPoint(), size: CGSize(width: constrainedSize.width, height: height)) {
if !transition.isAnimated {
strongSelf.backgroundNode.layer.removeAnimation(forKey: "position")
strongSelf.backgroundNode.layer.removeAnimation(forKey: "bounds")
}
transition.updateFrame(node: strongSelf.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: constrainedSize.width, height: height)))
}
if let accessoryComponentContainer = strongSelf.accessoryComponentContainer {
accessoryComponentContainer.frame = CGRect(origin: CGPoint(x: constrainedSize.width - accessoryComponentContainer.bounds.width - 4.0, y: floor((constrainedSize.height * expansionProgress - accessoryComponentContainer.bounds.height) / 2.0)), size: accessoryComponentContainer.bounds.size)
transition.updateAlpha(layer: accessoryComponentContainer.layer, alpha: innerAlpha)
}
}
})
if self.isTakenOut {
return self.currentLayoutHeight ?? 44.0
} else {
let height = self.update(params: params, transition: transition)
self.currentLayoutHeight = height
return height
}
}
private func update(params: Params, transition: ContainedViewLayoutTransition) -> CGFloat {
let height = self.contentView.updateLayout(placeholderString: params.placeholderString, compactPlaceholderString: params.compactPlaceholderString, constrainedSize: params.constrainedSize, expansionProgress: params.expansionProgress, iconColor: params.iconColor, foregroundColor: params.foregroundColor, backgroundColor: params.backgroundColor, controlColor: params.controlColor, transition: transition)
let size = CGSize(width: params.constrainedSize.width, height: height)
transition.updateFrame(view: self.containerView, frame: CGRect(origin: CGPoint(), size: size))
transition.updateFrame(view: self.contentView, frame: CGRect(origin: CGPoint(), size: size))
return height
}
@objc private func backgroundTap(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
if case .ended = recognizer.state {
self.activate?()

View file

@ -15,7 +15,6 @@ swift_library(
"//submodules/Display",
"//submodules/TelegramPresentationData",
"//submodules/SearchBarNode",
"//submodules/ChatListSearchItemNode",
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
"//submodules/ComponentFlow",
"//submodules/Components/ComponentDisplayAdapters",

View file

@ -1,33 +1,6 @@
import Foundation
import AsyncDisplayKit
import Display
import ChatListSearchItemNode
public func fixSearchableListNodeScrolling(_ listNode: ListView) {
var searchItemNode: ListViewItemNode?
var nextItemNode: ListViewItemNode?
listNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatListSearchItemNode {
searchItemNode = itemNode
} else if searchItemNode != nil && nextItemNode == nil {
nextItemNode = itemNode as? ListViewItemNode
}
}
if let searchItemNode = searchItemNode {
let itemFrame = searchItemNode.apparentFrame
if itemFrame.contains(CGPoint(x: 0.0, y: listNode.insets.top)) {
if itemFrame.minY + itemFrame.height * 0.6 < listNode.insets.top {
if let nextItemNode = nextItemNode {
listNode.ensureItemNodeVisibleAtTopInset(nextItemNode)
}
} else {
listNode.ensureItemNodeVisibleAtTopInset(searchItemNode)
}
}
}
}
public func fixNavigationSearchableListNodeScrolling(_ listNode: ListView, searchNode: NavigationBarSearchContentNode) -> Bool {
if searchNode.expansionProgress > 0.0 && searchNode.expansionProgress < 1.0 {

View file

@ -11,7 +11,7 @@ import AppBundle
import ActivityIndicator
private let searchBarFont = Font.regular(17.0)
public let navigationBarSearchContentHeight: CGFloat = 54.0
public let navigationBarSearchContentHeight: CGFloat = 60.0
public class NavigationBarSearchContentNode: NavigationBarContentNode {
private struct Params: Equatable {
@ -45,7 +45,7 @@ public class NavigationBarSearchContentNode: NavigationBarContentNode {
self.compactPlaceholder = compactPlaceholder ?? placeholder
self.inline = inline
self.placeholderNode = SearchBarPlaceholderNode(fieldStyle: .modern)
self.placeholderNode = SearchBarPlaceholderNode(fieldStyle: .glass)
self.placeholderNode.labelNode.displaysAsynchronously = false
super.init()
@ -56,6 +56,8 @@ public class NavigationBarSearchContentNode: NavigationBarContentNode {
self.addSubnode(self.placeholderNode)
self.placeholderNode.activate = activate
//self.backgroundColor = .red
}
public func updateThemeAndPlaceholder(theme: PresentationTheme, placeholder: String, compactPlaceholder: String? = nil) {
@ -117,10 +119,10 @@ public class NavigationBarSearchContentNode: NavigationBarContentNode {
}
private func updatePlaceholder(_ progress: CGFloat, size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
let padding: CGFloat = 10.0
let padding: CGFloat = 16.0
let baseWidth = size.width - padding * 2.0 - leftInset - rightInset
let fieldHeight: CGFloat = 36.0
let fieldHeight: CGFloat = 44.0
let fraction = fieldHeight / self.nominalHeight
let fullFraction = navigationBarSearchContentHeight / self.nominalHeight
@ -131,8 +133,6 @@ public class NavigationBarSearchContentNode: NavigationBarContentNode {
var visibleProgress: CGFloat = toLow + (self.expansionProgress - fromLow) * (toHigh - toLow) / (fromHigh - fromLow)
visibleProgress = max(0.0, min(1.0, visibleProgress))
let searchBarNodeLayout = self.placeholderNode.asyncLayout()
let textColor = self.theme?.rootController.navigationSearchBar.inputPlaceholderTextColor ?? UIColor(rgb: 0x8e8e93)
var fillColor = self.theme?.rootController.navigationSearchBar.inputFillColor ?? .clear
if self.inline, let theme = self.theme, fillColor.distance(to: theme.list.blocksBackgroundColor) < 100 {
@ -140,12 +140,12 @@ public class NavigationBarSearchContentNode: NavigationBarContentNode {
}
let backgroundColor = self.theme?.rootController.navigationBar.opaqueBackgroundColor ?? .clear
let controlColor = self.theme?.chat.inputPanel.panelControlColor ?? .black
let placeholderString = NSAttributedString(string: self.placeholder, font: searchBarFont, textColor: textColor)
let compactPlaceholderString = NSAttributedString(string: self.compactPlaceholder, font: searchBarFont, textColor: textColor)
let (searchBarHeight, searchBarApply) = searchBarNodeLayout(placeholderString, compactPlaceholderString, CGSize(width: baseWidth, height: fieldHeight), visibleProgress, textColor, fillColor, backgroundColor, transition)
searchBarApply()
let searchBarHeight = self.placeholderNode.updateLayout(placeholderString: placeholderString, compactPlaceholderString: compactPlaceholderString, constrainedSize: CGSize(width: baseWidth, height: fieldHeight), expansionProgress: visibleProgress, iconColor: textColor, foregroundColor: fillColor, backgroundColor: backgroundColor, controlColor: controlColor, transition: transition)
let searchBarFrame = CGRect(origin: CGPoint(x: padding + leftInset, y: size.height + (1.0 - visibleProgress) * fieldHeight - 8.0 - fieldHeight), size: CGSize(width: baseWidth, height: fieldHeight))
transition.updateFrame(node: self.placeholderNode, frame: searchBarFrame)

View file

@ -157,6 +157,8 @@ public final class SearchDisplayController {
}
public func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
let defaultNavigationBarHeight = navigationBarHeight
let statusBarHeight: CGFloat = layout.statusBarHeight ?? 0.0
let searchBarHeight: CGFloat = max(20.0, statusBarHeight) + 44.0
let navigationBarOffset: CGFloat
@ -173,14 +175,20 @@ public final class SearchDisplayController {
navigationBarFrame.size.height = 64.0
}
navigationBarFrame.size.height += 10.0
let navigationBarHeight = navigationBarFrame.maxY
var navigationBarHeight = navigationBarFrame.maxY
if !self.searchBarIsExternal, let searchBar = self.searchBar {
let searchBarFrame: CGRect
if case .navigation = self.mode {
searchBarFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: 54.0)
if case .glass = searchBar.fieldStyle {
navigationBarHeight = defaultNavigationBarHeight
searchBarFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: 44.0)
} else {
searchBarFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: 54.0)
}
} else {
searchBarFrame = navigationBarFrame
navigationBarHeight = navigationBarFrame.maxY + 8.0
}
transition.updateFrame(node: searchBar, frame: searchBarFrame)
searchBar.updateLayout(boundingSize: searchBarFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: transition)
@ -236,8 +244,6 @@ public final class SearchDisplayController {
if !self.contentNode.hasDim {
self.backgroundNode.alpha = 1.0
self.backgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, timingFunction: CAMediaTimingFunctionName.linear.rawValue)
self.backgroundNode.layer.animateScale(from: 0.85, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
}
if !self.searchBarIsExternal {
@ -247,7 +253,7 @@ public final class SearchDisplayController {
}
} else {
if let placeholder = placeholder {
let initialTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: nil)
let initialTextBackgroundFrame = placeholder.convert(placeholder.backgroundView.frame, to: nil)
let contentNodePosition = self.backgroundNode.layer.position
if contentNode.animateBackgroundAppearance {
self.backgroundNode.layer.animatePosition(from: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (initialTextBackgroundFrame.maxY + 8.0 - contentNavigationBarHeight)), to: contentNodePosition, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)

View file

@ -23,7 +23,6 @@ swift_library(
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/AvatarNode:AvatarNode",
"//submodules/CallListUI:CallListUI",
"//submodules/ChatListSearchItemNode:ChatListSearchItemNode",
"//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
"//submodules/ChatListUI:ChatListUI",
"//submodules/ContactsPeerItem:ContactsPeerItem",

View file

@ -36,7 +36,7 @@ public class LocalizationListController: ViewController {
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self.editItem = UIBarButtonItem(title: self.presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.editPressed))
self.doneItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed))
@ -86,7 +86,7 @@ public class LocalizationListController: ViewController {
private func updateThemeAndStrings() {
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.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.presentationData.strings.Settings_AppLanguage
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View file

@ -165,7 +165,7 @@ private final class LocalizationListSearchContainerNode: SearchDisplayController
self.presentationDataPromise = Promise(self.presentationData)
self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor.black.withAlphaComponent(0.5)
self.dimNode.backgroundColor = .clear
self.listNode = ListView()
self.listNode.accessibilityPageScrolledString = { row, count in
@ -809,7 +809,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: LocalizationListSearchContainerNode(context: self.context, listState: self.currentListState ?? LocalizationListState.defaultSettings, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, applyingCode: self.applyingCode.get()), inline: true, cancel: { [weak self] in
self?.requestDeactivateSearch()
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -243,7 +243,6 @@ private final class NotificationExceptionArguments {
}
private enum NotificationExceptionEntryId: Hashable {
case search
case peerId(Int64)
case addException
case removeAll
@ -254,13 +253,6 @@ private enum NotificationExceptionEntryId: Hashable {
static func ==(lhs: NotificationExceptionEntryId, rhs: NotificationExceptionEntryId) -> Bool {
switch lhs {
case .search:
switch rhs {
case .search:
return true
default:
return false
}
case .addException:
switch rhs {
case .addException:
@ -302,7 +294,6 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
typealias ItemGenerationArguments = NotificationExceptionArguments
case search(PresentationTheme, PresentationStrings)
case peer(index: Int, peer: EnginePeer, theme: PresentationTheme, strings: PresentationStrings, dateFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, description: String, notificationSettings: TelegramPeerNotificationSettings, revealed: Bool, editing: Bool, isSearching: Bool)
case addPeer(index: Int, peer: EnginePeer, theme: PresentationTheme, strings: PresentationStrings, dateFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder)
case addException(PresentationTheme, PresentationStrings, NotificationExceptionMode.Mode, Bool)
@ -311,10 +302,6 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! NotificationExceptionArguments
switch self {
case let .search(theme, strings):
return NotificationSearchItem(theme: theme, placeholder: strings.Common_Search, activate: {
arguments.activateSearch()
})
case let .addException(theme, strings, mode, editing):
let icon: UIImage?
switch mode {
@ -352,8 +339,6 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
var stableId: NotificationExceptionEntryId {
switch self {
case .search:
return .search
case .addException:
return .addException
case let .peer(_, peer, _, _, _, _, _, _, _, _, _):
@ -367,13 +352,6 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
static func == (lhs: NotificationExceptionEntry, rhs: NotificationExceptionEntry) -> Bool {
switch lhs {
case let .search(lhsTheme, lhsStrings):
switch rhs {
case let .search(rhsTheme, rhsStrings):
return lhsTheme === rhsTheme && lhsStrings === rhsStrings
default:
return false
}
case let .addException(lhsTheme, lhsStrings, lhsMode, lhsEditing):
switch rhs {
case let .addException(rhsTheme, rhsStrings, rhsMode, rhsEditing):
@ -406,18 +384,16 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
static func <(lhs: NotificationExceptionEntry, rhs: NotificationExceptionEntry) -> Bool {
switch lhs {
case .search:
return true
case .addException:
switch rhs {
case .search, .addException:
case .addException:
return false
default:
return true
}
case let .peer(lhsIndex, _, _, _, _, _, _, _, _, _, _):
switch rhs {
case .search, .addException:
case .addException:
return false
case let .peer(rhsIndex, _, _, _, _, _, _, _, _, _, _):
return lhsIndex < rhsIndex
@ -428,7 +404,7 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
}
case let .addPeer(lhsIndex, _, _, _, _, _):
switch rhs {
case .search, .addException:
case .addException:
return false
case let .peer(rhsIndex, _, _, _, _, _, _, _, _, _, _):
return lhsIndex < rhsIndex
@ -936,7 +912,7 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: NotificationExceptionsSearchContainerNode(context: self.context, mode: self.stateValue.modify {$0}.mode, arguments: self.arguments!), cancel: { [weak self] in
self?.requestDeactivateSearch(true)
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in
@ -1007,7 +983,7 @@ private final class NotificationExceptionsSearchContainerNode: SearchDisplayCont
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings))
self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor.black.withAlphaComponent(0.5)
self.dimNode.backgroundColor = .clear
self.listNode = ListView()
self.listNode.accessibilityPageScrolledString = { row, count in

View file

@ -39,7 +39,9 @@ public class NotificationExceptionsController: ViewController {
self.updatedMode = updatedMode
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.removeAllItem = UIBarButtonItem(title: self.presentationData.strings.Notification_Exceptions_DeleteAll, style: .plain, target: self, action: #selector(self.removeAllPressed))
self.editItem = UIBarButtonItem(title: self.presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.editPressed))
@ -90,7 +92,7 @@ public class NotificationExceptionsController: ViewController {
private func updateThemeAndStrings() {
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.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.presentationData.strings.Notifications_ExceptionsTitle
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View file

@ -1,139 +0,0 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Postbox
import Display
import SwiftSignalKit
import TelegramPresentationData
import ItemListUI
import PresentationDataUtils
import SearchBarNode
private let searchBarFont = Font.regular(14.0)
class NotificationSearchItem: ListViewItem, ItemListItem {
let selectable: Bool = false
var sectionId: ItemListSectionId {
return 0
}
var tag: ItemListItemTag? {
return nil
}
var requestsNoInset: Bool {
return true
}
let theme: PresentationTheme
private let placeholder: String
private let activate: () -> Void
init(theme: PresentationTheme, placeholder: String, activate: @escaping () -> Void) {
self.theme = theme
self.placeholder = placeholder
self.activate = activate
}
func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
async {
let node = NotificationSearchItemNode()
node.placeholder = self.placeholder
let makeLayout = node.asyncLayout()
let (layout, apply) = makeLayout(self, params)
node.contentSize = layout.contentSize
node.insets = layout.insets
node.activate = self.activate
Queue.mainQueue().async {
completion(node, {
return (nil, { _ in
apply(false)
})
})
}
}
}
func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
Queue.mainQueue().async {
if let nodeValue = node() as? NotificationSearchItemNode {
let layout = nodeValue.asyncLayout()
async {
let (nodeLayout, apply) = layout(self, params)
Queue.mainQueue().async {
completion(nodeLayout, { _ in
apply(animation.isAnimated)
})
}
}
}
}
}
}
class NotificationSearchItemNode: ListViewItemNode {
let searchBarNode: SearchBarPlaceholderNode
var placeholder: String?
fileprivate var activate: (() -> Void)? {
didSet {
self.searchBarNode.activate = self.activate
}
}
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
}
required init() {
self.searchBarNode = SearchBarPlaceholderNode()
super.init(layerBacked: false, dynamicBounce: false)
self.addSubnode(self.searchBarNode)
}
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
let makeLayout = self.asyncLayout()
let (layout, apply) = makeLayout(item as! NotificationSearchItem, params)
apply(false)
self.contentSize = layout.contentSize
self.insets = layout.insets
}
func asyncLayout() -> (_ item: NotificationSearchItem, _ params: ListViewItemLayoutParams) -> (ListViewItemNodeLayout, (Bool) -> Void) {
let searchBarNodeLayout = self.searchBarNode.asyncLayout()
let placeholder = self.placeholder
return { item, params in
let baseWidth = params.width - params.leftInset - params.rightInset
let backgroundColor = item.theme.chatList.itemBackgroundColor
let placeholderString = NSAttributedString(string: placeholder ?? "", font: searchBarFont, textColor: UIColor(rgb: 0x8e8e93))
let (_, searchBarApply) = searchBarNodeLayout(placeholderString, placeholderString, CGSize(width: baseWidth - 16.0, height: 28.0), 1.0, UIColor(rgb: 0x8e8e93), item.theme.chatList.regularSearchBarColor, backgroundColor, .immediate)
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 44.0), insets: UIEdgeInsets())
return (layout, { [weak self] animated in
if let strongSelf = self {
let transition: ContainedViewLayoutTransition
if animated {
transition = .animated(duration: 0.3, curve: .easeInOut)
} else {
transition = .immediate
}
strongSelf.searchBarNode.frame = CGRect(origin: CGPoint(x: params.leftInset + 8.0, y: 8.0), size: CGSize(width: baseWidth - 16.0, height: 28.0))
searchBarApply()
strongSelf.searchBarNode.bounds = CGRect(origin: CGPoint(), size: CGSize(width: baseWidth - 16.0, height: 28.0))
transition.updateBackgroundColor(node: strongSelf, color: backgroundColor)
}
})
}
}
}

View file

@ -608,7 +608,7 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode {
}
}, resolvedFaqUrl: self.resolvedFaqUrl, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasTwoStepAuth: self.hasTwoStepAuth, twoStepAuthData: self.twoStepAuthData, activeSessionsContext: self.activeSessionsContext, webSessionsContext: self.webSessionsContext), cancel: { [weak self] in
self?.cancel()
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -153,7 +153,6 @@ swift_library(
"//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
"//submodules/ItemListPeerItem:ItemListPeerItem",
"//submodules/ContactsPeerItem:ContactsPeerItem",
"//submodules/ChatListSearchItemNode:ChatListSearchItemNode",
"//submodules/TelegramPermissionsUI:TelegramPermissionsUI",
"//submodules/PeersNearbyIconNode:PeersNearbyIconNode",
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",

View file

@ -496,7 +496,7 @@ private final class RecentActionsSettingsSheetComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -227,7 +227,7 @@ public final class AnimatedTextComponent: Component {
itemText = [.icon(iconName, tint, offset)]
}
var index = 0
for character in itemText {
characterLoop: for character in itemText {
let characterKey = CharacterKey(itemId: item.id, index: index, value: character.value)
index += 1
@ -245,9 +245,17 @@ public final class AnimatedTextComponent: Component {
var characterOffset: CGPoint = .zero
switch character {
case let .text(text):
characterComponent = AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: text, font: component.font, textColor: component.color))
))
if text == " " {
let spaceSize = NSAttributedString(string: " ", font: component.font, textColor: .black).boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil).size
size.height = max(size.height, ceil(spaceSize.height))
size.width += max(0.0, ceil(spaceSize.width))
continue characterLoop
} else {
characterComponent = AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: text, font: component.font, textColor: component.color))
))
}
case let .icon(iconName, tint, offset):
characterComponent = AnyComponent(BundleIconComponent(
name: iconName,
@ -318,7 +326,7 @@ public final class AnimatedTextComponent: Component {
}
size.height = max(size.height, characterSize.height)
size.width += max(0.0, characterSize.width - UIScreenPixel * 2.0)
size.width += max(0.0, characterSize.width - UIScreenPixel)
}
}

View file

@ -468,7 +468,7 @@ public func makeAttachmentFileControllerImpl(context: AccountContext, updatedPre
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in
@ -495,7 +495,7 @@ public func makeAttachmentFileControllerImpl(context: AccountContext, updatedPre
component: AnyComponentWithIdentity(id: "search", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Search",
tintColor: presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in
@ -509,7 +509,7 @@ public func makeAttachmentFileControllerImpl(context: AccountContext, updatedPre
}
)
let searchButtonComponent = state.searching ? nil : AnyComponentWithIdentity(id: "search", component: AnyComponent(searchButton))
let searchButtonNode = existingSearchButton.modify { current in
let searchButtonNode: BarComponentHostNode? = !state.searching ? existingSearchButton.modify { current in
let buttonNode: BarComponentHostNode
if let current {
buttonNode = current
@ -518,7 +518,7 @@ public func makeAttachmentFileControllerImpl(context: AccountContext, updatedPre
buttonNode = BarComponentHostNode(component: searchButtonComponent, size: barButtonSize)
}
return buttonNode
}
} : nil
let previousRecentDocuments = previousRecentDocuments.swap(recentDocuments)
let crossfade = previousRecentDocuments == nil && recentDocuments != nil
@ -542,6 +542,7 @@ public func makeAttachmentFileControllerImpl(context: AccountContext, updatedPre
case .recent:
title = presentationData.strings.Attachment_File
case .audio:
//TODO:localize
title = "Audio"
}

View file

@ -56,7 +56,6 @@ public enum ChatHistoryEntry: Identifiable, Comparable {
case UnreadEntry(MessageIndex, ChatPresentationData)
case ReplyCountEntry(MessageIndex, Bool, Int, ChatPresentationData)
case ChatInfoEntry(ChatInfoData, ChatPresentationData)
case SearchEntry(PresentationTheme, PresentationStrings)
public var stableId: UInt64 {
switch self {
@ -79,8 +78,6 @@ public enum ChatHistoryEntry: Identifiable, Comparable {
return UInt64(5) << 40
case .ChatInfoEntry:
return UInt64(6) << 40
case .SearchEntry:
return UInt64(7) << 40
}
}
@ -101,8 +98,6 @@ public enum ChatHistoryEntry: Identifiable, Comparable {
default:
return MessageIndex.absoluteLowerBound()
}
case .SearchEntry:
return MessageIndex.absoluteLowerBound()
}
}
@ -123,8 +118,6 @@ public enum ChatHistoryEntry: Identifiable, Comparable {
default:
return MessageIndex.absoluteLowerBound()
}
case .SearchEntry:
return MessageIndex.absoluteLowerBound()
}
}
@ -297,12 +290,6 @@ public enum ChatHistoryEntry: Identifiable, Comparable {
} else {
return false
}
case let .SearchEntry(lhsTheme, lhsStrings):
if case let .SearchEntry(rhsTheme, rhsStrings) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings {
return true
} else {
return false
}
}
}

View file

@ -158,7 +158,7 @@ public final class ChatHistorySearchContainerNode: SearchDisplayControllerConten
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings, self.presentationData.dateTimeFormat, self.presentationData.listsFontSize))
self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor.black.withAlphaComponent(0.5)
self.dimNode.backgroundColor = .clear
self.listNode = ListView()
self.listNode.accessibilityPageScrolledString = { row, count in
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string

View file

@ -721,7 +721,7 @@ public final class ChatQrCodeScreenImpl: ViewController, ChatQrCodeScreen {
}
private func iconColors(theme: PresentationTheme) -> [String: UIColor] {
let accentColor = theme.rootController.navigationBar.glassBarButtonForegroundColor
let accentColor = theme.chat.inputPanel.panelControlColor
var colors: [String: UIColor] = [:]
colors["Sunny.Path 14.Path.Stroke 1"] = accentColor
colors["Sunny.Path 15.Path.Stroke 1"] = accentColor
@ -1470,7 +1470,7 @@ private class ChatQrCodeScreenNode: ViewControllerTracingNode, ASScrollViewDeleg
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: self.presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -60,7 +60,7 @@ public final class ChatSearchNavigationContentNode: NavigationBarContentNode {
primaryText: theme.chat.inputPanel.panelControlColor,
placeholder: theme.chat.inputPanel.inputPlaceholderColor,
inputIcon: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.panelControlColor,
accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor
),
@ -242,7 +242,7 @@ public final class ChatSearchNavigationContentNode: NavigationBarContentNode {
primaryText: presentationInterfaceState.theme.chat.inputPanel.panelControlColor,
placeholder: presentationInterfaceState.theme.chat.inputPanel.inputPlaceholderColor,
inputIcon: presentationInterfaceState.theme.chat.inputPanel.inputControlColor,
inputClear: presentationInterfaceState.theme.chat.inputPanel.inputControlColor,
inputClear: presentationInterfaceState.theme.chat.inputPanel.panelControlColor,
accent: presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor,
keyboard: presentationInterfaceState.theme.rootController.keyboardColor
),

View file

@ -30,13 +30,21 @@ public final class ChatListNavigationBar: Component {
}
}
public struct ActiveSearch: Equatable {
public var isExternal: Bool
public init(isExternal: Bool) {
self.isExternal = isExternal
}
}
public let context: AccountContext
public let theme: PresentationTheme
public let strings: PresentationStrings
public let statusBarHeight: CGFloat
public let sideInset: CGFloat
public let search: Search?
public let isSearchActive: Bool
public let activeSearch: ActiveSearch?
public let primaryContent: ChatListHeaderComponent.Content?
public let secondaryContent: ChatListHeaderComponent.Content?
public let secondaryTransition: CGFloat
@ -59,7 +67,7 @@ public final class ChatListNavigationBar: Component {
statusBarHeight: CGFloat,
sideInset: CGFloat,
search: Search?,
isSearchActive: Bool,
activeSearch: ActiveSearch?,
primaryContent: ChatListHeaderComponent.Content?,
secondaryContent: ChatListHeaderComponent.Content?,
secondaryTransition: CGFloat,
@ -81,7 +89,7 @@ public final class ChatListNavigationBar: Component {
self.statusBarHeight = statusBarHeight
self.sideInset = sideInset
self.search = search
self.isSearchActive = isSearchActive
self.activeSearch = activeSearch
self.primaryContent = primaryContent
self.secondaryContent = secondaryContent
self.secondaryTransition = secondaryTransition
@ -117,7 +125,7 @@ public final class ChatListNavigationBar: Component {
if lhs.search != rhs.search {
return false
}
if lhs.isSearchActive != rhs.isSearchActive {
if lhs.activeSearch != rhs.activeSearch {
return false
}
if lhs.primaryContent != rhs.primaryContent {
@ -290,16 +298,10 @@ public final class ChatListNavigationBar: Component {
let previousHeight = self.currentHeight
let edgeEffectHeight: CGFloat = currentLayout.size.height + 20.0
var edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: currentLayout.size.width, height: edgeEffectHeight))
if component.isSearchActive {
edgeEffectFrame.origin.y -= 20.0
}
transition.setFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
self.edgeEffectView.update(content: component.theme.list.plainBackgroundColor, blur: true, alpha: 0.55, rect: edgeEffectFrame, edge: .top, edgeSize: 40.0, transition: transition)
self.currentHeight = visibleSize.height
var embeddedSearchBarExpansionHeight: CGFloat = 0.0
var searchFrameValue: CGRect?
if let search = component.search {
let searchContentNode: NavigationBarSearchContentNode
if let current = self.searchContentNode {
@ -337,24 +339,37 @@ public final class ChatListNavigationBar: Component {
self.addSubview(searchContentNode.view)
}
let searchSize = CGSize(width: currentLayout.size.width - 6.0 * 2.0, height: navigationBarSearchContentHeight)
var searchFrame = CGRect(origin: CGPoint(x: 6.0, y: visibleSize.height - searchSize.height), size: searchSize)
let searchSize = CGSize(width: currentLayout.size.width, height: navigationBarSearchContentHeight)
var searchFrame = CGRect(origin: CGPoint(x: 0.0, y: visibleSize.height - searchSize.height - self.bottomContentsContainer.bounds.height), size: searchSize)
if let activeSearch = component.activeSearch, !activeSearch.isExternal {
searchFrame.origin.y = component.statusBarHeight + 8.0
}
if component.tabsNode != nil {
searchFrame.origin.y -= 40.0
}
if !component.isSearchActive {
if let activeSearch = component.activeSearch {
if !activeSearch.isExternal {
searchFrame.origin.y -= component.accessoryPanelContainerHeight
}
} else {
searchFrame.origin.y -= component.accessoryPanelContainerHeight
}
let clippedSearchOffset = max(0.0, min(clippedScrollOffset, searchOffsetDistance))
let searchOffsetFraction = clippedSearchOffset / searchOffsetDistance
searchContentNode.expansionProgress = 1.0 - searchOffsetFraction
embeddedSearchBarExpansionHeight = 60.0 - floorToScreenPixels((1.0 - searchOffsetFraction) * searchSize.height)
searchFrameValue = searchFrame
transition.setFrameWithAdditivePosition(view: searchContentNode.view, frame: searchFrame)
searchContentNode.updateLayout(size: searchSize, leftInset: component.sideInset, rightInset: component.sideInset, transition: transition.containedViewLayoutTransition)
transition.setAlpha(view: searchContentNode.view, alpha: search.isEnabled ? 1.0 : 0.5)
var searchAlpha: CGFloat = search.isEnabled ? 1.0 : 0.5
if let activeSearch = component.activeSearch, activeSearch.isExternal {
searchAlpha = 0.0
}
transition.setAlpha(view: searchContentNode.view, alpha: searchAlpha)
searchContentNode.isUserInteractionEnabled = search.isEnabled
} else {
if let searchContentNode = self.searchContentNode {
@ -363,6 +378,21 @@ public final class ChatListNavigationBar: Component {
}
}
let edgeEffectHeight: CGFloat = currentLayout.size.height + 20.0
var edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: currentLayout.size.width, height: edgeEffectHeight))
if component.search != nil {
if component.activeSearch != nil {
edgeEffectFrame.origin.y -= 16.0
} else {
edgeEffectFrame.origin.y -= embeddedSearchBarExpansionHeight
}
} else if component.activeSearch != nil {
edgeEffectFrame.origin.y -= 16.0
}
transition.setFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
self.edgeEffectView.update(content: component.theme.list.plainBackgroundColor, blur: true, alpha: 0.55, rect: edgeEffectFrame, edge: .top, edgeSize: 40.0, transition: transition)
let headerTransition = transition
let storiesOffsetFraction: CGFloat
@ -443,7 +473,7 @@ public final class ChatListNavigationBar: Component {
containerSize: CGSize(width: currentLayout.size.width, height: 44.0)
)
let headerContentY: CGFloat
if component.isSearchActive {
if component.activeSearch != nil {
headerContentY = -headerContentSize.height
} else {
if component.statusBarHeight < 1.0 {
@ -460,11 +490,11 @@ public final class ChatListNavigationBar: Component {
}
transition.setFrameWithAdditivePosition(view: headerContentView, frame: headerContentFrame)
if component.isSearchActive != (headerContentView.alpha == 0.0) {
headerContentView.alpha = component.isSearchActive ? 0.0 : 1.0
if (component.activeSearch != nil) != (headerContentView.alpha == 0.0) {
headerContentView.alpha = component.activeSearch != nil ? 0.0 : 1.0
if !transition.animation.isImmediate {
if component.isSearchActive {
if component.activeSearch != nil {
headerContentView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.14)
} else {
headerContentView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
@ -473,7 +503,17 @@ public final class ChatListNavigationBar: Component {
}
}
transition.setPosition(view: self.bottomContentsContainer, position: CGPoint(x: 0.0, y: component.isSearchActive ? -self.bottomContentsContainer.bounds.height : visibleSize.height - self.bottomContentsContainer.bounds.height))
let bottomContentsContainerPosition: CGPoint
if let activeSearch = component.activeSearch {
if let searchFrameValue, !activeSearch.isExternal {
bottomContentsContainerPosition = CGPoint(x: 0.0, y: searchFrameValue.maxY - 8.0)
} else {
bottomContentsContainerPosition = CGPoint(x: 0.0, y: -self.bottomContentsContainer.bounds.height)
}
} else {
bottomContentsContainerPosition = CGPoint(x: 0.0, y: visibleSize.height - self.bottomContentsContainer.bounds.height)
}
transition.setPosition(view: self.bottomContentsContainer, position: bottomContentsContainerPosition)
if component.tabsNode !== self.tabsNode {
if let tabsNode = self.tabsNode {
@ -495,7 +535,7 @@ public final class ChatListNavigationBar: Component {
}
var tabsFrame = CGRect(origin: CGPoint(x: 0.0, y: visibleSize.height), size: CGSize(width: visibleSize.width, height: 46.0))
if component.isSearchActive {
if component.activeSearch != nil {
} else {
tabsFrame.origin.y -= component.accessoryPanelContainerHeight
}
@ -504,7 +544,7 @@ public final class ChatListNavigationBar: Component {
}
var accessoryPanelContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: visibleSize.height), size: CGSize(width: visibleSize.width, height: component.accessoryPanelContainerHeight))
if component.isSearchActive {
if component.activeSearch != nil {
} else {
accessoryPanelContainerFrame.origin.y -= component.accessoryPanelContainerHeight
}
@ -571,7 +611,7 @@ public final class ChatListNavigationBar: Component {
statusBarHeight: component.statusBarHeight,
sideInset: component.sideInset,
search: component.search,
isSearchActive: component.isSearchActive,
activeSearch: component.activeSearch,
primaryContent: component.primaryContent,
secondaryContent: component.secondaryContent,
secondaryTransition: component.secondaryTransition,
@ -637,7 +677,11 @@ public final class ChatListNavigationBar: Component {
if component.statusBarHeight >= 1.0 {
contentHeight += 3.0
}
if !component.isSearchActive {
if let activeSearch = component.activeSearch {
if !activeSearch.isExternal {
contentHeight += navigationBarSearchContentHeight
}
} else {
contentHeight += 44.0
contentHeight += 8.0
@ -697,7 +741,13 @@ public final class ChatListNavigationBar: Component {
headersContentHeight += 3.0
transition.setBounds(view: self.bottomContentsContainer, bounds: CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: headersContentHeight)))
if !component.isSearchActive {
if let activeSearch = component.activeSearch, !activeSearch.isExternal {
transition.setAlpha(view: self.bottomContentsContainer, alpha: 0.0)
} else {
transition.setAlpha(view: self.bottomContentsContainer, alpha: 1.0)
}
if component.activeSearch == nil {
contentHeight += headersContentHeight
if component.tabsNode != nil {

View file

@ -229,7 +229,7 @@ public final class NavigationButtonComponent: Component {
self.addSubnode(moreButton)
}
let buttonSize = CGSize(width: 30.0, height: 44.0)
let buttonSize = CGSize(width: 44.0, height: 44.0)
size.width = 44.0
moreButton.setContent(.more(MoreHeaderButton.optionsCircleImage(color: theme.rootController.navigationBar.buttonColor)))

View file

@ -179,7 +179,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -1586,7 +1586,7 @@ final class ComposeTodoScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -897,7 +897,7 @@ final class NewContactScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -529,7 +529,7 @@ private final class SheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: isBack ? "back" : "close", component: AnyComponent(
BundleIconComponent(
name: isBack ? "Navigation/Back" : "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak state] _ in

View file

@ -116,7 +116,7 @@ private final class SheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -1152,7 +1152,7 @@ final class GiftOptionsScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -1122,7 +1122,7 @@ private final class GiftSetupScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -472,7 +472,7 @@ private final class GiftAuctionAcquiredScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -389,7 +389,7 @@ private final class GiftAuctionActiveBidsScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -2645,7 +2645,7 @@ private final class GiftAuctionBidScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in
@ -2678,7 +2678,7 @@ private final class GiftAuctionBidScreenComponent: Component {
content: LottieComponent.AppBundleContent(
name: "anim_morewide"
),
color: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor,
color: environment.theme.chat.inputPanel.panelControlColor,
size: CGSize(width: 34.0, height: 34.0),
playOnce: self.moreButtonPlayOnce
)

View file

@ -256,7 +256,7 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak state] _ in

View file

@ -97,7 +97,7 @@ private final class SheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -640,7 +640,7 @@ private final class GiftValueSheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak state] _ in

View file

@ -544,8 +544,8 @@ public class GlassBackgroundView: UIView {
nativeParamsView.lumaMin = 0.0
nativeParamsView.lumaMax = 0.15
} else {
nativeParamsView.lumaMin = 0.7
nativeParamsView.lumaMax = 0.71
nativeParamsView.lumaMin = 0.8
nativeParamsView.lumaMax = 0.801
}
}
}
@ -638,8 +638,8 @@ public final class GlassBackgroundContainerView: UIView {
nativeParamsView.lumaMin = 0.0
nativeParamsView.lumaMax = 0.15
} else {
nativeParamsView.lumaMin = 0.7
nativeParamsView.lumaMax = 0.71
nativeParamsView.lumaMin = 0.8
nativeParamsView.lumaMax = 0.801
}
transition.setFrame(view: nativeView, frame: CGRect(origin: CGPoint(), size: size))

View file

@ -168,7 +168,11 @@ public final class GlassBarButtonComponent: Component {
componentTransition.setFrame(view: view, frame: componentFrame)
}
let effectiveState = component.state ?? .glass
let effectiveState: DisplayState = component.state ?? .glass
/*if "".isEmpty {
effectiveState = .glass
}*/
var genericAlpha: CGFloat = 1.0
var glassAlpha: CGFloat = 1.0
switch effectiveState {

View file

@ -77,7 +77,7 @@ final class GroupStickerSearchNavigationContentNode: NavigationBarContentNode, I
primaryText: theme.chat.inputPanel.panelControlColor,
placeholder: theme.chat.inputPanel.inputPlaceholderColor,
inputIcon: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.inputControlColor,
inputClear: theme.chat.inputPanel.panelControlColor,
accent: theme.chat.inputPanel.panelControlAccentColor,
keyboard: theme.rootController.keyboardColor
),

View file

@ -109,7 +109,7 @@ private final class SheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -286,7 +286,7 @@ final class MiniAppListScreenComponent: Component {
statusBarHeight: statusBarHeight,
sideInset: insets.left,
search: ChatListNavigationBar.Search(isEnabled: true),
isSearchActive: self.isSearchDisplayControllerActive,
activeSearch: self.isSearchDisplayControllerActive ? ChatListNavigationBar.ActiveSearch(isExternal: false) : nil,
primaryContent: headerContent,
secondaryContent: nil,
secondaryTransition: 0.0,

View file

@ -793,6 +793,9 @@ public final class NavigationBarImpl: ASDisplayNode, NavigationBar {
let additionalExpansionHeight: CGFloat = self.secondaryContentNode != nil && appearsHidden ? (self.secondaryContentHeight * self.secondaryContentNodeDisplayFraction) : 0.0
contentNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - (appearsHidden ? 0.0 : additionalContentHeight) - expansionHeight - apparentAdditionalHeight - additionalExpansionHeight), size: CGSize(width: size.width, height: expansionHeight))
if appearsHidden {
contentNodeFrame.origin.y = size.height - contentNode.height + contentVerticalOrigin
}
if appearsHidden {
if self.secondaryContentNode != nil {
contentNodeFrame.origin.y += self.secondaryContentHeight * self.secondaryContentNodeDisplayFraction
@ -805,7 +808,7 @@ public final class NavigationBarImpl: ASDisplayNode, NavigationBar {
transition.updateFrame(node: self.stripeNode, frame: CGRect(x: (additionalCutout?.width ?? 0.0), y: size.height + additionalBackgroundHeight, width: size.width - (additionalCutout?.width ?? 0.0), height: UIScreenPixel))
let nominalHeight: CGFloat = 56.0
let nominalHeight: CGFloat = 60.0
var leftTitleInset: CGFloat = leftInset + 1.0
var rightTitleInset: CGFloat = rightInset + 1.0
@ -947,10 +950,7 @@ public final class NavigationBarImpl: ASDisplayNode, NavigationBar {
}
self.titleNode.alpha = 1.0
var titleOffset: CGFloat = 0.0
if self.presentationData.theme.backgroundColor == .clear && self.presentationData.theme.separatorColor == .clear {
titleOffset += 3.0
}
let titleOffset: CGFloat = 0.0
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: contentVerticalOrigin + titleOffset + floorToScreenPixels((nominalHeight - titleSize.height) / 2.0)), size: titleSize))
}
}

View file

@ -80,7 +80,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
self.selectedMessages = chatControllerInteraction.selectionState.flatMap { $0.selectedIds }
self.selectedMessagesPromise.set(.single(self.selectedMessages))
self.listNode = context.sharedContext.makeChatHistoryListNode(context: context, updatedPresentationData: updatedPresentationData ?? (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, tag: .tag(tagMask), source: .default, subject: nil, controllerInteraction: chatControllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), mode: .list(search: false, reversed: false, reverseGroups: false, displayHeaders: .allButLast, hintLinks: tagMask == .webPage, isGlobalSearch: false))
self.listNode = context.sharedContext.makeChatHistoryListNode(context: context, updatedPresentationData: updatedPresentationData ?? (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, tag: .tag(tagMask), source: .default, subject: nil, controllerInteraction: chatControllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), mode: .list(reversed: false, reverseGroups: false, displayHeaders: .allButLast, hintLinks: tagMask == .webPage, isGlobalSearch: false))
self.listNode.clipsToBounds = true
self.listNode.defaultToSynchronousTransactionWhileScrolling = true
self.listNode.scroller.bounces = false

View file

@ -11436,6 +11436,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
guard let (layout, navigationBarHeight) = self.validLayout, self.searchDisplayController == nil else {
return
}
guard let controller = self.controller else {
return
}
if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .savedMessages = currentPaneKey, let paneNode = self.paneContainerNode.currentPane?.node as? PeerInfoChatPaneNode {
paneNode.activateSearch()
@ -11448,8 +11451,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
self.headerNode.navigationButtonContainer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
if self.isSettings {
(self.controller?.parent as? TabBarController)?.updateIsTabBarHidden(true, transition: .animated(duration: 0.3, curve: .linear))
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
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
@ -11478,7 +11479,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
}, resolvedFaqUrl: self.cachedFaq.get(), exceptionsList: .single(settings.notificationExceptions), archivedStickerPacks: .single(settings.archivedStickerPacks), privacySettings: .single(settings.privacySettings), hasTwoStepAuth: self.hasTwoStepAuth.get(), twoStepAuthData: self.twoStepAccessConfiguration.get(), activeSessionsContext: self.activeSessionsContextAndCount.get() |> map { $0?.0 }, webSessionsContext: self.activeSessionsContextAndCount.get() |> map { $0?.2 }), cancel: { [weak self] in
self?.deactivateSearch()
})
}, 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
@ -11592,25 +11593,34 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
transition.updateAlpha(node: navigationBar, alpha: 0.0)
}
self.searchDisplayController?.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight + 10.0, transition: .immediate)
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)
}
}, placeholder: nil)
if self.isSettings {
controller.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: true), transition: transition)
if let searchBarNode = controller.currentTabBarSearchNode?() as? SearchBarNode {
self.searchDisplayController?.setSearchBar(searchBarNode)
searchBarNode.activate()
}
}
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationBarHeight, transition: .immediate)
}
private func deactivateSearch() {
guard let searchDisplayController = self.searchDisplayController else {
func deactivateSearch() {
guard let controller = self.controller, let searchDisplayController = self.searchDisplayController else {
return
}
self.searchDisplayController = nil
searchDisplayController.deactivate(placeholder: nil)
if self.isSettings {
(self.controller?.parent as? TabBarController)?.updateIsTabBarHidden(false, transition: .animated(duration: 0.3, curve: .linear))
(self.controller?.parent as? TabBarController)?.updateIsTabBarHidden(false, transition: .animated(duration: 0.4, curve: .spring))
controller.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: false), transition: .animated(duration: 0.4, curve: .spring))
}
let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .easeInOut)
@ -14276,6 +14286,10 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
self.controllerNode.activateSearch()
}
override public func tabBarDeactivateSearch() {
self.controllerNode.deactivateSearch()
}
public static func openSavedMessagesMoreMenu(context: AccountContext, sourceController: ViewController, isViewingAsTopics: Bool, sourceView: UIView, gesture: ContextGesture?) {
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|> deliverOnMainQueue).startStandalone(next: { peer in

View file

@ -391,7 +391,7 @@ private final class OldChannelsSearchItemNode: ItemListControllerSearchNode {
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: OldChannelsSearchContainerNode(context: self.context, peers: self.peers, selectedPeerIds: self.selectedPeerIds, togglePeer: self.togglePeer), cancel: { [weak self] in
self?.cancel()
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -113,7 +113,9 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self.immediatelyActivateMultipleSelection = params.immediatelyActivateMultipleSelection
self.multipleSelectionLimit = params.multipleSelectionLimit
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@ -245,7 +247,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
private func updateThemeAndStrings() {
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.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.customTitle ?? self.presentationData.strings.Conversation_ForwardTitle
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View file

@ -1363,7 +1363,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
}
}, fieldStyle: placeholderNode.fieldStyle
)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
@ -1438,7 +1438,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -292,7 +292,7 @@ public final class SearchInputPanelComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: component.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: component.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -816,7 +816,7 @@ final class QuickReplySetupScreenComponent: Component {
statusBarHeight: statusBarHeight,
sideInset: insets.left,
search: ChatListNavigationBar.Search(isEnabled: !self.isEditing),
isSearchActive: self.isSearchDisplayControllerActive,
activeSearch: self.isSearchDisplayControllerActive ? ChatListNavigationBar.ActiveSearch(isExternal: false) : nil,
primaryContent: headerContent,
secondaryContent: nil,
secondaryTransition: 0.0,

View file

@ -127,7 +127,7 @@ private final class BirthdayPickerSheetContentComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -540,7 +540,8 @@ final class LanguageSelectionScreenNode: ViewControllerTracingNode {
inline: true,
cancel: { [weak self] in
self?.requestDeactivateSearch()
}
},
fieldStyle: placeholderNode.fieldStyle
)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)

View file

@ -218,7 +218,7 @@ final class PeerSelectionScreenComponent: Component {
private var channels: [PeerSelectionScreen.ChannelInfo]?
private var channelsDisposable: Disposable?
private var isSearchDisplayControllerActive: Bool = false
private var isSearchDisplayControllerActive: ChatListNavigationBar.ActiveSearch?
private var searchQuery: String = ""
private let searchQueryComponentSeparationCharacterSet: CharacterSet
@ -318,7 +318,7 @@ final class PeerSelectionScreenComponent: Component {
statusBarHeight: statusBarHeight,
sideInset: insets.left,
search: ChatListNavigationBar.Search(isEnabled: true),
isSearchActive: self.isSearchDisplayControllerActive,
activeSearch: self.isSearchDisplayControllerActive,
primaryContent: headerContent,
secondaryContent: nil,
secondaryTransition: 0.0,
@ -335,7 +335,7 @@ final class PeerSelectionScreenComponent: Component {
return
}
self.isSearchDisplayControllerActive = true
self.isSearchDisplayControllerActive = ChatListNavigationBar.ActiveSearch(isExternal: false)
self.state?.updated(transition: .spring(duration: 0.4))
},
openStatusSetup: { _ in
@ -385,7 +385,7 @@ final class PeerSelectionScreenComponent: Component {
let resultingOffset = mainOffset
var offset = resultingOffset
if self.isSearchDisplayControllerActive {
if self.isSearchDisplayControllerActive != nil {
offset = 0.0
}
@ -468,7 +468,7 @@ final class PeerSelectionScreenComponent: Component {
self.navigationHeight = navigationHeight
var removedSearchBar: SearchBarNode?
if self.isSearchDisplayControllerActive {
if self.isSearchDisplayControllerActive != nil {
let searchBarNode: SearchBarNode
var searchBarTransition = transition
if let current = self.searchBarNode {
@ -488,7 +488,7 @@ final class PeerSelectionScreenComponent: Component {
guard let self else {
return
}
self.isSearchDisplayControllerActive = false
self.isSearchDisplayControllerActive = nil
self.state?.updated(transition: .spring(duration: 0.4))
}
searchBarNode.textUpdated = { [weak self] query, _ in

View file

@ -35,7 +35,9 @@ public class TimezoneSelectionScreen: ViewController {
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@ -82,7 +84,7 @@ public class TimezoneSelectionScreen: ViewController {
private func updateThemeAndStrings() {
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.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.presentationData.strings.Settings_AppLanguage
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View file

@ -109,7 +109,7 @@ private final class TimezoneListSearchContainerNode: SearchDisplayControllerCont
self.presentationDataPromise = Promise(self.presentationData)
self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor.black.withAlphaComponent(0.5)
self.dimNode.backgroundColor = .clear
self.listNode = ListView()
self.listNode.accessibilityPageScrolledString = { row, count in
@ -523,7 +523,7 @@ final class TimezoneSelectionScreenNode: ViewControllerTracingNode {
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: TimezoneListSearchContainerNode(context: self.context, timeZoneList: timeZoneList, action: self.action), inline: true, cancel: { [weak self] in
self?.requestDeactivateSearch()
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -889,7 +889,7 @@ final class LiveStreamSettingsScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -2772,7 +2772,7 @@ final class ShareWithPeersScreenComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in

View file

@ -677,7 +677,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -348,7 +348,7 @@ private final class SheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -95,7 +95,7 @@ private final class SheetContent: CombinedComponent {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -227,7 +227,7 @@ private final class StoryStealthModeSheetContentComponent: Component {
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: environment.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: environment.theme.chat.inputPanel.panelControlColor
)
)),
action: { _ in

View file

@ -202,7 +202,7 @@ public final class NavigationSearchView: UIView {
primaryText: params.theme.chat.inputPanel.panelControlColor,
placeholder: params.theme.chat.inputPanel.inputPlaceholderColor,
inputIcon: params.theme.chat.inputPanel.inputControlColor,
inputClear: params.theme.chat.inputPanel.inputControlColor,
inputClear: params.theme.chat.inputPanel.panelControlColor,
accent: params.theme.chat.inputPanel.panelControlAccentColor,
keyboard: params.theme.rootController.keyboardColor
),

View file

@ -7269,6 +7269,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
override public func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if #available(iOS 18.0, *) {
} else {
//TODO:release
}
UIView.performWithoutAnimation {
self.view.endEditing(true)
}

View file

@ -41,7 +41,6 @@ func chatHistoryEntriesForView(
includeUnreadEntry: Bool,
includeEmptyEntry: Bool,
includeChatInfoEntry: Bool,
includeSearchEntry: Bool,
includeEmbeddedSavedChatInfo: Bool,
reverse: Bool,
groupMessages: Bool,
@ -680,12 +679,6 @@ func chatHistoryEntriesForView(
entries.append(.MessageEntry(updatedMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false, authorStoryStats: nil, displayContinueThreadFooter: false)))
}
}
} else if includeSearchEntry {
if view.laterId == nil {
if !view.entries.isEmpty {
entries.append(.SearchEntry(presentationData.theme.theme, presentationData.strings))
}
}
}
if addBotForumHeader {
entries.append(.ChatInfoEntry(.newThreadInfo, presentationData))

View file

@ -11,7 +11,6 @@ import TelegramUIPreferences
import MediaResources
import AccountContext
import TemporaryCachedPeerDataManager
import ChatListSearchItemNode
import Emoji
import AppBundle
import ListMessageItem
@ -229,7 +228,7 @@ private func mappedInsertEntries(context: AccountContext, chatLocation: ChatLoca
switch mode {
case .bubbles:
item = ChatMessageItemImpl(presentationData: presentationData, context: context, chatLocation: chatLocation, associatedData: associatedData, controllerInteraction: controllerInteraction, content: .message(message: message, read: read, selection: selection, attributes: attributes, location: location), disableDate: disableFloatingDateHeaders || message.timestamp < 10)
case let .list(_, _, _, displayHeaders, hintLinks, isGlobalSearch):
case let .list(_, _, displayHeaders, hintLinks, isGlobalSearch):
let displayHeader: Bool
switch displayHeaders {
case .none:
@ -267,10 +266,6 @@ private func mappedInsertEntries(context: AccountContext, chatLocation: ChatLoca
item = ChatNewThreadInfoItem(controllerInteraction: controllerInteraction, presentationData: presentationData, context: context)
}
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
case let .SearchEntry(theme, strings):
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: {
controllerInteraction.openSearch()
}), directionHint: entry.directionHint)
}
}
}
@ -288,7 +283,7 @@ private func mappedUpdateEntries(context: AccountContext, chatLocation: ChatLoca
switch mode {
case .bubbles:
item = ChatMessageItemImpl(presentationData: presentationData, context: context, chatLocation: chatLocation, associatedData: associatedData, controllerInteraction: controllerInteraction, content: .message(message: message, read: read, selection: selection, attributes: attributes, location: location), disableDate: disableFloatingDateHeaders || message.timestamp < 10)
case let .list(_, _, _, displayHeaders, hintLinks, isGlobalSearch):
case let .list(_, _, displayHeaders, hintLinks, isGlobalSearch):
let displayHeader: Bool
switch displayHeaders {
case .none:
@ -326,10 +321,6 @@ private func mappedUpdateEntries(context: AccountContext, chatLocation: ChatLoca
item = ChatNewThreadInfoItem(controllerInteraction: controllerInteraction, presentationData: presentationData, context: context)
}
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
case let .SearchEntry(theme, strings):
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: {
controllerInteraction.openSearch()
}), directionHint: entry.directionHint)
}
}
}
@ -2022,14 +2013,11 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
var reverse = false
var reverseGroups = false
var includeSearchEntry = false
if case let .list(search, reverseValue, reverseGroupsValue, _, _, _) = mode {
includeSearchEntry = search
if case let .list(reverseValue, reverseGroupsValue, _, _, _) = mode {
reverse = reverseValue
reverseGroups = reverseGroupsValue
}
var isPremium = false
if case let .user(user) = accountPeer, user.isPremium {
isPremium = true
@ -2087,7 +2075,6 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
includeUnreadEntry: mode == .bubbles,
includeEmptyEntry: mode == .bubbles && tag == nil,
includeChatInfoEntry: mode == .bubbles,
includeSearchEntry: includeSearchEntry && tag != nil,
includeEmbeddedSavedChatInfo: includeEmbeddedSavedChatInfo,
reverse: reverse,
groupMessages: mode == .bubbles,
@ -4551,7 +4538,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
switch self.mode {
case .bubbles:
item = ChatMessageItemImpl(presentationData: presentationData, context: self.context, chatLocation: self.chatLocation, associatedData: associatedData, controllerInteraction: self.controllerInteraction, content: .message(message: message, read: read, selection: selection, attributes: attributes, location: location), disableDate: disableFloatingDateHeaders)
case let .list(_, _, _, displayHeaders, hintLinks, isGlobalSearch):
case let .list(_, _, displayHeaders, hintLinks, isGlobalSearch):
let displayHeader: Bool
switch displayHeaders {
case .none:
@ -4629,7 +4616,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
switch self.mode {
case .bubbles:
item = ChatMessageItemImpl(presentationData: presentationData, context: self.context, chatLocation: self.chatLocation, associatedData: associatedData, controllerInteraction: self.controllerInteraction, content: .message(message: message, read: read, selection: selection, attributes: attributes, location: location), disableDate: disableFloatingDateHeaders)
case let .list(_, _, _, displayHeaders, hintLinks, isGlobalSearch):
case let .list(_, _, displayHeaders, hintLinks, isGlobalSearch):
let displayHeader: Bool
switch displayHeaders {
case .none:

View file

@ -41,8 +41,9 @@ public class ComposeControllerImpl: ViewController, ComposeController {
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.navigationPresentation = .modal
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@ -51,8 +52,6 @@ public class ComposeControllerImpl: ViewController, ComposeController {
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(cancelPressed))
self.scrollToTop = { [weak self] in
if let strongSelf = self {
if let searchContentNode = strongSelf.searchContentNode {
@ -93,7 +92,7 @@ public class ComposeControllerImpl: ViewController, ComposeController {
private func updateThemeAndStrings() {
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.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.presentationData.strings.Compose_NewMessage
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View file

@ -131,7 +131,7 @@ final class ComposeControllerNode: ASDisplayNode {
self.requestOpenDisabledPeerFromSearch?(peer, reason)
}, contextAction: nil), cancel: { [weak self] in
self?.requestDeactivateSearch?()
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -133,7 +133,9 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
self.presentationData = self.presentationData.withUpdated(theme: self.presentationData.theme.withModalBlocksBackground())
}
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme, hideBackground: glass, hideSeparator: glass), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme, hideBackground: glass, hideSeparator: glass, style: .glass), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
self._hasGlassStyle = true
self.blocksBackgroundWhenInOverlay = true
self.acceptsFocusWhenInOverlay = true
@ -247,7 +249,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: self.presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in
@ -268,7 +270,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
component: AnyComponentWithIdentity(id: "search", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Search",
tintColor: self.presentationData.theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: self.presentationData.theme.chat.inputPanel.panelControlColor
)
)),
action: { [weak self] _ in
@ -307,7 +309,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
if case .glass = self.style {
glass = true
}
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme, hideBackground: glass, hideSeparator: glass), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)), transition: .immediate)
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme, hideBackground: glass, hideSeparator: glass, style: .glass), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)), transition: .immediate)
(self.searchContentNode as? NavigationBarSearchContentNode)?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.titleProducer(self.presentationData.strings)
self.tabBarItem.title = self.presentationData.strings.Contacts_Title

View file

@ -477,7 +477,7 @@ final class ContactSelectionControllerNode: ASDisplayNode {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in

View file

@ -259,7 +259,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
self.historyNode = ChatHistoryListNodeImpl(context: context, updatedPresentationData: (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, adMessagesContext: nil, tag: .tag(tagMask), source: self.source, subject: .message(id: .id(initialMessageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, reverseGroups: !self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch), isChatPreview: false, messageTransitionNode: { return nil })
self.historyNode = ChatHistoryListNodeImpl(context: context, updatedPresentationData: (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, adMessagesContext: nil, tag: .tag(tagMask), source: self.source, subject: .message(id: .id(initialMessageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(reversed: self.currentIsReversed, reverseGroups: !self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch), isChatPreview: false, messageTransitionNode: { return nil })
self.historyNode.clipsToBounds = true
super.init()
@ -881,7 +881,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
}
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
let historyNode = ChatHistoryListNodeImpl(context: self.context, updatedPresentationData: (self.context.sharedContext.currentPresentationData.with({ $0 }), self.context.sharedContext.presentationData), chatLocation: self.chatLocation, chatLocationContextHolder: chatLocationContextHolder, adMessagesContext: nil, tag: .tag(tagMask), source: self.source, subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, reverseGroups: !self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch), isChatPreview: false, messageTransitionNode: { return nil })
let historyNode = ChatHistoryListNodeImpl(context: self.context, updatedPresentationData: (self.context.sharedContext.currentPresentationData.with({ $0 }), self.context.sharedContext.presentationData), chatLocation: self.chatLocation, chatLocationContextHolder: chatLocationContextHolder, adMessagesContext: nil, tag: .tag(tagMask), source: self.source, subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(reversed: self.currentIsReversed, reverseGroups: !self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch), isChatPreview: false, messageTransitionNode: { return nil })
historyNode.clipsToBounds = true
historyNode.preloadPages = true
historyNode.stackFromBottom = true

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