mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Various improvements
This commit is contained in:
parent
5d1e4b4be0
commit
9ad1b7bf86
@ -160,7 +160,8 @@ class IncreaseLimitHeaderItemNode: ListViewItemNode {
|
|||||||
activeTitleColor: .white,
|
activeTitleColor: .white,
|
||||||
badgeIconName: badgeIconName,
|
badgeIconName: badgeIconName,
|
||||||
badgeText: "\(item.count)",
|
badgeText: "\(item.count)",
|
||||||
badgePosition: CGFloat(item.count) / CGFloat(item.premiumCount)
|
badgePosition: CGFloat(item.count) / CGFloat(item.premiumCount),
|
||||||
|
isPremiumDisabled: false
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: layout.size.width - params.leftInset - params.rightInset, height: 200.0)
|
containerSize: CGSize(width: layout.size.width - params.leftInset - params.rightInset, height: 200.0)
|
||||||
|
@ -1320,7 +1320,13 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
let availableProducts: Signal<[InAppPurchaseManager.Product], NoError>
|
||||||
if let inAppPurchaseManager = context.inAppPurchaseManager {
|
if let inAppPurchaseManager = context.inAppPurchaseManager {
|
||||||
|
availableProducts = inAppPurchaseManager.availableProducts
|
||||||
|
} else {
|
||||||
|
availableProducts = .single([])
|
||||||
|
}
|
||||||
|
|
||||||
let otherPeerName: Signal<String?, NoError>
|
let otherPeerName: Signal<String?, NoError>
|
||||||
if case let .profile(peerId) = source {
|
if case let .profile(peerId) = source {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
@ -1334,7 +1340,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
|||||||
|
|
||||||
self.disposable = combineLatest(
|
self.disposable = combineLatest(
|
||||||
queue: Queue.mainQueue(),
|
queue: Queue.mainQueue(),
|
||||||
inAppPurchaseManager.availableProducts,
|
availableProducts,
|
||||||
context.account.postbox.peerView(id: context.account.peerId)
|
context.account.postbox.peerView(id: context.account.peerId)
|
||||||
|> map { view -> Bool in
|
|> map { view -> Bool in
|
||||||
return view.peers[view.peerId]?.isPremium ?? false
|
return view.peers[view.peerId]?.isPremium ?? false
|
||||||
@ -1349,7 +1355,6 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.disposable?.dispose()
|
self.disposable?.dispose()
|
||||||
|
@ -44,6 +44,7 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
private let textColor: UIColor
|
private let textColor: UIColor
|
||||||
private let badgeText: String?
|
private let badgeText: String?
|
||||||
private let badgePosition: CGFloat
|
private let badgePosition: CGFloat
|
||||||
|
private let isPremiumDisabled: Bool
|
||||||
|
|
||||||
init(
|
init(
|
||||||
iconName: String?,
|
iconName: String?,
|
||||||
@ -51,7 +52,8 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
activeColors: [UIColor],
|
activeColors: [UIColor],
|
||||||
textColor: UIColor,
|
textColor: UIColor,
|
||||||
badgeText: String?,
|
badgeText: String?,
|
||||||
badgePosition: CGFloat
|
badgePosition: CGFloat,
|
||||||
|
isPremiumDisabled: Bool
|
||||||
) {
|
) {
|
||||||
self.iconName = iconName
|
self.iconName = iconName
|
||||||
self.inactiveColor = inactiveColor
|
self.inactiveColor = inactiveColor
|
||||||
@ -59,6 +61,7 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
self.textColor = textColor
|
self.textColor = textColor
|
||||||
self.badgeText = badgeText
|
self.badgeText = badgeText
|
||||||
self.badgePosition = badgePosition
|
self.badgePosition = badgePosition
|
||||||
|
self.isPremiumDisabled = isPremiumDisabled
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: PremiumLimitAnimationComponent, rhs: PremiumLimitAnimationComponent) -> Bool {
|
static func ==(lhs: PremiumLimitAnimationComponent, rhs: PremiumLimitAnimationComponent) -> Bool {
|
||||||
@ -80,6 +83,9 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
if lhs.badgePosition != rhs.badgePosition {
|
if lhs.badgePosition != rhs.badgePosition {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isPremiumDisabled != rhs.isPremiumDisabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,42 +189,39 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
func playAppearanceAnimation(component: PremiumLimitAnimationComponent, availableSize: CGSize) {
|
func playAppearanceAnimation(component: PremiumLimitAnimationComponent, availableSize: CGSize) {
|
||||||
self.badgeView.layer.animateScale(from: 0.1, to: 1.0, duration: 0.4, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
self.badgeView.layer.animateScale(from: 0.1, to: 1.0, duration: 0.4, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||||
|
|
||||||
let now = self.badgeView.layer.convertTime(CACurrentMediaTime(), from: nil)
|
|
||||||
|
|
||||||
let positionAnimation = CABasicAnimation(keyPath: "position.x")
|
let positionAnimation = CABasicAnimation(keyPath: "position.x")
|
||||||
positionAnimation.fromValue = NSValue(cgPoint: CGPoint(x: 0.0, y: 0.0))
|
positionAnimation.fromValue = NSValue(cgPoint: CGPoint(x: 0.0, y: 0.0))
|
||||||
positionAnimation.toValue = NSValue(cgPoint: self.badgeView.center)
|
positionAnimation.toValue = NSValue(cgPoint: self.badgeView.center)
|
||||||
positionAnimation.duration = 0.5
|
positionAnimation.duration = 0.5
|
||||||
positionAnimation.fillMode = .forwards
|
positionAnimation.fillMode = .forwards
|
||||||
positionAnimation.beginTime = now
|
self.badgeView.layer.add(positionAnimation, forKey: "appearance1")
|
||||||
|
|
||||||
|
|
||||||
|
Queue.mainQueue().after(0.5, {
|
||||||
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
|
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
|
||||||
rotateAnimation.fromValue = 0.0 as NSNumber
|
rotateAnimation.fromValue = 0.0 as NSNumber
|
||||||
rotateAnimation.toValue = 0.2 as NSNumber
|
rotateAnimation.toValue = 0.2 as NSNumber
|
||||||
rotateAnimation.isAdditive = true
|
|
||||||
rotateAnimation.duration = 0.2
|
rotateAnimation.duration = 0.2
|
||||||
rotateAnimation.beginTime = now + 0.5
|
|
||||||
rotateAnimation.fillMode = .forwards
|
rotateAnimation.fillMode = .forwards
|
||||||
rotateAnimation.timingFunction = CAMediaTimingFunction(name: .easeOut)
|
rotateAnimation.timingFunction = CAMediaTimingFunction(name: .easeOut)
|
||||||
|
rotateAnimation.isRemovedOnCompletion = false
|
||||||
|
self.badgeView.layer.add(rotateAnimation, forKey: "appearance2")
|
||||||
|
|
||||||
Queue.mainQueue().after(0.5, {
|
|
||||||
if !self.badgeView.isHidden {
|
if !self.badgeView.isHidden {
|
||||||
self.hapticFeedback.impact(.light)
|
self.hapticFeedback.impact(.light)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
|
Queue.mainQueue().after(0.2) {
|
||||||
let returnAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
|
let returnAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
|
||||||
returnAnimation.fromValue = 0.2 as NSNumber
|
returnAnimation.fromValue = 0.2 as NSNumber
|
||||||
returnAnimation.toValue = 0.0 as NSNumber
|
returnAnimation.toValue = 0.0 as NSNumber
|
||||||
returnAnimation.isAdditive = true
|
|
||||||
returnAnimation.duration = 0.18
|
returnAnimation.duration = 0.18
|
||||||
returnAnimation.beginTime = now + 0.5 + 0.2
|
|
||||||
returnAnimation.fillMode = .forwards
|
returnAnimation.fillMode = .forwards
|
||||||
returnAnimation.timingFunction = CAMediaTimingFunction(name: .easeIn)
|
returnAnimation.timingFunction = CAMediaTimingFunction(name: .easeIn)
|
||||||
|
|
||||||
self.badgeView.layer.add(positionAnimation, forKey: "appearance1")
|
|
||||||
self.badgeView.layer.add(rotateAnimation, forKey: "appearance2")
|
|
||||||
self.badgeView.layer.add(returnAnimation, forKey: "appearance3")
|
self.badgeView.layer.add(returnAnimation, forKey: "appearance3")
|
||||||
|
self.badgeView.layer.removeAnimation(forKey: "appearance2")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
self.badgeView.alpha = 1.0
|
self.badgeView.alpha = 1.0
|
||||||
self.badgeView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
self.badgeView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
@ -241,6 +244,7 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
let containerFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - lineHeight), size: CGSize(width: availableSize.width, height: lineHeight))
|
let containerFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - lineHeight), size: CGSize(width: availableSize.width, height: lineHeight))
|
||||||
self.container.frame = containerFrame
|
self.container.frame = containerFrame
|
||||||
|
|
||||||
|
if !component.isPremiumDisabled {
|
||||||
self.inactiveBackground.frame = CGRect(origin: .zero, size: CGSize(width: containerFrame.width / 2.0, height: lineHeight))
|
self.inactiveBackground.frame = CGRect(origin: .zero, size: CGSize(width: containerFrame.width / 2.0, height: lineHeight))
|
||||||
self.activeContainer.frame = CGRect(origin: CGPoint(x: containerFrame.width / 2.0, y: 0.0), size: CGSize(width: containerFrame.width / 2.0, height: lineHeight))
|
self.activeContainer.frame = CGRect(origin: CGPoint(x: containerFrame.width / 2.0, y: 0.0), size: CGSize(width: containerFrame.width / 2.0, height: lineHeight))
|
||||||
|
|
||||||
@ -248,6 +252,7 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
if self.activeBackground.animation(forKey: "movement") == nil {
|
if self.activeBackground.animation(forKey: "movement") == nil {
|
||||||
self.activeBackground.position = CGPoint(x: containerFrame.width * 3.0 / 4.0 - self.activeBackground.frame.width * 0.35, y: lineHeight / 2.0)
|
self.activeBackground.position = CGPoint(x: containerFrame.width * 3.0 / 4.0 - self.activeBackground.frame.width * 0.35, y: lineHeight / 2.0)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let countWidth: CGFloat
|
let countWidth: CGFloat
|
||||||
if let badgeText = component.badgeText {
|
if let badgeText = component.badgeText {
|
||||||
@ -276,26 +281,43 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
self.badgeMaskTailView.frame = CGRect(origin: CGPoint(x: badgeSize.width - 44.0, y: badgeSize.height - 36.0), size: CGSize(width: 44.0, height: 36.0))
|
self.badgeMaskTailView.frame = CGRect(origin: CGPoint(x: badgeSize.width - 44.0, y: badgeSize.height - 36.0), size: CGSize(width: 44.0, height: 36.0))
|
||||||
|
|
||||||
self.badgeView.bounds = CGRect(origin: .zero, size: badgeSize)
|
self.badgeView.bounds = CGRect(origin: .zero, size: badgeSize)
|
||||||
if component.badgePosition > 1.0 - .ulpOfOne {
|
|
||||||
|
var badgePosition = component.badgePosition
|
||||||
|
if component.isPremiumDisabled {
|
||||||
|
badgePosition = 0.5
|
||||||
|
}
|
||||||
|
if badgePosition > 1.0 - .ulpOfOne {
|
||||||
self.badgeView.layer.anchorPoint = CGPoint(x: 1.0, y: 1.0)
|
self.badgeView.layer.anchorPoint = CGPoint(x: 1.0, y: 1.0)
|
||||||
|
|
||||||
self.badgeMaskTailView.isHidden = false
|
self.badgeMaskTailView.isHidden = false
|
||||||
self.badgeMaskArrowView.isHidden = true
|
self.badgeMaskArrowView.isHidden = true
|
||||||
|
|
||||||
self.badgeView.center = CGPoint(x: 3.0 + (availableSize.width - 6.0) * component.badgePosition + 3.0, y: 82.0)
|
if let _ = self.badgeView.layer.animation(forKey: "appearance1") {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
self.badgeView.center = CGPoint(x: 3.0 + (availableSize.width - 6.0) * badgePosition + 3.0, y: 82.0)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.badgeView.layer.anchorPoint = CGPoint(x: 0.5, y: 1.0)
|
self.badgeView.layer.anchorPoint = CGPoint(x: 0.5, y: 1.0)
|
||||||
|
|
||||||
self.badgeMaskTailView.isHidden = true
|
self.badgeMaskTailView.isHidden = true
|
||||||
self.badgeMaskArrowView.isHidden = false
|
self.badgeMaskArrowView.isHidden = component.isPremiumDisabled
|
||||||
|
|
||||||
self.badgeView.center = CGPoint(x: 3.0 + (availableSize.width - 6.0) * component.badgePosition, y: 82.0)
|
if let _ = self.badgeView.layer.animation(forKey: "appearance1") {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
self.badgeView.center = CGPoint(x: 3.0 + (availableSize.width - 6.0) * badgePosition, y: 82.0)
|
||||||
|
}
|
||||||
|
|
||||||
if self.badgeView.frame.maxX > availableSize.width {
|
if self.badgeView.frame.maxX > availableSize.width {
|
||||||
let delta = self.badgeView.frame.maxX - availableSize.width - 6.0
|
let delta = self.badgeView.frame.maxX - availableSize.width - 6.0
|
||||||
|
if let _ = self.badgeView.layer.animation(forKey: "appearance1") {
|
||||||
|
|
||||||
|
} else {
|
||||||
self.badgeView.center = self.badgeView.center.offsetBy(dx: -delta, dy: 0.0)
|
self.badgeView.center = self.badgeView.center.offsetBy(dx: -delta, dy: 0.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
self.badgeForeground.bounds = CGRect(origin: CGPoint(), size: CGSize(width: badgeSize.width * 3.0, height: badgeSize.height))
|
self.badgeForeground.bounds = CGRect(origin: CGPoint(), size: CGSize(width: badgeSize.width * 3.0, height: badgeSize.height))
|
||||||
if self.badgeForeground.animation(forKey: "movement") == nil {
|
if self.badgeForeground.animation(forKey: "movement") == nil {
|
||||||
self.badgeForeground.position = CGPoint(x: badgeSize.width * 3.0 / 2.0 - self.badgeForeground.frame.width * 0.35, y: badgeSize.height / 2.0)
|
self.badgeForeground.position = CGPoint(x: badgeSize.width * 3.0 / 2.0 - self.badgeForeground.frame.width * 0.35, y: badgeSize.height / 2.0)
|
||||||
@ -304,8 +326,17 @@ private class PremiumLimitAnimationComponent: Component {
|
|||||||
self.badgeIcon.frame = CGRect(x: 15.0, y: 9.0, width: 30.0, height: 30.0)
|
self.badgeIcon.frame = CGRect(x: 15.0, y: 9.0, width: 30.0, height: 30.0)
|
||||||
self.badgeCountLabel.frame = CGRect(x: badgeSize.width - countWidth - 11.0, y: 10.0, width: countWidth, height: 48.0)
|
self.badgeCountLabel.frame = CGRect(x: badgeSize.width - countWidth - 11.0, y: 10.0, width: countWidth, height: 48.0)
|
||||||
|
|
||||||
|
if component.isPremiumDisabled {
|
||||||
if !self.didPlayAppearanceAnimation {
|
if !self.didPlayAppearanceAnimation {
|
||||||
self.didPlayAppearanceAnimation = true
|
self.didPlayAppearanceAnimation = true
|
||||||
|
|
||||||
|
self.badgeView.alpha = 1.0
|
||||||
|
if let badgeText = component.badgeText {
|
||||||
|
self.badgeCountLabel.configure(with: badgeText, duration: 0.3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if !self.didPlayAppearanceAnimation {
|
||||||
|
self.didPlayAppearanceAnimation = true
|
||||||
self.playAppearanceAnimation(component: component, availableSize: availableSize)
|
self.playAppearanceAnimation(component: component, availableSize: availableSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,6 +427,7 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
|
|||||||
let badgeIconName: String?
|
let badgeIconName: String?
|
||||||
let badgeText: String?
|
let badgeText: String?
|
||||||
let badgePosition: CGFloat
|
let badgePosition: CGFloat
|
||||||
|
let isPremiumDisabled: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
inactiveColor: UIColor,
|
inactiveColor: UIColor,
|
||||||
@ -408,7 +440,8 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
|
|||||||
activeTitleColor: UIColor,
|
activeTitleColor: UIColor,
|
||||||
badgeIconName: String?,
|
badgeIconName: String?,
|
||||||
badgeText: String?,
|
badgeText: String?,
|
||||||
badgePosition: CGFloat
|
badgePosition: CGFloat,
|
||||||
|
isPremiumDisabled: Bool
|
||||||
) {
|
) {
|
||||||
self.inactiveColor = inactiveColor
|
self.inactiveColor = inactiveColor
|
||||||
self.activeColors = activeColors
|
self.activeColors = activeColors
|
||||||
@ -421,6 +454,7 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
|
|||||||
self.badgeIconName = badgeIconName
|
self.badgeIconName = badgeIconName
|
||||||
self.badgeText = badgeText
|
self.badgeText = badgeText
|
||||||
self.badgePosition = badgePosition
|
self.badgePosition = badgePosition
|
||||||
|
self.isPremiumDisabled = isPremiumDisabled
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: PremiumLimitDisplayComponent, rhs: PremiumLimitDisplayComponent) -> Bool {
|
public static func ==(lhs: PremiumLimitDisplayComponent, rhs: PremiumLimitDisplayComponent) -> Bool {
|
||||||
@ -457,6 +491,9 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
|
|||||||
if lhs.badgePosition != rhs.badgePosition {
|
if lhs.badgePosition != rhs.badgePosition {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isPremiumDisabled != rhs.isPremiumDisabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,6 +510,25 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
|
|||||||
let height: CGFloat = 120.0
|
let height: CGFloat = 120.0
|
||||||
let lineHeight: CGFloat = 30.0
|
let lineHeight: CGFloat = 30.0
|
||||||
|
|
||||||
|
let animation = animation.update(
|
||||||
|
component: PremiumLimitAnimationComponent(
|
||||||
|
iconName: component.badgeIconName,
|
||||||
|
inactiveColor: component.inactiveColor,
|
||||||
|
activeColors: component.activeColors,
|
||||||
|
textColor: component.activeTitleColor,
|
||||||
|
badgeText: component.badgeText,
|
||||||
|
badgePosition: component.badgePosition,
|
||||||
|
isPremiumDisabled: component.isPremiumDisabled
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width, height: height),
|
||||||
|
transition: context.transition
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add(animation
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: height / 2.0))
|
||||||
|
)
|
||||||
|
|
||||||
|
if !component.isPremiumDisabled {
|
||||||
let inactiveTitle = inactiveTitle.update(
|
let inactiveTitle = inactiveTitle.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
text: .plain(
|
text: .plain(
|
||||||
@ -529,23 +585,6 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
|
|||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
let animation = animation.update(
|
|
||||||
component: PremiumLimitAnimationComponent(
|
|
||||||
iconName: component.badgeIconName,
|
|
||||||
inactiveColor: component.inactiveColor,
|
|
||||||
activeColors: component.activeColors,
|
|
||||||
textColor: component.activeTitleColor,
|
|
||||||
badgeText: component.badgeText,
|
|
||||||
badgePosition: component.badgePosition
|
|
||||||
),
|
|
||||||
availableSize: CGSize(width: context.availableSize.width, height: height),
|
|
||||||
transition: context.transition
|
|
||||||
)
|
|
||||||
|
|
||||||
context.add(animation
|
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: height / 2.0))
|
|
||||||
)
|
|
||||||
|
|
||||||
context.add(inactiveTitle
|
context.add(inactiveTitle
|
||||||
.position(CGPoint(x: inactiveTitle.size.width / 2.0 + 12.0, y: height - lineHeight / 2.0))
|
.position(CGPoint(x: inactiveTitle.size.width / 2.0 + 12.0, y: height - lineHeight / 2.0))
|
||||||
)
|
)
|
||||||
@ -561,6 +600,7 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
|
|||||||
context.add(activeValue
|
context.add(activeValue
|
||||||
.position(CGPoint(x: context.availableSize.width - activeValue.size.width / 2.0 - 12.0, y: height - lineHeight / 2.0))
|
.position(CGPoint(x: context.availableSize.width - activeValue.size.width / 2.0 - 12.0, y: height - lineHeight / 2.0))
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return CGSize(width: context.availableSize.width, height: height)
|
return CGSize(width: context.availableSize.width, height: height)
|
||||||
}
|
}
|
||||||
@ -656,6 +696,9 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
let state = context.state
|
let state = context.state
|
||||||
let subject = component.subject
|
let subject = component.subject
|
||||||
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
||||||
|
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
||||||
|
|
||||||
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
||||||
let textSideInset: CGFloat = 24.0 + environment.safeInsets.left
|
let textSideInset: CGFloat = 24.0 + environment.safeInsets.left
|
||||||
|
|
||||||
@ -684,7 +727,7 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
var titleText = strings.Premium_LimitReached
|
var titleText = strings.Premium_LimitReached
|
||||||
var buttonAnimationName = "premium_x2"
|
var buttonAnimationName = "premium_x2"
|
||||||
let iconName: String
|
let iconName: String
|
||||||
let badgeText: String
|
var badgeText: String
|
||||||
var string: String
|
var string: String
|
||||||
let defaultValue: String
|
let defaultValue: String
|
||||||
let premiumValue: String
|
let premiumValue: String
|
||||||
@ -703,6 +746,11 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
if !state.isPremium && badgePosition > 0.5 {
|
if !state.isPremium && badgePosition > 0.5 {
|
||||||
string = strings.Premium_MaxFoldersCountText("\(limit)", "\(premiumLimit)").string
|
string = strings.Premium_MaxFoldersCountText("\(limit)", "\(premiumLimit)").string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isPremiumDisabled {
|
||||||
|
badgeText = "\(limit)"
|
||||||
|
string = strings.Premium_MaxFoldersCountNoPremiumText("\(limit)").string
|
||||||
|
}
|
||||||
case .chatsPerFolder:
|
case .chatsPerFolder:
|
||||||
let limit = state.limits.maxFolderChatsCount
|
let limit = state.limits.maxFolderChatsCount
|
||||||
let premiumLimit = state.premiumLimits.maxFolderChatsCount
|
let premiumLimit = state.premiumLimits.maxFolderChatsCount
|
||||||
@ -712,6 +760,11 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
defaultValue = component.count > limit ? "\(limit)" : ""
|
defaultValue = component.count > limit ? "\(limit)" : ""
|
||||||
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
|
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
|
||||||
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
||||||
|
|
||||||
|
if isPremiumDisabled {
|
||||||
|
badgeText = "\(limit)"
|
||||||
|
string = strings.Premium_MaxChatsInFolderNoPremiumText("\(limit)").string
|
||||||
|
}
|
||||||
case .pins:
|
case .pins:
|
||||||
let limit = state.limits.maxPinnedChatCount
|
let limit = state.limits.maxPinnedChatCount
|
||||||
let premiumLimit = state.premiumLimits.maxPinnedChatCount
|
let premiumLimit = state.premiumLimits.maxPinnedChatCount
|
||||||
@ -721,6 +774,11 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
defaultValue = component.count > limit ? "\(limit)" : ""
|
defaultValue = component.count > limit ? "\(limit)" : ""
|
||||||
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
|
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
|
||||||
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
||||||
|
|
||||||
|
if isPremiumDisabled {
|
||||||
|
badgeText = "\(limit)"
|
||||||
|
string = strings.Premium_MaxPinsNoPremiumText("\(limit)").string
|
||||||
|
}
|
||||||
case .files:
|
case .files:
|
||||||
let limit = Int64(state.limits.maxUploadFileParts) * 512 * 1024 + 1024 * 1024 * 100
|
let limit = Int64(state.limits.maxUploadFileParts) * 512 * 1024 + 1024 * 1024 * 100
|
||||||
let premiumLimit = Int64(state.premiumLimits.maxUploadFileParts) * 512 * 1024 + 1024 * 1024 * 100
|
let premiumLimit = Int64(state.premiumLimits.maxUploadFileParts) * 512 * 1024 + 1024 * 1024 * 100
|
||||||
@ -731,6 +789,11 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
premiumValue = component.count != 4 ? dataSizeString(premiumLimit, formatting: DataSizeStringFormatting(strings: environment.strings, decimalSeparator: environment.dateTimeFormat.decimalSeparator)) : ""
|
premiumValue = component.count != 4 ? dataSizeString(premiumLimit, formatting: DataSizeStringFormatting(strings: environment.strings, decimalSeparator: environment.dateTimeFormat.decimalSeparator)) : ""
|
||||||
badgePosition = component.count == 4 ? 1.0 : 0.5
|
badgePosition = component.count == 4 ? 1.0 : 0.5
|
||||||
titleText = strings.Premium_FileTooLarge
|
titleText = strings.Premium_FileTooLarge
|
||||||
|
|
||||||
|
if isPremiumDisabled {
|
||||||
|
badgeText = dataSizeString(limit, formatting: DataSizeStringFormatting(strings: environment.strings, decimalSeparator: environment.dateTimeFormat.decimalSeparator))
|
||||||
|
string = strings.Premium_MaxFileSizeNoPremiumText(dataSizeString(premiumLimit, formatting: DataSizeStringFormatting(strings: environment.strings, decimalSeparator: environment.dateTimeFormat.decimalSeparator))).string
|
||||||
|
}
|
||||||
case .accounts:
|
case .accounts:
|
||||||
let limit = 3
|
let limit = 3
|
||||||
let premiumLimit = component.count + 1
|
let premiumLimit = component.count + 1
|
||||||
@ -745,6 +808,11 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
||||||
}
|
}
|
||||||
buttonAnimationName = "premium_addone"
|
buttonAnimationName = "premium_addone"
|
||||||
|
|
||||||
|
if isPremiumDisabled {
|
||||||
|
badgeText = "\(limit)"
|
||||||
|
string = strings.Premium_MaxAccountsNoPremiumText("\(limit)").string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var reachedMaximumLimit = badgePosition >= 1.0
|
var reachedMaximumLimit = badgePosition >= 1.0
|
||||||
if case .folders = subject, !state.isPremium {
|
if case .folders = subject, !state.isPremium {
|
||||||
@ -784,16 +852,26 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
|
|
||||||
if state.initialized {
|
let gradientColors: [UIColor]
|
||||||
let limit = limit.update(
|
if isPremiumDisabled {
|
||||||
component: PremiumLimitDisplayComponent(
|
gradientColors = [
|
||||||
inactiveColor: theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.5),
|
UIColor(rgb: 0x007afe),
|
||||||
activeColors: [
|
UIColor(rgb: 0x5494ff)
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
gradientColors = [
|
||||||
UIColor(rgb: 0x0077ff),
|
UIColor(rgb: 0x0077ff),
|
||||||
UIColor(rgb: 0x6b93ff),
|
UIColor(rgb: 0x6b93ff),
|
||||||
UIColor(rgb: 0x8878ff),
|
UIColor(rgb: 0x8878ff),
|
||||||
UIColor(rgb: 0xe46ace)
|
UIColor(rgb: 0xe46ace)
|
||||||
],
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.initialized {
|
||||||
|
let limit = limit.update(
|
||||||
|
component: PremiumLimitDisplayComponent(
|
||||||
|
inactiveColor: theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.5),
|
||||||
|
activeColors: gradientColors,
|
||||||
inactiveTitle: strings.Premium_Free,
|
inactiveTitle: strings.Premium_Free,
|
||||||
inactiveValue: defaultValue,
|
inactiveValue: defaultValue,
|
||||||
inactiveTitleColor: theme.list.itemPrimaryTextColor,
|
inactiveTitleColor: theme.list.itemPrimaryTextColor,
|
||||||
@ -802,7 +880,8 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
activeTitleColor: .white,
|
activeTitleColor: .white,
|
||||||
badgeIconName: iconName,
|
badgeIconName: iconName,
|
||||||
badgeText: badgeText,
|
badgeText: badgeText,
|
||||||
badgePosition: badgePosition
|
badgePosition: badgePosition,
|
||||||
|
isPremiumDisabled: isPremiumDisabled
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: context.availableSize.height),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: context.availableSize.height),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
@ -812,47 +891,50 @@ private final class LimitSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isIncreaseButton = !reachedMaximumLimit && !isPremiumDisabled
|
||||||
let button = button.update(
|
let button = button.update(
|
||||||
component: SolidRoundedButtonComponent(
|
component: SolidRoundedButtonComponent(
|
||||||
title: !reachedMaximumLimit ? strings.Premium_IncreaseLimit : strings.Common_OK,
|
title: isIncreaseButton ? strings.Premium_IncreaseLimit : strings.Common_OK,
|
||||||
|
|
||||||
theme: SolidRoundedButtonComponent.Theme(
|
theme: SolidRoundedButtonComponent.Theme(
|
||||||
backgroundColor: .black,
|
backgroundColor: .black,
|
||||||
backgroundColors: [
|
backgroundColors: gradientColors,
|
||||||
UIColor(rgb: 0x0077ff),
|
|
||||||
UIColor(rgb: 0x6b93ff),
|
|
||||||
UIColor(rgb: 0x8878ff),
|
|
||||||
UIColor(rgb: 0xe46ace)
|
|
||||||
],
|
|
||||||
foregroundColor: .white
|
foregroundColor: .white
|
||||||
),
|
),
|
||||||
font: .bold,
|
font: .bold,
|
||||||
fontSize: 17.0,
|
fontSize: 17.0,
|
||||||
height: 50.0,
|
height: 50.0,
|
||||||
cornerRadius: 10.0,
|
cornerRadius: 10.0,
|
||||||
gloss: !reachedMaximumLimit,
|
gloss: isIncreaseButton,
|
||||||
animationName: !reachedMaximumLimit ? buttonAnimationName : nil,
|
animationName: isIncreaseButton ? buttonAnimationName : nil,
|
||||||
iconPosition: .right,
|
iconPosition: .right,
|
||||||
action: { [weak component] in
|
action: { [weak component] in
|
||||||
guard let component = component else {
|
guard let component = component else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
component.dismiss()
|
component.dismiss()
|
||||||
|
if isIncreaseButton {
|
||||||
component.action()
|
component.action()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
|
||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var textOffset: CGFloat = 228.0
|
||||||
|
if isPremiumDisabled {
|
||||||
|
textOffset -= 68.0
|
||||||
|
}
|
||||||
|
|
||||||
context.add(title
|
context.add(title
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: 28.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: 28.0))
|
||||||
)
|
)
|
||||||
context.add(text
|
context.add(text
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: 228.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: textOffset))
|
||||||
)
|
)
|
||||||
|
|
||||||
let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: 228.0 + ceil(text.size.height / 2.0) + 38.0), size: button.size)
|
let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: textOffset + ceil(text.size.height / 2.0) + 38.0), size: button.size)
|
||||||
context.add(button
|
context.add(button
|
||||||
.position(CGPoint(x: buttonFrame.midX, y: buttonFrame.midY))
|
.position(CGPoint(x: buttonFrame.midX, y: buttonFrame.midY))
|
||||||
)
|
)
|
||||||
|
@ -167,7 +167,8 @@ private final class LimitComponent: CombinedComponent {
|
|||||||
activeTitleColor: component.activeTextColor,
|
activeTitleColor: component.activeTextColor,
|
||||||
badgeIconName: "",
|
badgeIconName: "",
|
||||||
badgeText: nil,
|
badgeText: nil,
|
||||||
badgePosition: 0.0
|
badgePosition: 0.0,
|
||||||
|
isPremiumDisabled: false
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: context.availableSize.height),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: context.availableSize.height),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
|
@ -30,7 +30,6 @@ open class RollingLabel: UILabel {
|
|||||||
open var showSymbol = false
|
open var showSymbol = false
|
||||||
private var scrollLayers: [CAScrollLayer] = []
|
private var scrollLayers: [CAScrollLayer] = []
|
||||||
private var scrollLabels: [UILabel] = []
|
private var scrollLabels: [UILabel] = []
|
||||||
private let duration = 1.12
|
|
||||||
private let durationOffset = 0.2
|
private let durationOffset = 0.2
|
||||||
private let textsNotAnimated = [","]
|
private let textsNotAnimated = [","]
|
||||||
|
|
||||||
@ -38,26 +37,26 @@ open class RollingLabel: UILabel {
|
|||||||
self.suffix = suffix
|
self.suffix = suffix
|
||||||
}
|
}
|
||||||
|
|
||||||
func configure(with string: String) {
|
func configure(with string: String, duration: Double = 0.9) {
|
||||||
fullText = string
|
self.fullText = string
|
||||||
|
|
||||||
clean()
|
self.clean()
|
||||||
setupSubviews()
|
self.setupSubviews()
|
||||||
|
|
||||||
self.text = " "
|
self.text = " "
|
||||||
self.animate()
|
self.animate(duration: duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func animate(ascending: Bool = true) {
|
private func animate(ascending: Bool = true, duration: Double) {
|
||||||
createAnimations(ascending: ascending)
|
self.createAnimations(ascending: ascending, duration: duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func clean() {
|
private func clean() {
|
||||||
self.text = nil
|
self.text = nil
|
||||||
self.subviews.forEach { $0.removeFromSuperview() }
|
self.subviews.forEach { $0.removeFromSuperview() }
|
||||||
self.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
|
self.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
|
||||||
scrollLayers.removeAll()
|
self.scrollLayers.removeAll()
|
||||||
scrollLabels.removeAll()
|
self.scrollLabels.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupSubviews() {
|
private func setupSubviews() {
|
||||||
@ -168,7 +167,7 @@ open class RollingLabel: UILabel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createAnimations(ascending: Bool) {
|
private func createAnimations(ascending: Bool, duration: Double) {
|
||||||
var offset: CFTimeInterval = 0.0
|
var offset: CFTimeInterval = 0.0
|
||||||
|
|
||||||
for scrollLayer in scrollLayers {
|
for scrollLayer in scrollLayers {
|
||||||
|
@ -257,7 +257,7 @@ private class StickerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let placeholderFrame = CGRect(origin: .zero, size: imageSize)
|
let placeholderFrame = CGRect(origin: CGPoint(x: -10.0, y: 0.0), size: imageSize)
|
||||||
let thumbnailDimensions = PixelDimensions(width: 512, height: 512)
|
let thumbnailDimensions = PixelDimensions(width: 512, height: 512)
|
||||||
self.placeholderNode.update(backgroundColor: nil, foregroundColor: UIColor(rgb: 0xffffff, alpha: 0.2), shimmeringColor: UIColor(rgb: 0xffffff, alpha: 0.3), data: self.file.immediateThumbnailData, size: placeholderFrame.size, imageSize: thumbnailDimensions.cgSize)
|
self.placeholderNode.update(backgroundColor: nil, foregroundColor: UIColor(rgb: 0xffffff, alpha: 0.2), shimmeringColor: UIColor(rgb: 0xffffff, alpha: 0.3), data: self.file.immediateThumbnailData, size: placeholderFrame.size, imageSize: thumbnailDimensions.cgSize)
|
||||||
self.placeholderNode.frame = placeholderFrame
|
self.placeholderNode.frame = placeholderFrame
|
||||||
@ -297,7 +297,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.clipsToBounds = true
|
// self.clipsToBounds = true
|
||||||
|
|
||||||
self.addSubnode(self.scrollNode)
|
self.addSubnode(self.scrollNode)
|
||||||
self.scrollNode.addSubnode(self.tapNode)
|
self.scrollNode.addSubnode(self.tapNode)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user