Various improvements

This commit is contained in:
Ilya Laktyushin 2022-05-29 21:50:59 +04:00
parent 5c87f52dd1
commit 3a97f035bd
20 changed files with 929 additions and 550 deletions

View File

@ -7644,3 +7644,24 @@ Sorry for the inconvenience.";
"ChatListFolder.MaxChatsInFolder" = "Sorry, you can't add more than %d chats to a folder.";
"Conversation.SaveGif" = "Save GIF";
"Premium.Limits.Title" = "Doubled Limits";
"Premium.Limits.GroupsAndChannels" = "Groups and Channels";
"Premium.Limits.PinnedChats" = "Pinned Chats";
"Premium.Limits.PublicLinks" = "Public Links";
"Premium.Limits.SavedGifs" = "Saved GIFs";
"Premium.Limits.FavedStickers" = "Favorite Stickers";
"Premium.Limits.Captions" = "Captions";
"Premium.Limits.Folders" = "Folders";
"Premium.Limits.ChatsPerFolder" = "Chats per Folder";
"Premium.Limits.Accounts" = "Connected Accounts";
"Premium.Limits.GroupsAndChannelsInfo" = "Join up to 1000 channels and large groups";
"Premium.Limits.PinnedChatsInfo" = "Pin up to 10 chats in your main chat list";
"Premium.Limits.PublicLinksInfo" = "Reserve up to 20 [t.me/name]() links";
"Premium.Limits.SavedGifsInfo" = "Save up to 400 GIFs in your Favorite GIFs";
"Premium.Limits.FavedStickersInfo" = "Save up to 10 stickers in your Favorite stickers";
"Premium.Limits.CaptionsInfo" = "Use longer descriptions for your photos and videos";
"Premium.Limits.FoldersInfo" = "Organize your chats into 20 folders";
"Premium.Limits.ChatsPerFolderInfo" = "Add up to 200 chats into each of your folders";
"Premium.Limits.AccountsInfo" = "Connect 4 accounts with different mobile numbers";

View File

@ -60,7 +60,12 @@ public final class List<ChildEnvironment: Equatable>: CombinedComponent {
)
}
return context.availableSize
switch context.component.direction {
case .horizontal:
return CGSize(width: min(context.availableSize.width, nextOrigin), height: context.availableSize.height)
case.vertical:
return CGSize(width: context.availableSize.width, height: min(context.availableSize.height, nextOrigin))
}
}
}
}

View File

@ -1257,7 +1257,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|> deliverOnMainQueue).start(next: { result in
switch result {
case .generic:
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil)
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), nil)
case let .limitExceeded(limit, premiumLimit):
let text: String
if limit == premiumLimit {
@ -1265,7 +1265,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} else {
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
}
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: true, animateInAsReplacement: true, action: { action in
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: true, animateInAsReplacement: false, action: { action in
if case .info = action {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .savedGifs)
controllerInteraction?.pushController(controller)
@ -1451,7 +1451,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|> deliverOnMainQueue).start(next: { result in
switch result {
case .generic:
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil)
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), nil)
case let .limitExceeded(limit, premiumLimit):
let text: String
if limit == premiumLimit {
@ -1459,7 +1459,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} else {
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
}
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: true, animateInAsReplacement: true, action: { action in
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: true, animateInAsReplacement: false, action: { action in
if case .info = action {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .savedGifs)
controllerInteraction?.pushController(controller)

View File

@ -78,18 +78,21 @@ final class IncreaseLimitFooterItemNode: ItemListControllerFooterItemNode {
self.backgroundNode.updateColor(color: self.item.theme.rootController.tabBar.backgroundColor, transition: .immediate)
self.separatorNode.backgroundColor = self.item.theme.rootController.tabBar.separatorColor
let textColor: UIColor
let backgroundColor = self.item.theme.list.itemCheckColors.fillColor
let backgroundColors: [UIColor]
let icon: UIImage?
if self.item.colorful {
textColor = .white
backgroundColors = [UIColor(rgb: 0x407af0), UIColor(rgb: 0x9551e8), UIColor(rgb: 0xbf499a), UIColor(rgb: 0xf17b30)]
icon = UIImage(bundleImageName: "Premium/X2")
} else {
textColor = self.item.theme.list.itemCheckColors.foregroundColor
backgroundColors = []
icon = nil
}
self.buttonNode.updateTheme(SolidRoundedButtonTheme(backgroundColor: backgroundColor, backgroundColors: backgroundColors, foregroundColor: self.item.theme.list.itemCheckColors.foregroundColor), animated: true)
self.buttonNode.updateTheme(SolidRoundedButtonTheme(backgroundColor: backgroundColor, backgroundColors: backgroundColors, foregroundColor: textColor), animated: true)
self.buttonNode.title = self.item.title
self.buttonNode.icon = icon

View File

@ -65,8 +65,8 @@ public enum PremiumSource: Equatable {
return "double_limits__dialog_filters_chats"
case .accounts:
return "double_limits__accounts"
case .profile:
return "profile"
case let .profile(id):
return "profile__\(id.id._internalGetInt64Value())"
case let .deeplink(reference):
if let reference = reference {
return "deeplink_\(reference)"
@ -576,16 +576,16 @@ private final class ScrollComponent<ChildEnvironment: Equatable>: Component {
}
}
final class PerkComponent: CombinedComponent {
public let iconName: String
public let iconBackgroundColors: [UIColor]
public let title: String
public let titleColor: UIColor
public let subtitle: String
public let subtitleColor: UIColor
public let arrowColor: UIColor
private final class PerkComponent: CombinedComponent {
let iconName: String
let iconBackgroundColors: [UIColor]
let title: String
let titleColor: UIColor
let subtitle: String
let subtitleColor: UIColor
let arrowColor: UIColor
public init(
init(
iconName: String,
iconBackgroundColors: [UIColor],
title: String,
@ -603,7 +603,7 @@ final class PerkComponent: CombinedComponent {
self.arrowColor = arrowColor
}
public static func ==(lhs: PerkComponent, rhs: PerkComponent) -> Bool {
static func ==(lhs: PerkComponent, rhs: PerkComponent) -> Bool {
if lhs.iconName != rhs.iconName {
return false
}
@ -962,8 +962,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
var demoSubject: PremiumDemoScreen.Subject
switch perk {
case .doubleLimits:
// let controller = PremimLimitsListScreen(context: accountContext)
// present(controller)
let controller = PremimLimitsListScreen(context: accountContext, buttonText: isPremium ? strings.Common_OK : strings.Premium_SubscribeFor(state?.price ?? "").string, isPremium: isPremium)
present(controller)
return
case .moreUpload:
demoSubject = .moreUpload

View File

@ -38,7 +38,7 @@ func generateCloseButtonImage(backgroundColor: UIColor, foregroundColor: UIColor
}
private class PremiumLimitAnimationComponent: Component {
private let iconName: String
private let iconName: String?
private let inactiveColor: UIColor
private let activeColors: [UIColor]
private let textColor: UIColor
@ -46,7 +46,7 @@ private class PremiumLimitAnimationComponent: Component {
private let badgePosition: CGFloat
init(
iconName: String,
iconName: String?,
inactiveColor: UIColor,
activeColors: [UIColor],
textColor: UIColor,
@ -231,9 +231,10 @@ private class PremiumLimitAnimationComponent: Component {
self.inactiveBackground.backgroundColor = component.inactiveColor.cgColor
self.activeBackground.backgroundColor = component.activeColors.last?.cgColor
self.badgeIcon.image = UIImage(bundleImageName: component.iconName)?.withRenderingMode(.alwaysTemplate)
self.badgeIcon.image = component.iconName.flatMap { UIImage(bundleImageName: $0)?.withRenderingMode(.alwaysTemplate) }
self.badgeIcon.tintColor = component.textColor
self.badgeView.isHidden = self.badgeIcon.image == nil
let lineHeight: CGFloat = 30.0
let containerFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - lineHeight), size: CGSize(width: availableSize.width, height: lineHeight))
self.container.frame = containerFrame
@ -380,17 +381,17 @@ private class PremiumLimitAnimationComponent: Component {
}
public final class PremiumLimitDisplayComponent: CombinedComponent {
public let inactiveColor: UIColor
public let activeColors: [UIColor]
public let inactiveTitle: String
public let inactiveValue: String
public let inactiveTitleColor: UIColor
public let activeTitle: String
public let activeValue: String
public let activeTitleColor: UIColor
public let badgeIconName: String
public let badgeText: String?
public let badgePosition: CGFloat
let inactiveColor: UIColor
let activeColors: [UIColor]
let inactiveTitle: String
let inactiveValue: String
let inactiveTitleColor: UIColor
let activeTitle: String
let activeValue: String
let activeTitleColor: UIColor
let badgeIconName: String?
let badgeText: String?
let badgePosition: CGFloat
public init(
inactiveColor: UIColor,
@ -401,7 +402,7 @@ public final class PremiumLimitDisplayComponent: CombinedComponent {
activeTitle: String,
activeValue: String,
activeTitleColor: UIColor,
badgeIconName: String,
badgeIconName: String?,
badgeText: String?,
badgePosition: CGFloat
) {
@ -677,6 +678,7 @@ private final class LimitSheetContent: CombinedComponent {
)
var titleText = strings.Premium_LimitReached
var buttonIconName = "Premium/X2"
let iconName: String
let badgeText: String
let string: String
@ -734,6 +736,7 @@ private final class LimitSheetContent: CombinedComponent {
} else {
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
}
buttonIconName = "Premium/AddOne"
}
var reachedMaximumLimit = badgePosition >= 1.0
if case .folders = subject, !state.isPremium {
@ -819,7 +822,7 @@ private final class LimitSheetContent: CombinedComponent {
height: 50.0,
cornerRadius: 10.0,
gloss: !reachedMaximumLimit,
iconName: !reachedMaximumLimit ? "Premium/X2" : nil,
iconName: !reachedMaximumLimit ? buttonIconName : nil,
iconPosition: .right,
action: { [weak component] in
guard let component = component else {

File diff suppressed because it is too large Load Diff

View File

@ -114,12 +114,19 @@ class PremiumStarComponent: Component {
self.timer?.invalidate()
}
private let hapticFeedback = HapticFeedback()
private var delayTapsTill: Double?
@objc private func handleTap(_ gesture: UITapGestureRecognizer) {
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
return
}
self.previousInteractionTimestamp = CACurrentMediaTime()
let currentTime = CACurrentMediaTime()
self.previousInteractionTimestamp = currentTime
if let delayTapsTill = self.delayTapsTill, currentTime < delayTapsTill {
return
}
var left: Bool?
var top: Bool?
@ -140,6 +147,8 @@ class PremiumStarComponent: Component {
if node.animationKeys.contains("tapRotate"), let left = left {
self.playAppearanceAnimation(velocity: nil, mirror: left, explode: true)
self.hapticFeedback.impact(.medium)
return
}
@ -175,6 +184,8 @@ class PremiumStarComponent: Component {
springAnimation.duration = springAnimation.settlingDuration * 0.8
node.addAnimation(springAnimation, forKey: "tapRotate")
}
self.hapticFeedback.tap()
}
private var previousYaw: Float = 0.0
@ -387,21 +398,33 @@ class PremiumStarComponent: Component {
return
}
self.previousInteractionTimestamp = CACurrentMediaTime()
let currentTime = CACurrentMediaTime()
self.previousInteractionTimestamp = currentTime
self.delayTapsTill = currentTime + 0.85
if explode, let node = scene.rootNode.childNode(withName: "swirl", recursively: false), let particles = scene.rootNode.childNode(withName: "particles", recursively: false) {
let particleSystem = particles.particleSystems?.first
particleSystem?.particleColorVariation = SCNVector4(0.15, 0.2, 0.35, 0.3)
particleSystem?.particleVelocity = 2.2
particleSystem?.birthRate = 4.5
particleSystem?.particleLifeSpan = 2.0
node.physicsField?.isActive = true
Queue.mainQueue().after(1.0) {
node.physicsField?.isActive = false
particles.particleSystems?.first?.birthRate = 1.2
particleSystem?.particleVelocity = 1.0
particleSystem?.particleLifeSpan = 4.0
if let particleSystem = particles.particleSystems?.first {
particleSystem.particleColorVariation = SCNVector4(0.15, 0.2, 0.35, 0.3)
particleSystem.speedFactor = 2.0
particleSystem.particleVelocity = 2.2
particleSystem.birthRate = 4.0
particleSystem.particleLifeSpan = 2.0
node.physicsField?.isActive = true
Queue.mainQueue().after(1.0) {
node.physicsField?.isActive = false
particles.particleSystems?.first?.birthRate = 1.2
particleSystem.particleVelocity = 1.0
particleSystem.particleLifeSpan = 4.0
particleSystem.speedFactor = 1.0
let animation = CABasicAnimation(keyPath: "speedFactor")
animation.fromValue = 2.0
animation.toValue = 1.0
animation.duration = 0.5
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
particleSystem.addAnimation(animation, forKey: "speedFactor")
}
}
}

View File

@ -433,6 +433,11 @@ private class ReactionCarouselNode: ASDisplayNode, UIScrollViewDelegate {
self.previousInteractionTimestamp = CACurrentMediaTime()
}
if let animator = self.animator {
animator.invalidate()
self.animator = nil
}
guard !self.ignoreContentOffsetChange, let (startContentOffset, startPosition) = self.scrollStartPosition else {
return
}

View File

@ -410,6 +410,11 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
self.previousInteractionTimestamp = CACurrentMediaTime()
}
if let animator = self.animator {
animator.invalidate()
self.animator = nil
}
guard !self.ignoreContentOffsetChange, let (startContentOffset, startPosition) = self.scrollStartPosition else {
return
}

View File

@ -135,6 +135,9 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode {
let expandedAnimationFrame = animationFrame
if isExpanded && !self.hasAppearAnimation {
self.staticAnimationNode.completed = { [weak self] _ in
self?.mainAnimationCompletion?()
}
self.staticAnimationNode.play(fromIndex: 0)
} else if isExpanded, self.animationNode == nil {
let animationNode = AnimatedStickerNode()

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "badgeuser_24.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,78 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 3.729980 3.500000 cm
0.000000 0.000000 0.000000 scn
8.269714 10.000000 m
10.478853 10.000000 12.269714 11.790861 12.269714 14.000000 c
12.269714 16.209139 10.478853 18.000000 8.269714 18.000000 c
6.060575 18.000000 4.269714 16.209139 4.269714 14.000000 c
4.269714 11.790861 6.060575 10.000000 8.269714 10.000000 c
h
16.238016 3.829396 m
15.145898 5.884616 12.897719 8.000000 8.269734 8.000000 c
3.641746 8.000000 1.393565 5.884617 0.301445 3.829397 c
-0.735194 1.878584 1.060591 0.000000 3.269730 0.000000 c
13.269731 0.000000 l
15.478869 0.000000 17.274656 1.878582 16.238016 3.829396 c
h
f*
n
Q
endstream
endobj
3 0 obj
664
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000754 00000 n
0000000776 00000 n
0000000949 00000 n
0000001023 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1082
%%EOF

View File

@ -1,6 +1,7 @@
{
"images" : [
{
"filename" : "badgedoc_24.pdf",
"idiom" : "universal"
}
],

View File

@ -0,0 +1,119 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.000000 3.000000 cm
0.000000 0.000000 0.000000 scn
5.330000 18.000000 m
5.807298 18.000000 6.123703 17.999550 6.367812 17.982895 c
6.604466 17.966749 6.711959 17.938187 6.777740 17.910938 c
7.064423 17.792191 7.292191 17.564423 7.410939 17.277740 c
7.438186 17.211960 7.466748 17.104465 7.482895 16.867813 c
7.499550 16.623703 7.500000 16.307299 7.500000 15.830000 c
7.500000 13.530003 l
7.500000 13.496872 l
7.499987 12.965037 7.499976 12.516354 7.530005 12.148819 c
7.561447 11.763987 7.629904 11.395631 7.808452 11.045210 c
8.079773 10.512712 8.512709 10.079777 9.045207 9.808455 c
9.395627 9.629908 9.763983 9.561451 10.148815 9.530008 c
10.516351 9.499980 10.965034 9.499990 11.496870 9.500004 c
11.530001 9.500004 l
13.829997 9.500004 l
14.307296 9.500004 14.623703 9.499555 14.867812 9.482899 c
15.104466 9.466752 15.211960 9.438190 15.277740 9.410942 c
15.564423 9.292194 15.792191 9.064426 15.910938 8.777744 c
15.938186 8.711964 15.966748 8.604470 15.982895 8.367816 c
15.999551 8.123706 16.000000 7.807300 16.000000 7.330000 c
16.000000 4.800000 l
16.000000 3.119843 16.000000 2.279763 15.673019 1.638029 c
15.385400 1.073542 14.926457 0.614601 14.361972 0.326981 c
13.720237 0.000000 12.880157 0.000000 11.200000 0.000000 c
4.800000 0.000000 l
3.119843 0.000000 2.279764 0.000000 1.638029 0.326981 c
1.073542 0.614601 0.614601 1.073542 0.326980 1.638029 c
0.000000 2.279763 0.000000 3.119843 0.000000 4.800000 c
0.000000 13.200001 l
0.000000 14.880157 0.000000 15.720236 0.326980 16.361971 c
0.614601 16.926458 1.073542 17.385399 1.638029 17.673019 c
2.279764 18.000000 3.119843 18.000000 4.800000 18.000000 c
5.330000 18.000000 l
h
15.621112 11.042418 m
15.558301 11.176268 15.488032 11.306717 15.410561 11.433140 c
15.163194 11.836806 14.817290 12.182710 14.125484 12.874516 c
10.874516 16.125484 l
10.182710 16.817291 9.836806 17.163193 9.433140 17.410561 c
9.306716 17.488033 9.176266 17.558304 9.042415 17.621115 c
9.097363 17.412268 9.124138 17.199299 9.139045 16.980810 c
9.160017 16.673437 9.160009 16.300030 9.160000 15.857494 c
9.160000 15.830000 l
9.160000 13.530003 l
9.160000 12.956255 9.160645 12.575861 9.184492 12.283996 c
9.207546 12.001820 9.248083 11.876238 9.287522 11.798835 c
9.399694 11.578686 9.578682 11.399698 9.798831 11.287526 c
9.876234 11.248087 10.001816 11.207550 10.283993 11.184496 c
10.575858 11.160649 10.956251 11.160004 11.530001 11.160004 c
13.829997 11.160004 l
13.857491 11.160004 l
14.300028 11.160013 14.673436 11.160021 14.980811 11.139048 c
15.199297 11.124141 15.412265 11.097366 15.621112 11.042418 c
h
f*
n
Q
endstream
endobj
3 0 obj
2637
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000002727 00000 n
0000002750 00000 n
0000002923 00000 n
0000002997 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
3056
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "addone.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,115 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 11.600000 m
0.000000 13.840210 0.000000 14.960315 0.435974 15.815962 c
0.819467 16.568611 1.431390 17.180532 2.184038 17.564026 c
3.039685 18.000000 4.159790 18.000000 6.400001 18.000000 c
17.600000 18.000000 l
19.840210 18.000000 20.960316 18.000000 21.815962 17.564026 c
22.568611 17.180532 23.180532 16.568611 23.564026 15.815962 c
24.000000 14.960315 24.000000 13.840210 24.000000 11.600000 c
24.000000 6.400000 l
24.000000 4.159790 24.000000 3.039685 23.564026 2.184038 c
23.180532 1.431389 22.568611 0.819468 21.815962 0.435974 c
20.960316 0.000000 19.840210 0.000000 17.600000 0.000000 c
6.400000 0.000000 l
4.159790 0.000000 3.039685 0.000000 2.184038 0.435974 c
1.431390 0.819468 0.819467 1.431389 0.435974 2.184038 c
0.000000 3.039685 0.000000 4.159790 0.000000 6.400001 c
0.000000 11.600000 l
h
16.820312 3.856445 m
17.428711 3.856445 17.838867 4.266602 17.838867 4.888672 c
17.838867 12.859375 l
17.838867 13.570312 17.401367 14.014648 16.669922 14.014648 c
16.246094 14.014648 15.917969 13.953125 15.439453 13.625000 c
13.484375 12.271484 l
13.163086 12.045898 13.040039 11.813477 13.040039 11.499023 c
13.040039 11.061523 13.347656 10.760742 13.764648 10.760742 c
13.976562 10.760742 14.120117 10.808594 14.311523 10.945312 c
15.753906 11.950195 l
15.794922 11.950195 l
15.794922 4.888672 l
15.794922 4.266602 16.211914 3.856445 16.820312 3.856445 c
h
9.388672 6.127930 m
9.388672 5.540039 9.053711 5.177734 8.500000 5.177734 c
7.939453 5.177734 7.604492 5.540039 7.604492 6.127930 c
7.604492 8.083008 l
5.738281 8.083008 l
5.177734 8.083008 4.822266 8.411133 4.822266 8.958008 c
4.822266 9.498047 5.177734 9.826172 5.738281 9.826172 c
7.604492 9.826172 l
7.604492 11.794922 l
7.604492 12.375977 7.946289 12.745117 8.500000 12.745117 c
9.053711 12.745117 9.388672 12.375977 9.388672 11.794922 c
9.388672 9.826172 l
11.248047 9.826172 l
11.815430 9.826172 12.170898 9.498047 12.170898 8.958008 c
12.170898 8.411133 11.808594 8.083008 11.241211 8.083008 c
9.388672 8.083008 l
9.388672 6.127930 l
h
f*
n
Q
endstream
endobj
3 0 obj
2145
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 18.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000002235 00000 n
0000002258 00000 n
0000002431 00000 n
0000002505 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2564
%%EOF

View File

@ -957,8 +957,10 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}, action: { _, f in
let _ = (saveToCameraRoll(context: context, postbox: context.account.postbox, mediaReference: mediaReference)
|> deliverOnMainQueue).start(completed: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .mediaSaved(text: isVideo ? presentationData.strings.Gallery_VideoSaved : presentationData.strings.Gallery_ImageSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return true }), nil)
Queue.mainQueue().after(0.2) {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .mediaSaved(text: isVideo ? presentationData.strings.Gallery_VideoSaved : presentationData.strings.Gallery_ImageSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return true }), nil)
}
})
f(.default)
})))
@ -1219,24 +1221,26 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let _ = (toggleGifSaved(account: context.account, fileReference: .message(message: MessageReference(message), media: file), saved: true)
|> deliverOnMainQueue).start(next: { result in
switch result {
case .generic:
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
case let .limitExceeded(limit, premiumLimit):
let text: String
if limit == premiumLimit {
text = presentationData.strings.Premium_MaxSavedGifsFinalText
} else {
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
}
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in
if case .info = action {
let controller = PremiumIntroScreen(context: context, source: .savedGifs)
controllerInteraction.navigationController()?.pushViewController(controller)
return true
Queue.mainQueue().after(0.2) {
switch result {
case .generic:
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil)
case let .limitExceeded(limit, premiumLimit):
let text: String
if limit == premiumLimit {
text = presentationData.strings.Premium_MaxSavedGifsFinalText
} else {
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
}
return false
}), nil)
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: false, action: { action in
if case .info = action {
let controller = PremiumIntroScreen(context: context, source: .savedGifs)
controllerInteraction.navigationController()?.pushViewController(controller)
return true
}
return false
}), nil)
}
}
})

View File

@ -1495,7 +1495,7 @@ final class ChatMediaInputNode: ChatInputNode {
|> deliverOnMainQueue).start(next: { result in
switch result {
case .generic:
controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil)
case let .limitExceeded(limit, premiumLimit):
let text: String
if limit == premiumLimit {
@ -1503,7 +1503,7 @@ final class ChatMediaInputNode: ChatInputNode {
} else {
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
}
controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in
controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: false, action: { action in
if case .info = action {
let controller = PremiumIntroScreen(context: context, source: .savedGifs)
controllerInteraction.navigationController()?.pushViewController(controller)

View File

@ -201,7 +201,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont
|> deliverOnMainQueue).start(next: { result in
switch result {
case .generic:
interfaceInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
interfaceInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil)
case let .limitExceeded(limit, premiumLimit):
let text: String
if limit == premiumLimit {
@ -209,7 +209,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont
} else {
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
}
interfaceInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in
interfaceInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: false, action: { action in
if case .info = action {
let controller = PremiumIntroScreen(context: context, source: .savedGifs)
interfaceInteraction?.getNavigationController()?.pushViewController(controller)