Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2025-12-29 10:05:59 +04:00
commit 150dfa934d
16 changed files with 78 additions and 52 deletions

View file

@ -1574,7 +1574,8 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
)
},
selectedTab: selectedTab,
isEditing: isEditing
isEditing: isEditing,
liftWhileSwitching: layout.deviceMetrics.type != .tablet
))
}

View file

@ -799,6 +799,9 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
}
filtersInsets.bottom = max(8.0, filtersInsets.bottom)
}
if self.stateValue.selectedMessageIds != nil {
filtersInsets.bottom += 48.0
}
transition.updateFrame(node: self.filterContainerNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + filtersInsets.left, y: layout.size.height - filtersInsets.bottom - 40.0), size: CGSize(width: layout.size.width - (layout.safeInsets.left + filtersInsets.left) * 2.0, height: 40.0)))
self.updateFilterContainerNode(layout: layout, transition: transition)
@ -809,13 +812,13 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
}
var bottomIntrinsicInset = layout.intrinsicInsets.bottom
if case .chatList(.root) = self.location {
/*if case .chatList(.root) = self.location {
if layout.safeInsets.left > 20.0 {
bottomIntrinsicInset -= 34.0
} else {
bottomIntrinsicInset -= 49.0
}
}
}*/
if let selectedMessageIds = self.stateValue.selectedMessageIds {
var wasAdded = false
@ -969,10 +972,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
bottomInset = inputHeight
} else if let _ = self.selectionPanelNode {
bottomInset = bottomIntrinsicInset
} else if case .chatList(.root) = self.location {
bottomInset -= bottomIntrinsicInset
}
bottomInset += 40.0 - 10.0
bottomInset += 10.0
let availablePanes: [ChatListSearchPaneKey]
var isForum = false

View file

@ -42,8 +42,9 @@ public final class ChannelMembersSearchControllerImpl: ViewController, ChannelMe
self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
}
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.navigationPresentation = .modal
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style

View file

@ -510,6 +510,12 @@ private class SearchBarTextField: UITextField, UIScrollViewDelegate {
}
fileprivate var tokensWidth: CGFloat = 0.0
var tokensInsetWidth: CGFloat {
if self.tokensWidth == 0.0 {
return 0.0
}
return self.tokensWidth + 8.0
}
private let measurePrefixLabel: ImmediateTextNode
let prefixLabel: ImmediateTextNode
@ -1201,7 +1207,9 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.textField.frame = textFrame
let searchPlaceholderFrame = CGRect(origin: CGPoint(x: 16.0, y: 0.0), size: CGSize(width: max(0.0, boundingSize.width - 16.0 * 2.0), height: 44.0))
let additionalPlaceholderInset = self.textField.tokensInsetWidth
let searchPlaceholderFrame = CGRect(origin: CGPoint(x: leftInset + 16.0, y: 0.0), size: CGSize(width: max(0.0, boundingSize.width - 16.0 * 2.0 - leftInset - rightInset), height: 44.0))
if case .glass = self.fieldStyle, self.takenSearchPlaceholderContentView == nil {
transition.updateFrame(node: self.inlineSearchPlaceholder, frame: searchPlaceholderFrame)
@ -1232,7 +1240,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
}
}
if let inlineSearchPlaceholderContentsView = self.inlineSearchPlaceholderContentsView {
inlineSearchPlaceholderContentsView.update(size: searchPlaceholderFrame.size, isActive: true, transition: transition)
inlineSearchPlaceholderContentsView.update(size: searchPlaceholderFrame.size, isActive: true, additionalPlaceholderInset: additionalPlaceholderInset, transition: transition)
transition.updateFrame(view: inlineSearchPlaceholderContentsView, frame: searchPlaceholderFrame)
if isFirstTime {
@ -1244,7 +1252,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
if !self.isAnimatingOut, let takenSearchPlaceholderContentView = self.takenSearchPlaceholderContentView {
transition.updateFrame(view: takenSearchPlaceholderContentView, frame: searchPlaceholderFrame)
takenSearchPlaceholderContentView.update(size: searchPlaceholderFrame.size, isActive: true, transition: transition)
takenSearchPlaceholderContentView.update(size: searchPlaceholderFrame.size, isActive: true, additionalPlaceholderInset: additionalPlaceholderInset, transition: transition)
}
}
@ -1263,6 +1271,10 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
}
public func animateIn(from node: SearchBarPlaceholderNode, duration: Double, timingFunction: String) {
guard let (boundingSize, leftInset, rightInset) = self.validLayout else {
return
}
self.inlineSearchPlaceholder.isHidden = true
let takenSearchPlaceholderContentView = node.takeContents()
@ -1279,11 +1291,11 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
}
let sourceFrame = node.view.convert(node.bounds, to: self.view)
let targetFrame = CGRect(origin: CGPoint(x: 16.0, y: 0.0), size: CGSize(width: max(0.0, self.bounds.width - 16.0 * 2.0), height: 44.0))
let targetFrame = CGRect(origin: CGPoint(x: leftInset + 16.0, y: 0.0), size: CGSize(width: max(0.0, boundingSize.width - 16.0 * 2.0 - leftInset - rightInset), height: 44.0))
let transition: ContainedViewLayoutTransition = .animated(duration: duration, curve: timingFunction == kCAMediaTimingFunctionSpring ? .spring : .easeInOut)
takenSearchPlaceholderContentView.frame = sourceFrame
transition.updateFrame(view: takenSearchPlaceholderContentView, frame: targetFrame)
takenSearchPlaceholderContentView.update(size: targetFrame.size, isActive: true, transition: transition)
takenSearchPlaceholderContentView.update(size: targetFrame.size, isActive: true, additionalPlaceholderInset: self.textField.tokensInsetWidth, transition: transition)
/*let initialTextBackgroundFrame = node.view.convert(node.backgroundView.frame, to: self.view)
@ -1487,7 +1499,7 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.2)
let sourceFrame = node.view.convert(node.bounds, to: self.view)
takenSearchPlaceholderContentView.update(size: sourceFrame.size, isActive: false, transition: transition.containedViewLayoutTransition)
takenSearchPlaceholderContentView.update(size: sourceFrame.size, isActive: false, additionalPlaceholderInset: 0.0, transition: transition.containedViewLayoutTransition)
takenSearchPlaceholderContentView.updatePlaceholderVisibility(isVisible: true)
takenSearchPlaceholderContentView.updateSearchIconVisibility(isVisible: true)

View file

@ -34,8 +34,9 @@ public final class SearchBarPlaceholderContentView: UIView {
var backgroundColor: UIColor
var controlColor: UIColor
var isActive: Bool
var additionalPlaceholderInset: CGFloat
init(placeholderString: NSAttributedString?, compactPlaceholderString: NSAttributedString?, constrainedSize: CGSize, expansionProgress: CGFloat, iconColor: UIColor, foregroundColor: UIColor, backgroundColor: UIColor, controlColor: UIColor, isActive: Bool) {
init(placeholderString: NSAttributedString?, compactPlaceholderString: NSAttributedString?, constrainedSize: CGSize, expansionProgress: CGFloat, iconColor: UIColor, foregroundColor: UIColor, backgroundColor: UIColor, controlColor: UIColor, isActive: Bool, additionalPlaceholderInset: CGFloat) {
self.placeholderString = placeholderString
self.compactPlaceholderString = compactPlaceholderString
self.constrainedSize = constrainedSize
@ -45,6 +46,7 @@ public final class SearchBarPlaceholderContentView: UIView {
self.backgroundColor = backgroundColor
self.controlColor = controlColor
self.isActive = isActive
self.additionalPlaceholderInset = additionalPlaceholderInset
}
}
@ -145,19 +147,21 @@ public final class SearchBarPlaceholderContentView: UIView {
foregroundColor: foregroundColor,
backgroundColor: backgroundColor,
controlColor: controlColor,
isActive: false
isActive: false,
additionalPlaceholderInset: 0.0
)
self.params = params
return self.updateLayout(params: params, transition: transition)
}
public func update(size: CGSize, isActive: Bool, transition: ContainedViewLayoutTransition) {
public func update(size: CGSize, isActive: Bool, additionalPlaceholderInset: CGFloat, transition: ContainedViewLayoutTransition) {
guard var params = self.params else {
return
}
params.constrainedSize = size
params.expansionProgress = 1.0
params.isActive = isActive
params.additionalPlaceholderInset = additionalPlaceholderInset
let _ = self.updateLayout(params: params, transition: transition)
}
@ -232,7 +236,7 @@ public final class SearchBarPlaceholderContentView: UIView {
if params.constrainedSize.height >= 36.0 {
textOffset += 1.0
}
let labelX: CGFloat = iconX + iconSize.width + spacing
let labelX: CGFloat = iconX + iconSize.width + spacing + params.additionalPlaceholderInset
let labelFrame = CGRect(origin: CGPoint(x: labelX, y: floorToScreenPixels((height - labelLayoutResult.size.height) / 2.0) + textOffset), size: labelLayoutResult.size)
transition.updateFrame(node: self.labelNode, frame: labelFrame)
transition.updateFrame(node: self.plainLabelNode, frame: labelFrame)

View file

@ -181,7 +181,7 @@ final class ItemNode: ASDisplayNode {
var iconInset: CGFloat = 0.0
if let image = self.iconNode.image {
iconInset = 22.0
self.iconNode.frame = CGRect(x: 0.0, y: floorToScreenPixels((height - image.size.height) / 2.0), width: image.size.width, height: image.size.height)
self.iconNode.frame = CGRect(x: 0.0, y: 4.0 + floorToScreenPixels((height - image.size.height) / 2.0), width: image.size.width, height: image.size.height)
}
let titleSize = self.titleNode.updateLayout(CGSize(width: 160.0, height: .greatestFiniteMagnitude))

View file

@ -726,9 +726,9 @@ public final class ChatListNavigationBar: Component {
transition: headerPanelsTransition,
component: headerPanels,
environment: {},
containerSize: CGSize(width: availableSize.width, height: 10000.0)
containerSize: CGSize(width: availableSize.width - component.sideInset * 2.0, height: 10000.0)
)
let headerPanelsFrame = CGRect(origin: CGPoint(x: 0.0, y: headersContentHeight), size: headerPanelsSize)
let headerPanelsFrame = CGRect(origin: CGPoint(x: component.sideInset, y: headersContentHeight), size: headerPanelsSize)
if let headerPanelsComponentView = headerPanelsView.view {
if headerPanelsComponentView.superview == nil {
self.bottomContentsContainer.addSubview(headerPanelsComponentView)

View file

@ -223,6 +223,7 @@ public final class HorizontalTabsComponent: Component {
public let selectedTab: Tab.Id?
public let isEditing: Bool
public let layout: Layout
public let liftWhileSwitching: Bool
public init(
context: AccountContext?,
@ -230,7 +231,8 @@ public final class HorizontalTabsComponent: Component {
tabs: [Tab],
selectedTab: Tab.Id?,
isEditing: Bool,
layout: Layout = .fill
layout: Layout = .fill,
liftWhileSwitching: Bool = true
) {
self.context = context
self.theme = theme
@ -238,6 +240,7 @@ public final class HorizontalTabsComponent: Component {
self.selectedTab = selectedTab
self.isEditing = isEditing
self.layout = layout
self.liftWhileSwitching = liftWhileSwitching
}
public static func ==(lhs: HorizontalTabsComponent, rhs: HorizontalTabsComponent) -> Bool {
@ -256,6 +259,9 @@ public final class HorizontalTabsComponent: Component {
if lhs.layout != rhs.layout {
return false
}
if lhs.liftWhileSwitching != rhs.liftWhileSwitching {
return false
}
return true
}
@ -568,7 +574,7 @@ public final class HorizontalTabsComponent: Component {
return
}
var isLifted = self.temporaryLiftTimer != nil
if component.theme.overallDarkAppearance {
if !component.liftWhileSwitching {
isLifted = false
}
self.lensView.update(size: CGSize(width: layoutData.size.width - 3.0 * 2.0, height: layoutData.size.height - 3.0 * 2.0), selectionOrigin: CGPoint(x: -self.scrollView.contentOffset.x + layoutData.selectedItemFrame.minX, y: 0.0), selectionSize: CGSize(width: layoutData.selectedItemFrame.width, height: layoutData.size.height - 3.0 * 2.0), inset: 0.0, liftedInset: 6.0, isDark: component.theme.overallDarkAppearance, isLifted: isLifted, transition: transition)

View file

@ -58,11 +58,11 @@ private final class SearchNavigationContentNode: ASDisplayNode, PeerInfoPanelNod
func update(width: CGFloat, defaultHeight: CGFloat, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) -> CGFloat {
self.params = Params(width: width, defaultHeight: defaultHeight, insets: insets)
let size = CGSize(width: width, height: defaultHeight)
transition.updateFrame(node: self.contentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 10.0), size: size))
let size = CGSize(width: width, height: 60.0)
transition.updateFrame(node: self.contentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -6.0), size: size))
let _ = self.contentNode.updateLayout(size: size, leftInset: insets.left, rightInset: insets.right, transition: transition)
var contentHeight: CGFloat = size.height + 10.0
var contentHeight: CGFloat = size.height
if self.appliedPanelNode !== self.panelNode {
if let previous = self.appliedPanelNode {
@ -81,7 +81,8 @@ private final class SearchNavigationContentNode: ASDisplayNode, PeerInfoPanelNod
panelNode.alpha = 0.0
transition.updateAlpha(node: panelNode, alpha: 1.0)
contentHeight += panelHeight - 1.0
contentHeight += 80.0
contentHeight += panelHeight
}
} else if let panelNode = self.panelNode, let chatController = self.chatController {
let panelLayout = panelNode.updateLayout(width: width, leftInset: insets.left, rightInset: insets.right, transition: transition, chatController: chatController)
@ -89,7 +90,8 @@ private final class SearchNavigationContentNode: ASDisplayNode, PeerInfoPanelNod
let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: panelHeight))
transition.updateFrame(node: panelNode, frame: panelFrame)
contentHeight += panelHeight - 1.0
contentHeight += 80.0
contentHeight += panelHeight
}
return contentHeight

View file

@ -2804,7 +2804,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
return result
}
if self.isSettings {
if self.isSettings && self.buttonsContainerNode.alpha != 0.0 {
if self.subtitleNodeRawContainer.bounds.contains(self.view.convert(point, to: self.subtitleNodeRawContainer.view)) {
return self.subtitleNodeRawContainer.view
}

View file

@ -1341,7 +1341,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
},
selectedTab: self.currentPaneKey.flatMap { HorizontalTabsComponent.Tab.Id($0) },
isEditing: false,
layout: .fit
layout: .fit,
liftWhileSwitching: deviceMetrics.type != .tablet
)),
environment: {},
containerSize: tabsContainerSize

View file

@ -12755,6 +12755,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
restoreContentOffset = self.scrollNode.view.contentOffset
}
if !self.isMediaOnly {
contentHeight -= 18.0
}
let paneContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: paneContainerSize)
if self.state.isEditing || (self.data?.availablePanes ?? []).isEmpty {
transition.updateAlpha(node: self.paneContainerNode, alpha: 0.0)

View file

@ -580,7 +580,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
if let params = self.currentParams {
let visibleBounds = self.scrollNode.bounds.insetBy(dx: 0.0, dy: -10.0)
var topInset: CGFloat = 60.0
var topInset: CGFloat = 66.0
var canEditCollections = false
if self.peerId == self.context.account.peerId || self.canManage {
@ -703,7 +703,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
)),
environment: {},
containerSize: CGSize(width: params.size.width - 10.0 * 2.0, height: 44.0)
containerSize: CGSize(width: params.size.width - 14.0 * 2.0, height: 44.0)
)
if let tabSelectorView = self.tabSelector.view {
if tabSelectorView.superview == nil {
@ -716,7 +716,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
transition.setFrame(view: tabSelectorView, frame: CGRect(origin: CGPoint(x: floor((params.size.width - tabSelectorSize.width) / 2.0), y: 66.0), size: tabSelectorSize))
topInset += tabSelectorSize.height + 28.0
topInset += tabSelectorSize.height + 15.0
}
} else if let tabSelectorView = self.tabSelector.view {
tabSelectorView.alpha = 0.0

View file

@ -4096,7 +4096,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
}
)),
environment: {},
containerSize: CGSize(width: size.width, height: 44.0)
containerSize: CGSize(width: size.width - 6.0 * 2.0, height: 44.0)
)
var folderTabFrame = CGRect(origin: CGPoint(x: floor((size.width - folderTabSize.width) * 0.5), y: topInset - 21.0), size: folderTabSize)

View file

@ -39,6 +39,7 @@ import Markdown
import GroupStickerPackSetupController
import PeerNameColorItem
import EmojiActionIconComponent
import EdgeEffect
final class ChannelAppearanceScreenComponent: Component {
typealias EnvironmentType = ViewControllerComponentContainer.Environment
@ -169,13 +170,13 @@ final class ChannelAppearanceScreenComponent: Component {
}
final class View: UIView, UIScrollViewDelegate {
private let edgeEffectView: EdgeEffectView
private let topOverscrollLayer = SimpleLayer()
private let scrollView: ScrollView
private let actionButton = ComponentView<Empty>()
private let bottomPanelBackgroundView: BlurredBackgroundView
private let bottomPanelSeparator: SimpleLayer
private let backButton = PeerInfoHeaderNavigationButton()
private let navigationTitle = ComponentView<Empty>()
private let previewSection = ComponentView<Empty>()
@ -227,6 +228,8 @@ final class ChannelAppearanceScreenComponent: Component {
private weak var emojiStatusSelectionController: ViewController?
override init(frame: CGRect) {
self.edgeEffectView = EdgeEffectView()
self.scrollView = ScrollView()
self.scrollView.showsVerticalScrollIndicator = true
self.scrollView.showsHorizontalScrollIndicator = false
@ -249,14 +252,10 @@ final class ChannelAppearanceScreenComponent: Component {
self.scrollView.layer.addSublayer(self.topOverscrollLayer)
self.addSubview(self.edgeEffectView)
self.addSubview(self.bottomPanelBackgroundView)
self.layer.addSublayer(self.bottomPanelSeparator)
self.backButton.action = { [weak self] _, _ in
if let self, let controller = self.environment?.controller() {
controller.navigationController?.popViewController(animated: true)
}
}
}
required init?(coder: NSCoder) {
@ -349,6 +348,8 @@ final class ChannelAppearanceScreenComponent: Component {
transition.setAlpha(view: navigationTitleView, alpha: navigationAlpha)
}
transition.setAlpha(view: self.edgeEffectView, alpha: navigationAlpha)
let bottomNavigationAlphaDistance: CGFloat = 16.0
let bottomNavigationAlpha: CGFloat = max(0.0, min(1.0, (self.scrollView.contentSize.height - self.scrollView.bounds.maxY) / bottomNavigationAlphaDistance))
@ -1006,6 +1007,10 @@ final class ChannelAppearanceScreenComponent: Component {
}
self.requiredBoostSubject = requiredBoostSubject
let edgeEffectHeight: CGFloat = environment.navigationHeight + 8.0
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: edgeEffectHeight))
transition.setFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
self.edgeEffectView.update(content: environment.theme.list.blocksBackgroundColor, blur: true, rect: edgeEffectFrame, edge: .top, edgeSize: min(30, edgeEffectFrame.height), transition: transition)
let headerColor: UIColor
if let profileColor {
@ -1016,7 +1021,6 @@ final class ChannelAppearanceScreenComponent: Component {
}
self.topOverscrollLayer.backgroundColor = headerColor.cgColor
let backSize = self.backButton.update(key: .back, presentationData: component.context.sharedContext.currentPresentationData.with { $0 }, height: 44.0)
var scrolledUp = self.scrolledUp
if profileColor == nil {
scrolledUp = false
@ -1025,14 +1029,6 @@ final class ChannelAppearanceScreenComponent: Component {
if let controller = self.environment?.controller() as? ChannelAppearanceScreen {
controller.statusBar.updateStatusBarStyle(scrolledUp ? .White : .Ignore, animated: true)
}
self.backButton.updateContentsColor(backgroundColor: scrolledUp ? UIColor(white: 0.0, alpha: 0.1) : .clear, contentsColor: scrolledUp ? .white : environment.theme.rootController.navigationBar.accentTextColor, canBeExpanded: !scrolledUp, transition: .animated(duration: 0.2, curve: .easeInOut))
self.backButton.frame = CGRect(origin: CGPoint(x: environment.safeInsets.left + 16.0, y: environment.navigationHeight - 44.0), size: backSize)
if self.backButton.view.superview == nil {
if let controller = self.environment?.controller(), let navigationBar = controller.navigationBar {
navigationBar.view.addSubview(self.backButton.view)
}
}
let navigationTitleSize = self.navigationTitle.update(
transition: transition,
@ -1911,12 +1907,11 @@ public class ChannelAppearanceScreen: ViewControllerComponentContainer {
context: context,
peerId: peerId,
boostStatus: boostStatus
), navigationBarAppearance: .default, theme: .default, updatedPresentationData: updatedPresentationData)
), navigationBarAppearance: .transparent, theme: .default, updatedPresentationData: updatedPresentationData)
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.title = ""
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView())
self.ready.set(.never())

View file

@ -357,7 +357,7 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode {
}
}
var nextLeftX: CGFloat = params.leftInset
var nextLeftX: CGFloat = params.leftInset + 4.0
var calendarButtonFrameValue: CGRect?
var membersButtonFrameValue: CGRect?