mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-20 10:11:10 +00:00
Merge commit 'c2a10931b6555f868db6d1527d3f6a6583864c48'
This commit is contained in:
commit
ea9f53acb8
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond1.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond1.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond2.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond2.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond3.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond3.tgs
Normal file
Binary file not shown.
@ -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?";
|
||||
|
@ -1178,6 +1178,10 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else if transaction.flags.contains(.isRefund) {
|
||||
title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Refund, font: font, textColor: theme.list.itemPrimaryTextColor)
|
||||
detailText = stringForMediumCompactDate(timestamp: transaction.date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
|
||||
} else if case .peer = transaction.peer {
|
||||
return StarsTransactionItem(context: arguments.context, presentationData: presentationData, transaction: transaction, action: {
|
||||
arguments.openStarsTransaction(transaction)
|
||||
}, sectionId: self.section, style: .blocks)
|
||||
} else {
|
||||
title = NSAttributedString()
|
||||
detailText = ""
|
||||
|
@ -278,17 +278,12 @@ final class StarsTransactionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
}
|
||||
|
||||
let itemLabel: NSAttributedString
|
||||
let labelString: String
|
||||
let formattedLabel = formatCurrencyAmountText(item.transaction.count, dateTimeFormat: item.presentationData.dateTimeFormat, showPlus: true)
|
||||
|
||||
let absCount = StarsAmount(value: abs(item.transaction.count.amount.value), nanos: abs(item.transaction.count.amount.nanos))
|
||||
let formattedLabel = presentationStringsFormattedNumber(absCount, item.presentationData.dateTimeFormat.groupingSeparator)
|
||||
if item.transaction.count.amount < StarsAmount.zero {
|
||||
labelString = "- \(formattedLabel)"
|
||||
} else {
|
||||
labelString = "+ \(formattedLabel)"
|
||||
}
|
||||
let itemLabelColor = labelString.hasPrefix("-") ? item.presentationData.theme.list.itemDestructiveColor : item.presentationData.theme.list.itemDisclosureActions.constructive.fillColor
|
||||
itemLabel = NSAttributedString(string: labelString, font: Font.medium(fontBaseDisplaySize), textColor: itemLabelColor)
|
||||
let smallLabelFont = Font.with(size: floor(fontBaseDisplaySize / 17.0 * 13.0))
|
||||
let labelFont = Font.medium(fontBaseDisplaySize)
|
||||
let labelColor = formattedLabel.hasPrefix("-") ? item.presentationData.theme.list.itemDestructiveColor : item.presentationData.theme.list.itemDisclosureActions.constructive.fillColor
|
||||
itemLabel = tonAmountAttributedString(formattedLabel, integralFont: labelFont, fractionalFont: smallLabelFont, color: labelColor, decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator)
|
||||
|
||||
var itemDateColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
itemDate = stringForMediumCompactDate(timestamp: item.transaction.date, strings: item.presentationData.strings, dateTimeFormat: item.presentationData.dateTimeFormat)
|
||||
@ -334,6 +329,18 @@ final class StarsTransactionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
maximumNumberOfLines: 1
|
||||
)))
|
||||
)
|
||||
|
||||
let itemIconName: String
|
||||
let itemIconColor: UIColor?
|
||||
switch item.transaction.count.currency {
|
||||
case .stars:
|
||||
itemIconName = "Premium/Stars/StarMedium"
|
||||
itemIconColor = nil
|
||||
case .ton:
|
||||
itemIconName = "Ads/TonAbout"
|
||||
itemIconColor = labelColor
|
||||
}
|
||||
|
||||
let itemSize = strongSelf.componentView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(ListActionItemComponent(
|
||||
@ -342,7 +349,7 @@ final class StarsTransactionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
contentInsets: UIEdgeInsets(top: 9.0, left: 0.0, bottom: 8.0, right: 0.0),
|
||||
leftIcon: .custom(AnyComponentWithIdentity(id: "avatar", component: AnyComponent(StarsAvatarComponent(context: item.context, theme: item.presentationData.theme, peer: item.transaction.peer, photo: nil, media: [], uniqueGift: nil, backgroundColor: item.presentationData.theme.list.itemBlocksBackgroundColor))), false),
|
||||
icon: nil,
|
||||
accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: "label", component: AnyComponent(StarsLabelComponent(text: itemLabel))), insets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16.0))),
|
||||
accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: "label", component: AnyComponent(StarsLabelComponent(text: itemLabel, iconName: itemIconName, iconColor: itemIconColor))), insets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16.0))),
|
||||
action: { [weak self] _ in
|
||||
guard let self, let item = self.item else {
|
||||
return
|
||||
|
@ -1447,7 +1447,7 @@ public struct PresentationResourcesChat {
|
||||
|
||||
public static func chatServiceMessageTodoAppendedIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.chatServiceMessageTodoAppendedIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/ServiceTodoIncompleted"), color: .white)
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/ServiceTodoAppended"), color: .white)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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, _):
|
||||
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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,7 +823,6 @@ public final class ListComposePollOptionComponent: Component {
|
||||
}
|
||||
self.deleteRevealView = deleteRevealView
|
||||
self.addSubview(deleteRevealView)
|
||||
}
|
||||
|
||||
if self.recognizer == nil {
|
||||
let recognizer = RevealOptionsGestureRecognizer(target: self, action: #selector(self.handlePan(_:)))
|
||||
@ -826,6 +830,10 @@ public final class ListComposePollOptionComponent: Component {
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
)
|
||||
|
@ -978,6 +978,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
} else if let incompletedTaskId = incompleted.first {
|
||||
todoTaskId = incompletedTaskId
|
||||
}
|
||||
} else if case let .todoAppendTasks(tasks) = action.action {
|
||||
if let task = tasks.first {
|
||||
todoTaskId = task.id
|
||||
}
|
||||
}
|
||||
self.navigateToMessage(from: message.id, to: .id(attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote.flatMap { quote in NavigateToMessageParams.Quote(string: quote.text, offset: quote.offset) } : nil, todoTaskId: todoTaskId)))
|
||||
break
|
||||
|
@ -2132,7 +2132,19 @@ extension ChatControllerImpl {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if canEdit {
|
||||
func areItemsOnlyAppended(existing: [TelegramMediaTodo.Item], updated: [TelegramMediaTodo.Item]) -> Bool {
|
||||
guard updated.count >= existing.count else {
|
||||
return false
|
||||
}
|
||||
for (index, existingItem) in existing.enumerated() {
|
||||
if index >= updated.count || updated[index] != existingItem {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if canEdit && !areItemsOnlyAppended(existing: existingTodo.items, updated: todo.items) {
|
||||
let _ = self.context.engine.messages.requestEditMessage(
|
||||
messageId: messageId,
|
||||
text: "",
|
||||
|
@ -90,12 +90,14 @@ 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))
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -328,11 +328,6 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
||||
|
||||
params.blockInteraction.set(.single(true))
|
||||
|
||||
var presentInCurrent = false
|
||||
if let channel = params.message.peers[params.message.id.peerId] as? TelegramChannel, case .broadcast = channel.info {
|
||||
presentInCurrent = true
|
||||
}
|
||||
|
||||
let _ = (gallery
|
||||
|> deliverOnMainQueue).startStandalone(next: { gallery in
|
||||
params.blockInteraction.set(.single(false))
|
||||
@ -340,13 +335,16 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
||||
gallery.centralItemUpdated = { messageId in
|
||||
params.centralItemUpdated?(messageId)
|
||||
}
|
||||
params.present(gallery, GalleryControllerPresentationArguments(transitionArguments: { messageId, media in
|
||||
|
||||
let arguments = GalleryControllerPresentationArguments(transitionArguments: { messageId, media in
|
||||
let selectedTransitionNode = params.transitionNode(messageId, media, false)
|
||||
if let selectedTransitionNode = selectedTransitionNode {
|
||||
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
||||
}
|
||||
return nil
|
||||
}), presentInCurrent ? .current : .window(.root))
|
||||
})
|
||||
|
||||
params.present(gallery, arguments, .window(.root))
|
||||
})
|
||||
return true
|
||||
case let .secretGallery(gallery):
|
||||
|
Loading…
x
Reference in New Issue
Block a user