mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-01 12:17:53 +00:00
Temp
This commit is contained in:
parent
e0d511165c
commit
5a8bd1d98d
@ -14,7 +14,7 @@ open class PagerExternalTopPanelContainer: SparseContainerView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public protocol PagerContentViewWithBackground: UIView {
|
public protocol PagerContentViewWithBackground: UIView {
|
||||||
func pagerUpdateBackground(backgroundFrame: CGRect, topPanelHeight: CGFloat, transition: ComponentTransition)
|
func pagerUpdateBackground(backgroundFrame: CGRect, topPanelHeight: CGFloat, externalTintMaskContainer: UIView?, transition: ComponentTransition)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class PagerComponentChildEnvironment: Equatable {
|
public final class PagerComponentChildEnvironment: Equatable {
|
||||||
@ -206,6 +206,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
public let externalTopPanelContainer: PagerExternalTopPanelContainer?
|
public let externalTopPanelContainer: PagerExternalTopPanelContainer?
|
||||||
public let bottomPanel: AnyComponent<PagerComponentPanelEnvironment<TopPanelEnvironment>>?
|
public let bottomPanel: AnyComponent<PagerComponentPanelEnvironment<TopPanelEnvironment>>?
|
||||||
public let externalBottomPanelContainer: PagerExternalTopPanelContainer?
|
public let externalBottomPanelContainer: PagerExternalTopPanelContainer?
|
||||||
|
public let externalTintMaskContainer: UIView?
|
||||||
public let panelStateUpdated: ((PagerComponentPanelState, ComponentTransition) -> Void)?
|
public let panelStateUpdated: ((PagerComponentPanelState, ComponentTransition) -> Void)?
|
||||||
public let isTopPanelExpandedUpdated: (Bool, ComponentTransition) -> Void
|
public let isTopPanelExpandedUpdated: (Bool, ComponentTransition) -> Void
|
||||||
public let isTopPanelHiddenUpdated: (Bool, ComponentTransition) -> Void
|
public let isTopPanelHiddenUpdated: (Bool, ComponentTransition) -> Void
|
||||||
@ -228,6 +229,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
externalTopPanelContainer: PagerExternalTopPanelContainer?,
|
externalTopPanelContainer: PagerExternalTopPanelContainer?,
|
||||||
bottomPanel: AnyComponent<PagerComponentPanelEnvironment<TopPanelEnvironment>>?,
|
bottomPanel: AnyComponent<PagerComponentPanelEnvironment<TopPanelEnvironment>>?,
|
||||||
externalBottomPanelContainer: PagerExternalTopPanelContainer?,
|
externalBottomPanelContainer: PagerExternalTopPanelContainer?,
|
||||||
|
externalTintMaskContainer: UIView?,
|
||||||
panelStateUpdated: ((PagerComponentPanelState, ComponentTransition) -> Void)?,
|
panelStateUpdated: ((PagerComponentPanelState, ComponentTransition) -> Void)?,
|
||||||
isTopPanelExpandedUpdated: @escaping (Bool, ComponentTransition) -> Void,
|
isTopPanelExpandedUpdated: @escaping (Bool, ComponentTransition) -> Void,
|
||||||
isTopPanelHiddenUpdated: @escaping (Bool, ComponentTransition) -> Void,
|
isTopPanelHiddenUpdated: @escaping (Bool, ComponentTransition) -> Void,
|
||||||
@ -249,6 +251,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
self.externalTopPanelContainer = externalTopPanelContainer
|
self.externalTopPanelContainer = externalTopPanelContainer
|
||||||
self.bottomPanel = bottomPanel
|
self.bottomPanel = bottomPanel
|
||||||
self.externalBottomPanelContainer = externalBottomPanelContainer
|
self.externalBottomPanelContainer = externalBottomPanelContainer
|
||||||
|
self.externalTintMaskContainer = externalTintMaskContainer
|
||||||
self.panelStateUpdated = panelStateUpdated
|
self.panelStateUpdated = panelStateUpdated
|
||||||
self.isTopPanelExpandedUpdated = isTopPanelExpandedUpdated
|
self.isTopPanelExpandedUpdated = isTopPanelExpandedUpdated
|
||||||
self.isTopPanelHiddenUpdated = isTopPanelHiddenUpdated
|
self.isTopPanelHiddenUpdated = isTopPanelHiddenUpdated
|
||||||
@ -292,6 +295,9 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
if lhs.externalBottomPanelContainer !== rhs.externalBottomPanelContainer {
|
if lhs.externalBottomPanelContainer !== rhs.externalBottomPanelContainer {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.externalTintMaskContainer !== rhs.externalTintMaskContainer {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.panelHideBehavior != rhs.panelHideBehavior {
|
if lhs.panelHideBehavior != rhs.panelHideBehavior {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -307,6 +313,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
public final class View: UIView, ComponentTaggedView {
|
public final class View: UIView, ComponentTaggedView {
|
||||||
private final class ContentView {
|
private final class ContentView {
|
||||||
let view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>
|
let view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>
|
||||||
|
let tintMaskContainer: UIView
|
||||||
var scrollingPanelOffsetToTopEdge: CGFloat = 0.0
|
var scrollingPanelOffsetToTopEdge: CGFloat = 0.0
|
||||||
var scrollingPanelOffsetToBottomEdge: CGFloat = .greatestFiniteMagnitude
|
var scrollingPanelOffsetToBottomEdge: CGFloat = .greatestFiniteMagnitude
|
||||||
var scrollingPanelOffsetFraction: CGFloat = 0.0
|
var scrollingPanelOffsetFraction: CGFloat = 0.0
|
||||||
@ -315,6 +322,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
|
|
||||||
init(view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>) {
|
init(view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>) {
|
||||||
self.view = view
|
self.view = view
|
||||||
|
self.tintMaskContainer = UIView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,6 +855,9 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
} else {
|
} else {
|
||||||
self.contentClippingView.insertSubview(contentView.view, at: 0)
|
self.contentClippingView.insertSubview(contentView.view, at: 0)
|
||||||
}
|
}
|
||||||
|
if let externalTintMaskContainer = component.externalTintMaskContainer {
|
||||||
|
externalTintMaskContainer.addSubview(contentView.tintMaskContainer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let childContentInsets = contentInsets
|
let childContentInsets = contentInsets
|
||||||
@ -890,6 +901,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
if wasAdded {
|
if wasAdded {
|
||||||
if case .none = transition.animation {
|
if case .none = transition.animation {
|
||||||
contentView.view.frame = contentFrame
|
contentView.view.frame = contentFrame
|
||||||
|
contentView.tintMaskContainer.frame = contentFrame
|
||||||
} else {
|
} else {
|
||||||
var referenceDirectionIsRight: Bool?
|
var referenceDirectionIsRight: Bool?
|
||||||
for (previousId, previousFrame) in referenceFrames {
|
for (previousId, previousFrame) in referenceFrames {
|
||||||
@ -906,6 +918,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
}
|
}
|
||||||
if let referenceDirectionIsRight = referenceDirectionIsRight {
|
if let referenceDirectionIsRight = referenceDirectionIsRight {
|
||||||
contentView.view.frame = contentFrame.offsetBy(dx: referenceDirectionIsRight ? contentFrame.width : (-contentFrame.width), dy: 0.0)
|
contentView.view.frame = contentFrame.offsetBy(dx: referenceDirectionIsRight ? contentFrame.width : (-contentFrame.width), dy: 0.0)
|
||||||
|
contentView.tintMaskContainer.frame = contentView.view.frame
|
||||||
transition.setFrame(view: contentView.view, frame: contentFrame, completion: { [weak self] completed in
|
transition.setFrame(view: contentView.view, frame: contentFrame, completion: { [weak self] completed in
|
||||||
if completed && !isInBounds && isPartOfTransition {
|
if completed && !isInBounds && isPartOfTransition {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@ -913,6 +926,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
transition.setFrame(view: contentView.tintMaskContainer, frame: contentFrame)
|
||||||
} else {
|
} else {
|
||||||
contentView.view.frame = contentFrame
|
contentView.view.frame = contentFrame
|
||||||
}
|
}
|
||||||
@ -925,10 +939,11 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
transition.setFrame(view: contentView.tintMaskContainer, frame: contentFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let contentViewWithBackground = contentView.view.componentView as? PagerContentViewWithBackground {
|
if let contentViewWithBackground = contentView.view.componentView as? PagerContentViewWithBackground {
|
||||||
contentViewWithBackground.pagerUpdateBackground(backgroundFrame: backgroundFrame, topPanelHeight: topPanelHeight, transition: contentTransition)
|
contentViewWithBackground.pagerUpdateBackground(backgroundFrame: backgroundFrame, topPanelHeight: topPanelHeight, externalTintMaskContainer: component.externalTintMaskContainer == nil ? nil : contentView.tintMaskContainer, transition: contentTransition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -941,7 +956,10 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for id in removedIds {
|
for id in removedIds {
|
||||||
self.contentViews.removeValue(forKey: id)?.view.removeFromSuperview()
|
if let contentView = self.contentViews.removeValue(forKey: id) {
|
||||||
|
contentView.view.removeFromSuperview()
|
||||||
|
contentView.tintMaskContainer.removeFromSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let panelStateUpdated = component.panelStateUpdated {
|
if let panelStateUpdated = component.panelStateUpdated {
|
||||||
|
|||||||
@ -707,6 +707,7 @@ final class ComposePollScreenComponent: Component {
|
|||||||
hasStickers: false,
|
hasStickers: false,
|
||||||
hasGifs: false,
|
hasGifs: false,
|
||||||
hideBackground: true,
|
hideBackground: true,
|
||||||
|
maskEdge: true,
|
||||||
sendGif: nil
|
sendGif: nil
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -237,7 +237,11 @@ public enum DeviceMetrics: CaseIterable, Equatable {
|
|||||||
public func onScreenNavigationHeight(inLandscape: Bool, systemOnScreenNavigationHeight: CGFloat?) -> CGFloat? {
|
public func onScreenNavigationHeight(inLandscape: Bool, systemOnScreenNavigationHeight: CGFloat?) -> CGFloat? {
|
||||||
switch self {
|
switch self {
|
||||||
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone16Pro, .iPhone16ProMax:
|
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone16Pro, .iPhone16ProMax:
|
||||||
return inLandscape ? 21.0 : 34.0
|
if #available(iOS 26.0, *) {
|
||||||
|
return 20.0
|
||||||
|
} else {
|
||||||
|
return inLandscape ? 21.0 : 34.0
|
||||||
|
}
|
||||||
case .iPhone14ProZoomed:
|
case .iPhone14ProZoomed:
|
||||||
return inLandscape ? 21.0 : 28.0
|
return inLandscape ? 21.0 : 28.0
|
||||||
case .iPhone14ProMaxZoomed:
|
case .iPhone14ProMaxZoomed:
|
||||||
|
|||||||
@ -312,6 +312,7 @@ open class BlurredBackgroundView: UIView {
|
|||||||
private var _color: UIColor?
|
private var _color: UIColor?
|
||||||
|
|
||||||
private var enableBlur: Bool
|
private var enableBlur: Bool
|
||||||
|
private var customBlurRadius: CGFloat?
|
||||||
|
|
||||||
public private(set) var effectView: UIVisualEffectView?
|
public private(set) var effectView: UIVisualEffectView?
|
||||||
private let backgroundView: UIView
|
private let backgroundView: UIView
|
||||||
@ -326,9 +327,10 @@ open class BlurredBackgroundView: UIView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(color: UIColor?, enableBlur: Bool = true) {
|
public init(color: UIColor?, enableBlur: Bool = true, customBlurRadius: CGFloat? = nil) {
|
||||||
self._color = nil
|
self._color = nil
|
||||||
self.enableBlur = enableBlur
|
self.enableBlur = enableBlur
|
||||||
|
self.customBlurRadius = customBlurRadius
|
||||||
|
|
||||||
self.backgroundView = UIView()
|
self.backgroundView = UIView()
|
||||||
|
|
||||||
@ -349,7 +351,6 @@ open class BlurredBackgroundView: UIView {
|
|||||||
if let color = self._color, self.enableBlur && !sharedIsReduceTransparencyEnabled && ((color.alpha > .ulpOfOne && color.alpha < 0.95) || forceKeepBlur) {
|
if let color = self._color, self.enableBlur && !sharedIsReduceTransparencyEnabled && ((color.alpha > .ulpOfOne && color.alpha < 0.95) || forceKeepBlur) {
|
||||||
if self.effectView == nil {
|
if self.effectView == nil {
|
||||||
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
|
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
|
||||||
//effectView.isHidden = true
|
|
||||||
|
|
||||||
for subview in effectView.subviews {
|
for subview in effectView.subviews {
|
||||||
if subview.description.contains("VisualEffectSubview") {
|
if subview.description.contains("VisualEffectSubview") {
|
||||||
@ -373,6 +374,9 @@ open class BlurredBackgroundView: UIView {
|
|||||||
if !allowedKeys.contains(filterName) {
|
if !allowedKeys.contains(filterName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if let customBlurRadius = self.customBlurRadius, filterName == "gaussianBlur" {
|
||||||
|
filter.setValue(customBlurRadius as NSNumber, forKey: "inputRadius")
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -179,9 +179,9 @@ final class TabBarControllerNode: ASDisplayNode {
|
|||||||
if bottomInset == 0.0 {
|
if bottomInset == 0.0 {
|
||||||
bottomInset = 8.0
|
bottomInset = 8.0
|
||||||
} else {
|
} else {
|
||||||
bottomInset = max(bottomInset - 13.0, 8.0)
|
bottomInset = max(bottomInset, 8.0)
|
||||||
}
|
}
|
||||||
let sideInset: CGFloat = 21.0
|
let sideInset: CGFloat = 20.0
|
||||||
|
|
||||||
var selectedId: AnyHashable?
|
var selectedId: AnyHashable?
|
||||||
if self.selectedIndex < self.tabBarItems.count {
|
if self.selectedIndex < self.tabBarItems.count {
|
||||||
|
|||||||
@ -941,7 +941,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio
|
|||||||
let inputPanel = PresentationThemeChatInputPanel(
|
let inputPanel = PresentationThemeChatInputPanel(
|
||||||
panelBackgroundColor: rootNavigationBar.blurredBackgroundColor,
|
panelBackgroundColor: rootNavigationBar.blurredBackgroundColor,
|
||||||
panelBackgroundColorNoWallpaper: UIColor(rgb: 0xffffff),
|
panelBackgroundColorNoWallpaper: UIColor(rgb: 0xffffff),
|
||||||
panelSeparatorColor: UIColor(rgb: 0xb2b2b2),
|
panelSeparatorColor: UIColor(white: 1.0, alpha: 0.5),
|
||||||
panelControlAccentColor: defaultDayAccentColor,
|
panelControlAccentColor: defaultDayAccentColor,
|
||||||
panelControlColor: UIColor(rgb: 0x858e99),
|
panelControlColor: UIColor(rgb: 0x858e99),
|
||||||
panelControlDisabledColor: UIColor(rgb: 0x727b87, alpha: 0.5),
|
panelControlDisabledColor: UIColor(rgb: 0x727b87, alpha: 0.5),
|
||||||
|
|||||||
@ -1219,6 +1219,7 @@ final class AvatarEditorScreenComponent: Component {
|
|||||||
defaultToEmojiTab: true,
|
defaultToEmojiTab: true,
|
||||||
externalTopPanelContainer: self.panelHostView,
|
externalTopPanelContainer: self.panelHostView,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
|
externalTintMaskContainer: nil,
|
||||||
displayTopPanelBackground: .blur,
|
displayTopPanelBackground: .blur,
|
||||||
topPanelExtensionUpdated: { _, _ in },
|
topPanelExtensionUpdated: { _, _ in },
|
||||||
topPanelScrollingOffset: { _, _ in },
|
topPanelScrollingOffset: { _, _ in },
|
||||||
|
|||||||
@ -99,7 +99,7 @@ public final class ChatRecordingViewOnceButtonNode: HighlightTrackingButtonNode
|
|||||||
|
|
||||||
let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(size.width / 2.0 - innerSize.width / 2.0), y: floorToScreenPixels(size.height / 2.0 - innerSize.height / 2.0)), size: innerSize)
|
let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(size.width / 2.0 - innerSize.width / 2.0), y: floorToScreenPixels(size.height / 2.0 - innerSize.height / 2.0)), size: innerSize)
|
||||||
self.backgroundView.frame = backgroundFrame
|
self.backgroundView.frame = backgroundFrame
|
||||||
self.backgroundView.update(size: backgroundFrame.size, cornerRadius: backgroundFrame.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)), transition: .immediate)
|
self.backgroundView.update(size: backgroundFrame.size, cornerRadius: backgroundFrame.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: .immediate)
|
||||||
|
|
||||||
if let iconImage = self.iconNode.image {
|
if let iconImage = self.iconNode.image {
|
||||||
let iconFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(size.width / 2.0 - iconImage.size.width / 2.0), y: floorToScreenPixels(size.height / 2.0 - iconImage.size.height / 2.0)), size: iconImage.size)
|
let iconFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(size.width / 2.0 - iconImage.size.width / 2.0), y: floorToScreenPixels(size.height / 2.0 - iconImage.size.height / 2.0)), size: iconImage.size)
|
||||||
|
|||||||
@ -334,7 +334,7 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag
|
|||||||
}
|
}
|
||||||
|
|
||||||
transition.updateFrame(view: self.micButtonBackgroundView, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(view: self.micButtonBackgroundView, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
self.micButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)), transition: ComponentTransition(transition))
|
self.micButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: ComponentTransition(transition))
|
||||||
|
|
||||||
transition.updateFrame(layer: self.micButton.layer, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(layer: self.micButton.layer, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
self.micButton.layoutItems()
|
self.micButton.layoutItems()
|
||||||
@ -349,7 +349,7 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag
|
|||||||
|
|
||||||
transition.updateFrame(view: self.expandMediaInputButton, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(view: self.expandMediaInputButton, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
transition.updateFrame(view: self.expandMediaInputButtonBackgroundView, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(view: self.expandMediaInputButtonBackgroundView, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
self.expandMediaInputButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)), transition: ComponentTransition(transition))
|
self.expandMediaInputButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: ComponentTransition(transition))
|
||||||
if let image = self.expandMediaInputButtonIcon.image {
|
if let image = self.expandMediaInputButtonIcon.image {
|
||||||
let expandIconFrame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) * 0.5), y: floor((size.height - image.size.height) * 0.5)), size: image.size)
|
let expandIconFrame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) * 0.5), y: floor((size.height - image.size.height) * 0.5)), size: image.size)
|
||||||
transition.updatePosition(layer: self.expandMediaInputButtonIcon.layer, position: expandIconFrame.center)
|
transition.updatePosition(layer: self.expandMediaInputButtonIcon.layer, position: expandIconFrame.center)
|
||||||
|
|||||||
@ -2213,7 +2213,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
let alphaTransitionIn: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut) : .immediate
|
let alphaTransitionIn: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut) : .immediate
|
||||||
let alphaTransitionOut: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut) : .immediate
|
let alphaTransitionOut: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut) : .immediate
|
||||||
|
|
||||||
let accessoryPanelAnimationBlurRadius: CGFloat = 10.0
|
let accessoryPanelAnimationBlurRadius: CGFloat = 20.0
|
||||||
var removedAccessoryPanelView: UIView?
|
var removedAccessoryPanelView: UIView?
|
||||||
|
|
||||||
if let currentAccessoryPanel = self.accessoryPanel, currentAccessoryPanel.component.id != accessoryPanel?.id {
|
if let currentAccessoryPanel = self.accessoryPanel, currentAccessoryPanel.component.id != accessoryPanel?.id {
|
||||||
@ -2334,7 +2334,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
transition.updateFrame(node: self.textInputContainer, frame: textInputContainerBackgroundFrame)
|
transition.updateFrame(node: self.textInputContainer, frame: textInputContainerBackgroundFrame)
|
||||||
transition.updateFrame(view: self.textInputContainerBackgroundView, frame: CGRect(origin: CGPoint(), size: textInputContainerBackgroundFrame.size))
|
transition.updateFrame(view: self.textInputContainerBackgroundView, frame: CGRect(origin: CGPoint(), size: textInputContainerBackgroundFrame.size))
|
||||||
|
|
||||||
self.textInputContainerBackgroundView.update(size: textInputContainerBackgroundFrame.size, cornerRadius: floor(minimalInputHeight * 0.5), isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)), transition: ComponentTransition(transition))
|
self.textInputContainerBackgroundView.update(size: textInputContainerBackgroundFrame.size, cornerRadius: floor(minimalInputHeight * 0.5), isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: ComponentTransition(transition))
|
||||||
|
|
||||||
if let removedAccessoryPanelView {
|
if let removedAccessoryPanelView {
|
||||||
if let removedAccessoryPanelView = removedAccessoryPanelView as? ChatInputAccessoryPanelView {
|
if let removedAccessoryPanelView = removedAccessoryPanelView as? ChatInputAccessoryPanelView {
|
||||||
@ -2625,7 +2625,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
|
|
||||||
let attachmentButtonFrame = CGRect(origin: CGPoint(x: attachmentButtonX, y: textInputFrame.maxY - 40.0), size: CGSize(width: 40.0, height: 40.0))
|
let attachmentButtonFrame = CGRect(origin: CGPoint(x: attachmentButtonX, y: textInputFrame.maxY - 40.0), size: CGSize(width: 40.0, height: 40.0))
|
||||||
self.attachmentButtonBackground.frame = CGRect(origin: CGPoint(), size: attachmentButtonFrame.size)
|
self.attachmentButtonBackground.frame = CGRect(origin: CGPoint(), size: attachmentButtonFrame.size)
|
||||||
self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: isEditingMedia ? .init(kind: .custom, color: interfaceState.theme.chat.inputPanel.actionControlFillColor) : .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)), transition: ComponentTransition(transition))
|
self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: isEditingMedia ? .init(kind: .custom, color: interfaceState.theme.chat.inputPanel.actionControlFillColor) : .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: ComponentTransition(transition))
|
||||||
|
|
||||||
transition.updateFrame(layer: self.attachmentButton.layer, frame: attachmentButtonFrame)
|
transition.updateFrame(layer: self.attachmentButton.layer, frame: attachmentButtonFrame)
|
||||||
transition.updateFrame(node: self.attachmentButtonDisabledNode, frame: self.attachmentButton.frame)
|
transition.updateFrame(node: self.attachmentButtonDisabledNode, frame: self.attachmentButton.frame)
|
||||||
|
|||||||
@ -41,6 +41,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/LegacyMessageInputPanelInputView:LegacyMessageInputPanelInputView",
|
"//submodules/TelegramUI/Components/LegacyMessageInputPanelInputView:LegacyMessageInputPanelInputView",
|
||||||
"//submodules/AttachmentTextInputPanelNode",
|
"//submodules/AttachmentTextInputPanelNode",
|
||||||
"//submodules/TelegramUI/Components/BatchVideoRendering",
|
"//submodules/TelegramUI/Components/BatchVideoRendering",
|
||||||
|
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import Pasteboard
|
|||||||
import EntityKeyboardGifContent
|
import EntityKeyboardGifContent
|
||||||
import LegacyMessageInputPanelInputView
|
import LegacyMessageInputPanelInputView
|
||||||
import AttachmentTextInputPanelNode
|
import AttachmentTextInputPanelNode
|
||||||
|
import GlassBackgroundComponent
|
||||||
|
|
||||||
public final class EmptyInputView: UIView, UIInputViewAudioFeedback {
|
public final class EmptyInputView: UIView, UIInputViewAudioFeedback {
|
||||||
public var enableInputClicksWhenVisible: Bool {
|
public var enableInputClicksWhenVisible: Bool {
|
||||||
@ -168,6 +169,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
hasStickers: Bool = true,
|
hasStickers: Bool = true,
|
||||||
hasGifs: Bool = true,
|
hasGifs: Bool = true,
|
||||||
hideBackground: Bool = false,
|
hideBackground: Bool = false,
|
||||||
|
maskEdge: Bool = false,
|
||||||
forceHasPremium: Bool = false,
|
forceHasPremium: Bool = false,
|
||||||
sendGif: ((FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool)?
|
sendGif: ((FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool)?
|
||||||
) -> Signal<InputData, NoError> {
|
) -> Signal<InputData, NoError> {
|
||||||
@ -187,7 +189,8 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
chatPeerId: chatPeerId,
|
chatPeerId: chatPeerId,
|
||||||
hasSearch: hasSearch,
|
hasSearch: hasSearch,
|
||||||
forceHasPremium: forceHasPremium,
|
forceHasPremium: forceHasPremium,
|
||||||
hideBackground: hideBackground
|
hideBackground: hideBackground,
|
||||||
|
maskEdge: maskEdge
|
||||||
)
|
)
|
||||||
|
|
||||||
let stickerNamespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks]
|
let stickerNamespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks]
|
||||||
@ -414,6 +417,14 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
return self.externalTopPanelContainerImpl
|
return self.externalTopPanelContainerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let clippingView: UIView
|
||||||
|
private var backgroundView: BlurredBackgroundView?
|
||||||
|
private var backgroundTintView: UIImageView?
|
||||||
|
private var backgroundChromeView: UIImageView?
|
||||||
|
private var backgroundTintMaskView: UIView?
|
||||||
|
private var backgroundTintMaskContentView: UIView?
|
||||||
|
private var externalBackground: EmojiPagerContentComponent.ExternalBackground?
|
||||||
|
|
||||||
public var switchToTextInput: (() -> Void)?
|
public var switchToTextInput: (() -> Void)?
|
||||||
|
|
||||||
private var currentState: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, interfaceState: ChatPresentationInterfaceState, layoutMetrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool)?
|
private var currentState: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, interfaceState: ChatPresentationInterfaceState, layoutMetrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool)?
|
||||||
@ -476,6 +487,10 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
|
|
||||||
self.interaction = interaction
|
self.interaction = interaction
|
||||||
|
|
||||||
|
self.clippingView = UIView()
|
||||||
|
self.clippingView.clipsToBounds = true
|
||||||
|
self.clippingView.layer.cornerRadius = 20.0
|
||||||
|
|
||||||
self.entityKeyboardView = ComponentHostView<Empty>()
|
self.entityKeyboardView = ComponentHostView<Empty>()
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@ -485,7 +500,41 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
self.topBackgroundExtension = 34.0
|
self.topBackgroundExtension = 34.0
|
||||||
self.followsDefaultHeight = true
|
self.followsDefaultHeight = true
|
||||||
|
|
||||||
self.view.addSubview(self.entityKeyboardView)
|
if "".isEmpty {
|
||||||
|
let backgroundView = BlurredBackgroundView(color: .black, enableBlur: true)
|
||||||
|
self.backgroundView = backgroundView
|
||||||
|
self.view.addSubview(backgroundView)
|
||||||
|
|
||||||
|
let backgroundTintView = UIImageView()
|
||||||
|
self.backgroundTintView = backgroundTintView
|
||||||
|
self.view.addSubview(backgroundTintView)
|
||||||
|
|
||||||
|
let backgroundTintMaskView = UIView()
|
||||||
|
backgroundTintMaskView.backgroundColor = .white
|
||||||
|
self.backgroundTintMaskView = backgroundTintMaskView
|
||||||
|
if let filter = CALayer.luminanceToAlpha() {
|
||||||
|
backgroundTintMaskView.layer.filters = [filter]
|
||||||
|
}
|
||||||
|
backgroundTintView.mask = backgroundTintMaskView
|
||||||
|
|
||||||
|
let backgroundTintMaskContentView = UIView()
|
||||||
|
backgroundTintMaskView.addSubview(backgroundTintMaskContentView)
|
||||||
|
self.backgroundTintMaskContentView = backgroundTintMaskContentView
|
||||||
|
|
||||||
|
let backgroundChromeView = UIImageView()
|
||||||
|
self.backgroundChromeView = backgroundChromeView
|
||||||
|
|
||||||
|
self.externalBackground = EmojiPagerContentComponent.ExternalBackground(
|
||||||
|
effectContainerView: backgroundTintMaskContentView
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.clippingView.addSubview(self.entityKeyboardView)
|
||||||
|
self.view.addSubview(self.clippingView)
|
||||||
|
|
||||||
|
if let backgroundChromeView = self.backgroundChromeView {
|
||||||
|
self.view.addSubview(backgroundChromeView)
|
||||||
|
}
|
||||||
|
|
||||||
self.externalTopPanelContainerImpl = PagerExternalTopPanelContainer()
|
self.externalTopPanelContainerImpl = PagerExternalTopPanelContainer()
|
||||||
|
|
||||||
@ -1162,7 +1211,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
chatPeerId: chatPeerId,
|
chatPeerId: chatPeerId,
|
||||||
peekBehavior: stickerPeekBehavior,
|
peekBehavior: stickerPeekBehavior,
|
||||||
customLayout: nil,
|
customLayout: nil,
|
||||||
externalBackground: nil,
|
externalBackground: self.externalBackground,
|
||||||
externalExpansionView: nil,
|
externalExpansionView: nil,
|
||||||
customContentView: nil,
|
customContentView: nil,
|
||||||
useOpaqueTheme: self.useOpaqueTheme,
|
useOpaqueTheme: self.useOpaqueTheme,
|
||||||
@ -1509,7 +1558,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
chatPeerId: chatPeerId,
|
chatPeerId: chatPeerId,
|
||||||
peekBehavior: stickerPeekBehavior,
|
peekBehavior: stickerPeekBehavior,
|
||||||
customLayout: nil,
|
customLayout: nil,
|
||||||
externalBackground: nil,
|
externalBackground: self.externalBackground,
|
||||||
externalExpansionView: nil,
|
externalExpansionView: nil,
|
||||||
customContentView: nil,
|
customContentView: nil,
|
||||||
useOpaqueTheme: self.useOpaqueTheme,
|
useOpaqueTheme: self.useOpaqueTheme,
|
||||||
@ -1739,6 +1788,22 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .immediate, interfaceState: interfaceState, layoutMetrics: layoutMetrics, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded)
|
let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .immediate, interfaceState: interfaceState, layoutMetrics: layoutMetrics, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
|
if let result = super.hitTest(point, with: event) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
if let backgroundView = self.backgroundView, backgroundView.frame.contains(point) {
|
||||||
|
for subview in self.view.subviews.reversed() {
|
||||||
|
if let result = subview.hitTest(self.view.convert(point, to: subview), with: event) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
public override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, layoutMetrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool) -> (CGFloat, CGFloat) {
|
public override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, layoutMetrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool) -> (CGFloat, CGFloat) {
|
||||||
self.currentState = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, layoutMetrics, deviceMetrics, isVisible, isExpanded)
|
self.currentState = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, layoutMetrics, deviceMetrics, isVisible, isExpanded)
|
||||||
|
|
||||||
@ -1849,7 +1914,8 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
defaultToEmojiTab: self.defaultToEmojiTab,
|
defaultToEmojiTab: self.defaultToEmojiTab,
|
||||||
externalTopPanelContainer: self.externalTopPanelContainerImpl,
|
externalTopPanelContainer: self.externalTopPanelContainerImpl,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
displayTopPanelBackground: self.opaqueTopPanelBackground ? .opaque : .none,
|
externalTintMaskContainer: self.backgroundTintMaskContentView,
|
||||||
|
displayTopPanelBackground: self.opaqueTopPanelBackground ? .opaque : .blur,
|
||||||
topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in
|
topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -1939,7 +2005,52 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: width, height: expandedHeight)
|
containerSize: CGSize(width: width, height: expandedHeight)
|
||||||
)
|
)
|
||||||
transition.updateFrame(view: self.entityKeyboardView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: entityKeyboardSize))
|
|
||||||
|
var clippingFrame = CGRect(origin: CGPoint(), size: entityKeyboardSize)
|
||||||
|
clippingFrame.size.height += 32.0
|
||||||
|
|
||||||
|
var entityKeyboardSizeFrame = CGRect(origin: CGPoint(), size: entityKeyboardSize)
|
||||||
|
if self.hideInput {
|
||||||
|
clippingFrame.size.height += self.topBackgroundExtension
|
||||||
|
clippingFrame.origin.y -= self.topBackgroundExtension
|
||||||
|
entityKeyboardSizeFrame.origin.y += self.topBackgroundExtension
|
||||||
|
}
|
||||||
|
|
||||||
|
transition.updateFrame(view: self.entityKeyboardView, frame: entityKeyboardSizeFrame)
|
||||||
|
|
||||||
|
transition.updateFrame(view: self.clippingView, frame: clippingFrame)
|
||||||
|
|
||||||
|
if let backgroundView = self.backgroundView, let backgroundTintView = self.backgroundTintView, let backgroundTintMaskView = self.backgroundTintMaskView, let backgroundTintMaskContentView = self.backgroundTintMaskContentView, let backgroundChromeView = self.backgroundChromeView {
|
||||||
|
var backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: entityKeyboardSize)
|
||||||
|
if self.hideInput {
|
||||||
|
backgroundFrame.size.height += self.topBackgroundExtension
|
||||||
|
backgroundFrame.origin.y -= self.topBackgroundExtension
|
||||||
|
}
|
||||||
|
backgroundFrame.size.height += 32.0
|
||||||
|
|
||||||
|
if backgroundChromeView.image == nil {
|
||||||
|
backgroundChromeView.image = GlassBackgroundView.generateForegroundImage(size: CGSize(width: 20.0 * 2.0, height: 20.0 * 2.0), isDark: interfaceState.theme.overallDarkAppearance, fillColor: .clear)
|
||||||
|
}
|
||||||
|
if backgroundTintView.image == nil {
|
||||||
|
backgroundTintView.image = generateStretchableFilledCircleImage(diameter: 20.0 * 2.0, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||||
|
}
|
||||||
|
backgroundTintView.tintColor = interfaceState.theme.chat.inputMediaPanel.backgroundColor
|
||||||
|
|
||||||
|
transition.updateFrame(view: backgroundView, frame: backgroundFrame)
|
||||||
|
backgroundView.updateColor(color: .clear, forceKeepBlur: true, transition: .immediate)
|
||||||
|
backgroundView.update(size: backgroundFrame.size, cornerRadius: 20.0, maskedCorners: [.layerMinXMinYCorner, .layerMaxXMinYCorner], transition: transition)
|
||||||
|
|
||||||
|
transition.updateFrame(view: backgroundChromeView, frame: backgroundFrame.insetBy(dx: -1.0, dy: 0.0))
|
||||||
|
|
||||||
|
var backgroundTintMaskContentFrame = CGRect(origin: CGPoint(), size: backgroundFrame.size)
|
||||||
|
if self.hideInput {
|
||||||
|
backgroundTintMaskContentFrame.origin.y += self.topBackgroundExtension
|
||||||
|
}
|
||||||
|
transition.updateFrame(view: backgroundTintView, frame: backgroundFrame)
|
||||||
|
|
||||||
|
transition.updateFrame(view: backgroundTintMaskView, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||||
|
transition.updateFrame(view: backgroundTintMaskContentView, frame: backgroundTintMaskContentFrame)
|
||||||
|
}
|
||||||
|
|
||||||
let layoutTime = CFAbsoluteTimeGetCurrent() - startTime
|
let layoutTime = CFAbsoluteTimeGetCurrent() - startTime
|
||||||
if layoutTime > 0.1 {
|
if layoutTime > 0.1 {
|
||||||
|
|||||||
@ -467,7 +467,7 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM
|
|||||||
tintColor = UIColor(white: 0.0, alpha: 0.5)
|
tintColor = UIColor(white: 0.0, alpha: 0.5)
|
||||||
} else {
|
} else {
|
||||||
isDark = self.theme.overallDarkAppearance
|
isDark = self.theme.overallDarkAppearance
|
||||||
tintColor = self.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)
|
tintColor = self.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)
|
||||||
}
|
}
|
||||||
|
|
||||||
let view = WrapperBlurrredBackgroundView(size: CGSize(width: 40.0, height: 72.0), isDark: isDark, tintColor: tintColor)
|
let view = WrapperBlurrredBackgroundView(size: CGSize(width: 40.0, height: 72.0), isDark: isDark, tintColor: tintColor)
|
||||||
|
|||||||
@ -187,6 +187,7 @@ public final class EmojiStatusSelectionComponent: Component {
|
|||||||
defaultToEmojiTab: true,
|
defaultToEmojiTab: true,
|
||||||
externalTopPanelContainer: self.panelHostView,
|
externalTopPanelContainer: self.panelHostView,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
|
externalTintMaskContainer: nil,
|
||||||
displayTopPanelBackground: .blur,
|
displayTopPanelBackground: .blur,
|
||||||
topPanelExtensionUpdated: { _, _ in },
|
topPanelExtensionUpdated: { _, _ in },
|
||||||
topPanelScrollingOffset: { _, _ in },
|
topPanelScrollingOffset: { _, _ in },
|
||||||
|
|||||||
@ -623,6 +623,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
public let searchState: SearchState
|
public let searchState: SearchState
|
||||||
public let warpContentsOnEdges: Bool
|
public let warpContentsOnEdges: Bool
|
||||||
public let hideBackground: Bool
|
public let hideBackground: Bool
|
||||||
|
public let maskEdge: Bool
|
||||||
public let displaySearchWithPlaceholder: String?
|
public let displaySearchWithPlaceholder: String?
|
||||||
public let searchCategories: EmojiSearchCategories?
|
public let searchCategories: EmojiSearchCategories?
|
||||||
public let searchInitiallyHidden: Bool
|
public let searchInitiallyHidden: Bool
|
||||||
@ -648,6 +649,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
searchState: SearchState,
|
searchState: SearchState,
|
||||||
warpContentsOnEdges: Bool,
|
warpContentsOnEdges: Bool,
|
||||||
hideBackground: Bool,
|
hideBackground: Bool,
|
||||||
|
maskEdge: Bool,
|
||||||
displaySearchWithPlaceholder: String?,
|
displaySearchWithPlaceholder: String?,
|
||||||
searchCategories: EmojiSearchCategories?,
|
searchCategories: EmojiSearchCategories?,
|
||||||
searchInitiallyHidden: Bool,
|
searchInitiallyHidden: Bool,
|
||||||
@ -672,6 +674,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
self.searchState = searchState
|
self.searchState = searchState
|
||||||
self.warpContentsOnEdges = warpContentsOnEdges
|
self.warpContentsOnEdges = warpContentsOnEdges
|
||||||
self.hideBackground = hideBackground
|
self.hideBackground = hideBackground
|
||||||
|
self.maskEdge = maskEdge
|
||||||
self.displaySearchWithPlaceholder = displaySearchWithPlaceholder
|
self.displaySearchWithPlaceholder = displaySearchWithPlaceholder
|
||||||
self.searchCategories = searchCategories
|
self.searchCategories = searchCategories
|
||||||
self.searchInitiallyHidden = searchInitiallyHidden
|
self.searchInitiallyHidden = searchInitiallyHidden
|
||||||
@ -699,6 +702,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
searchState: searchState,
|
searchState: searchState,
|
||||||
warpContentsOnEdges: self.warpContentsOnEdges,
|
warpContentsOnEdges: self.warpContentsOnEdges,
|
||||||
hideBackground: self.hideBackground,
|
hideBackground: self.hideBackground,
|
||||||
|
maskEdge: self.maskEdge,
|
||||||
displaySearchWithPlaceholder: self.displaySearchWithPlaceholder,
|
displaySearchWithPlaceholder: self.displaySearchWithPlaceholder,
|
||||||
searchCategories: self.searchCategories,
|
searchCategories: self.searchCategories,
|
||||||
searchInitiallyHidden: self.searchInitiallyHidden,
|
searchInitiallyHidden: self.searchInitiallyHidden,
|
||||||
@ -727,6 +731,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
searchState: searchState,
|
searchState: searchState,
|
||||||
warpContentsOnEdges: self.warpContentsOnEdges,
|
warpContentsOnEdges: self.warpContentsOnEdges,
|
||||||
hideBackground: self.hideBackground,
|
hideBackground: self.hideBackground,
|
||||||
|
maskEdge: self.maskEdge,
|
||||||
displaySearchWithPlaceholder: self.displaySearchWithPlaceholder,
|
displaySearchWithPlaceholder: self.displaySearchWithPlaceholder,
|
||||||
searchCategories: self.searchCategories,
|
searchCategories: self.searchCategories,
|
||||||
searchInitiallyHidden: self.searchInitiallyHidden,
|
searchInitiallyHidden: self.searchInitiallyHidden,
|
||||||
@ -755,6 +760,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
searchState: searchState,
|
searchState: searchState,
|
||||||
warpContentsOnEdges: self.warpContentsOnEdges,
|
warpContentsOnEdges: self.warpContentsOnEdges,
|
||||||
hideBackground: self.hideBackground,
|
hideBackground: self.hideBackground,
|
||||||
|
maskEdge: self.maskEdge,
|
||||||
displaySearchWithPlaceholder: self.displaySearchWithPlaceholder,
|
displaySearchWithPlaceholder: self.displaySearchWithPlaceholder,
|
||||||
searchCategories: self.searchCategories,
|
searchCategories: self.searchCategories,
|
||||||
searchInitiallyHidden: self.searchInitiallyHidden,
|
searchInitiallyHidden: self.searchInitiallyHidden,
|
||||||
@ -811,6 +817,9 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
if lhs.hideBackground != rhs.hideBackground {
|
if lhs.hideBackground != rhs.hideBackground {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.maskEdge != rhs.maskEdge {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.displaySearchWithPlaceholder != rhs.displaySearchWithPlaceholder {
|
if lhs.displaySearchWithPlaceholder != rhs.displaySearchWithPlaceholder {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -4016,12 +4025,12 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
self.state?.updated(transition: ComponentTransition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(ContentAnimation(type: .groupExpanded(id: groupId))))
|
self.state?.updated(transition: ComponentTransition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(ContentAnimation(type: .groupExpanded(id: groupId))))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func pagerUpdateBackground(backgroundFrame: CGRect, topPanelHeight: CGFloat, transition: ComponentTransition) {
|
public func pagerUpdateBackground(backgroundFrame: CGRect, topPanelHeight: CGFloat, externalTintMaskContainer: UIView?, transition: ComponentTransition) {
|
||||||
guard let component = self.component, let keyboardChildEnvironment = self.keyboardChildEnvironment, let pagerEnvironment = self.pagerEnvironment else {
|
guard let component = self.component, let keyboardChildEnvironment = self.keyboardChildEnvironment, let pagerEnvironment = self.pagerEnvironment else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if let externalBackground = component.inputInteractionHolder.inputInteraction?.externalBackground, let effectContainerView = externalBackground.effectContainerView {
|
if let effectContainerView = externalTintMaskContainer {
|
||||||
let mirrorContentClippingView: UIView
|
let mirrorContentClippingView: UIView
|
||||||
if let current = self.mirrorContentClippingView {
|
if let current = self.mirrorContentClippingView {
|
||||||
mirrorContentClippingView = current
|
mirrorContentClippingView = current
|
||||||
@ -4066,17 +4075,19 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
if component.hideBackground {
|
if component.hideBackground {
|
||||||
self.backgroundView.isHidden = true
|
self.backgroundView.isHidden = true
|
||||||
|
|
||||||
let maskLayer: FadingMaskLayer
|
if component.maskEdge {
|
||||||
if let current = self.fadingMaskLayer {
|
let maskLayer: FadingMaskLayer
|
||||||
maskLayer = current
|
if let current = self.fadingMaskLayer {
|
||||||
} else {
|
maskLayer = current
|
||||||
maskLayer = FadingMaskLayer()
|
} else {
|
||||||
self.fadingMaskLayer = maskLayer
|
maskLayer = FadingMaskLayer()
|
||||||
|
self.fadingMaskLayer = maskLayer
|
||||||
|
}
|
||||||
|
if self.layer.mask == nil {
|
||||||
|
self.layer.mask = maskLayer
|
||||||
|
}
|
||||||
|
maskLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((topPanelHeight - 34.0) * 0.75)), size: backgroundFrame.size)
|
||||||
}
|
}
|
||||||
if self.layer.mask == nil {
|
|
||||||
self.layer.mask = maskLayer
|
|
||||||
}
|
|
||||||
maskLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((topPanelHeight - 34.0) * 0.75)), size: backgroundFrame.size)
|
|
||||||
} else if component.warpContentsOnEdges {
|
} else if component.warpContentsOnEdges {
|
||||||
self.backgroundView.isHidden = true
|
self.backgroundView.isHidden = true
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -65,7 +65,8 @@ public extension EmojiPagerContentComponent {
|
|||||||
hasRecent: Bool = true,
|
hasRecent: Bool = true,
|
||||||
forceHasPremium: Bool = false,
|
forceHasPremium: Bool = false,
|
||||||
premiumIfSavedMessages: Bool = true,
|
premiumIfSavedMessages: Bool = true,
|
||||||
hideBackground: Bool = false
|
hideBackground: Bool = false,
|
||||||
|
maskEdge: Bool = false
|
||||||
) -> Signal<EmojiPagerContentComponent, NoError> {
|
) -> Signal<EmojiPagerContentComponent, NoError> {
|
||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||||
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
||||||
@ -1596,6 +1597,7 @@ public extension EmojiPagerContentComponent {
|
|||||||
searchState: .empty(hasResults: false),
|
searchState: .empty(hasResults: false),
|
||||||
warpContentsOnEdges: warpContentsOnEdges,
|
warpContentsOnEdges: warpContentsOnEdges,
|
||||||
hideBackground: hideBackground,
|
hideBackground: hideBackground,
|
||||||
|
maskEdge: maskEdge,
|
||||||
displaySearchWithPlaceholder: displaySearchWithPlaceholder,
|
displaySearchWithPlaceholder: displaySearchWithPlaceholder,
|
||||||
searchCategories: searchCategories,
|
searchCategories: searchCategories,
|
||||||
searchInitiallyHidden: searchInitiallyHidden,
|
searchInitiallyHidden: searchInitiallyHidden,
|
||||||
@ -1632,7 +1634,8 @@ public extension EmojiPagerContentComponent {
|
|||||||
hasAdd: Bool = false,
|
hasAdd: Bool = false,
|
||||||
searchIsPlaceholderOnly: Bool = true,
|
searchIsPlaceholderOnly: Bool = true,
|
||||||
subject: StickersSubject = .chatStickers,
|
subject: StickersSubject = .chatStickers,
|
||||||
hideBackground: Bool = false
|
hideBackground: Bool = false,
|
||||||
|
maskEdge: Bool = false
|
||||||
) -> Signal<EmojiPagerContentComponent, NoError> {
|
) -> Signal<EmojiPagerContentComponent, NoError> {
|
||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||||
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
||||||
@ -2178,6 +2181,7 @@ public extension EmojiPagerContentComponent {
|
|||||||
searchState: .empty(hasResults: false),
|
searchState: .empty(hasResults: false),
|
||||||
warpContentsOnEdges: warpContentsOnEdges,
|
warpContentsOnEdges: warpContentsOnEdges,
|
||||||
hideBackground: hideBackground,
|
hideBackground: hideBackground,
|
||||||
|
maskEdge: maskEdge,
|
||||||
displaySearchWithPlaceholder: hasSearch ? strings.StickersSearch_SearchStickersPlaceholder : nil,
|
displaySearchWithPlaceholder: hasSearch ? strings.StickersSearch_SearchStickersPlaceholder : nil,
|
||||||
searchCategories: searchCategories,
|
searchCategories: searchCategories,
|
||||||
searchInitiallyHidden: true,
|
searchInitiallyHidden: true,
|
||||||
@ -2197,7 +2201,8 @@ public extension EmojiPagerContentComponent {
|
|||||||
animationCache: AnimationCache,
|
animationCache: AnimationCache,
|
||||||
animationRenderer: MultiAnimationRenderer,
|
animationRenderer: MultiAnimationRenderer,
|
||||||
hasSearch: Bool,
|
hasSearch: Bool,
|
||||||
hideBackground: Bool = false
|
hideBackground: Bool = false,
|
||||||
|
maskEdge: Bool = false
|
||||||
) -> Signal<EmojiPagerContentComponent, NoError> {
|
) -> Signal<EmojiPagerContentComponent, NoError> {
|
||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||||
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
||||||
@ -2330,6 +2335,7 @@ public extension EmojiPagerContentComponent {
|
|||||||
searchState: .empty(hasResults: false),
|
searchState: .empty(hasResults: false),
|
||||||
warpContentsOnEdges: warpContentsOnEdges,
|
warpContentsOnEdges: warpContentsOnEdges,
|
||||||
hideBackground: hideBackground,
|
hideBackground: hideBackground,
|
||||||
|
maskEdge: maskEdge,
|
||||||
displaySearchWithPlaceholder: hasSearch ? strings.StickersSearch_SearchStickersPlaceholder : nil,
|
displaySearchWithPlaceholder: hasSearch ? strings.StickersSearch_SearchStickersPlaceholder : nil,
|
||||||
searchCategories: searchCategories,
|
searchCategories: searchCategories,
|
||||||
searchInitiallyHidden: true,
|
searchInitiallyHidden: true,
|
||||||
|
|||||||
@ -469,6 +469,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
|
|||||||
searchState: .empty(hasResults: false),
|
searchState: .empty(hasResults: false),
|
||||||
warpContentsOnEdges: false,
|
warpContentsOnEdges: false,
|
||||||
hideBackground: false,
|
hideBackground: false,
|
||||||
|
maskEdge: false,
|
||||||
displaySearchWithPlaceholder: self.presentationData.strings.EmojiSearch_SearchEmojiPlaceholder,
|
displaySearchWithPlaceholder: self.presentationData.strings.EmojiSearch_SearchEmojiPlaceholder,
|
||||||
searchCategories: nil,
|
searchCategories: nil,
|
||||||
searchInitiallyHidden: false,
|
searchInitiallyHidden: false,
|
||||||
@ -509,6 +510,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
|
|||||||
defaultToEmojiTab: true,
|
defaultToEmojiTab: true,
|
||||||
externalTopPanelContainer: self.panelHostView,
|
externalTopPanelContainer: self.panelHostView,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
|
externalTintMaskContainer: nil,
|
||||||
displayTopPanelBackground: .blur,
|
displayTopPanelBackground: .blur,
|
||||||
topPanelExtensionUpdated: { _, _ in },
|
topPanelExtensionUpdated: { _, _ in },
|
||||||
topPanelScrollingOffset: { _, _ in },
|
topPanelScrollingOffset: { _, _ in },
|
||||||
|
|||||||
@ -106,6 +106,7 @@ public final class EntityKeyboardComponent: Component {
|
|||||||
public let defaultToEmojiTab: Bool
|
public let defaultToEmojiTab: Bool
|
||||||
public let externalTopPanelContainer: PagerExternalTopPanelContainer?
|
public let externalTopPanelContainer: PagerExternalTopPanelContainer?
|
||||||
public let externalBottomPanelContainer: PagerExternalTopPanelContainer?
|
public let externalBottomPanelContainer: PagerExternalTopPanelContainer?
|
||||||
|
public let externalTintMaskContainer: UIView?
|
||||||
public let displayTopPanelBackground: DisplayTopPanelBackground
|
public let displayTopPanelBackground: DisplayTopPanelBackground
|
||||||
public let topPanelExtensionUpdated: (CGFloat, ComponentTransition) -> Void
|
public let topPanelExtensionUpdated: (CGFloat, ComponentTransition) -> Void
|
||||||
public let topPanelScrollingOffset: (CGFloat, ComponentTransition) -> Void
|
public let topPanelScrollingOffset: (CGFloat, ComponentTransition) -> Void
|
||||||
@ -141,6 +142,7 @@ public final class EntityKeyboardComponent: Component {
|
|||||||
defaultToEmojiTab: Bool,
|
defaultToEmojiTab: Bool,
|
||||||
externalTopPanelContainer: PagerExternalTopPanelContainer?,
|
externalTopPanelContainer: PagerExternalTopPanelContainer?,
|
||||||
externalBottomPanelContainer: PagerExternalTopPanelContainer?,
|
externalBottomPanelContainer: PagerExternalTopPanelContainer?,
|
||||||
|
externalTintMaskContainer: UIView?,
|
||||||
displayTopPanelBackground: DisplayTopPanelBackground,
|
displayTopPanelBackground: DisplayTopPanelBackground,
|
||||||
topPanelExtensionUpdated: @escaping (CGFloat, ComponentTransition) -> Void,
|
topPanelExtensionUpdated: @escaping (CGFloat, ComponentTransition) -> Void,
|
||||||
topPanelScrollingOffset: @escaping (CGFloat, ComponentTransition) -> Void,
|
topPanelScrollingOffset: @escaping (CGFloat, ComponentTransition) -> Void,
|
||||||
@ -175,6 +177,7 @@ public final class EntityKeyboardComponent: Component {
|
|||||||
self.defaultToEmojiTab = defaultToEmojiTab
|
self.defaultToEmojiTab = defaultToEmojiTab
|
||||||
self.externalTopPanelContainer = externalTopPanelContainer
|
self.externalTopPanelContainer = externalTopPanelContainer
|
||||||
self.externalBottomPanelContainer = externalBottomPanelContainer
|
self.externalBottomPanelContainer = externalBottomPanelContainer
|
||||||
|
self.externalTintMaskContainer = externalTintMaskContainer
|
||||||
self.displayTopPanelBackground = displayTopPanelBackground
|
self.displayTopPanelBackground = displayTopPanelBackground
|
||||||
self.topPanelExtensionUpdated = topPanelExtensionUpdated
|
self.topPanelExtensionUpdated = topPanelExtensionUpdated
|
||||||
self.topPanelScrollingOffset = topPanelScrollingOffset
|
self.topPanelScrollingOffset = topPanelScrollingOffset
|
||||||
@ -716,6 +719,12 @@ public final class EntityKeyboardComponent: Component {
|
|||||||
forceUpdate = true
|
forceUpdate = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bottomPanelContainerInsets = component.containerInsets
|
||||||
|
if bottomPanelContainerInsets.left == 0.0 && bottomPanelContainerInsets.bottom != 0.0 {
|
||||||
|
bottomPanelContainerInsets.left += 16.0
|
||||||
|
bottomPanelContainerInsets.right += 16.0
|
||||||
|
}
|
||||||
|
|
||||||
let isContentInFocus = component.isContentInFocus && self.searchComponent == nil
|
let isContentInFocus = component.isContentInFocus && self.searchComponent == nil
|
||||||
let pagerSize = self.pagerView.update(
|
let pagerSize = self.pagerView.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
@ -732,19 +741,20 @@ public final class EntityKeyboardComponent: Component {
|
|||||||
topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent(
|
topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent(
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
overflowHeight: component.hiddenInputHeight,
|
overflowHeight: component.hiddenInputHeight,
|
||||||
topInset: 12.0,
|
topInset: 6.0,
|
||||||
displayBackground: component.externalTopPanelContainer != nil ? .none : component.displayTopPanelBackground
|
displayBackground: component.externalTopPanelContainer != nil ? .none : component.displayTopPanelBackground
|
||||||
)),
|
)),
|
||||||
externalTopPanelContainer: component.externalTopPanelContainer,
|
externalTopPanelContainer: component.externalTopPanelContainer,
|
||||||
bottomPanel: component.displayBottomPanel ? AnyComponent(EntityKeyboardBottomPanelComponent(
|
bottomPanel: component.displayBottomPanel ? AnyComponent(EntityKeyboardBottomPanelComponent(
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
containerInsets: component.containerInsets,
|
containerInsets: bottomPanelContainerInsets,
|
||||||
deleteBackwards: { [weak self] in
|
deleteBackwards: { [weak self] in
|
||||||
self?.component?.emojiContent?.inputInteractionHolder.inputInteraction?.deleteBackwards?()
|
self?.component?.emojiContent?.inputInteractionHolder.inputInteraction?.deleteBackwards?()
|
||||||
AudioServicesPlaySystemSound(0x451)
|
AudioServicesPlaySystemSound(0x451)
|
||||||
}
|
}
|
||||||
)) : nil,
|
)) : nil,
|
||||||
externalBottomPanelContainer: component.externalBottomPanelContainer,
|
externalBottomPanelContainer: component.externalBottomPanelContainer,
|
||||||
|
externalTintMaskContainer: component.externalTintMaskContainer,
|
||||||
panelStateUpdated: { [weak self] panelState, transition in
|
panelStateUpdated: { [weak self] panelState, transition in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -163,7 +163,7 @@ final class EntityKeyboardBottomPanelComponent: Component {
|
|||||||
private var component: EntityKeyboardBottomPanelComponent?
|
private var component: EntityKeyboardBottomPanelComponent?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
self.backgroundView = BlurredBackgroundView(color: .clear, enableBlur: true)
|
self.backgroundView = BlurredBackgroundView(color: .clear, enableBlur: true, customBlurRadius: 5.0)
|
||||||
|
|
||||||
self.separatorView = UIView()
|
self.separatorView = UIView()
|
||||||
self.separatorView.isUserInteractionEnabled = false
|
self.separatorView.isUserInteractionEnabled = false
|
||||||
@ -186,8 +186,8 @@ final class EntityKeyboardBottomPanelComponent: Component {
|
|||||||
|
|
||||||
func update(component: EntityKeyboardBottomPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
|
func update(component: EntityKeyboardBottomPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
|
||||||
if self.component?.theme !== component.theme {
|
if self.component?.theme !== component.theme {
|
||||||
self.separatorView.backgroundColor = component.theme.chat.inputMediaPanel.panelSeparatorColor
|
self.separatorView.backgroundColor = component.theme.chat.inputPanel.panelSeparatorColor
|
||||||
self.backgroundView.updateColor(color: component.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(1.0), transition: .immediate)
|
self.backgroundView.updateColor(color: component.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.65), transition: .immediate)
|
||||||
self.highlightedIconBackgroundView.backgroundColor = component.theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor
|
self.highlightedIconBackgroundView.backgroundColor = component.theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -206,7 +206,8 @@ final class EntityKeyboardTopContainerPanelComponent: Component {
|
|||||||
if let current = self.backgroundView {
|
if let current = self.backgroundView {
|
||||||
backgroundView = current
|
backgroundView = current
|
||||||
} else {
|
} else {
|
||||||
backgroundView = BlurredBackgroundView(color: .clear, enableBlur: true)
|
backgroundView = BlurredBackgroundView(color: .clear, enableBlur: true, customBlurRadius: 5.0)
|
||||||
|
self.backgroundView = backgroundView
|
||||||
self.insertSubview(backgroundView, at: 0)
|
self.insertSubview(backgroundView, at: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,12 +219,12 @@ final class EntityKeyboardTopContainerPanelComponent: Component {
|
|||||||
self.insertSubview(backgroundSeparatorView, aboveSubview: backgroundView)
|
self.insertSubview(backgroundSeparatorView, aboveSubview: backgroundView)
|
||||||
}
|
}
|
||||||
|
|
||||||
backgroundView.updateColor(color: component.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(1.0), transition: .immediate)
|
backgroundView.updateColor(color: component.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.65), transition: .immediate)
|
||||||
backgroundView.update(size: CGSize(width: availableSize.width, height: height), transition: transition.containedViewLayoutTransition)
|
backgroundView.update(size: CGSize(width: availableSize.width, height: height + component.overflowHeight), transition: transition.containedViewLayoutTransition)
|
||||||
transition.setFrame(view: backgroundView, frame: CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: height)))
|
transition.setFrame(view: backgroundView, frame: CGRect(origin: CGPoint(x: 0.0, y: -component.overflowHeight), size: CGSize(width: availableSize.width, height: height + component.overflowHeight)))
|
||||||
|
|
||||||
backgroundSeparatorView.backgroundColor = component.theme.chat.inputPanel.panelSeparatorColor
|
backgroundSeparatorView.backgroundColor = component.theme.chat.inputPanel.panelSeparatorColor
|
||||||
transition.setFrame(view: backgroundSeparatorView, frame: CGRect(origin: CGPoint(x: 0.0, y: height), size: CGSize(width: availableSize.width, height: UIScreenPixel)))
|
transition.setFrame(view: backgroundSeparatorView, frame: CGRect(origin: CGPoint(x: 0.0, y: height - UIScreenPixel), size: CGSize(width: availableSize.width, height: UIScreenPixel)))
|
||||||
} else if case .none = component.displayBackground {
|
} else if case .none = component.displayBackground {
|
||||||
self.backgroundColor = nil
|
self.backgroundColor = nil
|
||||||
|
|
||||||
|
|||||||
@ -876,7 +876,7 @@ public final class GifPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func pagerUpdateBackground(backgroundFrame: CGRect, topPanelHeight: CGFloat, transition: ComponentTransition) {
|
public func pagerUpdateBackground(backgroundFrame: CGRect, topPanelHeight: CGFloat, externalTintMaskContainer: UIView?, transition: ComponentTransition) {
|
||||||
guard let theme = self.theme else {
|
guard let theme = self.theme else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -912,6 +912,8 @@ public final class GifPagerContentComponent: Component {
|
|||||||
transition.setFrame(view: self.backgroundView, frame: backgroundFrame)
|
transition.setFrame(view: self.backgroundView, frame: backgroundFrame)
|
||||||
self.backgroundView.update(size: backgroundFrame.size, transition: transition.containedViewLayoutTransition)
|
self.backgroundView.update(size: backgroundFrame.size, transition: transition.containedViewLayoutTransition)
|
||||||
|
|
||||||
|
self.backgroundView.isHidden = hideBackground
|
||||||
|
|
||||||
if let vibrancyEffectView = self.vibrancyEffectView {
|
if let vibrancyEffectView = self.vibrancyEffectView {
|
||||||
transition.setFrame(view: vibrancyEffectView, frame: CGRect(origin: CGPoint(x: 0.0, y: -backgroundFrame.minY), size: CGSize(width: backgroundFrame.width, height: backgroundFrame.height + backgroundFrame.minY)))
|
transition.setFrame(view: vibrancyEffectView, frame: CGRect(origin: CGPoint(x: 0.0, y: -backgroundFrame.minY), size: CGSize(width: backgroundFrame.width, height: backgroundFrame.height + backgroundFrame.minY)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -350,6 +350,7 @@ private final class TopicIconSelectionComponent: Component {
|
|||||||
defaultToEmojiTab: true,
|
defaultToEmojiTab: true,
|
||||||
externalTopPanelContainer: self.panelHostView,
|
externalTopPanelContainer: self.panelHostView,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
|
externalTintMaskContainer: nil,
|
||||||
displayTopPanelBackground: .blur,
|
displayTopPanelBackground: .blur,
|
||||||
topPanelExtensionUpdated: { _, _ in },
|
topPanelExtensionUpdated: { _, _ in },
|
||||||
topPanelScrollingOffset: { _, _ in },
|
topPanelScrollingOffset: { _, _ in },
|
||||||
|
|||||||
@ -4,86 +4,6 @@ import Display
|
|||||||
import ComponentFlow
|
import ComponentFlow
|
||||||
import ComponentDisplayAdapters
|
import ComponentDisplayAdapters
|
||||||
|
|
||||||
private func generateForegroundImage(size: CGSize, isDark: Bool, fillColor: UIColor) -> UIImage {
|
|
||||||
var size = size
|
|
||||||
if size == .zero {
|
|
||||||
size = CGSize(width: 1.0, height: 1.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return generateImage(size, rotatedContext: { size, context in
|
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
let maxColor = UIColor(white: 1.0, alpha: isDark ? 0.67 : 0.9)
|
|
||||||
let minColor = UIColor(white: 1.0, alpha: 0.0)
|
|
||||||
|
|
||||||
context.setFillColor(fillColor.cgColor)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
let lineWidth: CGFloat = isDark ? 0.66 : 0.66
|
|
||||||
|
|
||||||
context.saveGState()
|
|
||||||
|
|
||||||
let darkShadeColor = UIColor(white: isDark ? 1.0 : 0.0, alpha: 0.035)
|
|
||||||
let lightShadeColor = UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.035)
|
|
||||||
let innerShadowBlur: CGFloat = 24.0
|
|
||||||
|
|
||||||
context.resetClip()
|
|
||||||
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
|
||||||
context.clip()
|
|
||||||
context.addRect(CGRect(origin: CGPoint(), size: size).insetBy(dx: -100.0, dy: -100.0))
|
|
||||||
context.addEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
context.setFillColor(UIColor.black.cgColor)
|
|
||||||
context.setShadow(offset: CGSize(width: 10.0, height: -10.0), blur: innerShadowBlur, color: darkShadeColor.cgColor)
|
|
||||||
context.fillPath(using: .evenOdd)
|
|
||||||
|
|
||||||
context.resetClip()
|
|
||||||
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
|
||||||
context.clip()
|
|
||||||
context.addRect(CGRect(origin: CGPoint(), size: size).insetBy(dx: -100.0, dy: -100.0))
|
|
||||||
context.addEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
context.setFillColor(UIColor.black.cgColor)
|
|
||||||
context.setShadow(offset: CGSize(width: -10.0, height: 10.0), blur: innerShadowBlur, color: lightShadeColor.cgColor)
|
|
||||||
context.fillPath(using: .evenOdd)
|
|
||||||
|
|
||||||
context.restoreGState()
|
|
||||||
|
|
||||||
context.setLineWidth(lineWidth)
|
|
||||||
|
|
||||||
context.addRect(CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width * 0.5, height: size.height)))
|
|
||||||
context.clip()
|
|
||||||
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
|
||||||
context.replacePathWithStrokedPath()
|
|
||||||
context.clip()
|
|
||||||
|
|
||||||
do {
|
|
||||||
var locations: [CGFloat] = [0.0, 0.5, 0.5 + 0.2, 1.0 - 0.1, 1.0]
|
|
||||||
let colors: [CGColor] = [maxColor.cgColor, maxColor.cgColor, minColor.cgColor, minColor.cgColor, maxColor.cgColor]
|
|
||||||
|
|
||||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
|
||||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
|
|
||||||
|
|
||||||
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
|
||||||
}
|
|
||||||
|
|
||||||
context.resetClip()
|
|
||||||
context.addRect(CGRect(origin: CGPoint(x: size.width - size.width * 0.5, y: 0.0), size: CGSize(width: size.width * 0.5, height: size.height)))
|
|
||||||
context.clip()
|
|
||||||
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
|
||||||
context.replacePathWithStrokedPath()
|
|
||||||
context.clip()
|
|
||||||
|
|
||||||
do {
|
|
||||||
var locations: [CGFloat] = [0.0, 0.1, 0.5 - 0.2, 0.5, 1.0]
|
|
||||||
let colors: [CGColor] = [maxColor.cgColor, minColor.cgColor, minColor.cgColor, maxColor.cgColor, maxColor.cgColor]
|
|
||||||
|
|
||||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
|
||||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
|
|
||||||
|
|
||||||
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
|
||||||
}
|
|
||||||
})!.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5))
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class ContentContainer: UIView {
|
private final class ContentContainer: UIView {
|
||||||
private let maskContentView: UIView
|
private let maskContentView: UIView
|
||||||
|
|
||||||
@ -345,7 +265,6 @@ public final class GlassBackgroundView: UIView {
|
|||||||
|
|
||||||
private let foregroundView: UIImageView?
|
private let foregroundView: UIImageView?
|
||||||
private let shadowView: UIImageView?
|
private let shadowView: UIImageView?
|
||||||
private let shadowMaskView: UIImageView?
|
|
||||||
|
|
||||||
public let maskContentView: UIView
|
public let maskContentView: UIView
|
||||||
private let contentContainer: ContentContainer
|
private let contentContainer: ContentContainer
|
||||||
@ -371,14 +290,12 @@ public final class GlassBackgroundView: UIView {
|
|||||||
nativeView.traitOverrides.userInterfaceStyle = .light
|
nativeView.traitOverrides.userInterfaceStyle = .light
|
||||||
//self.foregroundView = UIImageView()
|
//self.foregroundView = UIImageView()
|
||||||
self.foregroundView = nil
|
self.foregroundView = nil
|
||||||
self.shadowView = nil
|
self.shadowView = UIImageView()
|
||||||
self.shadowMaskView = nil
|
|
||||||
} else {
|
} else {
|
||||||
self.backgroundNode = NavigationBackgroundNode(color: .black, enableBlur: true, customBlurRadius: 5.0)
|
self.backgroundNode = NavigationBackgroundNode(color: .black, enableBlur: true, customBlurRadius: 5.0)
|
||||||
self.nativeView = nil
|
self.nativeView = nil
|
||||||
self.foregroundView = UIImageView()
|
self.foregroundView = UIImageView()
|
||||||
self.shadowView = UIImageView()
|
self.shadowView = UIImageView()
|
||||||
self.shadowMaskView = UIImageView()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.maskContentView = UIView()
|
self.maskContentView = UIView()
|
||||||
@ -393,9 +310,6 @@ public final class GlassBackgroundView: UIView {
|
|||||||
|
|
||||||
if let shadowView = self.shadowView {
|
if let shadowView = self.shadowView {
|
||||||
self.addSubview(shadowView)
|
self.addSubview(shadowView)
|
||||||
if let shadowMaskView = self.shadowMaskView {
|
|
||||||
shadowView.mask = shadowMaskView
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let nativeView = self.nativeView {
|
if let nativeView = self.nativeView {
|
||||||
self.addSubview(nativeView)
|
self.addSubview(nativeView)
|
||||||
@ -435,39 +349,36 @@ public final class GlassBackgroundView: UIView {
|
|||||||
transition.setFrame(view: backgroundNode.view, frame: CGRect(origin: CGPoint(), size: size))
|
transition.setFrame(view: backgroundNode.view, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let shadowInset: CGFloat = 32.0
|
||||||
|
|
||||||
let params = Params(cornerRadius: cornerRadius, isDark: isDark, tintColor: tintColor)
|
let params = Params(cornerRadius: cornerRadius, isDark: isDark, tintColor: tintColor)
|
||||||
if self.params != params {
|
if self.params != params {
|
||||||
self.params = params
|
self.params = params
|
||||||
|
|
||||||
if let shadowView = self.shadowView {
|
if let shadowView = self.shadowView {
|
||||||
shadowView.layer.shadowRadius = 10.0
|
let shadowInnerInset: CGFloat = 0.5
|
||||||
shadowView.layer.shadowColor = UIColor(white: 0.0, alpha: 1.0).cgColor
|
shadowView.image = generateImage(CGSize(width: shadowInset * 2.0 + cornerRadius * 2.0, height: shadowInset * 2.0 + cornerRadius * 2.0), rotatedContext: { size, context in
|
||||||
shadowView.layer.shadowOpacity = 0.08
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
shadowView.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
|
|
||||||
|
context.setFillColor(UIColor.black.cgColor)
|
||||||
if let shadowMaskView = self.shadowMaskView {
|
context.setShadow(offset: CGSize(width: 0.0, height: 1.0), blur: 30.0, color: UIColor(white: 0.0, alpha: 0.08).cgColor)
|
||||||
let shadowInset: CGFloat = 32.0
|
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowInset + shadowInnerInset, y: shadowInset + shadowInnerInset), size: CGSize(width: size.width - shadowInset * 2.0 - shadowInnerInset * 2.0, height: size.height - shadowInset * 2.0 - shadowInnerInset * 2.0)))
|
||||||
let shadowInnerInset: CGFloat = 0.5
|
|
||||||
shadowMaskView.image = generateImage(CGSize(width: shadowInset * 2.0 + cornerRadius * 2.0, height: shadowInset * 2.0 + cornerRadius * 2.0), rotatedContext: { size, context in
|
context.setFillColor(UIColor.clear.cgColor)
|
||||||
context.setFillColor(UIColor.white.cgColor)
|
context.setBlendMode(.copy)
|
||||||
context.fill(CGRect(origin: CGPoint(), size: size))
|
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowInset + shadowInnerInset, y: shadowInset + shadowInnerInset), size: CGSize(width: size.width - shadowInset * 2.0 - shadowInnerInset * 2.0, height: size.height - shadowInset * 2.0 - shadowInnerInset * 2.0)))
|
||||||
|
})?.stretchableImage(withLeftCapWidth: Int(shadowInset + cornerRadius), topCapHeight: Int(shadowInset + cornerRadius))
|
||||||
context.setFillColor(UIColor.clear.cgColor)
|
|
||||||
context.setBlendMode(.copy)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowInset + shadowInnerInset, y: shadowInset + shadowInnerInset), size: CGSize(width: size.width - shadowInset * 2.0 - shadowInnerInset * 2.0, height: size.height - shadowInset * 2.0 - shadowInnerInset * 2.0)))
|
|
||||||
})?.stretchableImage(withLeftCapWidth: Int(shadowInset + cornerRadius), topCapHeight: Int(shadowInset + cornerRadius))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let foregroundView = self.foregroundView {
|
if let foregroundView = self.foregroundView {
|
||||||
foregroundView.image = generateForegroundImage(size: CGSize(width: cornerRadius * 2.0, height: cornerRadius * 2.0), isDark: isDark, fillColor: tintColor.color)
|
foregroundView.image = GlassBackgroundView.generateForegroundImage(size: CGSize(width: cornerRadius * 2.0, height: cornerRadius * 2.0), isDark: isDark, fillColor: tintColor.color)
|
||||||
} else {
|
} else {
|
||||||
if let nativeView {
|
if let nativeView {
|
||||||
if #available(iOS 26.0, *) {
|
if #available(iOS 26.0, *) {
|
||||||
let glassEffect = UIGlassEffect(style: .regular)
|
let glassEffect = UIGlassEffect(style: .clear)
|
||||||
switch tintColor.kind {
|
switch tintColor.kind {
|
||||||
case .panel:
|
case .panel:
|
||||||
glassEffect.tintColor = nil
|
glassEffect.tintColor = tintColor.color
|
||||||
case .custom:
|
case .custom:
|
||||||
glassEffect.tintColor = tintColor.color
|
glassEffect.tintColor = tintColor.color
|
||||||
}
|
}
|
||||||
@ -484,14 +395,7 @@ public final class GlassBackgroundView: UIView {
|
|||||||
transition.setFrame(view: foregroundView, frame: CGRect(origin: CGPoint(), size: size))
|
transition.setFrame(view: foregroundView, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
}
|
}
|
||||||
if let shadowView = self.shadowView {
|
if let shadowView = self.shadowView {
|
||||||
if shadowView.bounds.size != size {
|
transition.setFrame(view: shadowView, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: -shadowInset, dy: -shadowInset))
|
||||||
shadowView.layer.shadowPath = UIBezierPath(roundedRect: CGRect(origin: CGPoint(), size: size), cornerRadius: size.height * 0.5).cgPath
|
|
||||||
}
|
|
||||||
transition.setFrame(view: shadowView, frame: CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
if let shadowMaskView = self.shadowMaskView {
|
|
||||||
transition.setFrame(view: shadowMaskView, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: -32.0, dy: -32.0))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
transition.setFrame(view: self.contentContainer, frame: CGRect(origin: CGPoint(), size: size))
|
transition.setFrame(view: self.contentContainer, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
}
|
}
|
||||||
@ -585,3 +489,85 @@ public final class VariableBlurView: UIVisualEffectView {
|
|||||||
backdropLayer?.filters = [variableBlur]
|
backdropLayer?.filters = [variableBlur]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public extension GlassBackgroundView {
|
||||||
|
static func generateForegroundImage(size: CGSize, isDark: Bool, fillColor: UIColor) -> UIImage {
|
||||||
|
var size = size
|
||||||
|
if size == .zero {
|
||||||
|
size = CGSize(width: 1.0, height: 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateImage(size, rotatedContext: { size, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
let maxColor = UIColor(white: 1.0, alpha: isDark ? 0.25 : 0.9)
|
||||||
|
let minColor = UIColor(white: 1.0, alpha: 0.0)
|
||||||
|
|
||||||
|
context.setFillColor(fillColor.cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
let lineWidth: CGFloat = isDark ? 0.66 : 0.66
|
||||||
|
|
||||||
|
context.saveGState()
|
||||||
|
|
||||||
|
let darkShadeColor = UIColor(white: isDark ? 1.0 : 0.0, alpha: 0.035)
|
||||||
|
let lightShadeColor = UIColor(white: isDark ? 0.0 : 1.0, alpha: 0.035)
|
||||||
|
let innerShadowBlur: CGFloat = 24.0
|
||||||
|
|
||||||
|
context.resetClip()
|
||||||
|
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
||||||
|
context.clip()
|
||||||
|
context.addRect(CGRect(origin: CGPoint(), size: size).insetBy(dx: -100.0, dy: -100.0))
|
||||||
|
context.addEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
context.setFillColor(UIColor.black.cgColor)
|
||||||
|
context.setShadow(offset: CGSize(width: 10.0, height: -10.0), blur: innerShadowBlur, color: darkShadeColor.cgColor)
|
||||||
|
context.fillPath(using: .evenOdd)
|
||||||
|
|
||||||
|
context.resetClip()
|
||||||
|
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
||||||
|
context.clip()
|
||||||
|
context.addRect(CGRect(origin: CGPoint(), size: size).insetBy(dx: -100.0, dy: -100.0))
|
||||||
|
context.addEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
context.setFillColor(UIColor.black.cgColor)
|
||||||
|
context.setShadow(offset: CGSize(width: -10.0, height: 10.0), blur: innerShadowBlur, color: lightShadeColor.cgColor)
|
||||||
|
context.fillPath(using: .evenOdd)
|
||||||
|
|
||||||
|
context.restoreGState()
|
||||||
|
|
||||||
|
context.setLineWidth(lineWidth)
|
||||||
|
|
||||||
|
context.addRect(CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width * 0.5, height: size.height)))
|
||||||
|
context.clip()
|
||||||
|
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
||||||
|
context.replacePathWithStrokedPath()
|
||||||
|
context.clip()
|
||||||
|
|
||||||
|
do {
|
||||||
|
var locations: [CGFloat] = [0.0, 0.5, 0.5 + 0.2, 1.0 - 0.1, 1.0]
|
||||||
|
let colors: [CGColor] = [maxColor.cgColor, maxColor.cgColor, minColor.cgColor, minColor.cgColor, maxColor.cgColor]
|
||||||
|
|
||||||
|
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||||
|
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
|
||||||
|
|
||||||
|
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
||||||
|
}
|
||||||
|
|
||||||
|
context.resetClip()
|
||||||
|
context.addRect(CGRect(origin: CGPoint(x: size.width - size.width * 0.5, y: 0.0), size: CGSize(width: size.width * 0.5, height: size.height)))
|
||||||
|
context.clip()
|
||||||
|
context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
||||||
|
context.replacePathWithStrokedPath()
|
||||||
|
context.clip()
|
||||||
|
|
||||||
|
do {
|
||||||
|
var locations: [CGFloat] = [0.0, 0.1, 0.5 - 0.2, 0.5, 1.0]
|
||||||
|
let colors: [CGColor] = [maxColor.cgColor, minColor.cgColor, minColor.cgColor, maxColor.cgColor, maxColor.cgColor]
|
||||||
|
|
||||||
|
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||||
|
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
|
||||||
|
|
||||||
|
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
||||||
|
}
|
||||||
|
})!.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -407,6 +407,7 @@ final class MediaEditorScreenComponent: Component {
|
|||||||
areCustomEmojiEnabled: true,
|
areCustomEmojiEnabled: true,
|
||||||
hasSearch: true,
|
hasSearch: true,
|
||||||
hideBackground: true,
|
hideBackground: true,
|
||||||
|
maskEdge: true,
|
||||||
sendGif: nil
|
sendGif: nil
|
||||||
) |> map { inputData -> ChatEntityKeyboardInputNode.InputData in
|
) |> map { inputData -> ChatEntityKeyboardInputNode.InputData in
|
||||||
return ChatEntityKeyboardInputNode.InputData(
|
return ChatEntityKeyboardInputNode.InputData(
|
||||||
|
|||||||
@ -257,6 +257,7 @@ public final class EmojiSelectionComponent: Component {
|
|||||||
defaultToEmojiTab: true,
|
defaultToEmojiTab: true,
|
||||||
externalTopPanelContainer: self.panelHostView,
|
externalTopPanelContainer: self.panelHostView,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
|
externalTintMaskContainer: nil,
|
||||||
displayTopPanelBackground: .blur,
|
displayTopPanelBackground: .blur,
|
||||||
topPanelExtensionUpdated: { _, _ in },
|
topPanelExtensionUpdated: { _, _ in },
|
||||||
topPanelScrollingOffset: { _, _ in },
|
topPanelScrollingOffset: { _, _ in },
|
||||||
|
|||||||
@ -335,6 +335,7 @@ private final class EmojiSelectionComponent: Component {
|
|||||||
defaultToEmojiTab: true,
|
defaultToEmojiTab: true,
|
||||||
externalTopPanelContainer: self.panelHostView,
|
externalTopPanelContainer: self.panelHostView,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
|
externalTintMaskContainer: nil,
|
||||||
displayTopPanelBackground: .blur,
|
displayTopPanelBackground: .blur,
|
||||||
topPanelExtensionUpdated: { _, _ in },
|
topPanelExtensionUpdated: { _, _ in },
|
||||||
topPanelScrollingOffset: { _, _ in },
|
topPanelScrollingOffset: { _, _ in },
|
||||||
|
|||||||
@ -283,6 +283,7 @@ private final class StickerSelectionComponent: Component {
|
|||||||
defaultToEmojiTab: defaultToEmoji,
|
defaultToEmojiTab: defaultToEmoji,
|
||||||
externalTopPanelContainer: self.panelHostView,
|
externalTopPanelContainer: self.panelHostView,
|
||||||
externalBottomPanelContainer: nil,
|
externalBottomPanelContainer: nil,
|
||||||
|
externalTintMaskContainer: nil,
|
||||||
displayTopPanelBackground: .blur,
|
displayTopPanelBackground: .blur,
|
||||||
topPanelExtensionUpdated: { _, _ in
|
topPanelExtensionUpdated: { _, _ in
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1768,9 +1768,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
if let inputNode = inputNode as? ChatEntityKeyboardInputNode {
|
if let inputNode = inputNode as? ChatEntityKeyboardInputNode {
|
||||||
inputNode.externalTopPanelContainerImpl = nil
|
inputNode.externalTopPanelContainerImpl = nil
|
||||||
}
|
}
|
||||||
inputNode.clipsToBounds = true
|
|
||||||
inputNode.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
|
||||||
inputNode.layer.cornerRadius = 30.0
|
|
||||||
|
|
||||||
dismissedInputNode = self.inputNode
|
dismissedInputNode = self.inputNode
|
||||||
dismissedInputNodeExternalTopPanelContainer = self.inputNode?.externalTopPanelContainer
|
dismissedInputNodeExternalTopPanelContainer = self.inputNode?.externalTopPanelContainer
|
||||||
@ -2158,11 +2155,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
if self.dismissedAsOverlay {
|
if self.dismissedAsOverlay {
|
||||||
inputPanelFrame!.origin.y = layout.size.height
|
inputPanelFrame!.origin.y = layout.size.height
|
||||||
}
|
}
|
||||||
if let inputNode = self.inputNode, inputNode.hideInput, !inputNode.adjustLayoutForHiddenInput {
|
inputPanelsHeight += inputPanelSize!.height
|
||||||
inputPanelsHeight += inputPanelNodeBaseHeight
|
|
||||||
} else {
|
|
||||||
inputPanelsHeight += inputPanelSize!.height
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.secondaryInputPanelNode != nil {
|
if self.secondaryInputPanelNode != nil {
|
||||||
@ -3942,6 +3935,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
chatPeerId: self.chatLocation.peerId,
|
chatPeerId: self.chatLocation.peerId,
|
||||||
areCustomEmojiEnabled: self.chatPresentationInterfaceState.customEmojiAvailable,
|
areCustomEmojiEnabled: self.chatPresentationInterfaceState.customEmojiAvailable,
|
||||||
hasEdit: true,
|
hasEdit: true,
|
||||||
|
hideBackground: true,
|
||||||
sendGif: { [weak self] fileReference, sourceView, sourceRect, silentPosting, schedule in
|
sendGif: { [weak self] fileReference, sourceView, sourceRect, silentPosting, schedule in
|
||||||
if let self {
|
if let self {
|
||||||
return self.controllerInteraction.sendGif(fileReference, sourceView, sourceRect, silentPosting, schedule)
|
return self.controllerInteraction.sendGif(fileReference, sourceView, sourceRect, silentPosting, schedule)
|
||||||
@ -4235,15 +4229,20 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var maybeDismissOverlayContent = true
|
var maybeDismissOverlayContent = true
|
||||||
if let inputNode = self.inputNode, inputNode.bounds.contains(self.view.convert(point, to: inputNode.view)) {
|
if let inputNode = self.inputNode {
|
||||||
if let externalTopPanelContainer = inputNode.externalTopPanelContainer {
|
if let result = inputNode.view.hitTest(self.view.convert(point, to: inputNode.view), with: event) {
|
||||||
if externalTopPanelContainer.hitTest(self.view.convert(point, to: externalTopPanelContainer), with: nil) != nil {
|
return result
|
||||||
maybeDismissOverlayContent = true
|
}
|
||||||
|
if inputNode.bounds.contains(self.view.convert(point, to: inputNode.view)) {
|
||||||
|
if let externalTopPanelContainer = inputNode.externalTopPanelContainer {
|
||||||
|
if externalTopPanelContainer.hitTest(self.view.convert(point, to: externalTopPanelContainer), with: nil) != nil {
|
||||||
|
maybeDismissOverlayContent = true
|
||||||
|
} else {
|
||||||
|
maybeDismissOverlayContent = false
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
maybeDismissOverlayContent = false
|
maybeDismissOverlayContent = false
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
maybeDismissOverlayContent = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,7 @@ class ChatHistoryNavigationButtonNode: ContextControllerSourceNode {
|
|||||||
|
|
||||||
self.buttonNode.view.addSubview(self.backgroundView)
|
self.buttonNode.view.addSubview(self.backgroundView)
|
||||||
self.backgroundView.frame = CGRect(origin: CGPoint(), size: size)
|
self.backgroundView.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
self.backgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)), transition: .immediate)
|
self.backgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: .immediate)
|
||||||
self.imageView.tintColor = theme.chat.inputPanel.inputControlColor
|
self.imageView.tintColor = theme.chat.inputPanel.inputControlColor
|
||||||
|
|
||||||
self.backgroundView.contentView.addSubview(self.imageView)
|
self.backgroundView.contentView.addSubview(self.imageView)
|
||||||
@ -110,7 +110,7 @@ class ChatHistoryNavigationButtonNode: ContextControllerSourceNode {
|
|||||||
if self.theme !== theme {
|
if self.theme !== theme {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
|
||||||
self.backgroundView.update(size: self.backgroundView.bounds.size, cornerRadius: self.backgroundView.bounds.size.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.65)), transition: .immediate)
|
self.backgroundView.update(size: self.backgroundView.bounds.size, cornerRadius: self.backgroundView.bounds.size.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: .immediate)
|
||||||
self.imageView.tintColor = theme.chat.inputPanel.inputControlColor
|
self.imageView.tintColor = theme.chat.inputPanel.inputControlColor
|
||||||
|
|
||||||
switch self.type {
|
switch self.type {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user