mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-06-03 08:38:04 +02:00
feat: новые функции, исправлены критические ошибки сборки и баги интерфейса, больше подписей в файлах
This commit is contained in:
@@ -27,7 +27,6 @@ import MediaEditor
|
||||
import AvatarBackground
|
||||
import LottieComponent
|
||||
import UndoUI
|
||||
import PremiumAlertController
|
||||
|
||||
public struct AvatarKeyboardInputData: Equatable {
|
||||
var emoji: EmojiPagerContentComponent
|
||||
|
||||
+33
@@ -481,6 +481,10 @@ private func mapVisibility(_ visibility: ListViewItemNodeVisibility, boundsSize:
|
||||
}
|
||||
}
|
||||
|
||||
private func isDeletedBubbleMessage(_ message: Message) -> Bool {
|
||||
return AntiDeleteManager.shared.isMessageDeleted(peerId: message.id.peerId.toInt64(), messageId: message.id.id) || AntiDeleteManager.shared.isMessageDeleted(text: message.text)
|
||||
}
|
||||
|
||||
public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode {
|
||||
public class ContentContainer {
|
||||
public let contentMessageStableId: UInt32
|
||||
@@ -4368,6 +4372,14 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
}
|
||||
}
|
||||
|
||||
let deletedMessageAlpha = CGFloat(AntiDeleteManager.shared.deletedMessageDisplayAlpha)
|
||||
var deletedMessageStableIds = Set<UInt32>()
|
||||
for (message, _) in item.content {
|
||||
if isDeletedBubbleMessage(message) {
|
||||
deletedMessageStableIds.insert(message.stableId)
|
||||
}
|
||||
}
|
||||
|
||||
var incomingOffset: CGFloat = 0.0
|
||||
switch backgroundType {
|
||||
case .incoming:
|
||||
@@ -4512,10 +4524,31 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
}
|
||||
|
||||
contentContainer?.update(size: relativeFrame.size, contentOrigin: contentOrigin, selectionInsets: selectionInsets, index: index, presentationData: item.presentationData, graphics: graphics, backgroundType: backgroundType, presentationContext: item.controllerInteraction.presentationContext, mediaBox: item.context.account.postbox.mediaBox, messageSelection: itemSelection)
|
||||
|
||||
if let contentContainer = contentContainer {
|
||||
let containerAlpha: CGFloat = deletedMessageStableIds.contains(stableId) ? deletedMessageAlpha : 1.0
|
||||
if case .System = animation {
|
||||
animation.animator.updateAlpha(layer: contentContainer.sourceNode.contentNode.layer, alpha: containerAlpha, completion: nil)
|
||||
} else {
|
||||
contentContainer.sourceNode.contentNode.alpha = containerAlpha
|
||||
}
|
||||
}
|
||||
|
||||
index += 1
|
||||
}
|
||||
|
||||
let mainContainerAlpha: CGFloat
|
||||
if contentContainerNodeFrames.isEmpty, !deletedMessageStableIds.isEmpty {
|
||||
mainContainerAlpha = deletedMessageAlpha
|
||||
} else {
|
||||
mainContainerAlpha = 1.0
|
||||
}
|
||||
if case .System = animation {
|
||||
animation.animator.updateAlpha(layer: strongSelf.mainContextSourceNode.contentNode.layer, alpha: mainContainerAlpha, completion: nil)
|
||||
} else {
|
||||
strongSelf.mainContextSourceNode.contentNode.alpha = mainContainerAlpha
|
||||
}
|
||||
|
||||
if hasSelection {
|
||||
var currentMaskView: UIImageView?
|
||||
if let maskView = strongSelf.contentContainersWrapperNode.view.mask as? UIImageView {
|
||||
|
||||
+139
-16
@@ -29,6 +29,27 @@ public final class NavigationButtonComponent: Component {
|
||||
case more
|
||||
case icon(imageName: String)
|
||||
case proxy(status: ChatTitleProxyStatus)
|
||||
/// Liquid glass avatar button for account switching.
|
||||
/// peerId is used as a diff key; avatarImage is the rendered avatar.
|
||||
case avatar(peerId: String, avatarImage: UIImage?)
|
||||
|
||||
public static func ==(lhs: Content, rhs: Content) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (.text(lt, lb), .text(rt, rb)):
|
||||
return lt == rt && lb == rb
|
||||
case (.more, .more):
|
||||
return true
|
||||
case let (.icon(l), .icon(r)):
|
||||
return l == r
|
||||
case let (.proxy(l), .proxy(r)):
|
||||
return l == r
|
||||
case let (.avatar(lId, _), .avatar(rId, _)):
|
||||
// Re-render when peerId changes; image updates are handled by the view itself
|
||||
return lId == rId
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public let content: Content
|
||||
@@ -62,6 +83,12 @@ public final class NavigationButtonComponent: Component {
|
||||
|
||||
private var moreButton: MoreHeaderButton?
|
||||
|
||||
// MARK: - Liquid Glass Avatar
|
||||
private var avatarContainerView: UIView?
|
||||
private var avatarBlurView: UIVisualEffectView?
|
||||
private var avatarImageView: UIImageView?
|
||||
private var avatarBorderLayer: CAShapeLayer?
|
||||
|
||||
private var component: NavigationButtonComponent?
|
||||
private var theme: PresentationTheme?
|
||||
|
||||
@@ -74,19 +101,23 @@ public final class NavigationButtonComponent: Component {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if highlighted {
|
||||
self.textView?.alpha = 0.6
|
||||
self.proxyNode?.alpha = 0.6
|
||||
self.iconView?.alpha = 0.6
|
||||
} else {
|
||||
self.textView?.alpha = 1.0
|
||||
self.textView?.layer.animateAlpha(from: 0.6, to: 1.0, duration: 0.2)
|
||||
|
||||
self.proxyNode?.alpha = 1.0
|
||||
self.proxyNode?.layer.animateAlpha(from: 0.6, to: 1.0, duration: 0.2)
|
||||
|
||||
self.iconView?.alpha = 1.0
|
||||
self.iconView?.layer.animateAlpha(from: 0.6, to: 1.0, duration: 0.2)
|
||||
let alpha: CGFloat = highlighted ? 0.55 : 1.0
|
||||
self.textView?.alpha = alpha
|
||||
self.proxyNode?.alpha = alpha
|
||||
self.iconView?.alpha = alpha
|
||||
self.avatarContainerView?.alpha = alpha
|
||||
if !highlighted {
|
||||
let animateAlpha = { (layer: CALayer?) in
|
||||
let anim = CABasicAnimation(keyPath: "opacity")
|
||||
anim.fromValue = 0.55
|
||||
anim.toValue = 1.0
|
||||
anim.duration = 0.2
|
||||
layer?.add(anim, forKey: "opacity")
|
||||
}
|
||||
animateAlpha(self.textView?.layer)
|
||||
animateAlpha(self.proxyNode?.layer)
|
||||
animateAlpha(self.iconView?.layer)
|
||||
animateAlpha(self.avatarContainerView?.layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,6 +130,51 @@ public final class NavigationButtonComponent: Component {
|
||||
self.component?.pressed(self)
|
||||
}
|
||||
|
||||
// MARK: - Liquid glass avatar setup
|
||||
|
||||
private func setupAvatarViewsIfNeeded() {
|
||||
guard avatarContainerView == nil else { return }
|
||||
|
||||
// Container holds blur + image
|
||||
let container = UIView()
|
||||
container.isUserInteractionEnabled = false
|
||||
container.clipsToBounds = true
|
||||
|
||||
// Blur background — liquid glass effect
|
||||
let blurEffect = UIBlurEffect(style: .systemUltraThinMaterial)
|
||||
let blurView = UIVisualEffectView(effect: blurEffect)
|
||||
blurView.isUserInteractionEnabled = false
|
||||
container.addSubview(blurView)
|
||||
|
||||
// Avatar image on top of blur
|
||||
let imageView = UIImageView()
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
imageView.isUserInteractionEnabled = false
|
||||
imageView.clipsToBounds = true
|
||||
container.addSubview(imageView)
|
||||
|
||||
self.addSubview(container)
|
||||
self.avatarContainerView = container
|
||||
self.avatarBlurView = blurView
|
||||
self.avatarImageView = imageView
|
||||
|
||||
// Subtle glass ring border
|
||||
let borderLayer = CAShapeLayer()
|
||||
borderLayer.fillColor = UIColor.clear.cgColor
|
||||
borderLayer.strokeColor = UIColor.white.withAlphaComponent(0.22).cgColor
|
||||
borderLayer.lineWidth = 1.5
|
||||
container.layer.addSublayer(borderLayer)
|
||||
self.avatarBorderLayer = borderLayer
|
||||
}
|
||||
|
||||
private func removeAvatarViews() {
|
||||
avatarContainerView?.removeFromSuperview()
|
||||
avatarContainerView = nil
|
||||
avatarBlurView = nil
|
||||
avatarImageView = nil
|
||||
avatarBorderLayer = nil
|
||||
}
|
||||
|
||||
func update(component: NavigationButtonComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<NavigationButtonComponentEnvironment>, transition: ComponentTransition) -> CGSize {
|
||||
self.component = component
|
||||
|
||||
@@ -113,6 +189,7 @@ public final class NavigationButtonComponent: Component {
|
||||
var imageName: String?
|
||||
var proxyStatus: ChatTitleProxyStatus?
|
||||
var isMore: Bool = false
|
||||
var avatarContent: (peerId: String, image: UIImage?)? = nil
|
||||
|
||||
switch component.content {
|
||||
case let .text(title, isBold):
|
||||
@@ -123,10 +200,13 @@ public final class NavigationButtonComponent: Component {
|
||||
imageName = imageNameValue
|
||||
case let .proxy(status):
|
||||
proxyStatus = status
|
||||
case let .avatar(peerId, image):
|
||||
avatarContent = (peerId, image)
|
||||
}
|
||||
|
||||
var size = CGSize(width: 0.0, height: availableSize.height)
|
||||
|
||||
// MARK: Text
|
||||
if let textString = textString {
|
||||
let textView: ImmediateTextView
|
||||
if let current = self.textView {
|
||||
@@ -144,11 +224,13 @@ public final class NavigationButtonComponent: Component {
|
||||
size.width = max(44.0, textSize.width + textInset * 2.0)
|
||||
|
||||
textView.frame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: floor((availableSize.height - textSize.height) / 2.0)), size: textSize)
|
||||
removeAvatarViews()
|
||||
} else if let textView = self.textView {
|
||||
self.textView = nil
|
||||
textView.removeFromSuperview()
|
||||
}
|
||||
|
||||
// MARK: Icon
|
||||
if let imageName = imageName {
|
||||
let iconView: UIImageView
|
||||
if let current = self.iconView {
|
||||
@@ -166,15 +248,16 @@ public final class NavigationButtonComponent: Component {
|
||||
|
||||
if let iconSize = iconView.image?.size {
|
||||
size.width = 44.0
|
||||
|
||||
iconView.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((availableSize.height - iconSize.height) / 2.0)), size: iconSize)
|
||||
}
|
||||
removeAvatarViews()
|
||||
} else if let iconView = self.iconView {
|
||||
self.iconView = nil
|
||||
iconView.removeFromSuperview()
|
||||
self.iconImageName = nil
|
||||
}
|
||||
|
||||
// MARK: Proxy
|
||||
if let proxyStatus = proxyStatus {
|
||||
let proxyNode: ChatTitleProxyNode
|
||||
if let current = self.proxyNode {
|
||||
@@ -191,13 +274,14 @@ public final class NavigationButtonComponent: Component {
|
||||
|
||||
proxyNode.theme = theme
|
||||
proxyNode.status = proxyStatus
|
||||
|
||||
proxyNode.frame = CGRect(origin: CGPoint(x: floor((size.width - proxySize.width) / 2.0), y: floor((availableSize.height - proxySize.height) / 2.0)), size: proxySize)
|
||||
removeAvatarViews()
|
||||
} else if let proxyNode = self.proxyNode {
|
||||
self.proxyNode = nil
|
||||
proxyNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
// MARK: More
|
||||
if isMore {
|
||||
let moreButton: MoreHeaderButton
|
||||
if let current = self.moreButton, !themeUpdated {
|
||||
@@ -233,13 +317,52 @@ public final class NavigationButtonComponent: Component {
|
||||
size.width = 44.0
|
||||
|
||||
moreButton.setContent(.more(MoreHeaderButton.optionsCircleImage(color: theme.rootController.navigationBar.buttonColor)))
|
||||
|
||||
moreButton.frame = CGRect(origin: CGPoint(x: floor((size.width - buttonSize.width) / 2.0), y: floor((size.height - buttonSize.height) / 2.0)), size: buttonSize)
|
||||
removeAvatarViews()
|
||||
} else if let moreButton = self.moreButton {
|
||||
self.moreButton = nil
|
||||
moreButton.removeFromSupernode()
|
||||
}
|
||||
|
||||
// MARK: Liquid Glass Avatar
|
||||
if let (_, image) = avatarContent {
|
||||
setupAvatarViewsIfNeeded()
|
||||
|
||||
let avatarDiameter: CGFloat = 28.0
|
||||
size.width = 44.0
|
||||
|
||||
let containerRect = CGRect(
|
||||
x: floor((size.width - avatarDiameter) / 2.0),
|
||||
y: floor((availableSize.height - avatarDiameter) / 2.0),
|
||||
width: avatarDiameter,
|
||||
height: avatarDiameter
|
||||
)
|
||||
|
||||
avatarContainerView?.frame = containerRect
|
||||
avatarContainerView?.layer.cornerRadius = avatarDiameter / 2.0
|
||||
|
||||
avatarBlurView?.frame = CGRect(origin: .zero, size: containerRect.size)
|
||||
|
||||
if let image = image {
|
||||
avatarImageView?.image = image
|
||||
avatarImageView?.frame = CGRect(origin: .zero, size: containerRect.size)
|
||||
avatarImageView?.backgroundColor = nil
|
||||
} else {
|
||||
avatarImageView?.image = nil
|
||||
// Fallback: solid tinted background when no photo
|
||||
avatarImageView?.frame = CGRect(origin: .zero, size: containerRect.size)
|
||||
avatarImageView?.backgroundColor = theme.list.itemAccentColor.withAlphaComponent(0.35)
|
||||
}
|
||||
|
||||
// Update border ring path
|
||||
let borderPath = UIBezierPath(roundedRect: CGRect(origin: .zero, size: containerRect.size).insetBy(dx: 0.75, dy: 0.75), cornerRadius: avatarDiameter / 2.0)
|
||||
avatarBorderLayer?.path = borderPath.cgPath
|
||||
avatarBorderLayer?.frame = CGRect(origin: .zero, size: containerRect.size)
|
||||
|
||||
} else if avatarContent == nil && avatarContainerView != nil {
|
||||
removeAvatarViews()
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ swift_library(
|
||||
module_name = "GiftViewScreen",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
], exclude = [
|
||||
"Sources/TableComponent.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
|
||||
+6
-6
@@ -133,7 +133,7 @@ public func giftOfferAlertController(
|
||||
HStack(items, spacing: 4.0)
|
||||
)
|
||||
|
||||
tableItems.append(.init(
|
||||
tableItems.append(TableComponent.Item(
|
||||
id: id,
|
||||
title: title,
|
||||
hasBackground: false,
|
||||
@@ -180,12 +180,12 @@ public func giftOfferAlertController(
|
||||
AlertTextComponent(content: .plain(text))
|
||||
)
|
||||
))
|
||||
content.append(AnyComponentWithIdentity(
|
||||
let tableComponent = AnyComponent(AlertTableComponent(items: tableItems))
|
||||
let tableEntry = AnyComponentWithIdentity<AlertComponentEnvironment>(
|
||||
id: "table",
|
||||
component: AnyComponent(
|
||||
AlertTableComponent(items: tableItems)
|
||||
)
|
||||
))
|
||||
component: tableComponent
|
||||
)
|
||||
content.append(tableEntry)
|
||||
|
||||
if let valueAmount = gift.valueUsdAmount {
|
||||
let resaleConfiguration = StarsSubscriptionConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||
|
||||
+6
-6
@@ -118,7 +118,7 @@ public func giftTransferAlertController(
|
||||
HStack(items, spacing: 4.0)
|
||||
)
|
||||
|
||||
tableItems.append(.init(
|
||||
tableItems.append(TableComponent.Item(
|
||||
id: id,
|
||||
title: title,
|
||||
hasBackground: false,
|
||||
@@ -165,12 +165,12 @@ public func giftTransferAlertController(
|
||||
AlertTextComponent(content: .plain(text))
|
||||
)
|
||||
))
|
||||
content.append(AnyComponentWithIdentity(
|
||||
let tableComponent = AnyComponent(AlertTableComponent(items: tableItems))
|
||||
let tableEntry = AnyComponentWithIdentity<AlertComponentEnvironment>(
|
||||
id: "table",
|
||||
component: AnyComponent(
|
||||
AlertTableComponent(items: tableItems)
|
||||
)
|
||||
))
|
||||
component: tableComponent
|
||||
)
|
||||
content.append(tableEntry)
|
||||
|
||||
let alertController = ChatMessagePaymentAlertController(
|
||||
context: context,
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ import ChatPresentationInterfaceState
|
||||
import AsyncDisplayKit
|
||||
import AccountContext
|
||||
|
||||
open class ChatTitleAccessoryPanelNode: ASDisplayNode {
|
||||
open class LegacyChatTitleAccessoryPanelNode: ASDisplayNode {
|
||||
public typealias LayoutResult = ChatControllerCustomNavigationPanelNodeLayoutResult
|
||||
|
||||
open var interfaceInteraction: ChatPanelInterfaceInteraction?
|
||||
@@ -19,11 +19,11 @@ open class ChatTitleAccessoryPanelNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
public final class LegacyChatHeaderPanelComponent: Component {
|
||||
public let panelNode: ChatTitleAccessoryPanelNode
|
||||
public let panelNode: LegacyChatTitleAccessoryPanelNode
|
||||
public let interfaceState: ChatPresentationInterfaceState
|
||||
|
||||
public init(
|
||||
panelNode: ChatTitleAccessoryPanelNode,
|
||||
panelNode: LegacyChatTitleAccessoryPanelNode,
|
||||
interfaceState: ChatPresentationInterfaceState
|
||||
) {
|
||||
self.panelNode = panelNode
|
||||
|
||||
+27
-13
@@ -232,20 +232,34 @@ final class AffiliateProgramSetupScreenComponent: Component {
|
||||
)
|
||||
))
|
||||
|
||||
let tableItems: [TableComponent.Item] = [
|
||||
TableComponent.Item(id: 0, title: environment.strings.AffiliateSetup_AlertApply_SectionCommission, component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: commissionTitle, font: Font.regular(15.0), textColor: environment.theme.actionSheet.primaryTextColor))
|
||||
))),
|
||||
TableComponent.Item(id: 1, title: environment.strings.AffiliateSetup_AlertApply_SectionDuration, component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: durationTitle, font: Font.regular(15.0), textColor: environment.theme.actionSheet.primaryTextColor))
|
||||
)))
|
||||
]
|
||||
content.append(AnyComponentWithIdentity(
|
||||
let textColor = environment.theme.actionSheet.primaryTextColor
|
||||
let commissionItemText = NSAttributedString(
|
||||
string: commissionTitle,
|
||||
font: Font.regular(15.0),
|
||||
textColor: textColor
|
||||
)
|
||||
let durationItemText = NSAttributedString(
|
||||
string: durationTitle,
|
||||
font: Font.regular(15.0),
|
||||
textColor: textColor
|
||||
)
|
||||
let commissionItem = TableComponent.Item(
|
||||
id: 0,
|
||||
title: environment.strings.AffiliateSetup_AlertApply_SectionCommission,
|
||||
component: AnyComponent(MultilineTextComponent(text: .plain(commissionItemText)))
|
||||
)
|
||||
let durationItem = TableComponent.Item(
|
||||
id: 1,
|
||||
title: environment.strings.AffiliateSetup_AlertApply_SectionDuration,
|
||||
component: AnyComponent(MultilineTextComponent(text: .plain(durationItemText)))
|
||||
)
|
||||
let tableItems: [TableComponent.Item] = [commissionItem, durationItem]
|
||||
let tableComponent = AnyComponent(AlertTableComponent(items: tableItems))
|
||||
let tableEntry = AnyComponentWithIdentity<AlertComponentEnvironment>(
|
||||
id: "table",
|
||||
component: AnyComponent(
|
||||
AlertTableComponent(items: tableItems)
|
||||
)
|
||||
))
|
||||
component: tableComponent
|
||||
)
|
||||
content.append(tableEntry)
|
||||
|
||||
let alertController = AlertScreen(
|
||||
context: component.context,
|
||||
|
||||
+5
-19
@@ -6,7 +6,7 @@ import TelegramPresentationData
|
||||
import MultilineTextComponent
|
||||
import AlertComponent
|
||||
|
||||
final class TableComponent: CombinedComponent {
|
||||
final class AffiliateTableComponent: CombinedComponent {
|
||||
class Item: Equatable {
|
||||
public let id: AnyHashable
|
||||
public let title: String
|
||||
@@ -45,7 +45,7 @@ final class TableComponent: CombinedComponent {
|
||||
self.items = items
|
||||
}
|
||||
|
||||
public static func ==(lhs: TableComponent, rhs: TableComponent) -> Bool {
|
||||
public static func ==(lhs: AffiliateTableComponent, rhs: AffiliateTableComponent) -> Bool {
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
@@ -228,9 +228,9 @@ private final class TableAlertContentComponent: CombinedComponent {
|
||||
let theme: PresentationTheme
|
||||
let title: String
|
||||
let text: String
|
||||
let table: TableComponent
|
||||
let table: AffiliateTableComponent
|
||||
|
||||
init(theme: PresentationTheme, title: String, text: String, table: TableComponent) {
|
||||
init(theme: PresentationTheme, title: String, text: String, table: AffiliateTableComponent) {
|
||||
self.theme = theme
|
||||
self.title = title
|
||||
self.text = text
|
||||
@@ -256,7 +256,7 @@ private final class TableAlertContentComponent: CombinedComponent {
|
||||
public static var body: Body {
|
||||
let title = Child(MultilineTextComponent.self)
|
||||
let text = Child(MultilineTextComponent.self)
|
||||
let table = Child(TableComponent.self)
|
||||
let table = Child(AffiliateTableComponent.self)
|
||||
|
||||
return { context in
|
||||
let title = title.update(
|
||||
@@ -318,17 +318,3 @@ private final class TableAlertContentComponent: CombinedComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tableAlert(theme: PresentationTheme, title: String, text: String, table: TableComponent, actions: [ComponentAlertAction]) -> ViewController {
|
||||
return componentAlertController(
|
||||
theme: AlertControllerTheme(presentationTheme: theme, fontSize: .regular),
|
||||
content: AnyComponent(TableAlertContentComponent(
|
||||
theme: theme,
|
||||
title: title,
|
||||
text: text,
|
||||
table: table
|
||||
)),
|
||||
actions: actions,
|
||||
actionLayout: .horizontal
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -8,7 +8,8 @@ import TelegramPresentationData
|
||||
import ProgressNavigationButtonNode
|
||||
import AccountContext
|
||||
import SearchUI
|
||||
import ChatListUI
|
||||
import func ChatListUI.chatListFilterItems
|
||||
import enum ChatListUI.ChatListContainerNodeFilter
|
||||
import CounterControllerTitleView
|
||||
import ChatListFilterTabContainerNode
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ public final class BirthdayPickerComponent: Component {
|
||||
|
||||
private let calendar = Calendar(identifier: .gregorian)
|
||||
private var value = TelegramBirthday(day: 1, month: 1, year: nil)
|
||||
private var minYear: Int32 = 1900
|
||||
private var minYear: Int32 = 1
|
||||
private let maxYear: Int32
|
||||
|
||||
override init(frame: CGRect) {
|
||||
|
||||
Reference in New Issue
Block a user