diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 9985b8aaa9..df517312fb 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -9057,3 +9057,5 @@ Sorry for the inconvenience."; "Conversation.ForwardOptions.RecipientsMessageForwardHidden" = "Recipients won't see that it was forwarded"; "Conversation.ForwardOptions.RecipientsMessagesForwardVisible" = "Recipients will see they were forwarded"; "Conversation.ForwardOptions.RecipientsMessagesForwardHidden" = "Recipients won't see they were forwarded"; + +"Conversation.SendMessage.SendWhenOnline" = "Send When Online"; diff --git a/submodules/AccountContext/Sources/PeerSelectionController.swift b/submodules/AccountContext/Sources/PeerSelectionController.swift index d00ec3d92f..963dea8a81 100644 --- a/submodules/AccountContext/Sources/PeerSelectionController.swift +++ b/submodules/AccountContext/Sources/PeerSelectionController.swift @@ -83,6 +83,7 @@ public enum AttachmentTextInputPanelSendMode { case generic case silent case schedule + case whenOnline } public protocol PeerSelectionController: ViewController { diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index 4518152426..dd710e2c5e 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -117,6 +117,12 @@ public extension AttachmentContainable { } public enum AttachmentMediaPickerSendMode { + case generic + case silently + case whenOnline +} + +public enum AttachmentMediaPickerAttachmentMode { case media case files } @@ -131,7 +137,7 @@ public protocol AttachmentMediaPickerContext { func mainButtonAction() func setCaption(_ caption: NSAttributedString) - func send(silently: Bool, mode: AttachmentMediaPickerSendMode) + func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) func schedule() } @@ -380,12 +386,14 @@ public class AttachmentController: ViewController { self.panel.sendMessagePressed = { [weak self] mode in if let strongSelf = self { switch mode { - case .generic: - strongSelf.mediaPickerContext?.send(silently: false, mode: .media) - case .silent: - strongSelf.mediaPickerContext?.send(silently: true, mode: .media) - case .schedule: - strongSelf.mediaPickerContext?.schedule() + case .generic: + strongSelf.mediaPickerContext?.send(mode: .generic, attachmentMode: .media) + case .silent: + strongSelf.mediaPickerContext?.send(mode: .silently, attachmentMode: .media) + case .schedule: + strongSelf.mediaPickerContext?.schedule() + case .whenOnline: + strongSelf.mediaPickerContext?.send(mode: .whenOnline, attachmentMode: .media) } } } diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 7e594790c2..305e1df444 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -925,7 +925,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { return } textInputPanelNode.loadTextInputNodeIfNeeded() - guard let textInputNode = textInputPanelNode.textInputNode else { + guard let textInputNode = textInputPanelNode.textInputNode, let peerId = chatLocation.peerId else { return } @@ -933,15 +933,36 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { if case .media = strongSelf.presentationInterfaceState.inputMode { hasEntityKeyboard = true } - - let controller = ChatSendMessageActionSheetController(context: strongSelf.context, peerId: strongSelf.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, attachment: true, completion: { - }, sendMessage: { [weak textInputPanelNode] silently in - textInputPanelNode?.sendMessage(silently ? .silent : .generic) - }, schedule: { [weak textInputPanelNode] in - textInputPanelNode?.sendMessage(.schedule) + let _ = (strongSelf.context.account.viewTracker.peerView(peerId) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] peerView in + guard let strongSelf = self, let peer = peerViewMainPeer(peerView) else { + return + } + var sendWhenOnlineAvailable = false + if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case .present = presence.status { + sendWhenOnlineAvailable = true + } + if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 { + sendWhenOnlineAvailable = false + } + + let controller = ChatSendMessageActionSheetController(context: strongSelf.context, peerId: strongSelf.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, attachment: true, canSendWhenOnline: sendWhenOnlineAvailable, completion: { + }, sendMessage: { [weak textInputPanelNode] mode in + switch mode { + case .generic: + textInputPanelNode?.sendMessage(.generic) + case .silently: + textInputPanelNode?.sendMessage(.silent) + case .whenOnline: + textInputPanelNode?.sendMessage(.whenOnline) + } + }, schedule: { [weak textInputPanelNode] in + textInputPanelNode?.sendMessage(.schedule) + }) + controller.emojiViewProvider = textInputPanelNode.emojiViewProvider + strongSelf.presentInGlobalOverlay(controller) }) - controller.emojiViewProvider = textInputPanelNode.emojiViewProvider - strongSelf.presentInGlobalOverlay(controller) }, openScheduledMessages: { }, openPeersNearby: { }, displaySearchResultsTooltip: { _, _ in diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift index 1406029bcb..cb71a621da 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift @@ -10,6 +10,11 @@ import TelegramCore import TextFormat public final class ChatSendMessageActionSheetController: ViewController { + public enum SendMode { + case generic + case silently + case whenOnline + } private var controllerNode: ChatSendMessageActionSheetControllerNode { return self.displayNode as! ChatSendMessageActionSheetControllerNode } @@ -24,8 +29,9 @@ public final class ChatSendMessageActionSheetController: ViewController { private let sourceSendButton: ASDisplayNode private let textInputNode: EditableTextNode private let attachment: Bool + private let canSendWhenOnline: Bool private let completion: () -> Void - private let sendMessage: (Bool) -> Void + private let sendMessage: (SendMode) -> Void private let schedule: () -> Void private var presentationData: PresentationData @@ -39,7 +45,7 @@ public final class ChatSendMessageActionSheetController: ViewController { public var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id?, forwardMessageIds: [EngineMessage.Id]?, hasEntityKeyboard: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool = false, completion: @escaping () -> Void, sendMessage: @escaping (Bool) -> Void, schedule: @escaping () -> Void) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id?, forwardMessageIds: [EngineMessage.Id]?, hasEntityKeyboard: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool = false, canSendWhenOnline: Bool, completion: @escaping () -> Void, sendMessage: @escaping (SendMode) -> Void, schedule: @escaping () -> Void) { self.context = context self.peerId = peerId self.forwardMessageIds = forwardMessageIds @@ -48,6 +54,7 @@ public final class ChatSendMessageActionSheetController: ViewController { self.sourceSendButton = sourceSendButton self.textInputNode = textInputNode self.attachment = attachment + self.canSendWhenOnline = canSendWhenOnline self.completion = completion self.sendMessage = sendMessage self.schedule = schedule @@ -95,11 +102,14 @@ public final class ChatSendMessageActionSheetController: ViewController { canSchedule = !isSecret } - self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, forwardedCount: forwardedCount, hasEntityKeyboard: self.hasEntityKeyboard, emojiViewProvider: self.emojiViewProvider, send: { [weak self] in - self?.sendMessage(false) + self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, canSendWhenOnline: self.canSendWhenOnline, forwardedCount: forwardedCount, hasEntityKeyboard: self.hasEntityKeyboard, emojiViewProvider: self.emojiViewProvider, send: { [weak self] in + self?.sendMessage(.generic) self?.dismiss(cancel: false) }, sendSilently: { [weak self] in - self?.sendMessage(true) + self?.sendMessage(.silently) + self?.dismiss(cancel: false) + }, sendWhenOnline: { [weak self] in + self?.sendMessage(.whenOnline) self?.dismiss(cancel: false) }, schedule: !canSchedule ? nil : { [weak self] in self?.schedule() diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift index e90286ade0..7035561189 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -17,15 +17,18 @@ private let rightInset: CGFloat = 16.0 private enum ChatSendMessageActionIcon { case sendWithoutSound + case sendWhenOnline case schedule func image(theme: PresentationTheme) -> UIImage? { let imageName: String switch self { - case .sendWithoutSound: - imageName = "Chat/Input/Menu/SilentIcon" - case .schedule: - imageName = "Chat/Input/Menu/ScheduleIcon" + case .sendWithoutSound: + imageName = "Chat/Input/Menu/SilentIcon" + case .sendWhenOnline: + imageName = "Chat/Input/Menu/WhenOnlineIcon" + case .schedule: + imageName = "Chat/Input/Menu/ScheduleIcon" } return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor) } @@ -191,7 +194,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? - init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { + init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, canSendWhenOnline: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, send: (() -> Void)?, sendSilently: (() -> Void)?, sendWhenOnline: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { self.context = context self.presentationData = presentationData self.sourceSendButton = sourceSendButton @@ -249,6 +252,11 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, contentNodes.append(ActionSheetItemNode(theme: self.presentationData.theme, title: self.presentationData.strings.Conversation_SendMessage_SendSilently, icon: .sendWithoutSound, hasSeparator: true, action: { sendSilently?() })) + if canSendWhenOnline { + contentNodes.append(ActionSheetItemNode(theme: self.presentationData.theme, title: self.presentationData.strings.Conversation_SendMessage_SendWhenOnline, icon: .sendWhenOnline, hasSeparator: true, action: { + sendWhenOnline?() + })) + } } if let _ = schedule { contentNodes.append(ActionSheetItemNode(theme: self.presentationData.theme, title: reminders ? self.presentationData.strings.Conversation_SendMessage_SetReminder: self.presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: .schedule, hasSeparator: false, action: { diff --git a/submodules/ComposePollUI/Sources/CreatePollController.swift b/submodules/ComposePollUI/Sources/CreatePollController.swift index 1f5ba3164b..b964e37bdd 100644 --- a/submodules/ComposePollUI/Sources/CreatePollController.swift +++ b/submodules/ComposePollUI/Sources/CreatePollController.swift @@ -536,7 +536,7 @@ private final class CreatePollContext: AttachmentMediaPickerContext { func setCaption(_ caption: NSAttributedString) { } - func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { + func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { } func schedule() { @@ -558,6 +558,44 @@ public class CreatePollControllerImpl: ItemListController, AttachmentContainable public var mediaPickerContext: AttachmentMediaPickerContext? { return CreatePollContext() } + + fileprivate var stateValue: Atomic? + + private var hasContent: Bool { + if let stateValue { + let state = stateValue.with { $0 } + var hasNonEmptyOptions = false + for i in 0 ..< state.options.count { + let optionText = state.options[i].item.text.trimmingCharacters(in: .whitespacesAndNewlines) + if !optionText.isEmpty { + hasNonEmptyOptions = true + } + } + if hasNonEmptyOptions || !state.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + return true + } else { + return false + } + } else { + return false + } + } + + var context: AccountContext? + public func requestDismiss(completion: @escaping () -> Void) { + if self.hasContent, let context = self.context { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + self.present(textAlertController(context: context, updatedPresentationData: nil, title: nil, text: presentationData.strings.CreatePoll_CancelConfirmation, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: { + completion() + })]), in: .window(.root)) + } else { + completion() + } + } + + public func shouldDismissImmediately() -> Bool { + return !self.hasContent + } } public func createPollController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: EnginePeer, isQuiz: Bool? = nil, completion: @escaping (ComposedPoll) -> Void) -> CreatePollControllerImpl { @@ -579,7 +617,6 @@ public func createPollController(context: AccountContext, updatedPresentationDat var ensureSolutionVisibleImpl: (() -> Void)? var ensureQuestionVisibleImpl: (() -> Void)? var displayQuizTooltipImpl: ((Bool) -> Void)? - var attemptNavigationImpl: (() -> Bool)? let actionsDisposable = DisposableSet() @@ -923,9 +960,7 @@ public func createPollController(context: AccountContext, updatedPresentationDat }) let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { - if let attemptNavigationImpl = attemptNavigationImpl, attemptNavigationImpl() { - dismissImpl?() - } + dismissImpl?() }) let optionIds = state.options.map { $0.item.id } @@ -966,6 +1001,8 @@ public func createPollController(context: AccountContext, updatedPresentationDat weak var currentTooltipController: TooltipController? let controller = CreatePollControllerImpl(context: context, state: signal) + controller.context = context + controller.stateValue = stateValue controller.navigationPresentation = .modal controller.visibleBottomContentOffsetChanged = { [weak controller] _ in controller?.updateTabBarAlpha(1.0, .immediate) @@ -1193,31 +1230,6 @@ public func createPollController(context: AccountContext, updatedPresentationDat return .single(didReorder) }) - attemptNavigationImpl = { - let state = stateValue.with { $0 } - var hasNonEmptyOptions = false - for i in 0 ..< state.options.count { - let optionText = state.options[i].item.text.trimmingCharacters(in: .whitespacesAndNewlines) - if !optionText.isEmpty { - hasNonEmptyOptions = true - } - } - if hasNonEmptyOptions || !state.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.CreatePoll_CancelConfirmation, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: { - dismissImpl?() - })]), nil) - return false - } else { - return true - } - } - controller.attemptNavigation = { _ in - if let attemptNavigationImpl = attemptNavigationImpl, attemptNavigationImpl() { - return true - } - return false - } dismissInputImpl = { [weak controller] in controller?.view.endEditing(true) } diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Schedule.imageset/Contents.json b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Schedule.imageset/Contents.json new file mode 100644 index 0000000000..a8b8162849 --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Schedule.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "schedule.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Schedule.imageset/schedule.pdf b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Schedule.imageset/schedule.pdf new file mode 100644 index 0000000000..23e1733493 --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Schedule.imageset/schedule.pdf @@ -0,0 +1,97 @@ +%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.334961 3.334961 cm +0.000000 0.000000 0.000000 scn +8.000000 16.665077 m +8.000000 17.032347 8.297730 17.330078 8.665000 17.330078 c +13.450547 17.330078 17.330002 13.450625 17.330002 8.665078 c +17.330002 3.879531 13.450547 0.000076 8.665000 0.000076 c +3.879452 0.000076 0.000000 3.879531 0.000000 8.665078 c +0.000000 11.755159 1.617408 14.466341 4.050117 16.000078 c +2.165000 16.000078 l +1.797731 16.000078 1.500000 16.297810 1.500000 16.665077 c +1.500000 17.032347 1.797731 17.330078 2.165000 17.330078 c +5.665000 17.330078 l +6.032269 17.330078 6.330000 17.032347 6.330000 16.665077 c +6.330000 13.165078 l +6.330000 12.797809 6.032269 12.500078 5.665000 12.500078 c +5.297730 12.500078 5.000000 12.797809 5.000000 13.165078 c +5.000000 15.020401 l +2.805339 13.751994 1.330000 11.380217 1.330000 8.665078 c +1.330000 4.614069 4.613991 1.330078 8.665000 1.330078 c +12.716009 1.330078 16.000000 4.614069 16.000000 8.665078 c +16.000000 12.716087 12.716009 16.000078 8.665000 16.000078 c +8.297730 16.000078 8.000000 16.297810 8.000000 16.665077 c +h +8.665000 14.330078 m +9.032269 14.330078 9.330000 14.032348 9.330000 13.665078 c +9.330000 8.940530 l +12.135226 6.135303 l +12.394924 5.875606 12.394924 5.454551 12.135226 5.194852 c +11.875527 4.935153 11.454473 4.935153 11.194774 5.194852 c +8.194774 8.194853 l +8.070063 8.319564 8.000000 8.488708 8.000000 8.665078 c +8.000000 13.665078 l +8.000000 14.032348 8.297730 14.330078 8.665000 14.330078 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1511 +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 +0000001601 00000 n +0000001624 00000 n +0000001797 00000 n +0000001871 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1930 +%%EOF \ No newline at end of file diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Silently.imageset/Contents.json b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Silently.imageset/Contents.json new file mode 100644 index 0000000000..47cbacef29 --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Silently.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "sendwithoutsound.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Silently.imageset/sendwithoutsound.pdf b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Silently.imageset/sendwithoutsound.pdf new file mode 100644 index 0000000000..8ad58ec31b --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/Silently.imageset/sendwithoutsound.pdf @@ -0,0 +1,154 @@ +%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.334961 3.205078 cm +0.000000 0.000000 0.000000 scn +1.135226 17.265186 m +0.875527 17.524885 0.454473 17.524885 0.194774 17.265186 c +-0.064925 17.005487 -0.064925 16.584435 0.194774 16.324736 c +16.194775 0.324734 l +16.454473 0.065035 16.875528 0.065035 17.135227 0.324734 c +17.394926 0.584433 17.394926 1.005487 17.135227 1.265186 c +12.830019 5.570395 l +12.830019 13.984108 l +12.830019 14.015735 l +12.830019 14.015746 l +12.830019 14.015758 l +12.830032 14.503190 12.830044 14.912979 12.802612 15.227596 c +12.776955 15.521866 12.718998 15.904351 12.465319 16.192924 c +12.149200 16.552528 11.677307 16.734966 11.201504 16.681524 c +10.819681 16.638639 10.519508 16.394609 10.302576 16.194126 c +10.070642 15.979778 9.794991 15.676547 9.467113 15.315862 c +9.467100 15.315848 l +9.445834 15.292454 l +6.911015 12.504154 l +6.870810 12.460040 l +6.811123 12.459965 l +6.165019 12.459965 l +6.142232 12.459965 l +6.073141 12.459966 6.005919 12.459967 5.940522 12.459891 c +1.135226 17.265186 l +h +7.233788 11.166624 m +11.500019 6.900394 l +11.500019 13.984108 l +11.500019 14.511556 11.499405 14.862436 11.477638 15.112073 c +11.466372 15.241299 11.451292 15.307571 11.443966 15.335192 c +11.425201 15.348718 11.403254 15.357203 11.380270 15.359817 c +11.356270 15.344307 11.300531 15.305413 11.205269 15.217373 c +11.021238 15.047297 10.784756 14.788080 10.429955 14.397799 c +7.895135 11.609499 l +7.876595 11.588985 l +7.810806 11.515999 7.711236 11.405536 7.585287 11.322461 c +7.477557 11.251403 7.358773 11.198743 7.233788 11.166624 c +h +3.310589 11.708942 m +4.251275 10.768256 l +4.114416 10.639768 4.004863 10.482624 3.931640 10.305847 c +3.894677 10.216611 3.864227 10.089064 3.847507 9.844008 c +3.830379 9.592980 3.830019 9.270005 3.830019 8.794965 c +3.830019 8.319924 3.830379 7.996948 3.847507 7.745921 c +3.864227 7.500866 3.894677 7.373319 3.931640 7.284082 c +4.067134 6.956970 4.327024 6.697080 4.654137 6.561585 c +4.743373 6.524623 4.870920 6.494172 5.115975 6.477452 c +5.367003 6.460325 5.689979 6.459965 6.165019 6.459965 c +6.811123 6.459965 l +6.838768 6.460045 l +6.838777 6.460045 l +6.937038 6.460461 7.085750 6.461090 7.231940 6.423779 c +7.357602 6.391706 7.477026 6.338876 7.585287 6.267468 c +7.711238 6.184393 7.810808 6.073929 7.876598 6.000941 c +7.895135 5.980431 l +10.429956 3.192128 l +10.784757 2.801847 11.021239 2.542631 11.205269 2.372556 c +11.300533 2.284515 11.356270 2.245622 11.380270 2.230112 c +11.403254 2.232725 11.425201 2.241211 11.443966 2.254738 c +11.451292 2.282358 11.466372 2.348630 11.477638 2.477856 c +11.498196 2.713622 11.499886 3.039693 11.500010 3.519522 c +12.789057 2.230474 l +12.756243 1.960018 12.682525 1.644088 12.465319 1.397003 c +12.149200 1.037399 11.677307 0.854963 11.201504 0.908403 c +10.819681 0.951288 10.519508 1.195318 10.302577 1.395802 c +10.070659 1.610135 9.795034 1.913337 9.467189 2.273985 c +9.467137 2.274039 l +9.467128 2.274051 l +9.445836 2.297473 l +6.911015 5.085775 l +6.870807 5.129889 l +6.811123 5.129965 l +6.165019 5.129965 l +6.142203 5.129965 l +6.142138 5.129965 l +5.695606 5.129959 5.327103 5.129954 5.025440 5.150537 c +4.712668 5.171878 4.423473 5.217547 4.145168 5.332826 c +3.492168 5.603307 2.973362 6.122113 2.702880 6.775113 c +2.587602 7.053419 2.541932 7.342614 2.520592 7.655386 c +2.500008 7.957066 2.500013 8.325591 2.500019 8.772156 c +2.500019 8.772170 l +2.500019 8.794965 l +2.500019 8.817760 l +2.500019 8.817774 l +2.500013 9.264338 2.500008 9.632866 2.520592 9.934544 c +2.541932 10.247315 2.587602 10.536510 2.702880 10.814816 c +2.843596 11.154535 3.051523 11.457933 3.310589 11.708942 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 3618 +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 +0000003708 00000 n +0000003731 00000 n +0000003904 00000 n +0000003978 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4037 +%%EOF \ No newline at end of file diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/WhenOnline.imageset/Contents.json b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/WhenOnline.imageset/Contents.json new file mode 100644 index 0000000000..9478d5c466 --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/WhenOnline.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "sendthenonline.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/LegacyComponents/LegacyImages.xcassets/Editor/WhenOnline.imageset/sendthenonline.pdf b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/WhenOnline.imageset/sendthenonline.pdf new file mode 100644 index 0000000000..c3c0c5df3b --- /dev/null +++ b/submodules/LegacyComponents/LegacyImages.xcassets/Editor/WhenOnline.imageset/sendthenonline.pdf @@ -0,0 +1,123 @@ +%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 15.000000 4.000000 cm +0.000000 0.000000 0.000000 scn +5.000000 2.500000 m +5.000000 1.119288 3.880712 0.000000 2.500000 0.000000 c +1.119288 0.000000 0.000000 1.119288 0.000000 2.500000 c +0.000000 3.880712 1.119288 5.000000 2.500000 5.000000 c +3.880712 5.000000 5.000000 3.880712 5.000000 2.500000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 3.334961 3.334961 cm +0.000000 0.000000 0.000000 scn +1.330000 8.665078 m +1.330000 12.716087 4.613991 16.000078 8.665000 16.000078 c +12.716008 16.000078 16.000000 12.716087 16.000000 8.665078 c +16.000000 7.971566 15.903754 7.300534 15.723890 6.664610 c +16.154043 6.472708 16.542303 6.203824 16.871166 5.875466 c +17.168650 6.750837 17.330002 7.689115 17.330002 8.665078 c +17.330002 13.450625 13.450547 17.330078 8.665000 17.330078 c +3.879453 17.330078 0.000000 13.450625 0.000000 8.665078 c +0.000000 3.879531 3.879453 0.000076 8.665000 0.000076 c +9.641031 0.000076 10.579370 0.161449 11.454794 0.458973 c +11.126430 0.787828 10.857537 1.176086 10.665626 1.606233 c +10.029655 1.426340 9.358569 1.330078 8.665000 1.330078 c +6.949595 1.330078 5.371725 1.918934 4.122502 2.905533 c +4.297272 3.127586 4.536829 3.393646 4.847776 3.660172 c +5.621715 4.323548 6.847626 5.000078 8.665000 5.000078 c +9.428206 5.000078 10.087104 4.880767 10.652022 4.693223 c +10.837114 5.118156 11.097044 5.502989 11.415169 5.831069 c +10.648278 6.131837 9.735907 6.330078 8.665000 6.330078 c +6.482374 6.330078 4.958285 5.506608 3.982224 4.669984 c +3.639743 4.376429 3.365922 4.082502 3.154341 3.823979 c +2.018686 5.115683 1.330000 6.809955 1.330000 8.665078 c +h +12.678360 5.175269 m +12.317028 4.907584 12.030398 4.544794 11.855478 4.123891 c +12.090899 3.974664 12.299200 3.817050 12.482224 3.660172 c +12.793171 3.393646 13.032728 3.127586 13.207498 2.905533 c +12.806664 2.588965 12.371993 2.313348 11.909800 2.084994 c +12.111738 1.664135 12.428010 1.308554 12.818370 1.058498 c +14.273650 1.854803 15.475398 3.056577 16.271671 4.511877 c +16.021608 4.902231 15.666019 5.218495 15.245155 5.420424 c +14.958824 4.840852 14.598176 4.304554 14.175659 3.823979 c +13.964078 4.082502 13.690256 4.376430 13.347776 4.669984 c +13.147928 4.841282 12.925106 5.012029 12.678360 5.175269 c +h +6.830039 10.665039 m +6.830039 11.678482 7.651597 12.500039 8.665039 12.500039 c +9.678482 12.500039 10.500039 11.678482 10.500039 10.665039 c +10.500039 9.651596 9.678482 8.830039 8.665039 8.830039 c +7.651597 8.830039 6.830039 9.651596 6.830039 10.665039 c +h +8.665039 13.830039 m +6.917058 13.830039 5.500039 12.413020 5.500039 10.665039 c +5.500039 8.917058 6.917058 7.500039 8.665039 7.500039 c +10.413020 7.500039 11.830039 8.917058 11.830039 10.665039 c +11.830039 12.413020 10.413020 13.830039 8.665039 13.830039 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 2777 +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 +0000002867 00000 n +0000002890 00000 n +0000003063 00000 n +0000003137 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +3196 +%%EOF \ No newline at end of file diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h index 3e21657bdc..9f9dbbbeec 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h @@ -95,7 +95,7 @@ typedef enum - (UIBarButtonItem *)leftBarButtonItem; - (UIBarButtonItem *)rightBarButtonItem; -- (void)send:(bool)silently; +- (void)send:(bool)silently whenOnline:(bool)whenOnline; - (void)schedule:(bool)schedule; - (NSArray *)resultSignalsWithCurrentItem:(TGMediaAsset *)currentItem descriptionGenerator:(id (^)(id, NSAttributedString *, NSString *, NSString *))descriptionGenerator; diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerSendActionSheetController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerSendActionSheetController.h index 2dea552b66..e75e0da4f1 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerSendActionSheetController.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaPickerSendActionSheetController.h @@ -6,10 +6,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) void (^send)(void); @property (nonatomic, copy) void (^sendSilently)(void); +@property (nonatomic, copy) void (^sendWhenOnline)(void); @property (nonatomic, copy) void (^schedule)(void); @property (nonatomic, copy) void (^sendWithTimer)(void); -- (instancetype)initWithContext:(id)context isDark:(bool)isDark sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder hasTimer:(bool)hasTimer; +- (instancetype)initWithContext:(id)context isDark:(bool)isDark sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSendWhenOnline:(bool)canSendWhenOnline canSchedule:(bool)canSchedule reminder:(bool)reminder hasTimer:(bool)hasTimer; @end diff --git a/submodules/LegacyComponents/Sources/TGCameraController.m b/submodules/LegacyComponents/Sources/TGCameraController.m index a2319afee4..4dc4705dac 100644 --- a/submodules/LegacyComponents/Sources/TGCameraController.m +++ b/submodules/LegacyComponents/Sources/TGCameraController.m @@ -1568,7 +1568,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus } } - TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context isDark:true sendButtonFrame:strongModel.interfaceView.doneButtonFrame canSendSilently:strongSelf->_hasSilentPosting canSchedule:effectiveHasSchedule reminder:strongSelf->_reminder hasTimer:strongSelf->_hasTimer]; + TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context isDark:true sendButtonFrame:strongModel.interfaceView.doneButtonFrame canSendSilently:strongSelf->_hasSilentPosting canSendWhenOnline:false canSchedule:effectiveHasSchedule reminder:strongSelf->_reminder hasTimer:strongSelf->_hasTimer]; controller.send = ^{ __strong TGCameraController *strongSelf = weakSelf; __strong TGMediaPickerGalleryModel *strongModel = weakModel; @@ -1621,6 +1621,32 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus [strongSelf _dismissTransitionForResultController:strongController]; }; + controller.sendWhenOnline = ^{ + __strong TGCameraController *strongSelf = weakSelf; + __strong TGMediaPickerGalleryModel *strongModel = weakModel; + + if (strongSelf == nil || strongModel == nil) + return; + + __strong TGModernGalleryController *strongController = weakGalleryController; + if (strongController == nil) + return; + + if ([item isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) + { + TGMediaPickerGalleryVideoItemView *itemView = (TGMediaPickerGalleryVideoItemView *)[strongController itemViewForItem:item]; + [itemView stop]; + [itemView setPlayButtonHidden:true animated:true]; + } + + if (strongSelf->_selectionContext.allowGrouping) + [[NSUserDefaults standardUserDefaults] setObject:@(!strongSelf->_selectionContext.grouping) forKey:@"TG_mediaGroupingDisabled_v0"]; + + if (strongSelf.finishedWithResults != nil) + strongSelf.finishedWithResults(strongController, strongSelf->_selectionContext, strongSelf->_editingContext, item.asset, false, 0x7ffffffe); + + [strongSelf _dismissTransitionForResultController:strongController]; + }; controller.schedule = ^{ __strong TGCameraController *strongSelf = weakSelf; if (strongSelf == nil) diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m index 6b2cd0c26e..8d152ab221 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m @@ -1711,9 +1711,9 @@ } } -- (void)send:(bool)silently +- (void)send:(bool)silently whenOnline:(bool)whenOnlne { - [self completeWithCurrentItem:nil silentPosting:silently scheduleTime:0]; + [self completeWithCurrentItem:nil silentPosting:silently scheduleTime:whenOnlne ? 0x7ffffffe : 0]; } - (void)schedule:(bool)media { diff --git a/submodules/LegacyComponents/Sources/TGMediaPickerModernGalleryMixin.m b/submodules/LegacyComponents/Sources/TGMediaPickerModernGalleryMixin.m index c81218980e..b5103bb1f8 100644 --- a/submodules/LegacyComponents/Sources/TGMediaPickerModernGalleryMixin.m +++ b/submodules/LegacyComponents/Sources/TGMediaPickerModernGalleryMixin.m @@ -165,7 +165,7 @@ } } - TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context isDark:true sendButtonFrame:strongSelf.galleryModel.interfaceView.doneButtonFrame canSendSilently:hasSilentPosting canSchedule:effectiveHasSchedule reminder:reminder hasTimer:hasTimer]; + TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context isDark:true sendButtonFrame:strongSelf.galleryModel.interfaceView.doneButtonFrame canSendSilently:hasSilentPosting canSendWhenOnline:true canSchedule:effectiveHasSchedule reminder:reminder hasTimer:hasTimer]; controller.send = ^{ __strong TGMediaPickerModernGalleryMixin *strongSelf = weakSelf; if (strongSelf == nil) @@ -186,6 +186,16 @@ if (strongSelf.completeWithItem != nil) strongSelf.completeWithItem(item, true, 0); }; + controller.sendWhenOnline = ^{ + __strong TGMediaPickerModernGalleryMixin *strongSelf = weakSelf; + if (strongSelf == nil) + return; + + strongSelf->_galleryModel.dismiss(true, false); + + if (strongSelf.completeWithItem != nil) + strongSelf.completeWithItem(item, false, 0x7ffffffe); + }; controller.schedule = ^{ __strong TGMediaPickerModernGalleryMixin *strongSelf = weakSelf; if (strongSelf == nil) diff --git a/submodules/LegacyComponents/Sources/TGMediaPickerSendActionSheetController.m b/submodules/LegacyComponents/Sources/TGMediaPickerSendActionSheetController.m index 5916515eb6..e54924dd5b 100644 --- a/submodules/LegacyComponents/Sources/TGMediaPickerSendActionSheetController.m +++ b/submodules/LegacyComponents/Sources/TGMediaPickerSendActionSheetController.m @@ -105,6 +105,7 @@ bool _isDark; CGRect _sendButtonFrame; bool _canSendSilently; + bool _canSendWhenOnline; bool _canSchedule; bool _reminder; bool _hasTimer; @@ -117,6 +118,7 @@ UIView *_containerView; UIView *_separatorView; TGMediaPickerSendActionSheetItemView *_sendSilentlyButton; + TGMediaPickerSendActionSheetItemView *_sendWhenOnlineButton; TGMediaPickerSendActionSheetItemView *_scheduleButton; TGMediaPickerSendActionSheetItemView *_timerButton; } @@ -124,13 +126,14 @@ @implementation TGMediaPickerSendActionSheetController -- (instancetype)initWithContext:(id)context isDark:(bool)isDark sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule reminder:(bool)reminder hasTimer:(bool)hasTimer { +- (instancetype)initWithContext:(id)context isDark:(bool)isDark sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSendWhenOnline:(bool)canSendWhenOnline canSchedule:(bool)canSchedule reminder:(bool)reminder hasTimer:(bool)hasTimer { self = [super initWithContext:context]; if (self != nil) { _context = context; _isDark = isDark; _sendButtonFrame = sendButtonFrame; _canSendSilently = canSendSilently; + _canSendWhenOnline = canSendWhenOnline; _canSchedule = canSchedule; _reminder = reminder; _hasTimer = hasTimer; @@ -163,7 +166,7 @@ __weak TGMediaPickerSendActionSheetController *weakSelf = self; if (_canSendSilently) { - _sendSilentlyButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(@"Conversation.SendMessage.SendSilently") icon:TGComponentsImageNamed(@"MediaMute") isDark:_isDark isLast:!_canSchedule && !_hasTimer]; + _sendSilentlyButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(@"Conversation.SendMessage.SendSilently") icon:TGComponentsImageNamed(@"Editor/Silently") isDark:_isDark isLast:!_canSchedule && !_hasTimer && !_canSendWhenOnline]; _sendSilentlyButton.pressed = ^{ __strong TGMediaPickerSendActionSheetController *strongSelf = weakSelf; [strongSelf sendSilentlyPressed]; @@ -171,8 +174,17 @@ [_containerView addSubview:_sendSilentlyButton]; } + if (_canSendWhenOnline) { + _sendWhenOnlineButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(@"Conversation.SendMessage.SendWhenOnline") icon:TGComponentsImageNamed(@"Editor/WhenOnline") isDark:_isDark isLast:!_canSchedule && !_hasTimer]; + _sendWhenOnlineButton.pressed = ^{ + __strong TGMediaPickerSendActionSheetController *strongSelf = weakSelf; + [strongSelf sendWhenOnlinePressed]; + }; + [_containerView addSubview:_sendWhenOnlineButton]; + } + if (_canSchedule) { - _scheduleButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(_reminder ? @"Conversation.SendMessage.SetReminder" : @"Conversation.SendMessage.ScheduleMessage") icon:TGComponentsImageNamed(@"MediaSchedule") isDark:_isDark isLast:!_hasTimer]; + _scheduleButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(_reminder ? @"Conversation.SendMessage.SetReminder" : @"Conversation.SendMessage.ScheduleMessage") icon:TGComponentsImageNamed(@"Editor/Schedule") isDark:_isDark isLast:!_hasTimer]; _scheduleButton.pressed = ^{ __strong TGMediaPickerSendActionSheetController *strongSelf = weakSelf; [strongSelf schedulePressed]; @@ -295,8 +307,8 @@ CGFloat itemHeight = 44.0; CGFloat containerWidth = 240.0; - CGFloat containerHeight = (_canSendSilently + _canSchedule + _hasTimer) * itemHeight; - containerWidth = MAX(containerWidth, MAX(_timerButton.buttonLabel.frame.size.width, MAX(_sendSilentlyButton.buttonLabel.frame.size.width, _scheduleButton.buttonLabel.frame.size.width)) + 84.0); + CGFloat containerHeight = (_canSendSilently + _canSchedule + _hasTimer + _canSendWhenOnline) * itemHeight; + containerWidth = MAX(containerWidth, MAX(_timerButton.buttonLabel.frame.size.width, MAX(_sendSilentlyButton.buttonLabel.frame.size.width, MAX(_sendWhenOnlineButton.buttonLabel.frame.size.width, _scheduleButton.buttonLabel.frame.size.width))) + 84.0); if (!_dismissed) { _containerView.frame = CGRectMake(CGRectGetMaxX(_sendButtonFrame) - containerWidth - 8.0, _sendButtonFrame.origin.y - containerHeight - 4.0, containerWidth, containerHeight); } @@ -305,6 +317,9 @@ _sendSilentlyButton.frame = CGRectMake(0.0, offset, containerWidth, itemHeight); offset += _sendSilentlyButton.frame.size.height; + _sendWhenOnlineButton.frame = CGRectMake(0.0, offset, containerWidth, itemHeight); + offset += _sendWhenOnlineButton.frame.size.height; + _scheduleButton.frame = CGRectMake(0.0, offset, containerWidth, itemHeight); offset += _scheduleButton.frame.size.height; @@ -327,6 +342,14 @@ self.sendSilently(); } +- (void)sendWhenOnlinePressed { + [self animateOut:false]; + + if (self.sendWhenOnline != nil) + self.sendWhenOnline(); +} + + - (void)schedulePressed { [self animateOut:false]; diff --git a/submodules/LegacyComponents/Sources/TGVideoMessageCaptureController.m b/submodules/LegacyComponents/Sources/TGVideoMessageCaptureController.m index e9cc6b88c6..0e62e7d2c2 100644 --- a/submodules/LegacyComponents/Sources/TGVideoMessageCaptureController.m +++ b/submodules/LegacyComponents/Sources/TGVideoMessageCaptureController.m @@ -776,7 +776,7 @@ typedef enum [_generator impactOccurred]; } - TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:_context isDark:self.pallete.isDark sendButtonFrame:[_controlsView convertRect:[_controlsView frameForSendButton] toView:nil] canSendSilently:_canSendSilently canSchedule:_canSchedule reminder:_reminder hasTimer:false]; + TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:_context isDark:self.pallete.isDark sendButtonFrame:[_controlsView convertRect:[_controlsView frameForSendButton] toView:nil] canSendSilently:_canSendSilently canSendWhenOnline:false canSchedule:_canSchedule reminder:_reminder hasTimer:false]; __weak TGVideoMessageCaptureController *weakSelf = self; controller.send = ^{ __strong TGVideoMessageCaptureController *strongSelf = weakSelf; @@ -800,6 +800,17 @@ typedef enum _automaticDismiss = true; [strongSelf dismiss:false]; }; + controller.sendWhenOnline = ^{ + __strong TGVideoMessageCaptureController *strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + + [strongSelf finishWithURL:strongSelf->_url dimensions:CGSizeMake(240.0f, 240.0f) duration:strongSelf->_duration liveUploadData:strongSelf->_liveUploadData thumbnailImage:strongSelf->_thumbnailImage isSilent:false scheduleTimestamp:0x7ffffffe]; + + _automaticDismiss = true; + [strongSelf dismiss:false]; + }; controller.schedule = ^{ __strong TGVideoMessageCaptureController *strongSelf = weakSelf; if (strongSelf == nil) { diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index 601828c1ad..373f976b4b 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -105,8 +105,8 @@ public class LegacyAssetPickerContext: AttachmentMediaPickerContext { self.controller?.editingContext.setForcedCaption(caption, skipUpdate: true) } - public func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { - self.controller?.send(silently) + public func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { + self.controller?.send(mode == .silently, whenOnline: mode == .whenOnline) } public func schedule() { diff --git a/submodules/LocationUI/Sources/LocationPickerController.swift b/submodules/LocationUI/Sources/LocationPickerController.swift index d70344413e..4f6cd10a7b 100644 --- a/submodules/LocationUI/Sources/LocationPickerController.swift +++ b/submodules/LocationUI/Sources/LocationPickerController.swift @@ -389,7 +389,7 @@ private final class LocationPickerContext: AttachmentMediaPickerContext { func setCaption(_ caption: NSAttributedString) { } - func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { + func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { } func schedule() { diff --git a/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift b/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift index b135d60a43..d2e17bb4dc 100644 --- a/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift +++ b/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift @@ -236,52 +236,82 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, } } } - - let legacySheetController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil) - let sheetController = TGMediaPickerSendActionSheetController(context: legacyController.context, isDark: true, sendButtonFrame: model.interfaceView.doneButtonFrame, canSendSilently: hasSilentPosting, canSchedule: effectiveHasSchedule, reminder: reminder, hasTimer: hasTimer) - let dismissImpl = { [weak model] in - model?.dismiss(true, false) - dismissAll() - } - sheetController.send = { - completed(item.asset, false, nil, { - dismissImpl() - }) - } - sheetController.sendSilently = { - completed(item.asset, true, nil, { - dismissImpl() - }) - } - sheetController.schedule = { - presentSchedulePicker(true, { time in - completed(item.asset, false, time, { - dismissImpl() - }) - }) - } - sheetController.sendWithTimer = { - presentTimerPicker { time in - var items = selectionContext.selectedItems() ?? [] - items.append(item.asset as Any) - - for case let item as TGMediaEditableItem in items { - editingContext?.setTimer(time as NSNumber, for: item) + + let sendWhenOnlineAvailable: Signal + if let peer { + sendWhenOnlineAvailable = context.account.viewTracker.peerView(peer.id) + |> take(1) + |> map { peerView -> Bool in + guard let peer = peerViewMainPeer(peerView) else { + return false } - + var sendWhenOnlineAvailable = false + if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case .present = presence.status { + sendWhenOnlineAvailable = true + } + if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 { + sendWhenOnlineAvailable = false + } + return sendWhenOnlineAvailable + } + } else { + sendWhenOnlineAvailable = .single(false) + } + + let _ = (sendWhenOnlineAvailable + |> take(1) + |> deliverOnMainQueue).start(next: { sendWhenOnlineAvailable in + let legacySheetController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil) + let sheetController = TGMediaPickerSendActionSheetController(context: legacyController.context, isDark: true, sendButtonFrame: model.interfaceView.doneButtonFrame, canSendSilently: hasSilentPosting, canSendWhenOnline: sendWhenOnlineAvailable, canSchedule: effectiveHasSchedule, reminder: reminder, hasTimer: hasTimer) + let dismissImpl = { [weak model] in + model?.dismiss(true, false) + dismissAll() + } + sheetController.send = { completed(item.asset, false, nil, { dismissImpl() }) } - } - sheetController.customDismissBlock = { [weak legacySheetController] in - legacySheetController?.dismiss() - } - legacySheetController.bind(controller: sheetController) - present(legacySheetController, nil) - - let hapticFeedback = HapticFeedback() - hapticFeedback.impact() + sheetController.sendSilently = { + completed(item.asset, true, nil, { + dismissImpl() + }) + } + sheetController.sendWhenOnline = { + completed(item.asset, false, scheduleWhenOnlineTimestamp, { + dismissImpl() + }) + } + sheetController.schedule = { + presentSchedulePicker(true, { time in + completed(item.asset, false, time, { + dismissImpl() + }) + }) + } + sheetController.sendWithTimer = { + presentTimerPicker { time in + var items = selectionContext.selectedItems() ?? [] + items.append(item.asset as Any) + + for case let item as TGMediaEditableItem in items { + editingContext?.setTimer(time as NSNumber, for: item) + } + + completed(item.asset, false, nil, { + dismissImpl() + }) + } + } + sheetController.customDismissBlock = { [weak legacySheetController] in + legacySheetController?.dismiss() + } + legacySheetController.bind(controller: sheetController) + present(legacySheetController, nil) + + let hapticFeedback = HapticFeedback() + hapticFeedback.impact() + }) } } model.interfaceView.setThumbnailSignalForItem { item in diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 57b6f59862..948cea0e9c 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -1758,8 +1758,8 @@ final class MediaPickerContext: AttachmentMediaPickerContext { self.interaction?.editingState.setForcedCaption(caption, skipUpdate: true) } - func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { - self.interaction?.sendSelected(nil, silently, nil, true, {}) + func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { + self.interaction?.sendSelected(nil, mode == .silently, mode == .whenOnline ? scheduleWhenOnlineTimestamp : nil, true, {}) } func schedule() { diff --git a/submodules/ShareController/Sources/SharePeersContainerNode.swift b/submodules/ShareController/Sources/SharePeersContainerNode.swift index 663f389ea8..a9f094be3a 100644 --- a/submodules/ShareController/Sources/SharePeersContainerNode.swift +++ b/submodules/ShareController/Sources/SharePeersContainerNode.swift @@ -697,11 +697,11 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { if node.isHidden { continue } - if let result = node.hitTest(point.offsetBy(dx: -nodeFrame.minX, dy: -nodeFrame.minY), with: event) { + if let result = node.hitTest(point.offsetBy(dx: -self.headerNode.frame.minX, dy: -self.headerNode.frame.minY).offsetBy(dx: -nodeFrame.minX, dy: -nodeFrame.minY), with: event) { return result } } - + return super.hitTest(point, with: event) } diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/Contents.json index 38f0c81fc2..6e965652df 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/Contents.json @@ -1,9 +1,9 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "provides-namespace" : true } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Contents.json index 69aa9981a3..a8b8162849 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Contents.json @@ -1,22 +1,12 @@ { "images" : [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "Schedule@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "Schedule@3x.png", - "scale" : "3x" + "filename" : "schedule.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Schedule@2x.png b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Schedule@2x.png deleted file mode 100644 index 2829293819..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Schedule@2x.png and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Schedule@3x.png b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Schedule@3x.png deleted file mode 100644 index f4eb832ef8..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/Schedule@3x.png and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/schedule.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/schedule.pdf new file mode 100644 index 0000000000..23e1733493 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/ScheduleIcon.imageset/schedule.pdf @@ -0,0 +1,97 @@ +%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.334961 3.334961 cm +0.000000 0.000000 0.000000 scn +8.000000 16.665077 m +8.000000 17.032347 8.297730 17.330078 8.665000 17.330078 c +13.450547 17.330078 17.330002 13.450625 17.330002 8.665078 c +17.330002 3.879531 13.450547 0.000076 8.665000 0.000076 c +3.879452 0.000076 0.000000 3.879531 0.000000 8.665078 c +0.000000 11.755159 1.617408 14.466341 4.050117 16.000078 c +2.165000 16.000078 l +1.797731 16.000078 1.500000 16.297810 1.500000 16.665077 c +1.500000 17.032347 1.797731 17.330078 2.165000 17.330078 c +5.665000 17.330078 l +6.032269 17.330078 6.330000 17.032347 6.330000 16.665077 c +6.330000 13.165078 l +6.330000 12.797809 6.032269 12.500078 5.665000 12.500078 c +5.297730 12.500078 5.000000 12.797809 5.000000 13.165078 c +5.000000 15.020401 l +2.805339 13.751994 1.330000 11.380217 1.330000 8.665078 c +1.330000 4.614069 4.613991 1.330078 8.665000 1.330078 c +12.716009 1.330078 16.000000 4.614069 16.000000 8.665078 c +16.000000 12.716087 12.716009 16.000078 8.665000 16.000078 c +8.297730 16.000078 8.000000 16.297810 8.000000 16.665077 c +h +8.665000 14.330078 m +9.032269 14.330078 9.330000 14.032348 9.330000 13.665078 c +9.330000 8.940530 l +12.135226 6.135303 l +12.394924 5.875606 12.394924 5.454551 12.135226 5.194852 c +11.875527 4.935153 11.454473 4.935153 11.194774 5.194852 c +8.194774 8.194853 l +8.070063 8.319564 8.000000 8.488708 8.000000 8.665078 c +8.000000 13.665078 l +8.000000 14.032348 8.297730 14.330078 8.665000 14.330078 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1511 +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 +0000001601 00000 n +0000001624 00000 n +0000001797 00000 n +0000001871 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1930 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Contents.json index 13746b9a96..47cbacef29 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Contents.json @@ -1,22 +1,12 @@ { "images" : [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "Mute@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "Mute@3x.png", - "scale" : "3x" + "filename" : "sendwithoutsound.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@2x.png b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@2x.png deleted file mode 100644 index 036c06a6d1..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@2x.png and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@3x.png b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@3x.png deleted file mode 100644 index a79ac3bd68..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/Mute@3x.png and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/sendwithoutsound.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/sendwithoutsound.pdf new file mode 100644 index 0000000000..8ad58ec31b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/SilentIcon.imageset/sendwithoutsound.pdf @@ -0,0 +1,154 @@ +%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.334961 3.205078 cm +0.000000 0.000000 0.000000 scn +1.135226 17.265186 m +0.875527 17.524885 0.454473 17.524885 0.194774 17.265186 c +-0.064925 17.005487 -0.064925 16.584435 0.194774 16.324736 c +16.194775 0.324734 l +16.454473 0.065035 16.875528 0.065035 17.135227 0.324734 c +17.394926 0.584433 17.394926 1.005487 17.135227 1.265186 c +12.830019 5.570395 l +12.830019 13.984108 l +12.830019 14.015735 l +12.830019 14.015746 l +12.830019 14.015758 l +12.830032 14.503190 12.830044 14.912979 12.802612 15.227596 c +12.776955 15.521866 12.718998 15.904351 12.465319 16.192924 c +12.149200 16.552528 11.677307 16.734966 11.201504 16.681524 c +10.819681 16.638639 10.519508 16.394609 10.302576 16.194126 c +10.070642 15.979778 9.794991 15.676547 9.467113 15.315862 c +9.467100 15.315848 l +9.445834 15.292454 l +6.911015 12.504154 l +6.870810 12.460040 l +6.811123 12.459965 l +6.165019 12.459965 l +6.142232 12.459965 l +6.073141 12.459966 6.005919 12.459967 5.940522 12.459891 c +1.135226 17.265186 l +h +7.233788 11.166624 m +11.500019 6.900394 l +11.500019 13.984108 l +11.500019 14.511556 11.499405 14.862436 11.477638 15.112073 c +11.466372 15.241299 11.451292 15.307571 11.443966 15.335192 c +11.425201 15.348718 11.403254 15.357203 11.380270 15.359817 c +11.356270 15.344307 11.300531 15.305413 11.205269 15.217373 c +11.021238 15.047297 10.784756 14.788080 10.429955 14.397799 c +7.895135 11.609499 l +7.876595 11.588985 l +7.810806 11.515999 7.711236 11.405536 7.585287 11.322461 c +7.477557 11.251403 7.358773 11.198743 7.233788 11.166624 c +h +3.310589 11.708942 m +4.251275 10.768256 l +4.114416 10.639768 4.004863 10.482624 3.931640 10.305847 c +3.894677 10.216611 3.864227 10.089064 3.847507 9.844008 c +3.830379 9.592980 3.830019 9.270005 3.830019 8.794965 c +3.830019 8.319924 3.830379 7.996948 3.847507 7.745921 c +3.864227 7.500866 3.894677 7.373319 3.931640 7.284082 c +4.067134 6.956970 4.327024 6.697080 4.654137 6.561585 c +4.743373 6.524623 4.870920 6.494172 5.115975 6.477452 c +5.367003 6.460325 5.689979 6.459965 6.165019 6.459965 c +6.811123 6.459965 l +6.838768 6.460045 l +6.838777 6.460045 l +6.937038 6.460461 7.085750 6.461090 7.231940 6.423779 c +7.357602 6.391706 7.477026 6.338876 7.585287 6.267468 c +7.711238 6.184393 7.810808 6.073929 7.876598 6.000941 c +7.895135 5.980431 l +10.429956 3.192128 l +10.784757 2.801847 11.021239 2.542631 11.205269 2.372556 c +11.300533 2.284515 11.356270 2.245622 11.380270 2.230112 c +11.403254 2.232725 11.425201 2.241211 11.443966 2.254738 c +11.451292 2.282358 11.466372 2.348630 11.477638 2.477856 c +11.498196 2.713622 11.499886 3.039693 11.500010 3.519522 c +12.789057 2.230474 l +12.756243 1.960018 12.682525 1.644088 12.465319 1.397003 c +12.149200 1.037399 11.677307 0.854963 11.201504 0.908403 c +10.819681 0.951288 10.519508 1.195318 10.302577 1.395802 c +10.070659 1.610135 9.795034 1.913337 9.467189 2.273985 c +9.467137 2.274039 l +9.467128 2.274051 l +9.445836 2.297473 l +6.911015 5.085775 l +6.870807 5.129889 l +6.811123 5.129965 l +6.165019 5.129965 l +6.142203 5.129965 l +6.142138 5.129965 l +5.695606 5.129959 5.327103 5.129954 5.025440 5.150537 c +4.712668 5.171878 4.423473 5.217547 4.145168 5.332826 c +3.492168 5.603307 2.973362 6.122113 2.702880 6.775113 c +2.587602 7.053419 2.541932 7.342614 2.520592 7.655386 c +2.500008 7.957066 2.500013 8.325591 2.500019 8.772156 c +2.500019 8.772170 l +2.500019 8.794965 l +2.500019 8.817760 l +2.500019 8.817774 l +2.500013 9.264338 2.500008 9.632866 2.520592 9.934544 c +2.541932 10.247315 2.587602 10.536510 2.702880 10.814816 c +2.843596 11.154535 3.051523 11.457933 3.310589 11.708942 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 3618 +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 +0000003708 00000 n +0000003731 00000 n +0000003904 00000 n +0000003978 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4037 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/WhenOnlineIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/WhenOnlineIcon.imageset/Contents.json new file mode 100644 index 0000000000..9478d5c466 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/WhenOnlineIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "sendthenonline.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/WhenOnlineIcon.imageset/sendthenonline.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/WhenOnlineIcon.imageset/sendthenonline.pdf new file mode 100644 index 0000000000..c3c0c5df3b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Menu/WhenOnlineIcon.imageset/sendthenonline.pdf @@ -0,0 +1,123 @@ +%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 15.000000 4.000000 cm +0.000000 0.000000 0.000000 scn +5.000000 2.500000 m +5.000000 1.119288 3.880712 0.000000 2.500000 0.000000 c +1.119288 0.000000 0.000000 1.119288 0.000000 2.500000 c +0.000000 3.880712 1.119288 5.000000 2.500000 5.000000 c +3.880712 5.000000 5.000000 3.880712 5.000000 2.500000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 3.334961 3.334961 cm +0.000000 0.000000 0.000000 scn +1.330000 8.665078 m +1.330000 12.716087 4.613991 16.000078 8.665000 16.000078 c +12.716008 16.000078 16.000000 12.716087 16.000000 8.665078 c +16.000000 7.971566 15.903754 7.300534 15.723890 6.664610 c +16.154043 6.472708 16.542303 6.203824 16.871166 5.875466 c +17.168650 6.750837 17.330002 7.689115 17.330002 8.665078 c +17.330002 13.450625 13.450547 17.330078 8.665000 17.330078 c +3.879453 17.330078 0.000000 13.450625 0.000000 8.665078 c +0.000000 3.879531 3.879453 0.000076 8.665000 0.000076 c +9.641031 0.000076 10.579370 0.161449 11.454794 0.458973 c +11.126430 0.787828 10.857537 1.176086 10.665626 1.606233 c +10.029655 1.426340 9.358569 1.330078 8.665000 1.330078 c +6.949595 1.330078 5.371725 1.918934 4.122502 2.905533 c +4.297272 3.127586 4.536829 3.393646 4.847776 3.660172 c +5.621715 4.323548 6.847626 5.000078 8.665000 5.000078 c +9.428206 5.000078 10.087104 4.880767 10.652022 4.693223 c +10.837114 5.118156 11.097044 5.502989 11.415169 5.831069 c +10.648278 6.131837 9.735907 6.330078 8.665000 6.330078 c +6.482374 6.330078 4.958285 5.506608 3.982224 4.669984 c +3.639743 4.376429 3.365922 4.082502 3.154341 3.823979 c +2.018686 5.115683 1.330000 6.809955 1.330000 8.665078 c +h +12.678360 5.175269 m +12.317028 4.907584 12.030398 4.544794 11.855478 4.123891 c +12.090899 3.974664 12.299200 3.817050 12.482224 3.660172 c +12.793171 3.393646 13.032728 3.127586 13.207498 2.905533 c +12.806664 2.588965 12.371993 2.313348 11.909800 2.084994 c +12.111738 1.664135 12.428010 1.308554 12.818370 1.058498 c +14.273650 1.854803 15.475398 3.056577 16.271671 4.511877 c +16.021608 4.902231 15.666019 5.218495 15.245155 5.420424 c +14.958824 4.840852 14.598176 4.304554 14.175659 3.823979 c +13.964078 4.082502 13.690256 4.376430 13.347776 4.669984 c +13.147928 4.841282 12.925106 5.012029 12.678360 5.175269 c +h +6.830039 10.665039 m +6.830039 11.678482 7.651597 12.500039 8.665039 12.500039 c +9.678482 12.500039 10.500039 11.678482 10.500039 10.665039 c +10.500039 9.651596 9.678482 8.830039 8.665039 8.830039 c +7.651597 8.830039 6.830039 9.651596 6.830039 10.665039 c +h +8.665039 13.830039 m +6.917058 13.830039 5.500039 12.413020 5.500039 10.665039 c +5.500039 8.917058 6.917058 7.500039 8.665039 7.500039 c +10.413020 7.500039 11.830039 8.917058 11.830039 10.665039 c +11.830039 12.413020 10.413020 13.830039 8.665039 13.830039 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 2777 +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 +0000002867 00000 n +0000002890 00000 n +0000003063 00000 n +0000003137 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +3196 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/AttachmentFileController.swift b/submodules/TelegramUI/Sources/AttachmentFileController.swift index 7550b1a2ae..30cc6cfffc 100644 --- a/submodules/TelegramUI/Sources/AttachmentFileController.swift +++ b/submodules/TelegramUI/Sources/AttachmentFileController.swift @@ -183,7 +183,7 @@ private final class AttachmentFileContext: AttachmentMediaPickerContext { func setCaption(_ caption: NSAttributedString) { } - func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { + func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { } func schedule() { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 752a2e7bed..5a9cacb82d 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -430,6 +430,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private weak var searchResultsTooltipController: TooltipController? private weak var messageTooltipController: TooltipController? private weak var videoUnmuteTooltipController: TooltipController? + private var didDisplayVideoUnmuteTooltip = false private weak var silentPostTooltipController: TooltipController? private weak var mediaRecordingModeTooltipController: TooltipController? private weak var mediaRestrictedTooltipController: TooltipController? @@ -8986,14 +8987,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } }, displayVideoUnmuteTip: { [weak self] location in - guard let strongSelf = self, let layout = strongSelf.validLayout, strongSelf.traceVisibility() && isTopmostChatController(strongSelf) else { + guard let strongSelf = self, !strongSelf.didDisplayVideoUnmuteTooltip, let layout = strongSelf.validLayout, strongSelf.traceVisibility() && isTopmostChatController(strongSelf) else { return } - if let location = location, location.y < strongSelf.navigationLayout(layout: layout).navigationFrame.maxY { return } - let icon: UIImage? if layout.deviceMetrics.hasTopNotch || layout.deviceMetrics.hasDynamicIsland { icon = UIImage(bundleImageName: "Chat/Message/VolumeButtonIconX") @@ -9001,6 +9000,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G icon = UIImage(bundleImageName: "Chat/Message/VolumeButtonIcon") } if let location = location, let icon = icon { + strongSelf.didDisplayVideoUnmuteTooltip = true strongSelf.videoUnmuteTooltipController?.dismiss() let tooltipController = TooltipController(content: .iconAndText(icon, strongSelf.presentationInterfaceState.strings.Conversation_PressVolumeButtonForSound), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, timeout: 3.5, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true) strongSelf.videoUnmuteTooltipController = tooltipController @@ -9832,7 +9832,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.window?.presentInGlobalOverlay(slowmodeTooltipController) }, displaySendMessageOptions: { [weak self] node, gesture in - if let strongSelf = self, let textInputNode = strongSelf.chatDisplayNode.textInputNode(), let layout = strongSelf.validLayout { + if let strongSelf = self, let peerId = strongSelf.chatLocation.peerId, let textInputNode = strongSelf.chatDisplayNode.textInputNode(), let layout = strongSelf.validLayout { let previousSupportedOrientations = strongSelf.supportedOrientations if layout.size.width > layout.size.height { strongSelf.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .landscape) @@ -9847,26 +9847,55 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G hasEntityKeyboard = true } - let controller = ChatSendMessageActionSheetController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: strongSelf.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, completion: { [weak self] in - if let strongSelf = self { - strongSelf.supportedOrientations = previousSupportedOrientations + let _ = (strongSelf.context.account.viewTracker.peerView(peerId) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] peerView in + guard let strongSelf = self, let peer = peerViewMainPeer(peerView) else { + return } - }, sendMessage: { [weak self] silently in - if let strongSelf = self { - strongSelf.controllerInteraction?.sendCurrentMessage(silently) + var sendWhenOnlineAvailable = false + if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case .present = presence.status { + sendWhenOnlineAvailable = true } - }, schedule: { [weak self] in - if let strongSelf = self { - strongSelf.controllerInteraction?.scheduleCurrentMessage() + if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 { + sendWhenOnlineAvailable = false + } + + let controller = ChatSendMessageActionSheetController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: strongSelf.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, canSendWhenOnline: sendWhenOnlineAvailable, completion: { [weak self] in + if let strongSelf = self { + strongSelf.supportedOrientations = previousSupportedOrientations + } + }, sendMessage: { [weak self] mode in + if let strongSelf = self { + switch mode { + case .generic: + strongSelf.controllerInteraction?.sendCurrentMessage(false) + case .silently: + strongSelf.controllerInteraction?.sendCurrentMessage(true) + case .whenOnline: + strongSelf.chatDisplayNode.sendCurrentMessage(scheduleTime: scheduleWhenOnlineTimestamp) { [weak self] in + if let strongSelf = self { + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, saveInterfaceState: strongSelf.presentationInterfaceState.subject != .scheduledMessages, { + $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) } + }) + strongSelf.openScheduledMessages() + } + } + } + } + }, schedule: { [weak self] in + if let strongSelf = self { + strongSelf.controllerInteraction?.scheduleCurrentMessage() + } + }) + controller.emojiViewProvider = strongSelf.chatDisplayNode.textInputPanelNode?.emojiViewProvider + strongSelf.sendMessageActionsController = controller + if layout.isNonExclusive { + strongSelf.present(controller, in: .window(.root)) + } else { + strongSelf.presentInGlobalOverlay(controller, with: nil) } }) - controller.emojiViewProvider = strongSelf.chatDisplayNode.textInputPanelNode?.emojiViewProvider - strongSelf.sendMessageActionsController = controller - if layout.isNonExclusive { - strongSelf.present(controller, in: .window(.root)) - } else { - strongSelf.presentInGlobalOverlay(controller, with: nil) - } } }, openScheduledMessages: { [weak self] in if let strongSelf = self { @@ -16331,6 +16360,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G commit(transformedMessages) } }) + case .whenOnline: + let transformedMessages = strongSelf.transformEnqueueMessages(result, silentPosting: false, scheduleTime: scheduleWhenOnlineTimestamp) + commit(transformedMessages) } } controller.peerSelected = { [weak self, weak controller] peer, threadId in @@ -17340,7 +17372,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G @available(iOSApplicationExtension 11.0, iOS 11.0, *) public func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { session.loadObjects(ofClass: UIImage.self) { [weak self] imageItems in - guard let strongSelf = self else { + guard let strongSelf = self, !imageItems.isEmpty else { return } let images = imageItems as! [UIImage] diff --git a/submodules/TelegramUI/Sources/ContactSelectionController.swift b/submodules/TelegramUI/Sources/ContactSelectionController.swift index bf62a19908..893009e8bc 100644 --- a/submodules/TelegramUI/Sources/ContactSelectionController.swift +++ b/submodules/TelegramUI/Sources/ContactSelectionController.swift @@ -444,8 +444,8 @@ final class ContactsPickerContext: AttachmentMediaPickerContext { self.controller?.caption = caption } - func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { - self.controller?.contactsNode.requestMultipleAction?(silently, nil) + func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { + self.controller?.contactsNode.requestMultipleAction?(mode == .silently, mode == .whenOnline ? scheduleWhenOnlineTimestamp : nil) } func schedule() { diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index 70f0e5c6e9..aa279516d7 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -124,7 +124,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(id: PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil) - self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds).withUpdatedForwardOptionsState(ChatInterfaceForwardOptionsState(hideNames: false, hideCaptions: false, unhideNamesOnCaptionChange: false)) } + self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds) } self.presentationInterfaceStatePromise.set(self.presentationInterfaceState) if let _ = self.requestPeerType { @@ -342,9 +342,9 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, forwardSelectedMessages: { }, forwardCurrentForwardMessages: { }, forwardMessages: { _ in - }, updateForwardOptionsState: { [weak self] value in + }, updateForwardOptionsState: { [weak self] f in if let strongSelf = self { - strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardOptionsState($0.forwardOptionsState) }) }) + strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardOptionsState(f($0.forwardOptionsState ?? ChatInterfaceForwardOptionsState(hideNames: false, hideCaptions: false, unhideNamesOnCaptionChange: false))) }) }) } }, presentForwardOptions: { [weak self] sourceNode in guard let strongSelf = self else { @@ -659,9 +659,16 @@ final class PeerSelectionControllerNode: ASDisplayNode { hasEntityKeyboard = true } - let controller = ChatSendMessageActionSheetController(context: strongSelf.context, peerId: strongSelf.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, completion: { - }, sendMessage: { [weak textInputPanelNode] silently in - textInputPanelNode?.sendMessage(silently ? .silent : .generic) + let controller = ChatSendMessageActionSheetController(context: strongSelf.context, peerId: strongSelf.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, canSendWhenOnline: false, completion: { + }, sendMessage: { [weak textInputPanelNode] mode in + switch mode { + case .generic: + textInputPanelNode?.sendMessage(.generic) + case .silently: + textInputPanelNode?.sendMessage(.silent) + case .whenOnline: + textInputPanelNode?.sendMessage(.whenOnline) + } }, schedule: { [weak textInputPanelNode] in textInputPanelNode?.sendMessage(.schedule) }) diff --git a/submodules/WebSearchUI/Sources/WebSearchController.swift b/submodules/WebSearchUI/Sources/WebSearchController.swift index fb2b69a473..7d8bfe60a7 100644 --- a/submodules/WebSearchUI/Sources/WebSearchController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchController.swift @@ -576,8 +576,8 @@ public class WebSearchPickerContext: AttachmentMediaPickerContext { self.interaction?.editingState.setForcedCaption(caption, skipUpdate: true) } - public func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { - self.interaction?.sendSelected(nil, silently, nil) + public func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { + self.interaction?.sendSelected(nil, mode == .silently, nil) } public func schedule() { diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 5f8256c709..1b29b48576 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -1340,7 +1340,7 @@ final class WebAppPickerContext: AttachmentMediaPickerContext { func setCaption(_ caption: NSAttributedString) { } - func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { + func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { } func schedule() {