This commit is contained in:
Isaac 2025-11-26 23:05:30 +08:00
parent ddcea95734
commit 0055396d4d
80 changed files with 2312 additions and 2249 deletions

View file

@ -5,8 +5,12 @@
"Bash(.build/debug/makeproject:*)",
"Bash(mkdir:*)",
"Bash(find:*)",
"Bash(grep:*)"
"Bash(grep:*)",
"Skill(superpowers:brainstorming)",
"Bash(cat:*)",
"Bash(python3:*)",
"Skill(superpowers:writing-plans)"
],
"deny": []
}
}
}

6
MODULE.bazel.lock generated
View file

@ -98,8 +98,8 @@
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/8.12.0/MODULE.bazel": "8e6590b961f2defdfc2811c089c75716cb2f06c8a4edeb9a8d85eaa64ee2a761",
"https://bcr.bazel.build/modules/rules_java/8.12.0/source.json": "cbd5d55d9d38d4008a7d00bee5b5a5a4b6031fcd4a56515c9accbcd42c7be2ba",
"https://bcr.bazel.build/modules/rules_java/8.14.0/MODULE.bazel": "717717ed40cc69994596a45aec6ea78135ea434b8402fb91b009b9151dd65615",
"https://bcr.bazel.build/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc",
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
@ -156,7 +156,7 @@
"moduleExtensions": {
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "hUTp2w+RUVdL7ma5esCXZJAFnX7vLbVfLd7FwnQI6bU=",
"bzlTransitiveDigest": "OlvsB0HsvxbR8ZN+J9Vf00X/+WVz/Y/5Xrq2LgcVfdo=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},

View file

@ -335,6 +335,7 @@ filegroup(
objc_library(
name = "Main",
module_name = "Main",
srcs = [
"Telegram-iOS/main.m"
],
@ -342,6 +343,7 @@ objc_library(
swift_library(
name = "Lib",
module_name = "Lib",
srcs = glob([
"Telegram-iOS/Application.swift",
]),

View file

@ -369,17 +369,15 @@ class BazelCommandLine:
print(subprocess.list2cmdline(combined_arguments))
call_executable(combined_arguments)
def get_spm_aspect_invocation(self):
def invoke_spm_build(self):
combined_arguments = [
self.build_environment.bazel_path
]
combined_arguments += self.get_startup_bazel_arguments()
combined_arguments += ['build']
if self.custom_target is not None:
combined_arguments += [self.custom_target]
else:
combined_arguments += ['Telegram/Telegram']
# Build the generate_spm target directly to get the dependency tree JSON
combined_arguments += ['//Telegram:spm_build_root']
if self.continue_on_error:
combined_arguments += ['--keep_going']
@ -409,8 +407,6 @@ class BazelCommandLine:
combined_arguments += self.configuration_args
combined_arguments += ['--aspects', '//build-system/bazel-utils:spm.bzl%spm_text_aspect']
print(subprocess.list2cmdline(combined_arguments))
call_executable(combined_arguments)
@ -719,7 +715,7 @@ def query(bazel, arguments):
bazel_command_line.invoke_query(query_args)
def get_spm_aspect_invocation(bazel, arguments):
def build_spm(bazel, arguments):
bazel_command_line = BazelCommandLine(
bazel=bazel,
override_bazel_version=arguments.overrideBazelVersion,
@ -741,13 +737,12 @@ def get_spm_aspect_invocation(bazel, arguments):
bazel_command_line.set_configuration(arguments.configuration)
bazel_command_line.set_build_number(arguments.buildNumber)
bazel_command_line.set_custom_target(arguments.target)
bazel_command_line.set_continue_on_error(False)
bazel_command_line.set_show_actions(False)
bazel_command_line.set_enable_sandbox(False)
bazel_command_line.set_split_swiftmodules(False)
bazel_command_line.get_spm_aspect_invocation()
bazel_command_line.invoke_spm_build()
def add_codesigning_common_arguments(current_parser: argparse.ArgumentParser):
configuration_group = current_parser.add_mutually_exclusive_group(required=True)
@ -1188,13 +1183,7 @@ if __name__ == '__main__':
metavar='query_string'
)
spm_parser = subparsers.add_parser('spm', help='Generate SPM package')
spm_parser.add_argument(
'--target',
type=str,
help='A custom bazel target name to build.',
metavar='target_name'
)
spm_parser = subparsers.add_parser('spm', help='Generate SPM package (outputs bazel-bin/Telegram/spm_build_root_modules.json)')
spm_parser.add_argument(
'--buildNumber',
required=False,
@ -1351,7 +1340,7 @@ if __name__ == '__main__':
elif args.commandName == 'query':
query(bazel=bazel_path, arguments=args)
elif args.commandName == 'spm':
get_spm_aspect_invocation(bazel=bazel_path, arguments=args)
build_spm(bazel=bazel_path, arguments=args)
else:
raise Exception('Unknown command')
except KeyboardInterrupt:

View file

@ -73,7 +73,7 @@ public final class AdInfoScreen: ViewController {
self.titleNode = ImmediateTextNode()
self.titleNode.maximumNumberOfLines = 1
self.titleNode.attributedText = NSAttributedString(string: self.presentationData.strings.SponsoredMessageInfoScreen_Title, font: NavigationBar.titleFont, textColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.presentationData.strings.SponsoredMessageInfoScreen_Title, font: Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor)
self.scrollNode = ASScrollNode()
self.scrollNode.view.showsVerticalScrollIndicator = true

View file

@ -33,7 +33,7 @@ private enum InnerState: Equatable {
public final class AuthorizationSequenceController: NavigationController, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
static func navigationBarTheme(_ theme: PresentationTheme) -> NavigationBarTheme {
return NavigationBarTheme(buttonColor: theme.intro.accentTextColor, disabledButtonColor: theme.intro.disabledTextColor, primaryTextColor: theme.intro.primaryTextColor, backgroundColor: .clear, opaqueBackgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: theme.rootController.navigationBar.badgeBackgroundColor, badgeStrokeColor: theme.rootController.navigationBar.badgeStrokeColor, badgeTextColor: theme.rootController.navigationBar.badgeTextColor)
return NavigationBarTheme(overallDarkAppearance: theme.overallDarkAppearance, buttonColor: theme.intro.accentTextColor, disabledButtonColor: theme.intro.disabledTextColor, primaryTextColor: theme.intro.primaryTextColor, backgroundColor: .clear, opaqueBackgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: theme.rootController.navigationBar.badgeBackgroundColor, badgeStrokeColor: theme.rootController.navigationBar.badgeStrokeColor, badgeTextColor: theme.rootController.navigationBar.badgeTextColor)
}
private let sharedContext: SharedAccountContext

View file

@ -441,7 +441,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))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
}

View file

@ -205,7 +205,7 @@ public final class CallListController: TelegramBaseController {
}
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
if self.isNodeLoaded {
self.controllerNode.updateThemeAndStrings(presentationData: self.presentationData)
@ -780,6 +780,10 @@ public final class CallListController: TelegramBaseController {
let controller = ContextController(presentationData: self.presentationData, source: .reference(CallListTabBarContextReferenceContentSource(controller: self, sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), recognizer: nil, gesture: gesture)
self.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller)
}
override public func tabBarActivateSearch() {
self.beginCallImpl()
}
}
private final class CallListTabBarContextReferenceContentSource: ContextReferenceContentSource {

View file

@ -438,23 +438,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}).strict()
if !previewing {
/*
self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: placeholder, compactPlaceholder: compactPlaceholder, activate: { [weak self] in
self?.chatListDisplayNode.mainContainerNode.currentItemNode.cancelTracking()
self?.activateSearch(filter: isForum ? .topics : .chats)
})
self.searchContentNode?.updateExpansionProgress(0.0)
self.navigationBar?.setContentNode(self.searchContentNode, animated: false)*/
let tabsIsEmpty: Bool
if let (resolvedItems, displayTabsAtBottom, _) = self.tabContainerData {
tabsIsEmpty = resolvedItems.count <= 1 || displayTabsAtBottom
} else {
tabsIsEmpty = true
}
self.navigationBar?.secondaryContentHeight = !tabsIsEmpty ? NavigationBar.defaultSecondaryContentHeight : 0.0
enum State: Equatable {
case empty(hasDownloads: Bool)
case downloading(progress: Double)
@ -937,7 +920,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
if let layout = self.validLayout {
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.effectiveContainerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, filtersLimit: self.tabContainerData?.2, transitionFraction: self.chatListDisplayNode.effectiveContainerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate)
@ -3522,8 +3505,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
tabContainerOffset += 44.0 + 20.0
}
let navigationBarHeight: CGFloat = 0.0//self.navigationBar?.frame.maxY ?? 0.0
//let secondaryContentHeight = self.navigationBar?.secondaryContentHeight ?? 0.0
let navigationBarHeight: CGFloat = 0.0
transition.updateFrame(node: self.tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: 46.0)))

View file

@ -130,6 +130,9 @@ public class ChatTitleActivityNode: ASDisplayNode {
}
public func updateLayout(_ constrainedSize: CGSize, offset: CGFloat = 0.0, alignment: NSTextAlignment) -> CGSize {
return CGSize(width: 0.0, height: self.contentNode?.updateLayout(constrainedSize, offset: offset, alignment: alignment).height ?? 0.0)
guard let contentSize = self.contentNode?.updateLayout(constrainedSize, offset: offset, alignment: alignment) else {
return CGSize()
}
return contentSize
}
}

View file

@ -361,7 +361,7 @@ open class ViewControllerComponentContainer: ViewController {
navigationBarPresentationData = NavigationBarPresentationData(presentationData: presentationData)
}
if let navigationBarPresentationData {
strongSelf.navigationBar?.updatePresentationData(navigationBarPresentationData)
strongSelf.navigationBar?.updatePresentationData(navigationBarPresentationData, transition: .immediate)
}
if let layout = strongSelf.validLayout {

View file

@ -48,6 +48,7 @@ swift_library(
"//submodules/ContextUI",
"//submodules/TelegramUI/Components/EdgeEffect",
"//submodules/TelegramUI/Components/SearchInputPanelComponent",
"//submodules/SearchBarNode",
],
visibility = [
"//visibility:public",

View file

@ -24,6 +24,7 @@ import ChatListHeaderComponent
import TelegramIntents
import UndoUI
import ShareController
import SearchBarNode
private final class HeaderContextReferenceContentSource: ContextReferenceContentSource {
private let controller: ViewController
@ -141,7 +142,6 @@ public class ContactsController: ViewController {
self.sortButton = SortHeaderButton(presentationData: self.presentationData)
//super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: nil)
self.tabBarItemContextActionType = .always
@ -244,7 +244,6 @@ public class ContactsController: ViewController {
private func updateThemeAndStrings() {
self.sortButton.update(theme: self.presentationData.theme, strings: self.presentationData.strings)
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.title = self.presentationData.strings.Contacts_Title
self.tabBarItem.title = self.presentationData.strings.Contacts_Title
@ -282,8 +281,6 @@ public class ContactsController: ViewController {
|> take(1)
|> map { _ -> Bool in true })
self.contactsNode.navigationBar = self.navigationBar
let openPeer: (ContactListPeer, Bool) -> Void = { [weak self] peer, fromSearch in
if let strongSelf = self {
switch peer {
@ -583,17 +580,19 @@ public class ContactsController: ViewController {
}
private func activateSearch() {
if let searchContentNode = self.searchContentNode() {
self.contactsNode.activateSearch(placeholderNode: searchContentNode.placeholderNode)
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()
}
self.requestLayout(transition: .animated(duration: 0.5, curve: .spring))
}
private func deactivateSearch(animated: Bool) {
if let searchContentNode = self.searchContentNode() {
self.contactsNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode, animated: animated)
self.requestLayout(transition: .animated(duration: 0.5, curve: .spring))
}
self.contactsNode.deactivateSearch(placeholderNode: self.searchContentNode()?.placeholderNode, animated: animated)
self.updateTabBarSearchState(ViewController.TabBarSearchState(isActive: false), transition: .animated(duration: 0.5, curve: .spring))
self.requestLayout(transition: .animated(duration: 0.5, curve: .spring))
}
func presentSortMenu(sourceView: UIView, gesture: ContextGesture?) {
@ -798,6 +797,14 @@ public class ContactsController: ViewController {
let controller = ContextController(presentationData: self.presentationData, source: .reference(ContactsTabBarContextReferenceContentSource(controller: self, sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), recognizer: nil, gesture: gesture)
self.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller)
}
override public func tabBarActivateSearch() {
self.activateSearch()
}
override public func tabBarDeactivateSearch() {
self.deactivateSearch(animated: true)
}
}
private final class ContactsTabBarContextReferenceContentSource: ContextReferenceContentSource {

View file

@ -58,7 +58,6 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
private var containerLayout: (ContainerViewLayout, CGFloat)?
var navigationBar: NavigationBar?
let navigationBarView = ComponentView<Empty>()
var requestDeactivateSearch: (() -> Void)?
@ -361,7 +360,7 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
strings: self.presentationData.strings,
statusBarHeight: layout.statusBarHeight ?? 0.0,
sideInset: layout.safeInsets.left,
search: ChatListNavigationBar.Search(isEnabled: true),
search: nil,//ChatListNavigationBar.Search(isEnabled: true),
isSearchActive: self.isSearchDisplayControllerActive,
primaryContent: primaryContent,
secondaryContent: nil,
@ -477,7 +476,7 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
}
}
func activateSearch(placeholderNode: SearchBarPlaceholderNode) {
func activateSearch(placeholderNode: SearchBarPlaceholderNode?) {
guard let (containerLayout, navigationBarHeight) = self.containerLayout, self.searchDisplayController == nil else {
return
}
@ -503,7 +502,7 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
})
}, searchBarIsExternal: placeholderNode == nil)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self] subnode, isSearchBar in
@ -519,16 +518,22 @@ final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
}, placeholder: placeholderNode)
}
func deactivateSearch(placeholderNode: SearchBarPlaceholderNode, animated: Bool) {
func deactivateSearch(placeholderNode: SearchBarPlaceholderNode?, animated: Bool) {
self.isSearchDisplayControllerActive = false
if let searchDisplayController = self.searchDisplayController {
let previousFrame = placeholderNode.frame
placeholderNode.frame = previousFrame.offsetBy(dx: 0.0, dy: 54.0)
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
placeholderNode.frame = previousFrame
if let placeholderNode, let previousFrame {
placeholderNode.frame = previousFrame
}
}
}
}

View file

@ -86,7 +86,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))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), 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

@ -13,7 +13,7 @@ public struct ImmediateTextNodeLayoutInfo {
}
}
public class ImmediateTextNode: TextNode {
open class ImmediateTextNode: TextNode {
public var attributedText: NSAttributedString?
public var textAlignment: NSTextAlignment = .natural
public var verticalAlignment: TextVerticalAlignment = .top
@ -60,7 +60,7 @@ public class ImmediateTextNode: TextNode {
public var trailingLineWidth: CGFloat?
var constrainedSize: CGSize?
public var constrainedSize: CGSize?
public var highlightAttributeAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)? {
didSet {
@ -94,7 +94,7 @@ public class ImmediateTextNode: TextNode {
return node
}
public func updateLayout(_ constrainedSize: CGSize) -> CGSize {
open func updateLayout(_ constrainedSize: CGSize) -> CGSize {
self.constrainedSize = constrainedSize
let makeLayout = TextNode.asyncLayout(self)

View file

@ -109,7 +109,7 @@ public final class NavigationModalFrame: ASDisplayNode {
let contentScale = (layout.size.width - sideInset * 2.0) / layout.size.width
let bottomInset: CGFloat = layout.size.height - contentScale * layout.size.height - topInset
let cornerRadius: CGFloat = 28.0
let cornerRadius: CGFloat = 38.0
let initialCornerRadius: CGFloat
if !layout.safeInsets.top.isZero {
initialCornerRadius = layout.deviceMetrics.screenCornerRadius

View file

@ -0,0 +1,332 @@
import Foundation
import UIKit
import AsyncDisplayKit
private var sharedIsReduceTransparencyEnabled = UIAccessibility.isReduceTransparencyEnabled
public final class NavigationBackgroundNode: ASDisplayNode {
private var _color: UIColor
public var color: UIColor {
return self._color
}
private var enableBlur: Bool
private var enableSaturation: Bool
private var customBlurRadius: CGFloat?
public var effectView: UIVisualEffectView?
private let backgroundNode: ASDisplayNode
public var backgroundView: UIView {
return self.backgroundNode.view
}
private var validLayout: (CGSize, CGFloat)?
public var backgroundCornerRadius: CGFloat {
if let (_, cornerRadius) = self.validLayout {
return cornerRadius
} else {
return 0.0
}
}
public init(color: UIColor, enableBlur: Bool = true, enableSaturation: Bool = true, customBlurRadius: CGFloat? = nil) {
self._color = .clear
self.enableBlur = enableBlur
self.enableSaturation = enableSaturation
self.customBlurRadius = customBlurRadius
self.backgroundNode = ASDisplayNode()
super.init()
self.addSubnode(self.backgroundNode)
self.updateColor(color: color, transition: .immediate)
}
public override func didLoad() {
super.didLoad()
if self.scheduledUpdate {
self.scheduledUpdate = false
self.updateBackgroundBlur(forceKeepBlur: false)
}
}
private var scheduledUpdate = false
private func updateBackgroundBlur(forceKeepBlur: Bool) {
guard self.isNodeLoaded else {
self.scheduledUpdate = true
return
}
if self.enableBlur && !sharedIsReduceTransparencyEnabled && ((self._color.alpha > .ulpOfOne && self._color.alpha < 0.95) || forceKeepBlur) {
if self.effectView == nil {
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
for subview in effectView.subviews {
if subview.description.contains("VisualEffectSubview") {
subview.isHidden = true
}
}
if let sublayer = effectView.layer.sublayers?[0], let filters = sublayer.filters {
sublayer.backgroundColor = nil
sublayer.isOpaque = false
var allowedKeys: [String] = [
"gaussianBlur"
]
if self.enableSaturation {
allowedKeys.append("colorSaturate")
}
sublayer.filters = filters.filter { filter in
guard let filter = filter as? NSObject else {
return true
}
let filterName = String(describing: filter)
if !allowedKeys.contains(filterName) {
return false
}
if let customBlurRadius = self.customBlurRadius, filterName == "gaussianBlur" {
filter.setValue(customBlurRadius as NSNumber, forKey: "inputRadius")
}
return true
}
}
if let (size, cornerRadius) = self.validLayout {
effectView.frame = CGRect(origin: CGPoint(), size: size)
ContainedViewLayoutTransition.immediate.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius)
effectView.clipsToBounds = !cornerRadius.isZero
}
self.effectView = effectView
self.view.insertSubview(effectView, at: 0)
}
} else if let effectView = self.effectView {
self.effectView = nil
effectView.removeFromSuperview()
}
}
public func updateColor(color: UIColor, enableBlur: Bool? = nil, enableSaturation: Bool? = nil, forceKeepBlur: Bool = false, transition: ContainedViewLayoutTransition) {
let effectiveEnableBlur = enableBlur ?? self.enableBlur
let effectiveEnableSaturation = enableSaturation ?? self.enableSaturation
if self._color.isEqual(color) && self.enableBlur == effectiveEnableBlur && self.enableSaturation == effectiveEnableSaturation {
return
}
self._color = color
self.enableBlur = effectiveEnableBlur
self.enableSaturation = effectiveEnableSaturation
if sharedIsReduceTransparencyEnabled {
transition.updateBackgroundColor(node: self.backgroundNode, color: self._color.withAlphaComponent(1.0))
} else {
transition.updateBackgroundColor(node: self.backgroundNode, color: self._color)
}
self.updateBackgroundBlur(forceKeepBlur: forceKeepBlur)
}
public func update(size: CGSize, cornerRadius: CGFloat = 0.0, transition: ContainedViewLayoutTransition, beginWithCurrentState: Bool = true) {
self.validLayout = (size, cornerRadius)
let contentFrame = CGRect(origin: CGPoint(), size: size)
transition.updateFrame(node: self.backgroundNode, frame: contentFrame, beginWithCurrentState: true)
if let effectView = self.effectView, effectView.frame != contentFrame {
transition.updateFrame(layer: effectView.layer, frame: contentFrame, beginWithCurrentState: true)
if let sublayers = effectView.layer.sublayers {
for sublayer in sublayers {
transition.updateFrame(layer: sublayer, frame: contentFrame, beginWithCurrentState: true)
}
}
}
transition.updateCornerRadius(node: self.backgroundNode, cornerRadius: cornerRadius)
if let effectView = self.effectView {
transition.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius)
effectView.clipsToBounds = !cornerRadius.isZero
}
}
public func update(size: CGSize, cornerRadius: CGFloat = 0.0, animator: ControlledTransitionAnimator) {
self.validLayout = (size, cornerRadius)
let contentFrame = CGRect(origin: CGPoint(), size: size)
animator.updateFrame(layer: self.backgroundNode.layer, frame: contentFrame, completion: nil)
if let effectView = self.effectView, effectView.frame != contentFrame {
animator.updateFrame(layer: effectView.layer, frame: contentFrame, completion: nil)
if let sublayers = effectView.layer.sublayers {
for sublayer in sublayers {
animator.updateFrame(layer: sublayer, frame: contentFrame, completion: nil)
}
}
}
animator.updateCornerRadius(layer: self.backgroundNode.layer, cornerRadius: cornerRadius, completion: nil)
if let effectView = self.effectView {
animator.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius, completion: nil)
effectView.clipsToBounds = !cornerRadius.isZero
}
}
}
open class BlurredBackgroundView: UIView {
private var _color: UIColor?
private var enableBlur: Bool
private var customBlurRadius: CGFloat?
public private(set) var effectView: UIVisualEffectView?
private let backgroundView: UIView
private var validLayout: (CGSize, CGFloat)?
public var backgroundCornerRadius: CGFloat {
if let (_, cornerRadius) = self.validLayout {
return cornerRadius
} else {
return 0.0
}
}
public init(color: UIColor?, enableBlur: Bool = true, customBlurRadius: CGFloat? = nil) {
self._color = nil
self.enableBlur = enableBlur
self.customBlurRadius = customBlurRadius
self.backgroundView = UIView()
super.init(frame: CGRect())
self.addSubview(self.backgroundView)
if let color = color {
self.updateColor(color: color, transition: .immediate)
}
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func updateBackgroundBlur(forceKeepBlur: Bool) {
if let color = self._color, self.enableBlur && !sharedIsReduceTransparencyEnabled && ((color.alpha > .ulpOfOne && color.alpha < 0.95) || forceKeepBlur) {
if self.effectView == nil {
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
for subview in effectView.subviews {
if subview.description.contains("VisualEffectSubview") {
subview.isHidden = true
}
}
if let sublayer = effectView.layer.sublayers?[0], let filters = sublayer.filters {
sublayer.backgroundColor = nil
sublayer.isOpaque = false
//sublayer.setValue(true as NSNumber, forKey: "allowsInPlaceFiltering")
let allowedKeys: [String] = [
"colorSaturate",
"gaussianBlur"
]
sublayer.filters = filters.filter { filter in
guard let filter = filter as? NSObject else {
return true
}
let filterName = String(describing: filter)
if !allowedKeys.contains(filterName) {
return false
}
if let customBlurRadius = self.customBlurRadius, filterName == "gaussianBlur" {
filter.setValue(customBlurRadius as NSNumber, forKey: "inputRadius")
}
return true
}
}
if let (size, cornerRadius) = self.validLayout {
effectView.frame = CGRect(origin: CGPoint(), size: size)
ContainedViewLayoutTransition.immediate.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius)
effectView.clipsToBounds = !cornerRadius.isZero
}
self.effectView = effectView
self.insertSubview(effectView, at: 0)
}
} else if let effectView = self.effectView {
self.effectView = nil
effectView.removeFromSuperview()
}
}
public func updateColor(color: UIColor, enableBlur: Bool? = nil, forceKeepBlur: Bool = false, transition: ContainedViewLayoutTransition) {
let effectiveEnableBlur = enableBlur ?? self.enableBlur
if self._color == color && self.enableBlur == effectiveEnableBlur {
return
}
self._color = color
self.enableBlur = effectiveEnableBlur
if sharedIsReduceTransparencyEnabled {
transition.updateBackgroundColor(layer: self.backgroundView.layer, color: color.withAlphaComponent(1.0))
} else {
transition.updateBackgroundColor(layer: self.backgroundView.layer, color: color)
}
self.updateBackgroundBlur(forceKeepBlur: forceKeepBlur)
}
public func update(size: CGSize, cornerRadius: CGFloat = 0.0, maskedCorners: CACornerMask = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner], transition: ContainedViewLayoutTransition) {
self.validLayout = (size, cornerRadius)
let contentFrame = CGRect(origin: CGPoint(), size: size)
transition.updateFrame(view: self.backgroundView, frame: contentFrame, beginWithCurrentState: true)
if let effectView = self.effectView, effectView.frame != contentFrame {
transition.updateFrame(layer: effectView.layer, frame: contentFrame, beginWithCurrentState: true)
if let sublayers = effectView.layer.sublayers {
for sublayer in sublayers {
transition.updateFrame(layer: sublayer, frame: contentFrame, beginWithCurrentState: true)
}
}
}
if #available(iOS 11.0, *) {
self.backgroundView.layer.maskedCorners = maskedCorners
}
transition.updateCornerRadius(layer: self.backgroundView.layer, cornerRadius: cornerRadius)
if let effectView = self.effectView {
transition.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius)
effectView.clipsToBounds = !cornerRadius.isZero
if #available(iOS 11.0, *) {
effectView.layer.maskedCorners = maskedCorners
}
}
}
public func update(size: CGSize, cornerRadius: CGFloat = 0.0, animator: ControlledTransitionAnimator) {
self.validLayout = (size, cornerRadius)
let contentFrame = CGRect(origin: CGPoint(), size: size)
animator.updateFrame(layer: self.backgroundView.layer, frame: contentFrame, completion: nil)
if let effectView = self.effectView, effectView.frame != contentFrame {
animator.updateFrame(layer: effectView.layer, frame: contentFrame, completion: nil)
if let sublayers = effectView.layer.sublayers {
for sublayer in sublayers {
animator.updateFrame(layer: sublayer, frame: contentFrame, completion: nil)
}
}
}
animator.updateCornerRadius(layer: self.backgroundView.layer, cornerRadius: cornerRadius, completion: nil)
if let effectView = self.effectView {
animator.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius, completion: nil)
effectView.clipsToBounds = !cornerRadius.isZero
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ public final class NavigationBarBadgeNode: ASDisplayNode {
private let font: UIFont = Font.regular(13.0)
var text: String = "" {
public var text: String = "" {
didSet {
self.textNode.attributedText = NSAttributedString(string: self.text, font: self.font, textColor: self.textColor)
self.invalidateCalculatedLayout()
@ -39,7 +39,7 @@ public final class NavigationBarBadgeNode: ASDisplayNode {
self.addSubnode(self.textNode)
}
func updateTheme(fillColor: UIColor, strokeColor: UIColor, textColor: UIColor) {
public func updateTheme(fillColor: UIColor, strokeColor: UIColor, textColor: UIColor) {
self.fillColor = fillColor
self.strokeColor = strokeColor
self.textColor = textColor

View file

@ -1,21 +0,0 @@
import Foundation
import UIKit
enum NavigationBarTransitionRole {
case top
case bottom
}
final class NavigationBarTransitionState {
weak var navigationBar: NavigationBar?
let transition: NavigationTransition
let role: NavigationBarTransitionRole
let progress: CGFloat
init(navigationBar: NavigationBar, transition: NavigationTransition, role: NavigationBarTransitionRole, progress: CGFloat) {
self.navigationBar = navigationBar
self.transition = transition
self.role = role
self.progress = progress
}
}

View file

@ -201,10 +201,9 @@ final class NavigationTransitionCoordinator {
position = progress
}
transition.animateView {
topNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: bottomNavigationBar, transition: self.transition, role: .top, progress: position)
bottomNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: topNavigationBar, transition: self.transition, role: .bottom, progress: position)
}
let _ = position
let _ = topNavigationBar
let _ = bottomNavigationBar
}
}
@ -218,15 +217,16 @@ final class NavigationTransitionCoordinator {
position = progress
}
topNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: bottomNavigationBar, transition: self.transition, role: .top, progress: position)
bottomNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: topNavigationBar, transition: self.transition, role: .bottom, progress: position)
let _ = position
let _ = topNavigationBar
let _ = bottomNavigationBar
}
}
func endNavigationBarTransition() {
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar, self.inlineNavigationBarTransition {
topNavigationBar.transitionState = nil
bottomNavigationBar.transitionState = nil
let _ = topNavigationBar
let _ = bottomNavigationBar
}
}

View file

@ -0,0 +1,47 @@
import Foundation
import UIKit
import AsyncDisplayKit
open class SparseNode: ASDisplayNode {
override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.alpha.isZero {
return nil
}
for view in self.view.subviews.reversed() {
if let result = view.hitTest(self.view.convert(point, to: view), with: event), result.isUserInteractionEnabled {
return result
}
}
if !self.bounds.inset(by: self.hitTestSlop).contains(point) {
return nil
}
let result = super.hitTest(point, with: event)
if result != self.view {
return result
} else {
return nil
}
}
}
open class SparseContainerView: UIView {
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.alpha.isZero {
return nil
}
for view in self.subviews.reversed() {
if let result = view.hitTest(self.convert(point, to: view), with: event), result.isUserInteractionEnabled {
return result
}
}
let result = super.hitTest(point, with: event)
if result != self {
return result
} else {
return nil
}
}
}

View file

@ -387,7 +387,7 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
public init(navigationBarPresentationData: NavigationBarPresentationData?) {
self.statusBar = StatusBar()
if let navigationBarPresentationData = navigationBarPresentationData {
self.navigationBar = NavigationBar(presentationData: navigationBarPresentationData)
self.navigationBar = defaultNavigationBarImpl!(navigationBarPresentationData)
} else {
self.navigationBar = nil
}
@ -554,14 +554,14 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
UIView.transition(with: navigationBar.view, duration: 0.3, options: [.transitionCrossDissolve], animations: {
}, completion: nil)
}
self.navigationBar?.updatePresentationData(presentationData)
self.navigationBar?.updatePresentationData(presentationData, transition: .immediate)
if let parent = self.parent as? TabBarController {
if parent.currentController === self {
if animated, let navigationBar = parent.navigationBar {
UIView.transition(with: navigationBar.view, duration: 0.3, options: [.transitionCrossDissolve], animations: {
}, completion: nil)
}
parent.navigationBar?.updatePresentationData(presentationData)
parent.navigationBar?.updatePresentationData(presentationData, transition: .immediate)
}
}
}

View file

@ -919,7 +919,7 @@ public final class FeaturedStickersScreen: ViewController {
private func updatePresentationData() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.searchNavigationNode?.updatePresentationData(theme: self.presentationData.theme, strings: self.presentationData.strings)

View file

@ -576,8 +576,8 @@ private func galleryEntriesForMessageHistoryEntries(_ entries: [MessageHistoryEn
}
public class GalleryController: ViewController, StandalonePresentableController, KeyShortcutResponder, GalleryControllerProtocol {
public static let darkNavigationTheme = NavigationBarTheme(buttonColor: .white, disabledButtonColor: UIColor(rgb: 0x525252), primaryTextColor: .white, backgroundColor: UIColor(white: 0.0, alpha: 0.6), enableBackgroundBlur: false, separatorColor: UIColor(white: 0.0, alpha: 0.8), badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
public static let lightNavigationTheme = NavigationBarTheme(buttonColor: UIColor(rgb: 0x0088ff), disabledButtonColor: UIColor(rgb: 0xd0d0d0), primaryTextColor: .black, backgroundColor: UIColor(red: 0.968626451, green: 0.968626451, blue: 0.968626451, alpha: 1.0), enableBackgroundBlur: false, separatorColor: UIColor(red: 0.6953125, green: 0.6953125, blue: 0.6953125, alpha: 1.0), badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
public static let darkNavigationTheme = NavigationBarTheme(overallDarkAppearance: true, buttonColor: .white, disabledButtonColor: UIColor(rgb: 0x525252), primaryTextColor: .white, backgroundColor: UIColor(white: 0.0, alpha: 0.6), enableBackgroundBlur: false, separatorColor: UIColor(white: 0.0, alpha: 0.8), badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
public static let lightNavigationTheme = NavigationBarTheme(overallDarkAppearance: false, buttonColor: UIColor(rgb: 0x0088ff), disabledButtonColor: UIColor(rgb: 0xd0d0d0), primaryTextColor: .black, backgroundColor: UIColor(red: 0.968626451, green: 0.968626451, blue: 0.968626451, alpha: 1.0), enableBackgroundBlur: false, separatorColor: UIColor(red: 0.6953125, green: 0.6953125, blue: 0.6953125, alpha: 1.0), badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
private var galleryNode: GalleryControllerNode {
return self.displayNode as! GalleryControllerNode
@ -942,12 +942,12 @@ public class GalleryController: ViewController, StandalonePresentableController,
switch style {
case .dark:
strongSelf.statusBar.statusBarStyle = .White
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)))
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)), transition: .immediate)
strongSelf.galleryNode.backgroundNode.backgroundColor = UIColor.black
strongSelf.galleryNode.isBackgroundExtendedOverNavigationBar = true
case .light:
strongSelf.statusBar.statusBarStyle = .Black
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)))
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)), transition: .immediate)
strongSelf.galleryNode.backgroundNode.backgroundColor = UIColor(rgb: 0xbdbdc2)
strongSelf.galleryNode.isBackgroundExtendedOverNavigationBar = false
}

View file

@ -87,7 +87,7 @@ public final class HashtagSearchController: TelegramBaseController {
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.controllerNode.updatePresentationData(self.presentationData)
}
}

View file

@ -281,11 +281,12 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
self.presentationData = presentationData
self.hideNavigationBarBackground = hideNavigationBarBackground
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme, hideBackground: hideNavigationBarBackground, hideSeparator: hideNavigationBarBackground), strings: NavigationBarStrings(presentationStrings: presentationData.strings)))
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme, hideBackground: hideNavigationBarBackground, hideSeparator: hideNavigationBarBackground, style: .glass), strings: NavigationBarStrings(presentationStrings: presentationData.strings)))
self.isOpaqueWhenInOverlay = true
self.blocksBackgroundWhenInOverlay = true
self.automaticallyControlPresentationContextLayout = false
self._hasGlassStyle = true
self.statusBar.statusBarStyle = presentationData.theme.rootController.statusBarStyle.style
@ -518,7 +519,7 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
if strongSelf.presentationData != controllerState.presentationData {
strongSelf.presentationData = controllerState.presentationData
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: strongSelf.presentationData.theme, hideBackground: strongSelf.hideNavigationBarBackground, hideSeparator: strongSelf.hideNavigationBarBackground), strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)))
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: strongSelf.presentationData.theme, hideBackground: strongSelf.hideNavigationBarBackground, hideSeparator: strongSelf.hideNavigationBarBackground, edgeEffectColor: state.0.style == .blocks ? strongSelf.presentationData.theme.list.blocksBackgroundColor : strongSelf.presentationData.theme.list.plainBackgroundColor, style: .glass), strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)), transition: .immediate)
strongSelf.statusBar.updateStatusBarStyle(strongSelf.presentationData.theme.rootController.statusBarStyle.style, animated: true)
strongSelf.segmentedTitleView?.theme = controllerState.presentationData.theme

View file

@ -129,7 +129,7 @@ public final class LocationPickerController: ViewController, AttachmentContainab
let navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: strongSelf.presentationData.theme, hideBackground: style == .glass, hideSeparator: true), strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings))
strongSelf.navigationBar?.updatePresentationData(navigationBarPresentationData)
strongSelf.navigationBar?.updatePresentationData(navigationBarPresentationData, transition: .immediate)
strongSelf.searchNavigationContentNode?.updatePresentationData(strongSelf.presentationData)
strongSelf.updateBarButtons()

View file

@ -109,7 +109,7 @@ public final class LocationViewController: ViewController {
}
strongSelf.presentationData = presentationData
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: strongSelf.presentationData.theme).withUpdatedSeparatorColor(.clear), strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)))
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: strongSelf.presentationData.theme).withUpdatedSeparatorColor(.clear), strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)), transition: .immediate)
strongSelf.updateRightBarButton()

View file

@ -2673,7 +2673,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
} else {
navigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData)
}
self.navigationBar?.updatePresentationData(navigationBarPresentationData)
self.navigationBar?.updatePresentationData(navigationBarPresentationData, transition: .immediate)
self.titleView.theme = self.presentationData.theme
self.cancelButtonNode.theme = self.presentationData.theme
self.moreButtonNode.theme = self.presentationData.theme

View file

@ -18,7 +18,7 @@ final class MediaPickerTitleView: UIView {
public var theme: PresentationTheme {
didSet {
self.titleNode.attributedText = NSAttributedString(string: self.title, font: NavigationBar.titleFont, textColor: self.isDark ? .white : self.theme.rootController.navigationBar.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.isDark ? .white : self.theme.rootController.navigationBar.primaryTextColor)
self.subtitleNode.attributedText = NSAttributedString(string: self.subtitle, font: Font.regular(12.0), textColor: self.isDark ? .white.withAlphaComponent(0.5) : self.theme.rootController.navigationBar.secondaryTextColor)
self.segmentedControlNode.updateTheme(SegmentedControlTheme(theme: self.theme))
if self.glass {
@ -31,7 +31,7 @@ final class MediaPickerTitleView: UIView {
public var isDark: Bool = false {
didSet {
if self.isDark != oldValue {
self.titleNode.attributedText = NSAttributedString(string: self.title, font: NavigationBar.titleFont, textColor: self.isDark ? .white : self.theme.rootController.navigationBar.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.isDark ? .white : self.theme.rootController.navigationBar.primaryTextColor)
self.subtitleNode.attributedText = NSAttributedString(string: self.subtitle, font: Font.regular(12.0), textColor: self.isDark ? .white.withAlphaComponent(0.5) : self.theme.rootController.navigationBar.secondaryTextColor)
if self.glass {
self.arrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Navigation/TitleExpand"), color: self.isDark ? UIColor.white.withAlphaComponent(0.5) : self.theme.rootController.navigationBar.primaryTextColor.withAlphaComponent(0.4))
@ -44,7 +44,7 @@ final class MediaPickerTitleView: UIView {
public var title: String = "" {
didSet {
if self.title != oldValue {
self.titleNode.attributedText = NSAttributedString(string: self.title, font: NavigationBar.titleFont, textColor: self.isDark ? .white : self.theme.rootController.navigationBar.primaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.isDark ? .white : self.theme.rootController.navigationBar.primaryTextColor)
self.setNeedsLayout()
}
}

View file

@ -39,7 +39,7 @@ public class SetupTwoStepVerificationController: ViewController {
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(buttonColor: self.presentationData.theme.rootController.navigationBar.accentTextColor, disabledButtonColor: self.presentationData.theme.rootController.navigationBar.disabledButtonColor, primaryTextColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(overallDarkAppearance: self.presentationData.theme.overallDarkAppearance, buttonColor: self.presentationData.theme.rootController.navigationBar.accentTextColor, disabledButtonColor: self.presentationData.theme.rootController.navigationBar.disabledButtonColor, primaryTextColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@ -89,7 +89,7 @@ public class SetupTwoStepVerificationController: ViewController {
private func updateThemeAndStrings() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
self.controllerNode.updatePresentationData(self.presentationData)
}

View file

@ -71,7 +71,7 @@ public final class TwoFactorDataInputScreen: ViewController {
self.presentationData = self.sharedContext.currentPresentationData.with { $0 }
let defaultTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme)
let navigationBarTheme = NavigationBarTheme(buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor)
let navigationBarTheme = NavigationBarTheme(overallDarkAppearance: defaultTheme.overallDarkAppearance, buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor)
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close)))

View file

@ -57,7 +57,7 @@ public final class TwoFactorAuthSplashScreen: ViewController {
self.presentationData = self.sharedContext.currentPresentationData.with { $0 }
let defaultTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme)
let navigationBarTheme = NavigationBarTheme(buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor)
let navigationBarTheme = NavigationBarTheme(overallDarkAppearance: defaultTheme.overallDarkAppearance, buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor)
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close)))

View file

@ -77,7 +77,7 @@ public final class QrCodeScanScreen: ViewController {
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
let navigationBarTheme = NavigationBarTheme(buttonColor: .white, disabledButtonColor: .white, primaryTextColor: .white, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
let navigationBarTheme = NavigationBarTheme(overallDarkAppearance: self.presentationData.theme.overallDarkAppearance, buttonColor: .white, disabledButtonColor: .white, primaryTextColor: .white, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close)))

View file

@ -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))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), 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

@ -90,7 +90,7 @@ public class NotificationExceptionsController: ViewController {
private func updateThemeAndStrings() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), 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

@ -161,7 +161,7 @@ public final class PrivacyIntroController: ViewController {
private func updateThemeAndStrings() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
self.controllerNode.updatePresentationData(self.presentationData)
}

View file

@ -157,7 +157,7 @@ public final class ThemePreviewController: ViewController {
let titleView = CounterControllerTitleView(theme: strongSelf.previewTheme)
titleView.title = CounterControllerTitle(title: themeName, counter: hasInstallsCount ? strongSelf.presentationData.strings.Theme_UsersCount(max(1, theme.installCount ?? 0)) : "")
strongSelf.navigationItem.titleView = titleView
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationTheme: presentationTheme, presentationStrings: strongSelf.presentationData.strings))
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationTheme: presentationTheme, presentationStrings: strongSelf.presentationData.strings), transition: .immediate)
}
})

View file

@ -149,7 +149,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
case .back:
text = presentationData.strings.Common_Back
accessibilityText = presentationData.strings.Common_Back
icon = NavigationBar.backArrowImage(color: .white)
icon = navigationBarBackArrowImage(color: .white)
case .edit:
text = presentationData.strings.Common_Edit
accessibilityText = text

View file

@ -38,7 +38,7 @@ public final class PermissionController: ViewController {
let navigationBarPresentationData: NavigationBarPresentationData
if splashScreen {
navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(buttonColor: self.presentationData.theme.rootController.navigationBar.accentTextColor, disabledButtonColor: self.presentationData.theme.rootController.navigationBar.disabledButtonColor, primaryTextColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings))
navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(overallDarkAppearance: self.presentationData.theme.overallDarkAppearance, buttonColor: self.presentationData.theme.rootController.navigationBar.accentTextColor, disabledButtonColor: self.presentationData.theme.rootController.navigationBar.disabledButtonColor, primaryTextColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings))
} else {
navigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData)
}
@ -88,12 +88,12 @@ public final class PermissionController: ViewController {
let navigationBarPresentationData: NavigationBarPresentationData
if self.splashScreen {
navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(buttonColor: self.presentationData.theme.rootController.navigationBar.accentTextColor, disabledButtonColor: self.presentationData.theme.rootController.navigationBar.disabledButtonColor, primaryTextColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings))
navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(overallDarkAppearance: self.presentationData.theme.overallDarkAppearance, buttonColor: self.presentationData.theme.rootController.navigationBar.accentTextColor, disabledButtonColor: self.presentationData.theme.rootController.navigationBar.disabledButtonColor, primaryTextColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings))
} else {
navigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData)
}
self.navigationBar?.updatePresentationData(navigationBarPresentationData)
self.navigationBar?.updatePresentationData(navigationBarPresentationData, transition: .immediate)
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: nil, style: .plain, target: nil, action: nil)
if self.navigationItem.rightBarButtonItem != nil {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Permissions_Skip, style: .plain, target: self, action: #selector(PermissionController.nextPressed))

View file

@ -46,9 +46,26 @@ public extension ToolbarTheme {
}
public extension NavigationBarTheme {
convenience init(rootControllerTheme: PresentationTheme, enableBackgroundBlur: Bool = true, hideBackground: Bool = false, hideBadge: Bool = false, hideSeparator: Bool = false) {
convenience init(rootControllerTheme: PresentationTheme, enableBackgroundBlur: Bool = true, hideBackground: Bool = false, hideBadge: Bool = false, hideSeparator: Bool = false, edgeEffectColor: UIColor? = nil, style: NavigationBar.Style = .legacy) {
let theme = rootControllerTheme.rootController.navigationBar
self.init(buttonColor: theme.buttonColor, disabledButtonColor: theme.disabledButtonColor, primaryTextColor: theme.primaryTextColor, backgroundColor: hideBackground ? .clear : theme.blurredBackgroundColor, opaqueBackgroundColor: hideBackground ? .clear : theme.opaqueBackgroundColor, enableBackgroundBlur: enableBackgroundBlur, separatorColor: hideBackground || hideSeparator ? .clear : theme.separatorColor, badgeBackgroundColor: hideBadge ? .clear : theme.badgeBackgroundColor, badgeStrokeColor: hideBadge ? .clear : theme.badgeStrokeColor, badgeTextColor: hideBadge ? .clear : theme.badgeTextColor)
let buttonColor: UIColor
let disabledButtonColor: UIColor
let badgeBackgroundColor: UIColor
let badgeTextColor: UIColor
if case .glass = style {
buttonColor = rootControllerTheme.chat.inputPanel.panelControlColor
disabledButtonColor = buttonColor.withMultipliedAlpha(0.5)
badgeBackgroundColor = rootControllerTheme.chat.inputPanel.panelControlColor
badgeTextColor = rootControllerTheme.list.itemCheckColors.foregroundColor
} else {
buttonColor = theme.buttonColor
disabledButtonColor = theme.disabledButtonColor
badgeBackgroundColor = theme.badgeBackgroundColor
badgeTextColor = theme.badgeTextColor
}
self.init(overallDarkAppearance: rootControllerTheme.overallDarkAppearance, buttonColor: buttonColor, disabledButtonColor: disabledButtonColor, primaryTextColor: theme.primaryTextColor, backgroundColor: hideBackground ? .clear : theme.blurredBackgroundColor, opaqueBackgroundColor: hideBackground ? .clear : theme.opaqueBackgroundColor, enableBackgroundBlur: enableBackgroundBlur, separatorColor: hideBackground || hideSeparator ? .clear : theme.separatorColor, badgeBackgroundColor: hideBadge ? .clear : badgeBackgroundColor, badgeStrokeColor: .clear, badgeTextColor: hideBadge ? .clear : badgeTextColor, edgeEffectColor: edgeEffectColor, style: style)
}
}
@ -59,16 +76,16 @@ public extension NavigationBarStrings {
}
public extension NavigationBarPresentationData {
convenience init(presentationData: PresentationData) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(presentationStrings: presentationData.strings))
convenience init(presentationData: PresentationData, style: NavigationBar.Style = .legacy) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme, style: style), strings: NavigationBarStrings(presentationStrings: presentationData.strings))
}
convenience init(presentationData: PresentationData, hideBackground: Bool, hideBadge: Bool, hideSeparator: Bool = false) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme, hideBackground: hideBackground, hideBadge: hideBadge, hideSeparator: hideSeparator), strings: NavigationBarStrings(presentationStrings: presentationData.strings))
convenience init(presentationData: PresentationData, hideBackground: Bool, hideBadge: Bool, hideSeparator: Bool = false, style: NavigationBar.Style = .legacy) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme, hideBackground: hideBackground, hideBadge: hideBadge, hideSeparator: hideSeparator, style: style), strings: NavigationBarStrings(presentationStrings: presentationData.strings))
}
convenience init(presentationTheme: PresentationTheme, presentationStrings: PresentationStrings) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationTheme), strings: NavigationBarStrings(presentationStrings: presentationStrings))
convenience init(presentationTheme: PresentationTheme, presentationStrings: PresentationStrings, style: NavigationBar.Style = .legacy) {
self.init(theme: NavigationBarTheme(rootControllerTheme: presentationTheme, style: style), strings: NavigationBarStrings(presentationStrings: presentationStrings))
}
}

View file

@ -70,7 +70,7 @@ public struct PresentationResourcesRootController {
public static func navigationCompactSearchIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.navigationCompactSearchIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/SearchIcon"), color: theme.rootController.navigationBar.accentTextColor)
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/SearchIcon"), color: theme.chat.inputPanel.panelControlColor)
})
}
@ -82,7 +82,7 @@ public struct PresentationResourcesRootController {
public static func navigationCompactTagsSearchIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.navigationCompactTagsSearchIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/NavigationSearchTagsIcon"), color: theme.rootController.navigationBar.accentTextColor)
return generateTintedImage(image: UIImage(bundleImageName: "Chat/NavigationSearchTagsIcon"), color: theme.chat.inputPanel.panelControlColor)
})
}

View file

@ -497,6 +497,7 @@ swift_library(
"//submodules/TelegramUI/Components/AttachmentFileController",
"//submodules/TelegramUI/Components/Contacts/NewContactScreen",
"//submodules/TelegramUI/Components/Chat/ChatSendAsContextMenu",
"//submodules/TelegramUI/Components/NavigationBarImpl",
] + select({
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
"//build-system:ios_sim_arm64": [],

View file

@ -88,7 +88,7 @@ public final class BackButtonComponent: Component {
self.component = component
if self.arrowView.image == nil {
self.arrowView.image = NavigationBar.backArrowImage(color: .white)?.withRenderingMode(.alwaysTemplate)
self.arrowView.image = navigationBarBackArrowImage(color: .white)?.withRenderingMode(.alwaysTemplate)
}
self.arrowView.tintColor = component.color

View file

@ -29,7 +29,7 @@ final class BackButtonView: HighlightableButton {
var pressAction: (() -> Void)?
override init(frame: CGRect) {
self.iconView = UIImageView(image: NavigationBar.backArrowImage(color: .white))
self.iconView = UIImageView(image: navigationBarBackArrowImage(color: .white))
self.iconView.isUserInteractionEnabled = false
self.textView = TextView()

View file

@ -75,12 +75,8 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
strongSelf.contextAction?(strongSelf.containerNode, gesture)
}
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 37.0, height: 37.0)).offsetBy(dx: 10.0, dy: 1.0)
self.avatarNode.frame = self.containerNode.bounds
#if DEBUG
//self.hasUnseenStories = true
#endif
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 44.0, height: 44.0))
self.avatarNode.frame = self.containerNode.bounds.insetBy(dx: 3.0, dy: 3.0)
}
deinit {
@ -265,7 +261,7 @@ public final class ChatAvatarNavigationNode: ASDisplayNode {
}
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
return CGSize(width: 37.0, height: 37.0)
return CGSize(width: 44.0, height: 44.0)
}
public func onLayout() {

View file

@ -263,7 +263,7 @@ public final class ChatRecentActionsController: TelegramBaseController {
self.navigationItem.setRightBarButton(rightButton.buttonItem, animated: false)
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.controllerNode.updatePresentationData(self.presentationData)
}

View file

@ -715,7 +715,7 @@ public final class ChatListHeaderComponent: Component {
}
}
public final class View: UIView, NavigationBarHeaderView {
public final class View: UIView {
private var component: ChatListHeaderComponent?
private weak var state: EmptyComponentState?
@ -770,17 +770,6 @@ public final class ChatListHeaderComponent: Component {
return self.effectiveContentView?.titleContentView?.view
}
public func makeTransitionBackArrowView(accentColor: UIColor) -> UIView? {
if let backArrowView = self.backArrowView {
let view = UIImageView()
view.image = NavigationBar.backArrowImage(color: accentColor)
view.frame = backArrowView.convert(backArrowView.bounds, to: self)
return view
} else {
return nil
}
}
public func storyPeerListView() -> StoryPeerListComponent.View? {
return self.storyPeerList?.view as? StoryPeerListComponent.View
}

View file

@ -31,6 +31,7 @@ swift_library(
"//submodules/TelegramUI/Components/AnimationCache:AnimationCache",
"//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer",
"//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters",
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
],
visibility = [
"//visibility:public",

View file

@ -22,6 +22,7 @@ import EmojiStatusComponent
import AnimationCache
import MultiAnimationRenderer
import ComponentDisplayAdapters
import GlassBackgroundComponent
private let titleFont = Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers])
private let subtitleFont = Font.regular(13.0)
@ -170,7 +171,6 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
private let context: AccountContext
private var theme: PresentationTheme
private var hasEmbeddedTitleContent: Bool = false
private var strings: PresentationStrings
private var dateTimeFormat: PresentationDateTimeFormat
private var nameDisplayOrder: PresentationPersonNameOrder
@ -178,6 +178,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
private let animationRenderer: MultiAnimationRenderer
private let contentContainer: ASDisplayNode
private let backgroundView: GlassBackgroundView
public let titleContainerView: PortalSourceView
public let titleTextNode: ImmediateAnimatedCountLabelNode
public let titleLeftIconNode: ASImageNode
@ -239,7 +240,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
public var titleContent: ChatTitleContent? {
didSet {
if let titleContent = self.titleContent {
let titleTheme = self.hasEmbeddedTitleContent ? defaultDarkPresentationTheme : self.theme
let titleTheme = self.theme
var segments: [AnimatedCountLabelNode.Segment] = []
var titleLeftIcon: ChatTitleIcon = .none
@ -487,7 +488,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
}
}
let titleTheme = self.hasEmbeddedTitleContent ? defaultDarkPresentationTheme : self.theme
let titleTheme = self.theme
var state = ChatTitleActivityNodeState.none
switch self.networkState {
@ -739,6 +740,8 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.contentContainer = ASDisplayNode()
self.backgroundView = GlassBackgroundView()
self.titleContainerView = PortalSourceView()
self.titleTextNode = ImmediateAnimatedCountLabelNode()
@ -770,6 +773,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.accessibilityTraits = .header
self.addSubnode(self.contentContainer)
self.contentContainer.view.addSubview(self.backgroundView)
self.titleContainerView.addSubnode(self.titleTextNode)
self.contentContainer.view.addSubview(self.titleContainerView)
self.contentContainer.addSubnode(self.activityNode)
@ -818,10 +822,9 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
}
}
public func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings, hasEmbeddedTitleContent: Bool) {
if self.theme !== theme || self.strings !== strings || self.hasEmbeddedTitleContent != hasEmbeddedTitleContent {
public func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
if self.theme !== theme || self.strings !== strings {
self.theme = theme
self.hasEmbeddedTitleContent = hasEmbeddedTitleContent
self.strings = strings
let titleContent = self.titleContent
@ -986,107 +989,86 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
}
let statusSpacing: CGFloat = 3.0
let titleSideInset: CGFloat = 6.0
let titleSideInset: CGFloat = 12.0 + 8.0
var titleFrame: CGRect
if size.height > 40.0 {
var titleInsets: UIEdgeInsets = .zero
if case .emojiStatus = self.titleVerifiedIcon, verifiedIconWidth > 0.0 {
titleInsets.left = verifiedIconWidth
}
var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - verifiedIconWidth - statusIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), insets: titleInsets, animated: titleTransition.isAnimated)
titleSize.width += credibilityIconWidth
titleSize.width += verifiedIconWidth
if statusIconWidth > 0.0 {
titleSize.width += statusIconWidth
if credibilityIconWidth > 0.0 {
titleSize.width += statusSpacing
}
}
let activitySize = self.activityNode.updateLayout(CGSize(width: clearBounds.size.width - titleSideInset * 2.0, height: clearBounds.size.height), alignment: .center)
let titleInfoSpacing: CGFloat = 0.0
if activitySize.height.isZero {
titleFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - titleSize.width) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
if titleFrame.size.width < size.width {
titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0)
}
titleTransition.updateFrameAdditive(view: self.titleContainerView, frame: titleFrame)
titleTransition.updateFrameAdditive(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
} else {
let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing
titleFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - titleSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize)
if titleFrame.size.width < size.width {
titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0)
}
titleFrame.origin.x = max(titleFrame.origin.x, clearBounds.minX + leftIconWidth)
titleTransition.updateFrameAdditive(view: self.titleContainerView, frame: titleFrame)
titleTransition.updateFrameAdditive(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
var activityFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - activitySize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize)
if activitySize.width < size.width {
activityFrame.origin.x = -clearBounds.minX + floor((size.width - activityFrame.width) / 2.0)
}
titleTransition.updateFrameAdditiveToCenter(node: self.activityNode, frame: activityFrame)
}
if let image = self.titleLeftIconNode.image {
titleTransition.updateFrame(node: self.titleLeftIconNode, frame: CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size))
}
var nextIconX: CGFloat = titleFrame.width
titleTransition.updateFrame(view: self.titleVerifiedIconView, frame: CGRect(origin: CGPoint(x: 0.0, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize))
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
nextIconX -= titleCredibilitySize.width
if credibilityIconWidth > 0.0 {
nextIconX -= statusSpacing
}
self.titleStatusIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleStatusSize.width, y: floor((titleFrame.height - titleStatusSize.height) / 2.0)), size: titleStatusSize)
nextIconX -= titleStatusSize.width
if let image = self.titleRightIconNode.image {
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0 + UIScreenPixel, y: 6.0), size: image.size)
}
} else {
let titleSize = self.titleTextNode.updateLayout(size: CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - verifiedIconWidth - statusIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height), animated: titleTransition.isAnimated)
let activitySize = self.activityNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height), alignment: .center)
let titleInfoSpacing: CGFloat = 8.0
let combinedWidth = titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + statusIconWidth + rightIconWidth + activitySize.width + titleInfoSpacing
titleFrame = CGRect(origin: CGPoint(x: leftIconWidth + floor((clearBounds.width - combinedWidth) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
titleTransition.updateFrameAdditiveToCenter(view: self.titleContainerView, frame: titleFrame)
titleTransition.updateFrameAdditiveToCenter(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
titleTransition.updateFrameAdditiveToCenter(node: self.activityNode, frame: CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + statusIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize))
if let image = self.titleLeftIconNode.image {
self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size)
}
var nextIconX: CGFloat = titleFrame.maxX
self.titleVerifiedIconView.frame = CGRect(origin: CGPoint(x: 0.0, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize)
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
nextIconX -= titleCredibilitySize.width
titleTransition.updateFrame(view: self.titleStatusIconView, frame: CGRect(origin: CGPoint(x: nextIconX - titleStatusSize.width, y: floor((titleFrame.height - titleStatusSize.height) / 2.0)), size: titleStatusSize))
nextIconX -= titleStatusSize.width
if let image = self.titleRightIconNode.image {
titleTransition.updateFrame(node: self.titleRightIconNode, frame: CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: titleFrame.minY + 6.0), size: image.size))
var titleInsets: UIEdgeInsets = .zero
if case .emojiStatus = self.titleVerifiedIcon, verifiedIconWidth > 0.0 {
titleInsets.left = verifiedIconWidth
}
var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - verifiedIconWidth - statusIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), insets: titleInsets, animated: titleTransition.isAnimated)
titleSize.width += credibilityIconWidth
titleSize.width += verifiedIconWidth
if statusIconWidth > 0.0 {
titleSize.width += statusIconWidth
if credibilityIconWidth > 0.0 {
titleSize.width += statusSpacing
}
}
let activitySize = self.activityNode.updateLayout(CGSize(width: clearBounds.size.width - titleSideInset * 2.0, height: clearBounds.size.height), alignment: .center)
let titleInfoSpacing: CGFloat = 0.0
var activityFrame = CGRect()
if activitySize.height.isZero {
titleFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - titleSize.width) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
if titleFrame.size.width < size.width {
titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0)
}
titleTransition.updateFrameAdditive(view: self.titleContainerView, frame: titleFrame)
titleTransition.updateFrameAdditive(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
} else {
let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing
let contentWidth = max(titleSize.width + rightIconWidth, activitySize.width)
var contentX = floor((clearBounds.width - contentWidth) / 2.0)
contentX = max(contentX, clearBounds.minX + 20.0)
titleFrame = CGRect(origin: CGPoint(x: contentX + floor((contentWidth - titleSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize)
titleFrame.origin.x = max(titleFrame.origin.x, clearBounds.minX + leftIconWidth)
titleTransition.updateFrameAdditive(view: self.titleContainerView, frame: titleFrame)
titleTransition.updateFrameAdditive(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
activityFrame = CGRect(origin: CGPoint(x: titleFrame.minX + floor((titleFrame.width - activitySize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize)
titleTransition.updateFrameAdditiveToCenter(node: self.activityNode, frame: activityFrame.offsetBy(dx: activitySize.width * 0.5, dy: 0.0))
}
if let image = self.titleLeftIconNode.image {
titleTransition.updateFrame(node: self.titleLeftIconNode, frame: CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size))
}
var nextIconX: CGFloat = titleFrame.width
titleTransition.updateFrame(view: self.titleVerifiedIconView, frame: CGRect(origin: CGPoint(x: 0.0, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize))
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
nextIconX -= titleCredibilitySize.width
if credibilityIconWidth > 0.0 {
nextIconX -= statusSpacing
}
self.titleStatusIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleStatusSize.width, y: floor((titleFrame.height - titleStatusSize.height) / 2.0)), size: titleStatusSize)
nextIconX -= titleStatusSize.width
if let image = self.titleRightIconNode.image {
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0 + UIScreenPixel, y: 6.0), size: image.size)
}
self.pointerInteraction = PointerInteraction(view: self, style: .rectangle(CGSize(width: titleFrame.width + 16.0, height: 40.0)))
var backgroundFrame = CGRect(origin: CGPoint(x: titleFrame.minX, y: 0.0), size: CGSize(width: titleFrame.width, height: 44.0))
if !activityFrame.isEmpty {
backgroundFrame.origin.x = min(backgroundFrame.minX, activityFrame.minX)
backgroundFrame.size.width = max(backgroundFrame.maxX, activityFrame.maxX) - backgroundFrame.minX
}
backgroundFrame = backgroundFrame.insetBy(dx: -12.0, dy: 0.0)
let componentTransition = ComponentTransition(transition)
componentTransition.setFrame(view: self.backgroundView, frame: backgroundFrame)
self.backgroundView.update(size: backgroundFrame.size, cornerRadius: backgroundFrame.height * 0.5, isDark: self.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: UIColor(white: self.theme.overallDarkAppearance ? 0.0 : 1.0, alpha: 0.6)), isInteractive: false, transition: componentTransition)
return titleFrame
}
@ -1264,7 +1246,7 @@ public final class ChatTitleComponent: Component {
if contentView.titleContent != component.content {
contentView.titleContent = component.content
}
contentView.updateThemeAndStrings(theme: component.theme, strings: component.strings, hasEmbeddedTitleContent: false)
contentView.updateThemeAndStrings(theme: component.theme, strings: component.strings)
let _ = contentView.updateLayout(size: availableSize, clearBounds: CGRect(origin: CGPoint(), size: availableSize), transition: transition.containedViewLayoutTransition)
transition.setFrame(view: contentView, frame: CGRect(origin: CGPoint(), size: availableSize))

View file

@ -292,12 +292,14 @@ public class GlassBackgroundView: UIView {
public let isDark: Bool
public let tintColor: TintColor
public let isInteractive: Bool
public let isVisible: Bool
init(shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool) {
init(shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool, isVisible: Bool) {
self.shape = shape
self.isDark = isDark
self.tintColor = tintColor
self.isInteractive = isInteractive
self.isVisible = isVisible
}
}
@ -402,11 +404,11 @@ public class GlassBackgroundView: UIView {
return nil
}
public func update(size: CGSize, cornerRadius: CGFloat, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, transition: ComponentTransition) {
self.update(size: size, shape: .roundedRect(cornerRadius: cornerRadius), isDark: isDark, tintColor: tintColor, isInteractive: isInteractive, transition: transition)
public func update(size: CGSize, cornerRadius: CGFloat, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, isVisible: Bool = true, transition: ComponentTransition) {
self.update(size: size, shape: .roundedRect(cornerRadius: cornerRadius), isDark: isDark, tintColor: tintColor, isInteractive: isInteractive, isVisible: isVisible, transition: transition)
}
public func update(size: CGSize, shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, transition: ComponentTransition) {
public func update(size: CGSize, shape: Shape, isDark: Bool, tintColor: TintColor, isInteractive: Bool = false, isVisible: Bool = true, transition: ComponentTransition) {
if let nativeView = self.nativeView, let nativeViewClippingContext = self.nativeViewClippingContext, (nativeView.bounds.size != size || nativeViewClippingContext.shape != shape) {
nativeViewClippingContext.update(shape: shape, size: size, transition: transition)
@ -468,7 +470,7 @@ public class GlassBackgroundView: UIView {
innerBackgroundView.removeFromSuperview()
}
let params = Params(shape: shape, isDark: isDark, tintColor: tintColor, isInteractive: isInteractive)
let params = Params(shape: shape, isDark: isDark, tintColor: tintColor, isInteractive: isInteractive, isVisible: isVisible)
if self.params != params {
self.params = params
@ -498,21 +500,44 @@ public class GlassBackgroundView: UIView {
} else {
if let nativeParamsView = self.nativeParamsView, let nativeView = self.nativeView {
if #available(iOS 26.0, *) {
let glassEffect = UIGlassEffect(style: .regular)
switch tintColor.kind {
case .panel:
glassEffect.tintColor = UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.1)
case .custom:
glassEffect.tintColor = tintColor.color
}
glassEffect.isInteractive = params.isInteractive
var glassEffect: UIGlassEffect?
if transition.animation.isImmediate {
nativeView.effect = glassEffect
} else {
UIView.animate(withDuration: 0.2, animations: {
if isVisible {
let glassEffectValue = UIGlassEffect(style: .regular)
switch tintColor.kind {
case .panel:
glassEffectValue.tintColor = UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.1)
case .custom:
glassEffectValue.tintColor = tintColor.color
}
glassEffectValue.isInteractive = params.isInteractive
glassEffect = glassEffectValue
}
if glassEffect == nil && nativeView.effect != nil {
if transition.animation.isImmediate {
if #available(iOS 26.2, *) {
} else {
nativeView.effect = UIBlurEffect(style: .regular)
}
nativeView.effect = glassEffect
})
} else {
UIView.animate(withDuration: 0.2, animations: {
if #available(iOS 26.2, *) {
} else {
nativeView.effect = UIBlurEffect(style: .regular)
}
nativeView.effect = glassEffect
})
}
} else {
if transition.animation.isImmediate {
nativeView.effect = glassEffect
} else {
UIView.animate(withDuration: 0.2, animations: {
nativeView.effect = glassEffect
})
}
}
if isDark {

View file

@ -0,0 +1,24 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "NavigationBarImpl",
module_name = "NavigationBarImpl",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/ComponentFlow",
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
"//submodules/TelegramUI/Components/EdgeEffect",
"//submodules/Components/ComponentDisplayAdapters",
"//submodules/Components/MultilineTextComponent",
],
visibility = [
"//visibility:public",
],
)

View file

@ -1,11 +1,208 @@
import UIKit
import AsyncDisplayKit
import Display
import ComponentFlow
import MultilineTextComponent
public protocol NavigationButtonCustomDisplayNode {
var isHighlightable: Bool { get }
let glassBackArrowImage: UIImage? = {
let imageSize = CGSize(width: 44.0, height: 44.0)
let topRightPoint = CGPoint(x: 24.6, y: 14.0)
let centerPoint = CGPoint(x: 17.0, y: imageSize.height * 0.5)
return generateImage(imageSize, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setStrokeColor(UIColor.white.cgColor)
context.setLineWidth(2.0)
context.setLineCap(.round)
context.setLineJoin(.round)
context.move(to: topRightPoint)
context.addLine(to: centerPoint)
context.addLine(to: CGPoint(x: topRightPoint.x, y: size.height - topRightPoint.y))
context.strokePath()
})?.withRenderingMode(.alwaysTemplate)
}()
private final class ItemComponent: Component {
enum Content: Equatable {
case back
case item(UIBarButtonItem)
}
let color: UIColor
let content: Content
init(
color: UIColor,
content: Content
) {
self.color = color
self.content = content
}
static func ==(lhs: ItemComponent, rhs: ItemComponent) -> Bool {
if lhs.color != rhs.color {
return false
}
if lhs.content != rhs.content {
return false
}
return true
}
final class View: UIView {
private var iconView: UIImageView?
private var title: ComponentView<Empty>?
private var component: ItemComponent?
private weak var state: EmptyComponentState?
var isUpdating: Bool = false
private var setEnabledListener: Int?
private var setTitleListener: Int?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(component: ItemComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
self.isUpdating = true
defer {
self.isUpdating = false
}
if component.content != self.component?.content {
if case let .item(item) = self.component?.content {
if let setEnabledListener = self.setEnabledListener {
self.setEnabledListener = nil
item.removeSetEnabledListener(setEnabledListener)
}
if let setTitleListener = self.setTitleListener {
self.setTitleListener = nil
item.removeSetTitleListener(setTitleListener)
}
}
switch component.content {
case .back:
break
case let .item(item):
self.setEnabledListener = item.addSetEnabledListener { [weak self] _ in
guard let self else {
return
}
if !self.isUpdating {
self.state?.updated(transition: .immediate)
}
}
self.setTitleListener = item.addSetTitleListener { [weak self] _ in
guard let self else {
return
}
if !self.isUpdating {
self.state?.updated(transition: .immediate)
}
}
}
}
self.component = component
self.state = state
var iconImage: UIImage?
var titleString: String?
switch component.content {
case .back:
iconImage = glassBackArrowImage
case let .item(item):
if item.image != nil {
iconImage = item.image
} else if let title = item.title {
titleString = title
}
}
var size = CGSize(width: 44.0, height: 44.0)
if let iconImage {
let iconView: UIImageView
var iconTransition = transition
if let current = self.iconView {
iconView = current
} else {
iconTransition = iconTransition.withAnimation(.none)
iconView = UIImageView()
self.iconView = iconView
}
iconView.image = iconImage
iconView.tintColor = component.color
let iconFrame = iconImage.size.centered(in: CGRect(origin: CGPoint(), size: size))
iconTransition.setFrame(view: iconView, frame: iconFrame)
} else if let iconView = self.iconView {
self.iconView = nil
iconView.removeFromSuperview()
}
if let titleString {
let titleFont: UIFont
if case let .item(item) = component.content, case .done = item.style {
titleFont = Font.bold(17.0)
} else {
titleFont = Font.regular(17.0)
}
let title: ComponentView<Empty>
if let current = self.title {
title = current
} else {
title = ComponentView()
self.title = title
}
let titleSize = title.update(
transition: .immediate,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: titleString, font: titleFont, textColor: component.color))
)),
environment: {},
containerSize: CGSize(width: 200.0, height: 100.0)
)
let titleInset: CGFloat = 6.0
size.width = titleInset * 2.0 + titleSize.width
let titleFrame = CGRect(origin: CGPoint(x: titleInset, y: floorToScreenPixels((size.height - titleSize.height) * 0.5)), size: titleSize)
if let titleView = title.view {
if titleView.superview == nil {
self.addSubview(titleView)
}
titleView.frame = titleFrame
}
} else if let title = self.title {
self.title = nil
if let titleView = title.view {
titleView.removeFromSuperview()
}
}
return size
}
}
func makeView() -> View {
return View(frame: CGRect())
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}
private final class NavigationButtonItemNode: ImmediateTextNode {
private let isGlass: Bool
private func fontForCurrentState() -> UIFont {
return self.bold ? UIFont.boldSystemFont(ofSize: 17.0) : UIFont.systemFont(ofSize: 17.0)
}
@ -56,7 +253,6 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
}
private(set) var imageNode: ASImageNode?
private let imageRippleNode: ASImageNode
private var _image: UIImage?
public var image: UIImage? {
@ -71,10 +267,6 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
imageNode.displayWithoutProcessing = true
imageNode.displaysAsynchronously = false
self.imageNode = imageNode
if self.imageRippleNode.supernode != nil {
self.imageRippleNode.image = nil
self.imageRippleNode.removeFromSupernode()
}
self.addSubnode(imageNode)
}
@ -82,10 +274,6 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
} else if let imageNode = self.imageNode {
imageNode.removeFromSupernode()
self.imageNode = nil
if self.imageRippleNode.supernode != nil {
self.imageRippleNode.image = nil
self.imageRippleNode.removeFromSupernode()
}
}
self.invalidateCalculatedLayout()
@ -115,14 +303,6 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
}
}
public var rippleColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.05) {
didSet {
if self.imageRippleNode.image != nil {
self.imageRippleNode.image = generateFilledCircleImage(diameter: 30.0, color: self.rippleColor)
}
}
}
public var disabledColor: UIColor = UIColor(rgb: 0xd0d0d0) {
didSet {
if let text = self._text {
@ -183,11 +363,8 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
var pointerInteraction: PointerInteraction?
override public init() {
self.imageRippleNode = ASImageNode()
self.imageRippleNode.displaysAsynchronously = false
self.imageRippleNode.displayWithoutProcessing = true
self.imageRippleNode.alpha = 0.0
init(isGlass: Bool) {
self.isGlass = isGlass
super.init()
@ -195,7 +372,9 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
self.isUserInteractionEnabled = true
self.isExclusiveTouch = true
self.hitTestSlop = UIEdgeInsets(top: -16.0, left: -10.0, bottom: -16.0, right: -10.0)
if !isGlass {
self.hitTestSlop = UIEdgeInsets(top: -16.0, left: -10.0, bottom: -16.0, right: -10.0)
}
self.displaysAsynchronously = false
self.verticalAlignment = .middle
@ -231,7 +410,6 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
let size = CGSize(width: max(nodeSize.width, superSize.width), height: max(44.0, max(nodeSize.height, superSize.height)))
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - nodeSize.width) / 2.0), y: floorToScreenPixels((size.height - nodeSize.height) / 2.0)), size: nodeSize)
imageNode.frame = imageFrame
self.imageRippleNode.frame = imageFrame
return size
} else {
superSize.height = max(44.0, superSize.height)
@ -268,7 +446,7 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
self.touchCount = max(0, self.touchCount - touches.count)
var touchInside = true
if let touch = touches.first {
if let touch = touches.first, !self.isGlass {
touchInside = self.touchInsideApparentBounds(touch)
}
if previousTouchCount != 0 && self.touchCount == 0 && self.isEnabled && touchInside {
@ -328,7 +506,10 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
}
public final class NavigationButtonNode: ContextControllerSourceNode {
public final class NavigationButtonNodeImpl: ContextControllerSourceNode, NavigationButtonNode {
private let isGlass: Bool
private var isBack: Bool = false
private var nodes: [NavigationButtonItemNode] = []
private var disappearingNodes: [(frame: CGRect, size: CGSize, node: NavigationButtonItemNode)] = []
@ -357,16 +538,6 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
}
}
public var rippleColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.05) {
didSet {
if !self.rippleColor.isEqual(oldValue) {
for node in self.nodes {
node.rippleColor = self.rippleColor
}
}
}
}
public var disabledColor: UIColor = UIColor(rgb: 0xd0d0d0) {
didSet {
if !self.disabledColor.isEqual(oldValue) {
@ -384,18 +555,20 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
}
}
override public init() {
public init(isGlass: Bool) {
self.isGlass = isGlass
super.init()
self.isAccessibilityElement = false
self.isGestureEnabled = false
}
var manualText: String {
public var manualText: String {
return self.nodes.first?.text ?? ""
}
var manualAlpha: CGFloat = 1.0 {
public var manualAlpha: CGFloat = 1.0 {
didSet {
for node in self.nodes {
node.alpha = self.manualAlpha
@ -411,14 +584,15 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
}
}
func updateManualText(_ text: String, isBack: Bool = true) {
public func updateManualText(_ text: String, isBack: Bool = true) {
self.isBack = isBack
let node: NavigationButtonItemNode
if self.nodes.count > 0 {
node = self.nodes[0]
} else {
node = NavigationButtonItemNode()
node = NavigationButtonItemNode(isGlass: self.isGlass)
node.color = self.color
node.rippleColor = self.rippleColor
node.layer.layerTintColor = self.contentsColor?.cgColor
node.highlightChanged = { [weak node, weak self] value in
if let strongSelf = self, let node = node {
@ -444,7 +618,9 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
node.bold = false
node.isEnabled = true
node.node = nil
node.hitTestSlop = isBack ? UIEdgeInsets(top: 0.0, left: -20.0, bottom: 0.0, right: 0.0) : UIEdgeInsets()
if !self.isGlass {
node.hitTestSlop = isBack ? UIEdgeInsets(top: 0.0, left: -20.0, bottom: 0.0, right: 0.0) : UIEdgeInsets()
}
if 1 < self.nodes.count {
for i in 1 ..< self.nodes.count {
@ -454,15 +630,14 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
}
}
func updateItems(_ items: [UIBarButtonItem], animated: Bool) {
public func updateItems(_ items: [UIBarButtonItem], animated: Bool) {
for i in 0 ..< items.count {
let node: NavigationButtonItemNode
if self.nodes.count > i {
node = self.nodes[i]
} else {
node = NavigationButtonItemNode()
node = NavigationButtonItemNode(isGlass: self.isGlass)
node.color = self.color
node.rippleColor = self.rippleColor
node.layer.layerTintColor = self.contentsColor?.cgColor
node.highlightChanged = { [weak node, weak self] value in
if let strongSelf = self, let node = node {
@ -523,27 +698,36 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
}
public func updateLayout(constrainedSize: CGSize, isLandscape: Bool, isLeftAligned: Bool) -> CGSize {
var nodeOrigin = CGPoint()
var nodeOrigin = CGPoint(x: 0.0, y: 0.0)
var totalHeight: CGFloat = 0.0
for i in 0 ..< self.nodes.count {
if i != 0 {
if i != 0 && !self.isGlass {
nodeOrigin.x += 15.0
}
let node = self.nodes[i]
var nodeSize = node.updateLayout(constrainedSize)
var nodeInset: CGFloat = 0.0
if self.isGlass {
if node.image == nil && node.node == nil {
nodeInset += 10.0
}
if nodeSize.width + nodeInset * 2.0 < 44.0 {
nodeInset = floorToScreenPixels((44.0 - nodeSize.width) * 0.5)
}
}
nodeSize.width = ceil(nodeSize.width)
nodeSize.height = ceil(nodeSize.height)
totalHeight = max(totalHeight, nodeSize.height)
node.frame = CGRect(origin: CGPoint(x: nodeOrigin.x, y: floor((totalHeight - nodeSize.height) / 2.0)), size: nodeSize)
nodeOrigin.x += node.bounds.width
if isLandscape {
node.frame = CGRect(origin: CGPoint(x: nodeOrigin.x + nodeInset, y: floor((totalHeight - nodeSize.height) / 2.0)), size: nodeSize)
nodeOrigin.x += nodeInset + node.bounds.width + nodeInset
if isLandscape && !self.isGlass {
nodeOrigin.x += 16.0
}
if node.node == nil && node.imageNode != nil && i == self.nodes.count - 1 {
if !self.isGlass && node.node == nil && node.imageNode != nil && i == self.nodes.count - 1 {
nodeOrigin.x -= 5.0
}
}
@ -557,11 +741,32 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
return CGSize(width: nodeOrigin.x, height: totalHeight)
}
func internalHitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.nodes.count == 1 {
return self.nodes[0].view
if self.isGlass && self.isBack {
if self.bounds.contains(point) {
return self.nodes[0].view
}
}
if self.bounds.contains(point) {
return self.nodes[0].view
} else {
return nil
}
} else {
return super.hitTest(point, with: event)
}
}
var isEmpty: Bool {
if self.isBack {
return false
}
for node in self.nodes {
if node.bounds.width != 0.0 {
return false
}
}
return true
}
}

View file

@ -260,7 +260,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
case .back:
text = presentationData.strings.Common_Back
accessibilityText = presentationData.strings.Common_Back
icon = NavigationBar.backArrowImage(color: .white)
icon = navigationBarBackArrowImage(color: .white)
case .edit:
text = presentationData.strings.Common_Edit
accessibilityText = text

View file

@ -648,11 +648,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let avatarOverlayFarme = self.editingContentNode.convert(self.editingContentNode.avatarNode.frame, to: self)
transition.updateFrame(node: self.avatarOverlayNode, frame: avatarOverlayFarme)
var transitionSourceHeight: CGFloat = 0.0
var transitionFraction: CGFloat = 0.0
var transitionSourceAvatarFrame: CGRect?
var transitionSourceTitleFrame = CGRect()
var transitionSourceSubtitleFrame = CGRect()
let transitionSourceHeight: CGFloat = 0.0
let transitionFraction: CGFloat = 0.0
let transitionSourceAvatarFrame: CGRect? = nil
let transitionSourceTitleFrame = CGRect()
let transitionSourceSubtitleFrame = CGRect()
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 22.0), size: CGSize(width: avatarSize, height: avatarSize))
@ -766,7 +766,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let backgroundBannerAlpha: CGFloat
var effectiveSeparatorAlpha: CGFloat
if let navigationTransition = self.navigationTransition {
/*if let navigationTransition = self.navigationTransition {
transitionSourceHeight = navigationTransition.sourceNavigationBar.backgroundNode.bounds.height
transitionFraction = navigationTransition.fraction
@ -799,7 +799,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.avatarListNode.animateAvatarCollapse(transition: transition)
}
self.avatarClippingNode.clipsToBounds = false
} else {
} else*/ do {
let backgroundTransitionStepDistance: CGFloat = 50.0
var backgroundTransitionDistance: CGFloat = navigationHeight + panelWithAvatarHeight - backgroundTransitionStepDistance
if self.isSettings || self.isMyProfile {

View file

@ -11446,7 +11446,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
}
private func activateSearch() {
func activateSearch() {
guard let (layout, navigationBarHeight) = self.validLayout, self.searchDisplayController == nil else {
return
}
@ -13604,6 +13604,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
let baseNavigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData)
super.init(navigationBarPresentationData: NavigationBarPresentationData(
theme: NavigationBarTheme(
overallDarkAppearance: true,
buttonColor: .white,
disabledButtonColor: .white,
primaryTextColor: .white,
@ -13786,22 +13787,11 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
}
if self.chatLocation.peerId != nil {
/*self.navigationBar?.shouldTransitionInline = { [weak self] in
guard let strongSelf = self else {
return false
}
if strongSelf.navigationItem.leftBarButtonItem != nil {
return false
}
if strongSelf.controllerNode.scrollNode.view.contentOffset.y > .ulpOfOne {
return false
}
if strongSelf.controllerNode.headerNode.isAvatarExpanded {
return false
}
return false
}*/
self.navigationBar?.makeCustomTransitionNode = { [weak self] other, isInteractive in
if "".isEmpty {
return nil
}
guard let strongSelf = self else {
return nil
}
@ -14173,9 +14163,9 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
chatNavigationStack = summary.peerNavigationItems.filter({ $0 != ChatNavigationStackItem(peerId: self.peerId, threadId: self.chatLocation.threadId) })
}
if !chatNavigationStack.isEmpty {
self.navigationBar?.backButtonNode.isGestureEnabled = true
self.navigationBar?.backButtonNode.activated = { [weak self] gesture, _ in
if !chatNavigationStack.isEmpty, let backButtonNode = self.navigationBar?.backButtonNode as? ContextControllerSourceNode {
backButtonNode.isGestureEnabled = true
backButtonNode.activated = { [weak self] gesture, _ in
guard let strongSelf = self, let backButtonNode = strongSelf.navigationBar?.backButtonNode, let navigationController = strongSelf.navigationController as? NavigationController else {
gesture.cancel()
return
@ -14296,6 +14286,10 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
self.controllerNode.headerNode.navigationButtonContainer.performAction?(.edit, nil, nil)
}
override public func tabBarActivateSearch() {
self.controllerNode.activateSearch()
}
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
@ -14463,7 +14457,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
}
func setup(topNavigationBar: NavigationBar, bottomNavigationBar: NavigationBar) {
if let _ = bottomNavigationBar.userInfo as? PeerInfoNavigationSourceTag {
/*if let _ = bottomNavigationBar.userInfo as? PeerInfoNavigationSourceTag {
self.topNavigationBar = topNavigationBar
self.bottomNavigationBar = bottomNavigationBar
} else {
@ -14475,54 +14469,10 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
topNavigationBar.isHidden = true
bottomNavigationBar.isHidden = true
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar {
if let _ = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar {
self.addSubnode(bottomNavigationBar.additionalContentNode)
/*if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let previousBackButtonArrow = headerView.makeTransitionBackArrowView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButtonArrow = previousBackButtonArrow
self.view.addSubview(previousBackButtonArrow)
}
if let previousBackButton = headerView.makeTransitionBackButtonView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButton = previousBackButton
self.view.addSubview(previousBackButton)
}
} else*/ do {
if let previousBackButtonArrow = bottomNavigationBar.makeTransitionBackArrowView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButtonArrow = previousBackButtonArrow
self.view.addSubview(previousBackButtonArrow)
}
if let previousBackButton = bottomNavigationBar.makeTransitionBackButtonView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButton = previousBackButton
self.view.addSubview(previousBackButton)
}
}
if let currentBackButtonArrow = topNavigationBar.makeTransitionBackArrowNode(accentColor: .white) {
self.currentBackButtonArrow = currentBackButtonArrow
//self.addSubnode(currentBackButtonArrow)
}
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
let _ = headerView
} else {
if let previousBackButtonBadge = bottomNavigationBar.makeTransitionBadgeNode() {
self.previousBackButtonBadge = previousBackButtonBadge
self.addSubnode(previousBackButtonBadge)
}
}
if let currentBackButton = topNavigationBar.makeTransitionBackButtonNode(accentColor: .white) {
self.currentBackButton = currentBackButton
//self.addSubnode(currentBackButton)
}
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let previousRightButton = headerView.rightButtonView?.layer.snapshotContentTree() {
self.previousRightButton = previousRightButton
self.view.layer.addSublayer(previousRightButton)
}
} else {
do {
if let avatarNavigationNode = bottomNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode, let previousAvatarView = avatarNavigationNode.view.snapshotContentTree() {
self.previousAvatarView = previousAvatarView
self.view.addSubview(previousAvatarView)
@ -14547,11 +14497,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
}
var previousTitleView: UIView?
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let componentView = headerView.titleContentView as? ChatTitleComponent.View {
previousTitleView = componentView.contentView
}
} else {
do {
previousTitleView = bottomNavigationBar.titleView
}
@ -14571,7 +14517,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
self.previousStatusNode = (previousStatusContainerNode, previousStatusNode)
self.addSubnode(previousStatusContainerNode)
}
}
}*/
}
func update(containerSize: CGSize, fraction: CGFloat, transition: ContainedViewLayoutTransition) {
@ -14582,13 +14528,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
let fraction = self.reverseFraction ? (1.0 - fraction) : fraction
if let previousBackButtonArrow = self.previousBackButtonArrow {
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let backArrowView = headerView.backArrowView {
let previousBackButtonArrowFrame = backArrowView.convert(backArrowView.bounds, to: bottomNavigationBar.view)
previousBackButtonArrow.frame = previousBackButtonArrowFrame
transition.updateAlpha(layer: previousBackButtonArrow.layer, alpha: fraction)
}
} else {
do {
let previousBackButtonArrowFrame = bottomNavigationBar.backButtonArrow.view.convert(bottomNavigationBar.backButtonArrow.view.bounds, to: bottomNavigationBar.view)
previousBackButtonArrow.frame = previousBackButtonArrowFrame
transition.updateAlpha(layer: previousBackButtonArrow.layer, alpha: fraction)
@ -14596,13 +14536,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
}
if let previousBackButton = self.previousBackButton {
/*if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let backButtonTitleView = headerView.backButtonTitleView {
let previousBackButtonFrame = backButtonTitleView.convert(backButtonTitleView.bounds, to: bottomNavigationBar.view)
previousBackButton.frame = previousBackButtonFrame
transition.updateAlpha(layer: previousBackButton.layer, alpha: fraction)
}
} else*/ do {
do {
let previousBackButtonFrame = bottomNavigationBar.backButtonNode.view.convert(bottomNavigationBar.backButtonNode.view.bounds, to: bottomNavigationBar.view)
previousBackButton.frame = previousBackButtonFrame
transition.updateAlpha(layer: previousBackButton.layer, alpha: fraction)
@ -14610,13 +14544,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
}
if let previousRightButton = self.previousRightButton {
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let rightButtonView = headerView.rightButtonView {
let previousRightButtonFrame = rightButtonView.convert(rightButtonView.bounds, to: bottomNavigationBar.view)
previousRightButton.frame = previousRightButtonFrame
transition.updateAlpha(layer: previousRightButton, alpha: fraction)
}
} else {
do {
let previousRightButtonFrame = bottomNavigationBar.rightButtonNode.view.convert(bottomNavigationBar.rightButtonNode.view.bounds, to: bottomNavigationBar.view)
previousRightButton.frame = previousRightButtonFrame
transition.updateAlpha(layer: previousRightButton, alpha: fraction)
@ -14645,11 +14573,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
}
var previousTitleView: UIView?
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let componentView = headerView.titleContentView as? ChatTitleComponent.View {
previousTitleView = componentView.contentView
}
} else {
do {
previousTitleView = bottomNavigationBar.titleView
}

View file

@ -245,7 +245,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))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), 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

@ -85,7 +85,7 @@ public class LanguageSelectionScreen: ViewController {
private func updateThemeAndStrings() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), 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

@ -149,7 +149,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
case .back:
text = presentationData.strings.Common_Back
accessibilityText = presentationData.strings.Common_Back
icon = NavigationBar.backArrowImage(color: .white)
icon = navigationBarBackArrowImage(color: .white)
case .edit:
text = presentationData.strings.Common_Edit
accessibilityText = text

View file

@ -374,7 +374,7 @@ public final class ThemeAccentColorController: ViewController {
}, ready: self._ready)
self.controllerNode.themeUpdated = { [weak self] theme in
if let strongSelf = self {
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationTheme: theme, presentationStrings: strongSelf.presentationData.strings))
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationTheme: theme, presentationStrings: strongSelf.presentationData.strings), transition: .immediate)
strongSelf.segmentedTitleView.theme = theme
}
}

View file

@ -82,7 +82,7 @@ public class TimezoneSelectionScreen: ViewController {
private func updateThemeAndStrings() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), 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

@ -396,7 +396,7 @@ public class WallpaperGalleryController: ViewController {
self.title = self.presentationData.strings.WallpaperPreview_Title
}
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.toolbarNode?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings)
self.patternPanelNode?.updateTheme(self.presentationData.theme)

View file

@ -216,7 +216,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
private func updateThemeAndStrings() {
self.title = self.presentationData.strings.WallpaperColors_Title
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
if self.isNodeLoaded {
self.controllerNode.updatePresentationData(self.presentationData)

View file

@ -128,7 +128,7 @@ public final class ThemeGridController: ViewController {
}
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Wallpaper_Search)
if self.isNodeLoaded {

View file

@ -42,6 +42,7 @@ import TelegramUIDeclareEncodables
import ContextMenuScreen
import MetalEngine
import RecaptchaEnterprise
import NavigationBarImpl
#if canImport(AppCenter)
import AppCenter
@ -330,6 +331,10 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
let launchStartTime = CFAbsoluteTimeGetCurrent()
defaultNavigationBarImpl = { presentationData in
return NavigationBarImpl(presentationData: presentationData)
}
let (window, hostView) = nativeWindowHostView()
let statusBarHost = ApplicationStatusBarHost(scene: window.windowScene)
self.mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)

View file

@ -524,9 +524,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let joinChannelDisposable = MetaDisposable()
var shouldDisplayDownButton = false
var hasEmbeddedTitleContent = false
var isEmbeddedTitleContentHidden = false
var chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
@ -738,10 +735,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
case .inline, .standard(.embedded):
navigationBarPresentationData = nil
default:
navigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData, hideBackground: self.context.sharedContext.immediateExperimentalUISettings.playerEmbedding ? true : false, hideBadge: false)
navigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData, hideBackground: false, hideBadge: false, style: .glass)
}
self.moreBarButton = MoreHeaderButton(color: self.presentationData.theme.rootController.navigationBar.buttonColor)
self.moreBarButton = MoreHeaderButton(color: self.presentationData.theme.chat.inputPanel.inputControlColor)
self.moreBarButton.isUserInteractionEnabled = true
super.init(context: context, navigationBarPresentationData: navigationBarPresentationData, mediaAccessoryPanelVisibility: mediaAccessoryPanelVisibility, locationBroadcastPanelSource: locationBroadcastPanelSource, groupCallPanelSource: groupCallPanelSource)
@ -6298,18 +6295,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let presentationTheme: PresentationTheme
if let forcedNavigationBarTheme = self.forcedNavigationBarTheme {
presentationTheme = forcedNavigationBarTheme
navigationBarTheme = NavigationBarTheme(rootControllerTheme: forcedNavigationBarTheme, hideBackground: false, hideBadge: true)
} else if self.hasEmbeddedTitleContent {
presentationTheme = self.presentationData.theme
navigationBarTheme = NavigationBarTheme(rootControllerTheme: defaultDarkPresentationTheme, hideBackground: self.context.sharedContext.immediateExperimentalUISettings.playerEmbedding ? true : false, hideBadge: true)
navigationBarTheme = NavigationBarTheme(rootControllerTheme: forcedNavigationBarTheme, hideBackground: false, hideBadge: true, edgeEffectColor: .clear, style: .glass)
} else {
presentationTheme = self.presentationData.theme
navigationBarTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme, hideBackground: self.context.sharedContext.immediateExperimentalUISettings.playerEmbedding ? true : false, hideBadge: false)
navigationBarTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme, hideBackground: false, hideBadge: false, edgeEffectColor: .clear, style: .glass)
}
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)), transition: .immediate)
self.chatTitleView?.updateThemeAndStrings(theme: presentationTheme, strings: self.presentationData.strings, hasEmbeddedTitleContent: self.hasEmbeddedTitleContent)
self.chatTitleView?.updateThemeAndStrings(theme: presentationTheme, strings: self.presentationData.strings)
}
enum PinnedReferenceMessage {
@ -6728,9 +6722,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
if !chatNavigationStack.isEmpty {
self.chatDisplayNode.navigationBar?.backButtonNode.isGestureEnabled = true
self.chatDisplayNode.navigationBar?.backButtonNode.activated = { [weak self] gesture, _ in
if !chatNavigationStack.isEmpty, let backButtonNode = self.chatDisplayNode.navigationBar?.backButtonNode as? ContextControllerSourceNode {
backButtonNode.isGestureEnabled = true
backButtonNode.activated = { [weak self] gesture, _ in
guard let strongSelf = self, let backButtonNode = strongSelf.chatDisplayNode.navigationBar?.backButtonNode, let navigationController = strongSelf.effectiveNavigationController else {
gesture.cancel()
return

View file

@ -218,8 +218,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
private let inputPanelClippingNode: SparseNode
let inputPanelBackgroundNode: NavigationBackgroundNode
private var navigationBarBackgroundContent: WallpaperBubbleBackgroundNode?
private var intrinsicInputPanelBackgroundNodeSize: CGSize?
private var inputPanelBottomBackgroundSeparatorBaseOffset: CGFloat = 0.0
private var plainInputSeparatorAlpha: CGFloat?
@ -238,6 +236,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
private var floatingTopicsPanelContainer: ChatControllerTitlePanelNodeContainer
private var floatingTopicsPanel: (view: ComponentView<ChatSidePanelEnvironment>, component: ChatFloatingTopicsPanel)?
private var topBackgroundEdgeEffectNode: WallpaperEdgeEffectNode?
private var bottomBackgroundEdgeEffectNode: WallpaperEdgeEffectNode?
private(set) var inputPanelNode: ChatInputPanelNode?
@ -1392,6 +1391,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
}
//TODO:localize
if "".isEmpty {
hasTranslationPanel = false
}
/*#if DEBUG
if "".isEmpty {
hasTranslationPanel = true
@ -2187,6 +2191,28 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
}
var topBackgroundEdgeEffectNode: WallpaperEdgeEffectNode?
if let current = self.topBackgroundEdgeEffectNode {
topBackgroundEdgeEffectNode = current
} else {
if let value = self.backgroundNode.makeEdgeEffectNode() {
topBackgroundEdgeEffectNode = value
self.topBackgroundEdgeEffectNode = value
self.historyNodeContainer.view.superview?.insertSubview(value.view, aboveSubview: self.historyNodeContainer.view)
}
}
if let topBackgroundEdgeEffectNode {
let blurFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: navigationBarHeight + 24.0))
transition.updateFrame(node: topBackgroundEdgeEffectNode, frame: blurFrame)
topBackgroundEdgeEffectNode.update(
rect: blurFrame,
edge: WallpaperEdgeEffectEdge(edge: .top, size: 40.0),
blur: true,
containerSize: wallpaperBounds.size,
transition: transition
)
}
var bottomBackgroundEdgeEffectNode: WallpaperEdgeEffectNode?
if let current = self.bottomBackgroundEdgeEffectNode {
bottomBackgroundEdgeEffectNode = current
@ -2205,6 +2231,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
bottomBackgroundEdgeEffectNode.update(
rect: blurFrame,
edge: WallpaperEdgeEffectEdge(edge: .bottom, size: 80.0),
blur: false,
containerSize: wallpaperBounds.size,
transition: transition
)
@ -2502,11 +2529,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
})*/
dismissedFloatingTopicsPanelView.removeFromSuperview()
}
if let navigationBarBackgroundContent = self.navigationBarBackgroundContent {
transition.updateFrame(node: navigationBarBackgroundContent, frame: CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: navigationBarHeight + (titleAccessoryPanelBackgroundHeight ?? 0.0) + (translationPanelHeight ?? 0.0))), beginWithCurrentState: true)
navigationBarBackgroundContent.update(rect: CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: navigationBarHeight + (titleAccessoryPanelBackgroundHeight ?? 0.0) + (translationPanelHeight ?? 0.0))), within: layout.size, transition: transition)
}
transition.updateFrame(node: self.contentDimNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: apparentInputBackgroundFrame.origin.y)))
@ -3485,22 +3507,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.updatePlainInputSeparator(transition: .immediate)
self.backgroundNode.updateBubbleTheme(bubbleTheme: chatPresentationInterfaceState.theme, bubbleCorners: chatPresentationInterfaceState.bubbleCorners)
if self.backgroundNode.hasExtraBubbleBackground() {
if self.navigationBarBackgroundContent == nil {
if let navigationBarBackgroundContent = self.backgroundNode.makeBubbleBackground(for: .free) {
self.navigationBarBackgroundContent = navigationBarBackgroundContent
navigationBarBackgroundContent.allowsGroupOpacity = true
navigationBarBackgroundContent.implicitContentUpdate = false
navigationBarBackgroundContent.alpha = 0.3
self.navigationBar?.insertSubnode(navigationBarBackgroundContent, at: 1)
}
}
} else {
self.navigationBarBackgroundContent?.removeFromSupernode()
self.navigationBarBackgroundContent = nil
}
}
let keepSendButtonEnabled = chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil || chatPresentationInterfaceState.interfaceState.editMessage != nil

View file

@ -8,6 +8,10 @@ import ComponentFlow
import ChatSideTopicsPanel
func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatTitleAccessoryPanelNode?, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, force: Bool) -> ChatTitleAccessoryPanelNode? {
if "".isEmpty {
return nil
}
if !force, case .standard(.embedded) = chatPresentationInterfaceState.mode {
return nil
}

View file

@ -43,7 +43,7 @@ final class ChatSearchResultsController: ViewController {
|> deliverOnMainQueue).startStrict(next: { [weak self] presentationData in
if let strongSelf = self {
strongSelf.presentationData = presentationData
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationTheme: presentationData.theme, presentationStrings: presentationData.strings))
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationTheme: presentationData.theme, presentationStrings: presentationData.strings), transition: .immediate)
strongSelf.controllerNode.updatePresentationData(presentationData)
}
})

View file

@ -93,7 +93,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))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), 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

@ -226,7 +226,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection
private func updateThemeAndStrings() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData), transition: .immediate)
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
self.updateTitle()
self.contactsNode.updatePresentationData(self.presentationData)

View file

@ -307,7 +307,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)))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme, hideBackground: glass, hideSeparator: 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

@ -32,7 +32,6 @@ public struct ExperimentalUISettings: Codable, Equatable {
public var chatListPhotos: Bool
public var knockoutWallpaper: Bool
public var foldersTabAtBottom: Bool
public var playerEmbedding: Bool
public var preferredVideoCodec: String?
public var disableVideoAspectScaling: Bool
public var enableVoipTcp: Bool
@ -80,7 +79,6 @@ public struct ExperimentalUISettings: Codable, Equatable {
chatListPhotos: false,
knockoutWallpaper: false,
foldersTabAtBottom: false,
playerEmbedding: false,
preferredVideoCodec: nil,
disableVideoAspectScaling: false,
enableVoipTcp: false,
@ -129,7 +127,6 @@ public struct ExperimentalUISettings: Codable, Equatable {
chatListPhotos: Bool,
knockoutWallpaper: Bool,
foldersTabAtBottom: Bool,
playerEmbedding: Bool,
preferredVideoCodec: String?,
disableVideoAspectScaling: Bool,
enableVoipTcp: Bool,
@ -175,7 +172,6 @@ public struct ExperimentalUISettings: Codable, Equatable {
self.chatListPhotos = chatListPhotos
self.knockoutWallpaper = knockoutWallpaper
self.foldersTabAtBottom = foldersTabAtBottom
self.playerEmbedding = playerEmbedding
self.preferredVideoCodec = preferredVideoCodec
self.disableVideoAspectScaling = disableVideoAspectScaling
self.enableVoipTcp = enableVoipTcp
@ -225,7 +221,6 @@ public struct ExperimentalUISettings: Codable, Equatable {
self.chatListPhotos = (try container.decodeIfPresent(Int32.self, forKey: "chatListPhotos") ?? 0) != 0
self.knockoutWallpaper = (try container.decodeIfPresent(Int32.self, forKey: "knockoutWallpaper") ?? 0) != 0
self.foldersTabAtBottom = (try container.decodeIfPresent(Int32.self, forKey: "foldersTabAtBottom") ?? 0) != 0
self.playerEmbedding = (try container.decodeIfPresent(Int32.self, forKey: "playerEmbedding") ?? 0) != 0
self.preferredVideoCodec = try container.decodeIfPresent(String.self.self, forKey: "preferredVideoCodec")
self.disableVideoAspectScaling = (try container.decodeIfPresent(Int32.self, forKey: "disableVideoAspectScaling") ?? 0) != 0
self.enableVoipTcp = (try container.decodeIfPresent(Int32.self, forKey: "enableVoipTcp") ?? 0) != 0
@ -275,7 +270,6 @@ public struct ExperimentalUISettings: Codable, Equatable {
try container.encode((self.chatListPhotos ? 1 : 0) as Int32, forKey: "chatListPhotos")
try container.encode((self.knockoutWallpaper ? 1 : 0) as Int32, forKey: "knockoutWallpaper")
try container.encode((self.foldersTabAtBottom ? 1 : 0) as Int32, forKey: "foldersTabAtBottom")
try container.encode((self.playerEmbedding ? 1 : 0) as Int32, forKey: "playerEmbedding")
try container.encodeIfPresent(self.preferredVideoCodec, forKey: "preferredVideoCodec")
try container.encode((self.disableVideoAspectScaling ? 1 : 0) as Int32, forKey: "disableVideoAspectScaling")
try container.encode((self.enableVoipTcp ? 1 : 0) as Int32, forKey: "enableVoipTcp")

View file

@ -68,6 +68,7 @@ swift_library(
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
"//submodules/Components/HierarchyTrackingLayer:HierarchyTrackingLayer",
"//submodules/TelegramUI/Components/EdgeEffect",
],
visibility = [
"//visibility:public",

View file

@ -16,6 +16,7 @@ import AppBundle
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import HierarchyTrackingLayer
import EdgeEffect
private let motionAmount: CGFloat = 32.0
@ -97,7 +98,7 @@ public struct WallpaperEdgeEffectEdge: Equatable {
}
public protocol WallpaperEdgeEffectNode: ASDisplayNode {
func update(rect: CGRect, edge: WallpaperEdgeEffectEdge, containerSize: CGSize, transition: ContainedViewLayoutTransition)
func update(rect: CGRect, edge: WallpaperEdgeEffectEdge, blur: Bool, containerSize: CGSize, transition: ContainedViewLayoutTransition)
}
public protocol WallpaperBackgroundNode: ASDisplayNode {
@ -1796,11 +1797,13 @@ private final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEff
private struct Params: Equatable {
let rect: CGRect
let edge: WallpaperEdgeEffectEdge
let blur: Bool
let containerSize: CGSize
init(rect: CGRect, edge: WallpaperEdgeEffectEdge, containerSize: CGSize) {
init(rect: CGRect, edge: WallpaperEdgeEffectEdge, blur: Bool, containerSize: CGSize) {
self.rect = rect
self.edge = edge
self.blur = blur
self.containerSize = containerSize
}
}
@ -1813,6 +1816,8 @@ private final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEff
private let overlayNode: ASDisplayNode
private let maskView: UIImageView
private var blurView: VariableBlurView?
private weak var parentNode: WallpaperBackgroundNodeImpl?
private var index: Int?
private var params: Params?
@ -1870,7 +1875,7 @@ private final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEff
self.containerNode.insertSubnode(gradientNode, at: 0)
if let params = self.params {
self.updateImpl(rect: params.rect, edge: params.edge, containerSize: params.containerSize, transition: .immediate)
self.updateImpl(rect: params.rect, edge: params.edge, blur: params.blur, containerSize: params.containerSize, transition: .immediate)
}
}
} else {
@ -1889,26 +1894,26 @@ private final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEff
}
}
func update(rect: CGRect, edge: WallpaperEdgeEffectEdge, containerSize: CGSize, transition: ContainedViewLayoutTransition) {
let params = Params(rect: rect, edge: edge, containerSize: containerSize)
func update(rect: CGRect, edge: WallpaperEdgeEffectEdge, blur: Bool, containerSize: CGSize, transition: ContainedViewLayoutTransition) {
let params = Params(rect: rect, edge: edge, blur: blur, containerSize: containerSize)
if self.params != params {
self.params = params
self.updateImpl(rect: params.rect, edge: params.edge, containerSize: params.containerSize, transition: transition)
self.updateImpl(rect: params.rect, edge: params.edge, blur: params.blur, containerSize: params.containerSize, transition: transition)
}
}
private func updateImpl(rect: CGRect, edge: WallpaperEdgeEffectEdge, containerSize: CGSize, transition: ContainedViewLayoutTransition) {
private func updateImpl(rect: CGRect, edge: WallpaperEdgeEffectEdge, blur: Bool, containerSize: CGSize, transition: ContainedViewLayoutTransition) {
transition.updateFrame(node: self.containerMaskingNode, frame: CGRect(origin: CGPoint(), size: rect.size))
transition.updateBounds(node: self.containerNode, bounds: CGRect(origin: CGPoint(x: rect.minX, y: rect.minY), size: rect.size))
if self.maskView.image?.size.height != edge.size {
let baseGradientAlpha: CGFloat = 0.75
let baseGradientAlpha: CGFloat = blur ? 0.55 : 0.75
let numSteps = 8
let firstStep = 1
let firstLocation = 0.0
let colors: [UIColor] = (0 ..< numSteps).map { i in
if i < firstStep {
return UIColor(white: 1.0, alpha: 1.0)
return UIColor(white: 1.0, alpha: 0.0)
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
let value: CGFloat = bezierPoint(0.42, 0.0, 0.58, 1.0, step)
@ -1931,7 +1936,14 @@ private final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEff
)?.stretchableImage(withLeftCapWidth: 0, topCapHeight: Int(edge.size))
}
transition.updateFrame(view: self.maskView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: rect.size))
let maskFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: rect.size)
transition.updatePosition(layer: self.maskView.layer, position: maskFrame.center)
transition.updateBounds(layer: self.maskView.layer, bounds: CGRect(origin: CGPoint(), size: maskFrame.size))
if case .top = edge.edge {
self.maskView.transform = CGAffineTransformMakeScale(1.0, -1.0)
} else {
self.maskView.transform = CGAffineTransformIdentity
}
transition.updateFrame(node: self.overlayNode, frame: CGRect(origin: CGPoint(), size: containerSize))
@ -1939,6 +1951,50 @@ private final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEff
transition.updateFrame(node: gradientNode, frame: CGRect(origin: CGPoint(), size: containerSize))
}
transition.updateFrame(layer: self.patternImageLayer, frame: CGRect(origin: CGPoint(), size: containerSize))
if blur {
let gradientMaskLayer = SimpleGradientLayer()
let baseGradientAlpha: CGFloat = 1.0
let numSteps = 8
let firstStep = 1
let firstLocation = 0.8
gradientMaskLayer.colors = (0 ..< numSteps).map { i in
if i < firstStep {
return UIColor(white: 1.0, alpha: 1.0).cgColor
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
let value: CGFloat = 1.0 - bezierPoint(0.42, 0.0, 0.58, 1.0, step)
return UIColor(white: 1.0, alpha: baseGradientAlpha * value).cgColor
}
}
gradientMaskLayer.locations = (0 ..< numSteps).map { i -> NSNumber in
if i < firstStep {
return 0.0 as NSNumber
} else {
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
return (firstLocation + (1.0 - firstLocation) * step) as NSNumber
}
}
let blurView: VariableBlurView
if let current = self.blurView {
blurView = current
} else {
blurView = VariableBlurView(gradientMask: self.maskView.image ?? UIImage(), maxBlurRadius: 8.0)
blurView.layer.mask = gradientMaskLayer
self.view.insertSubview(blurView, at: 0)
self.blurView = blurView
}
transition.updateFrame(view: blurView, frame: bounds)
if let maskLayer = blurView.layer.mask {
transition.updateFrame(layer: maskLayer, frame: bounds)
maskLayer.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
}
blurView.transform = self.maskView.transform
} else if let blurView = self.blurView {
self.blurView = nil
blurView.removeFromSuperview()
}
}
}

View file

@ -60,7 +60,7 @@ final class WebSearchGalleryControllerPresentationArguments {
}
class WebSearchGalleryController: ViewController {
private static let navigationTheme = NavigationBarTheme(buttonColor: .white, disabledButtonColor: UIColor(rgb: 0x525252), primaryTextColor: .white, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
private static let navigationTheme = NavigationBarTheme(overallDarkAppearance: false, buttonColor: .white, disabledButtonColor: UIColor(rgb: 0x525252), primaryTextColor: .white, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear)
private var galleryNode: GalleryControllerNode {
return self.displayNode as! GalleryControllerNode

View file

@ -3621,6 +3621,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
if let backgroundColor = self.controllerNode.headerColor, let textColor = self.controllerNode.headerPrimaryTextColor {
navigationBarPresentationData = NavigationBarPresentationData(
theme: NavigationBarTheme(
overallDarkAppearance: false,
buttonColor: textColor,
disabledButtonColor: textColor,
primaryTextColor: textColor,
@ -3639,7 +3640,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
strings: NavigationBarStrings(back: "", close: "")
)
}
self.navigationBar?.updatePresentationData(navigationBarPresentationData)
self.navigationBar?.updatePresentationData(navigationBarPresentationData, transition: .immediate)
}
@objc fileprivate func cancelPressed() {