diff --git a/Telegram/Telegram-iOS/Resources/GiftDiamond.tgs b/Telegram/Telegram-iOS/Resources/GiftDiamond.tgs deleted file mode 100644 index 60709e5bbd..0000000000 Binary files a/Telegram/Telegram-iOS/Resources/GiftDiamond.tgs and /dev/null differ diff --git a/Telegram/Telegram-iOS/Resources/GiftDiamond1.tgs b/Telegram/Telegram-iOS/Resources/GiftDiamond1.tgs new file mode 100644 index 0000000000..7a0a883ac4 Binary files /dev/null and b/Telegram/Telegram-iOS/Resources/GiftDiamond1.tgs differ diff --git a/Telegram/Telegram-iOS/Resources/GiftDiamond2.tgs b/Telegram/Telegram-iOS/Resources/GiftDiamond2.tgs new file mode 100644 index 0000000000..caa69f5266 Binary files /dev/null and b/Telegram/Telegram-iOS/Resources/GiftDiamond2.tgs differ diff --git a/Telegram/Telegram-iOS/Resources/GiftDiamond3.tgs b/Telegram/Telegram-iOS/Resources/GiftDiamond3.tgs new file mode 100644 index 0000000000..bcf3609d1f Binary files /dev/null and b/Telegram/Telegram-iOS/Resources/GiftDiamond3.tgs differ diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 2ee614d0c8..8fbcc99a42 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -14504,4 +14504,6 @@ Sorry for the inconvenience."; "Bot.AddToGroup.Title" = "Add to Group"; "Bot.AddToChannel.Title" = "Add to Channel"; -"ScheduledMessages.TodoUnavailable" = "Voting will become available after the message is published."; +"ScheduledMessages.TodoUnavailable" = "Completing tasks will become available after the message is published."; + +"Attachment.DiscardTodoAlertText" = "Discard checklist items?"; diff --git a/submodules/ComposePollUI/Sources/ComposePollScreen.swift b/submodules/ComposePollUI/Sources/ComposePollScreen.swift index ad42d62299..5e11feb4dd 100644 --- a/submodules/ComposePollUI/Sources/ComposePollScreen.swift +++ b/submodules/ComposePollUI/Sources/ComposePollScreen.swift @@ -1834,7 +1834,7 @@ public class ComposePollScreen: ViewControllerComponentContainer, AttachmentCont public func prepareForReuse() { } - public func requestDismiss(completion: @escaping () -> Void) { + public func requestDismiss(completion: @escaping () -> Void) { completion() } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift index c32acf3826..1f898eb3df 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift @@ -442,7 +442,7 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { } } for i in 0 ..< labelRects.count { - labelRects[i] = labelRects[i].insetBy(dx: -6.0, dy: floor((labelRects[i].height - 22.0) / 2.0)) + labelRects[i] = labelRects[i].insetBy(dx: -7.0, dy: floor((labelRects[i].height - 22.0) / 2.0)) labelRects[i].size.height = 22.0 labelRects[i].origin.x = floor((labelLayout.size.width - labelRects[i].width) / 2.0) } @@ -458,7 +458,7 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { if let (currentOffset, currentImage, currentRects) = cachedMaskBackgroundImage, currentRects == labelRects { backgroundMaskImage = (currentOffset, currentImage) } else { - backgroundMaskImage = LinkHighlightingNode.generateImage(color: .white, inset: 0.0, innerRadius: 10.0, outerRadius: 10.0, rects: labelRects, useModernPathCalculation: false) + backgroundMaskImage = LinkHighlightingNode.generateImage(color: .white, inset: 0.0, innerRadius: 11.0, outerRadius: 11.0, rects: labelRects, useModernPathCalculation: false) backgroundMaskUpdated = true } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift index 44bf777edc..6bdd21ecc7 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode/Sources/ChatMessageGiftBubbleContentNode.swift @@ -417,21 +417,22 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { } title = item.presentationData.strings.Notification_StarsGift_Title(Int32(count)) text = incoming ? item.presentationData.strings.Notification_StarsGift_Subtitle : item.presentationData.strings.Notification_StarsGift_SubtitleYou(peerName).string - case let .giftTon(currency, amount, cryptoCurrency, cryptoAmount, _): - months = 1000 + case let .giftTon(_, amount, _, cryptoAmount, _): + if amount < 10000000000 { + months = 1000 + } else if amount < 50000000000 { + months = 2000 + } else { + months = 3000 + } var peerName = "" if let peer = item.message.peers[item.message.id.peerId] { peerName = EnginePeer(peer).compactDisplayTitle } - //TODO:localize - let _ = currency - let _ = amount - let _ = cryptoCurrency - let cryptoAmount = cryptoAmount ?? 0 - title = "$ \(formatTonAmountText(cryptoAmount, dateTimeFormat: item.presentationData.dateTimeFormat))" + title = "$ \(formatTonAmountText(cryptoAmount, dateTimeFormat: item.presentationData.dateTimeFormat, maxDecimalPositions: 3))" text = incoming ? "Use TON to submit post suggestions to channels." : "With TON, \(peerName) will be able to submit post suggestions to channels." buttonTitle = "" case let .prizeStars(count, _, channelId, _, _): @@ -644,7 +645,11 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { switch months { case 1000: - animationName = "GiftDiamond" + animationName = "GiftDiamond1" + case 2000: + animationName = "GiftDiamond2" + case 3000: + animationName = "GiftDiamond3" case 12: animationName = "Gift12" case 6: @@ -787,8 +792,8 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { } } for i in 0 ..< labelRects.count { - labelRects[i] = labelRects[i].insetBy(dx: -6.0, dy: floor((labelRects[i].height - 20.0) / 2.0)) - labelRects[i].size.height = 20.0 + labelRects[i] = labelRects[i].insetBy(dx: -7.0, dy: floor((labelRects[i].height - 22.0) / 2.0)) + labelRects[i].size.height = 22.0 labelRects[i].origin.x = floor((labelLayout.size.width - labelRects[i].width) / 2.0) } @@ -798,7 +803,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { if let (currentOffset, currentImage, currentRects) = cachedMaskBackgroundImage, currentRects == labelRects { backgroundMaskImage = (currentOffset, currentImage) } else { - backgroundMaskImage = LinkHighlightingNode.generateImage(color: .black, inset: 0.0, innerRadius: 10.0, outerRadius: 10.0, rects: labelRects, useModernPathCalculation: false) + backgroundMaskImage = LinkHighlightingNode.generateImage(color: .black, inset: 0.0, innerRadius: 11.0, outerRadius: 11.0, rects: labelRects, useModernPathCalculation: false) backgroundMaskUpdated = true } } else { @@ -807,7 +812,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { var backgroundSize = giftSize if hasServiceMessage { - backgroundSize.height += labelLayout.size.height + 18.0 + backgroundSize.height += labelLayout.size.height + 20.0 } else { backgroundSize.height += 4.0 } @@ -828,7 +833,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { let overlayColor = item.presentationData.theme.theme.overallDarkAppearance && uniquePatternFile == nil ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12) - let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - giftSize.width) / 2.0), y: hasServiceMessage ? labelLayout.size.height + 12.0 : 0.0), size: giftSize) + let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - giftSize.width) / 2.0), y: hasServiceMessage ? labelLayout.size.height + 13.0 : 0.0), size: giftSize) let mediaBackgroundFrame = imageFrame.insetBy(dx: -2.0, dy: -2.0) var iconSize = CGSize(width: 160.0, height: 160.0) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift index 3cd40d5a24..fe537f66c2 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift @@ -376,6 +376,7 @@ private final class ChatMessageTodoItemNode: ASDisplayNode { private var backgroundWallpaperNode: ChatMessageBubbleBackdrop? private var backgroundNode: ChatMessageBackground? private var extractedRadioView: UIView? + private var extractedIconView: UIView? private var extractedAvatarView: UIView? private var extractedTitleNode: TextNodeWithEntities? private var extractedNameView: UIView? @@ -549,6 +550,11 @@ private final class ChatMessageTodoItemNode: ASDisplayNode { // self.backgroundWallpaperNode?.update(rect: mappedRect, within: containerSize) // } + if let extractedIconView = self.iconNode?.view.snapshotContentTree() { + self.extractedIconView = extractedIconView + self.contextSourceNode.contentNode.view.addSubview(extractedIconView) + } + if let extractedRadioView = self.radioNode?.view.snapshotContentTree() { self.extractedRadioView = extractedRadioView self.contextSourceNode.contentNode.view.addSubview(extractedRadioView) @@ -585,6 +591,8 @@ private final class ChatMessageTodoItemNode: ASDisplayNode { transition.updateAlpha(node: backgroundNode, alpha: 0.0, completion: { [weak backgroundNode] _ in self.extractedRadioView?.removeFromSuperview() self.extractedRadioView = nil + self.extractedIconView?.removeFromSuperview() + self.extractedIconView = nil self.extractedAvatarView?.removeFromSuperview() self.extractedAvatarView = nil self.extractedTitleNode?.textNode.removeFromSupernode() @@ -737,7 +745,7 @@ private final class ChatMessageTodoItemNode: ASDisplayNode { } else { titleNodeFrame = CGRect(origin: CGPoint(x: leftInset, y: 12.0), size: titleLayout.size) } - if let _ = completion, canMark && todo.flags.contains(.othersCanComplete) { + if let _ = completion, todo.flags.contains(.othersCanComplete) { titleNodeFrame = titleNodeFrame.offsetBy(dx: 0.0, dy: -6.0) } diff --git a/submodules/TelegramUI/Components/ComposeTodoScreen/Sources/ComposeTodoScreen.swift b/submodules/TelegramUI/Components/ComposeTodoScreen/Sources/ComposeTodoScreen.swift index 45e196a195..11bf50912b 100644 --- a/submodules/TelegramUI/Components/ComposeTodoScreen/Sources/ComposeTodoScreen.swift +++ b/submodules/TelegramUI/Components/ComposeTodoScreen/Sources/ComposeTodoScreen.swift @@ -28,6 +28,7 @@ import TextFormat import TextFieldComponent import ListComposePollOptionComponent import Markdown +import PresentationDataUtils final class ComposeTodoScreenComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -1750,10 +1751,30 @@ public class ComposeTodoScreen: ViewControllerComponentContainer, AttachmentCont } public func requestDismiss(completion: @escaping () -> Void) { - completion() + guard let componentView = self.node.hostView.componentView as? ComposeTodoScreenComponent.View else { + return + } + let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } + if let input = componentView.validatedInput(), !input.text.isEmpty || !input.items.isEmpty { + let text = presentationData.strings.Attachment_DiscardTodoAlertText + let controller = textAlertController(context: self.context, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Attachment_CancelSelectionAlertNo, action: { + }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Attachment_CancelSelectionAlertYes, action: { + completion() + })]) + self.present(controller, in: .window(.root)) + } else { + completion() + } } public func shouldDismissImmediately() -> Bool { - return true + guard let componentView = self.node.hostView.componentView as? ComposeTodoScreenComponent.View else { + return true + } + if let input = componentView.validatedInput(), !input.text.isEmpty || !input.items.isEmpty { + return false + } else { + return true + } } } diff --git a/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift b/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift index f58ef64eeb..d30878f224 100644 --- a/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift +++ b/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift @@ -802,8 +802,13 @@ public final class ListComposePollOptionComponent: Component { } if let deleteAction = component.deleteAction { - if self.deleteRevealView == nil { - let deleteRevealView = DeleteRevealView(title: component.strings.Common_Delete, color: component.theme.list.itemDisclosureActions.destructive.fillColor) + var deleteRevealViewTransition = transition + let deleteRevealView: DeleteRevealView + if let current = self.deleteRevealView { + deleteRevealView = current + } else { + deleteRevealViewTransition = .immediate + deleteRevealView = DeleteRevealView(title: component.strings.Common_Delete, color: component.theme.list.itemDisclosureActions.destructive.fillColor) deleteRevealView.tapped = { [weak self] action in guard let self else { return @@ -818,14 +823,17 @@ public final class ListComposePollOptionComponent: Component { } self.deleteRevealView = deleteRevealView self.addSubview(deleteRevealView) + + if self.recognizer == nil { + let recognizer = RevealOptionsGestureRecognizer(target: self, action: #selector(self.handlePan(_:))) + recognizer.delegate = self + self.addGestureRecognizer(recognizer) + self.recognizer = recognizer + } } - if self.recognizer == nil { - let recognizer = RevealOptionsGestureRecognizer(target: self, action: #selector(self.handlePan(_:))) - recognizer.delegate = self - self.addGestureRecognizer(recognizer) - self.recognizer = recognizer - } + let _ = deleteRevealView.updateLayout(availableSize: size, revealOffset: self.revealOffset, transition: deleteRevealViewTransition) + deleteRevealView.frame = CGRect(origin: .zero, size: size) } else { if let deleteRevealView = self.deleteRevealView { self.deleteRevealView = nil @@ -841,11 +849,6 @@ public final class ListComposePollOptionComponent: Component { self.revealOffset = 0.0 } - if let deleteRevealView = self.deleteRevealView { - let _ = deleteRevealView.updateLayout(availableSize: size, revealOffset: self.revealOffset, transition: transition) - deleteRevealView.frame = CGRect(origin: .zero, size: size) - } - self.separatorInset = leftInset return size diff --git a/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift b/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift index 01e9437a83..fe3287bfe5 100644 --- a/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift +++ b/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift @@ -851,10 +851,26 @@ public final class StarsImageComponent: Component { if let current = self.animationNode { animationNode = current } else { - let stickerName: String = count == 1000 ? "GiftDiamond" : "Gift\(count)" + let animationName: String + switch count { + case 1000: + animationName = "GiftDiamond1" + case 2000: + animationName = "GiftDiamond2" + case 3000: + animationName = "GiftDiamond3" + case 12: + animationName = "Gift12" + case 6: + animationName = "Gift6" + case 3: + animationName = "Gift3" + default: + animationName = "Gift3" + } animationNode = DefaultAnimatedStickerNodeImpl() animationNode.autoplay = true - animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: stickerName), width: 384, height: 384, playbackMode: .still(.end), mode: .direct(cachePathPrefix: nil)) + animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 384, height: 384, playbackMode: .still(.end), mode: .direct(cachePathPrefix: nil)) animationNode.visibility = true containerNode.view.addSubview(animationNode.view) self.animationNode = animationNode diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenTodoContextMenu.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenTodoContextMenu.swift index 4e7950a5f3..e82d49d104 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenTodoContextMenu.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenTodoContextMenu.swift @@ -222,14 +222,12 @@ extension ChatControllerImpl { self.canReadHistory.set(false) - //TODO:localize var sources: [ContextController.Source] = [] sources.append( ContextController.Source( id: AnyHashable(OptionsId.item), title: self.presentationData.strings.Chat_Todo_ContextMenu_SectionTask, footer: self.presentationData.strings.Chat_Todo_ContextMenu_SectionsInfo, - //source: .extracted(ChatMessageLinkContextExtractedContentSource(chatNode: self.chatDisplayNode, contentNode: contentNode)), source: .extracted(ChatTodoItemContextExtractedContentSource(chatNode: self.chatDisplayNode, contentNode: contentNode)), items: .single(ContextController.Items(content: .list(items))) ) diff --git a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift index 8de16d6c54..367095962b 100644 --- a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift +++ b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift @@ -90,9 +90,11 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou if item.content.contains(where: { $0.0.stableId == self.message.stableId }), let contentNode = itemNode.getMessageContextSourceNode(stableId: self.selectAll ? nil : self.message.stableId) { result = ContextControllerTakeViewInfo(containingItem: .node(contentNode), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) - if self.snapshot, let snapshotView = contentNode.contentNode.view.snapshotContentTree(unhide: false, keepPortals: true, keepTransform: true) { - contentNode.view.superview?.addSubview(snapshotView) - self.snapshotView = snapshotView + Queue.mainQueue().justDispatch { + if self.snapshot, let snapshotView = contentNode.contentNode.view.snapshotContentTree(unhide: false, keepPortals: true, keepTransform: true) { + contentNode.view.superview?.addSubview(snapshotView) + self.snapshotView = snapshotView + } } } }