Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2022-04-05 16:50:18 +04:00
commit 45eb31ebc8
14 changed files with 195 additions and 26 deletions

View File

@ -1152,6 +1152,15 @@
"MuteFor.Days_many" = "Mute for %@ days"; "MuteFor.Days_many" = "Mute for %@ days";
"MuteFor.Days_0" = "Mute for %@ days"; "MuteFor.Days_0" = "Mute for %@ days";
"MutedForTime.Minutes_1" = "1 minute";
"MutedForTime.Minutes_any" = "%@ minutes";
"MutedForTime.Hours_1" = "1 hour";
"MutedForTime.Hours_any" = "%@ hours";
"MutedForTime.Days_1" = "1 day";
"MutedForTime.Days_any" = "%@ days";
"MuteExpires.Minutes_1" = "in 1 minute"; "MuteExpires.Minutes_1" = "in 1 minute";
"MuteExpires.Minutes_2" = "in 2 minutes"; "MuteExpires.Minutes_2" = "in 2 minutes";
"MuteExpires.Minutes_3_10" = "in %@ minutes"; "MuteExpires.Minutes_3_10" = "in %@ minutes";
@ -7469,3 +7478,10 @@ Sorry for the inconvenience.";
"PeerInfo.ClearMessages" = "Clear Messages"; "PeerInfo.ClearMessages" = "Clear Messages";
"PeerInfo.ClearConfirmationUser" = "Are you sure you want to delete all messages with %@?"; "PeerInfo.ClearConfirmationUser" = "Are you sure you want to delete all messages with %@?";
"PeerInfo.ClearConfirmationGroup" = "Are you sure you want to delete all messages in %@?"; "PeerInfo.ClearConfirmationGroup" = "Are you sure you want to delete all messages in %@?";
"PeerInfo.TooltipSoundEnabled" = "You will receive notifications with sound.";
"PeerInfo.TooltipSoundDisabled" = "You will receive silent notifications.";
"PeerInfo.TooltipUnmuted" = "Notifications are unmuted.";
"PeerInfo.TooltipMutedFor" = "Notifications are muted for %@.";
"PeerInfo.TooltipMutedUntil" = "Notifications are muted until %@.";
"PeerInfo.TooltipMutedForever" = "Notifications are muted.";

View File

@ -44,7 +44,7 @@ class BazelCommandLine:
# repository), but disabling it also causes a noticeable build time regression # repository), but disabling it also causes a noticeable build time regression
# so it can be explicitly re-enabled by users who are not affected by those # so it can be explicitly re-enabled by users who are not affected by those
# crashes. # crashes.
'--features=swift.use_global_module_cache', #'--features=swift.use_global_module_cache',
# https://docs.bazel.build/versions/master/command-line-reference.html # https://docs.bazel.build/versions/master/command-line-reference.html
# Print the subcommand details in case of failure. # Print the subcommand details in case of failure.

View File

@ -554,7 +554,7 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
(self.navigationController as? NavigationController)?.pushViewController(controller) (self.navigationController as? NavigationController)?.pushViewController(controller)
} }
public func present(_ controller: ViewController, in context: PresentationContextType, with arguments: Any? = nil, blockInteraction: Bool = false, completion: @escaping () -> Void = {}) { open func present(_ controller: ViewController, in context: PresentationContextType, with arguments: Any? = nil, blockInteraction: Bool = false, completion: @escaping () -> Void = {}) {
if !(controller is StandalonePresentableController), case .window = context, let arguments = arguments as? ViewControllerPresentationArguments, case .modalSheet = arguments.presentationAnimation, self.navigationController != nil { if !(controller is StandalonePresentableController), case .window = context, let arguments = arguments as? ViewControllerPresentationArguments, case .modalSheet = arguments.presentationAnimation, self.navigationController != nil {
controller.navigationPresentation = .modal controller.navigationPresentation = .modal
self.push(controller) self.push(controller)

View File

@ -146,6 +146,16 @@ public func muteForIntervalString(strings: PresentationStrings, value: Int32) ->
} }
} }
public func mutedForTimeIntervalString(strings: PresentationStrings, value: Int32) -> String {
if value < 60 * 60 {
return strings.MutedForTime_Minutes(max(1, value / (60)))
} else if value < 60 * 60 * 24 {
return strings.MutedForTime_Hours(max(1, value / (60 * 60)))
} else {
return strings.MutedForTime_Days(max(1, value / (60 * 60 * 24)))
}
}
public func unmuteIntervalString(strings: PresentationStrings, value: Int32) -> String { public func unmuteIntervalString(strings: PresentationStrings, value: Int32) -> String {
if value < 60 * 60 { if value < 60 * 60 {
return strings.MuteExpires_Minutes(max(1, value / 60)) return strings.MuteExpires_Minutes(max(1, value / 60))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -316,20 +316,70 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
actionTitle = nil actionTitle = nil
} }
var displayCloseButton = false
var displayListButton = false
if isReplyThread || actionTitle != nil { if isReplyThread || actionTitle != nil {
self.closeButton.isHidden = true displayCloseButton = false
self.listButton.isHidden = true displayListButton = false
} else if let message = interfaceState.pinnedMessage { } else if let message = interfaceState.pinnedMessage {
if message.totalCount > 1 { if message.totalCount > 1 {
self.listButton.isHidden = false displayCloseButton = false
self.closeButton.isHidden = true displayListButton = true
} else { } else {
self.listButton.isHidden = true displayCloseButton = true
self.closeButton.isHidden = false displayListButton = false
} }
} else { } else {
displayCloseButton = false
displayListButton = true
}
if displayCloseButton != !self.closeButton.isHidden {
if transition.isAnimated {
if displayCloseButton {
self.closeButton.isHidden = false
self.closeButton.layer.removeAllAnimations()
self.closeButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.closeButton.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2)
} else {
self.closeButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak self] completed in
guard let strongSelf = self, completed else {
return
}
strongSelf.closeButton.isHidden = true
strongSelf.closeButton.layer.removeAllAnimations()
})
self.closeButton.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
}
} else {
self.closeButton.isHidden = !displayCloseButton
self.closeButton.layer.removeAllAnimations()
}
}
if displayListButton != !self.listButton.isHidden {
if transition.isAnimated {
if displayListButton {
self.listButton.isHidden = false self.listButton.isHidden = false
self.closeButton.isHidden = true self.listButton.layer.removeAllAnimations()
self.listButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.listButton.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2)
} else {
self.listButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak self] completed in
guard let strongSelf = self, completed else {
return
}
strongSelf.listButton.isHidden = true
strongSelf.listButton.layer.removeAllAnimations()
})
self.listButton.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
}
} else {
self.listButton.isHidden = !displayCloseButton
self.listButton.layer.removeAllAnimations()
}
} }
let rightInset: CGFloat = 18.0 + rightInset let rightInset: CGFloat = 18.0 + rightInset
@ -343,8 +393,21 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
if let actionTitle = actionTitle { if let actionTitle = actionTitle {
var actionButtonTransition = transition var actionButtonTransition = transition
var animateButtonIn = false
if self.actionButton.isHidden { if self.actionButton.isHidden {
actionButtonTransition = .immediate actionButtonTransition = .immediate
animateButtonIn = true
} else if transition.isAnimated, messageUpdated, actionTitle != self.actionButtonTitleNode.attributedText?.string {
if let buttonSnapshot = self.actionButton.view.snapshotView(afterScreenUpdates: false) {
animateButtonIn = true
buttonSnapshot.frame = self.actionButton.frame
self.actionButton.view.superview?.insertSubview(buttonSnapshot, belowSubview: self.actionButton.view)
buttonSnapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonSnapshot] _ in
buttonSnapshot?.removeFromSuperview()
})
buttonSnapshot.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2)
}
} }
self.actionButton.isHidden = false self.actionButton.isHidden = false
@ -361,10 +424,27 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
actionButtonTransition.updateFrame(node: self.actionButtonTitleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((actionButtonFrame.width - actionButtonTitleSize.width) / 2.0), y: floorToScreenPixels((actionButtonFrame.height - actionButtonTitleSize.height) / 2.0)), size: actionButtonTitleSize)) actionButtonTransition.updateFrame(node: self.actionButtonTitleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((actionButtonFrame.width - actionButtonTitleSize.width) / 2.0), y: floorToScreenPixels((actionButtonFrame.height - actionButtonTitleSize.height) / 2.0)), size: actionButtonTitleSize))
tapButtonRightInset = 18.0 + actionButtonFrame.width tapButtonRightInset = 18.0 + actionButtonFrame.width
} else {
if animateButtonIn {
self.actionButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.actionButton.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2)
}
} else if !self.actionButton.isHidden {
self.actionButton.isHidden = true self.actionButton.isHidden = true
self.actionButtonBackgroundNode.isHidden = true self.actionButtonBackgroundNode.isHidden = true
self.actionButtonTitleNode.isHidden = true self.actionButtonTitleNode.isHidden = true
if transition.isAnimated {
if let buttonSnapshot = self.actionButton.view.snapshotView(afterScreenUpdates: false) {
buttonSnapshot.frame = self.actionButton.frame
self.actionButton.view.superview?.insertSubview(buttonSnapshot, belowSubview: self.actionButton.view)
buttonSnapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonSnapshot] _ in
buttonSnapshot?.removeFromSuperview()
})
buttonSnapshot.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2)
}
}
} }
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: buttonsContainerSize.width - closeButtonSize.width + 1.0, y: 19.0), size: closeButtonSize)) transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: buttonsContainerSize.width - closeButtonSize.width + 1.0, y: 19.0), size: closeButtonSize))

View File

@ -487,6 +487,8 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
if #available(iOS 13.4, *) { if #available(iOS 13.4, *) {
pickerView.preferredDatePickerStyle = .wheels pickerView.preferredDatePickerStyle = .wheels
} }
pickerView.setValue(self.presentationData.theme.list.itemPrimaryTextColor, forKey: "textColor")
pickerView.setValue(false, forKey: "highlightsToday")
pickerView.selectorColor = UIColor(rgb: 0xffffff, alpha: 0.18) pickerView.selectorColor = UIColor(rgb: 0xffffff, alpha: 0.18)
pickerView.addTarget(self, action: #selector(self.dataPickerChanged), for: .valueChanged) pickerView.addTarget(self, action: #selector(self.dataPickerChanged), for: .valueChanged)

View File

@ -1857,7 +1857,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
UIPasteboard.general.string = linkForCopying UIPasteboard.general.string = linkForCopying
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
}))) })))
} }
@ -2898,7 +2898,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
if let strongSelf = self { if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_PhoneCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_PhoneCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
} }
})) }))
} }
@ -2909,7 +2909,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
if let strongSelf = self { if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_UsernameCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_UsernameCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
} }
})) }))
} }
@ -3534,6 +3534,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
case .mute: case .mute:
if let notificationSettings = self.data?.notificationSettings, case .muted = notificationSettings.muteState { if let notificationSettings = self.data?.notificationSettings, case .muted = notificationSettings.muteState {
let _ = self.context.engine.peers.updatePeerMuteSetting(peerId: self.peerId, muteInterval: nil).start() let _ = self.context.engine.peers.updatePeerMuteSetting(peerId: self.peerId, muteInterval: nil).start()
let iconColor: UIColor = .white
self.controller?.present(UndoOverlayController(presentationData: self.presentationData, content: .universal(animation: "anim_profileunmute", scale: 0.075, colors: [
"Middle.Group 1.Fill 1": iconColor,
"Top.Group 1.Fill 1": iconColor,
"Bottom.Group 1.Fill 1": iconColor,
"EXAMPLE.Group 1.Fill 1": iconColor,
"Line.Group 1.Stroke 1": iconColor
], title: nil, text: self.presentationData.strings.PeerInfo_TooltipUnmuted), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
} else { } else {
self.state = self.state.withHighlightedButton(.mute) self.state = self.state.withHighlightedButton(.mute)
if let (layout, navigationHeight) = self.validLayout { if let (layout, navigationHeight) = self.validLayout {
@ -3574,6 +3583,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
return return
} }
let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: value).start() let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: value).start()
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_mute_for", scale: 0.066, colors: [:], title: nil, text: strongSelf.presentationData.strings.PeerInfo_TooltipMutedFor(mutedForTimeIntervalString(strings: strongSelf.presentationData.strings, value: value)).string), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}))) })))
} }
@ -3610,6 +3621,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
return return
} }
let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .default).start() let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .default).start()
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_sound_on", scale: 0.056, colors: [:], title: nil, text: strongSelf.presentationData.strings.PeerInfo_TooltipSoundEnabled), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}))) })))
} else { } else {
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.PeerInfo_DisableSound, icon: { theme in items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.PeerInfo_DisableSound, icon: { theme in
@ -3621,6 +3634,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
return return
} }
let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .none).start() let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .none).start()
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_sound_off", scale: 0.056, colors: [:], title: nil, text: strongSelf.presentationData.strings.PeerInfo_TooltipSoundDisabled), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}))) })))
} }
@ -3655,7 +3670,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}, updatePeerNotificationInterval: { peerId, muteInterval in }, updatePeerNotificationInterval: { peerId, muteInterval in
let _ = (updatePeerNotificationInterval(peerId, muteInterval) let _ = (updatePeerNotificationInterval(peerId, muteInterval)
|> deliverOnMainQueue).start(next: { _ in |> deliverOnMainQueue).start(next: { _ in
guard let strongSelf = self else {
return
}
if let muteInterval = muteInterval, muteInterval == Int32.max {
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_mute_for", scale: 0.056, colors: [:], title: nil, text: strongSelf.presentationData.strings.PeerInfo_TooltipMutedForever), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}
}) })
}, updatePeerDisplayPreviews: { peerId, displayPreviews in }, updatePeerDisplayPreviews: { peerId, displayPreviews in
let _ = (updatePeerDisplayPreviews(peerId, displayPreviews) let _ = (updatePeerDisplayPreviews(peerId, displayPreviews)
@ -3680,6 +3700,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: Int32.max).start() let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: Int32.max).start()
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_mute_for", scale: 0.056, colors: [:], title: nil, text: strongSelf.presentationData.strings.PeerInfo_TooltipMutedForever), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}))) })))
self.view.endEditing(true) self.view.endEditing(true)
@ -3941,7 +3963,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
} }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
} }
}) })
} }
@ -4199,6 +4221,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: nil).start() let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: nil).start()
} else { } else {
let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: value).start() let _ = strongSelf.context.engine.peers.updatePeerMuteSetting(peerId: strongSelf.peerId, muteInterval: value).start()
let timeString = stringForPreciseRelativeTimestamp(strings: strongSelf.presentationData.strings, relativeTimestamp: Int32(Date().timeIntervalSince1970) + value, relativeTo: Int32(Date().timeIntervalSince1970), dateTimeFormat: strongSelf.presentationData.dateTimeFormat)
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_mute_for", scale: 0.056, colors: [:], title: nil, text: strongSelf.presentationData.strings.PeerInfo_TooltipMutedUntil(timeString).string), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
} }
}) })
self.controller?.view.endEditing(true) self.controller?.view.endEditing(true)
@ -4422,7 +4448,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
} }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
} }
}) })
} }
@ -4430,7 +4456,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
shareController.actionCompleted = { [weak self] in shareController.actionCompleted = { [weak self] in
if let strongSelf = self { if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
} }
} }
self.view.endEditing(true) self.view.endEditing(true)
@ -5151,7 +5177,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
} }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
} }
}) })
} }
@ -5159,7 +5185,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
shareController.actionCompleted = { [weak self] in shareController.actionCompleted = { [weak self] in
if let strongSelf = self { if let strongSelf = self {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
} }
} }
strongSelf.view.endEditing(true) strongSelf.view.endEditing(true)
@ -5409,7 +5435,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
var actions: [ContextMenuAction] = [ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuCopy, accessibilityLabel: presentationData.strings.Conversation_ContextMenuCopy), action: { [weak self] in var actions: [ContextMenuAction] = [ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuCopy, accessibilityLabel: presentationData.strings.Conversation_ContextMenuCopy), action: { [weak self] in
UIPasteboard.general.string = text UIPasteboard.general.string = text
self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_TextCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_TextCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
})] })]
let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: false, ignoredLanguages: translationSettings.ignoredLanguages) let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: false, ignoredLanguages: translationSettings.ignoredLanguages)
@ -5436,7 +5462,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
UIPasteboard.general.string = phone UIPasteboard.general.string = phone
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_PhoneCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_PhoneCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
})]) })])
controller.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self, weak sourceNode] in controller.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self, weak sourceNode] in
if let controller = self?.controller, let sourceNode = sourceNode { if let controller = self?.controller, let sourceNode = sourceNode {
@ -5460,7 +5486,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
UIPasteboard.general.string = text UIPasteboard.general.string = text
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
})]) })])
controller.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self, weak sourceNode] in controller.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self, weak sourceNode] in
if let controller = self?.controller, let sourceNode = sourceNode { if let controller = self?.controller, let sourceNode = sourceNode {
@ -6352,7 +6378,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
if let strongSelf = self, let _ = peerSelectionController { if let strongSelf = self, let _ = peerSelectionController {
if peerId == strongSelf.context.account.peerId { if peerId == strongSelf.context.account.peerId {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .window(.root)) strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messageIds.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil) strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone, nil, nil)
@ -7874,6 +7900,12 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
}) })
} }
override public func present(_ controller: ViewController, in context: PresentationContextType, with arguments: Any? = nil, blockInteraction: Bool = false, completion: @escaping () -> Void = {}) {
self.dismissAllTooltips()
super.present(controller, in: context, with: arguments, blockInteraction: blockInteraction, completion: completion)
}
override public func viewWillDisappear(_ animated: Bool) { override public func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated) super.viewWillDisappear(animated)

View File

@ -5,6 +5,7 @@
#import "Instance.h" #import "Instance.h"
#import "InstanceImpl.h" #import "InstanceImpl.h"
#import "v2/InstanceV2Impl.h" #import "v2/InstanceV2Impl.h"
#import "v2_4_0_0/InstanceV2_4_0_0Impl.h"
#include "StaticThreads.h" #include "StaticThreads.h"
#import "VideoCaptureInterface.h" #import "VideoCaptureInterface.h"
@ -918,6 +919,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
tgcalls::Register<tgcalls::InstanceImpl>(); tgcalls::Register<tgcalls::InstanceImpl>();
tgcalls::Register<tgcalls::InstanceV2_4_0_0Impl>();
tgcalls::Register<tgcalls::InstanceV2Impl>(); tgcalls::Register<tgcalls::InstanceV2Impl>();
}); });

@ -1 +1 @@
Subproject commit 96b2bbf3a7b352924998e93c649ef30174a1a433 Subproject commit 4c1a39c67d4b03dd96ac82a9aa2420243f5bd106

View File

@ -41,6 +41,7 @@ public enum UndoOverlayContent {
case inviteRequestSent(title: String, text: String) case inviteRequestSent(title: String, text: String)
case image(image: UIImage, text: String) case image(image: UIImage, text: String)
case notificationSoundAdded(title: String, text: String, action: (() -> Void)?) case notificationSoundAdded(title: String, text: String, action: (() -> Void)?)
case universal(animation: String, scale: CGFloat, colors: [String: UIColor], title: String?, text: String)
} }
public enum UndoOverlayAction { public enum UndoOverlayAction {

View File

@ -789,6 +789,29 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
} }
} }
} }
case let .universal(animation, scale, colors, title, text):
self.avatarNode = nil
self.iconNode = nil
self.iconCheckNode = nil
self.animationNode = AnimationNode(animation: animation, colors: colors, scale: scale)
self.animatedStickerNode = nil
if let title = title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
} else {
self.titleNode.attributedText = nil
}
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor)
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { contents in
return ("URL", contents)
}), textAlignment: .natural)
self.textNode.attributedText = attributedText
self.textNode.maximumNumberOfLines = 5
displayUndo = false
self.originalRemainingSeconds = 3
case let .image(image, text): case let .image(image, text):
self.avatarNode = nil self.avatarNode = nil
self.iconNode = ASImageNode() self.iconNode = ASImageNode()
@ -831,7 +854,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
switch content { switch content {
case .removedChat: case .removedChat:
self.panelWrapperNode.addSubnode(self.timerTextNode) self.panelWrapperNode.addSubnode(self.timerTextNode)
case .archivedChat, .hidArchive, .revealedArchive, .autoDelete, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert, .invitedToVoiceChat, .linkCopied, .banned, .importedMessage, .audioRate, .forward, .gigagroupConversion, .linkRevoked, .voiceChatRecording, .voiceChatFlag, .voiceChatCanSpeak, .sticker, .copy, .mediaSaved, .paymentSent, .image, .inviteRequestSent, .notificationSoundAdded: case .archivedChat, .hidArchive, .revealedArchive, .autoDelete, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert, .invitedToVoiceChat, .linkCopied, .banned, .importedMessage, .audioRate, .forward, .gigagroupConversion, .linkRevoked, .voiceChatRecording, .voiceChatFlag, .voiceChatCanSpeak, .sticker, .copy, .mediaSaved, .paymentSent, .image, .inviteRequestSent, .notificationSoundAdded, .universal:
if self.textNode.tapAttributeAction != nil { if self.textNode.tapAttributeAction != nil {
self.isUserInteractionEnabled = true self.isUserInteractionEnabled = true
} else { } else {