mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-31 07:30:40 +00:00
Display error when sharing to a slowmode-restricted group
This commit is contained in:
parent
bda8c53d41
commit
53de2b9dc0
@ -3749,20 +3749,21 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
||||
self.failedMessageEventsDisposable.set((self.context.account.pendingMessageManager.failedMessageEvents(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] reason in
|
||||
if let strongSelf = self {
|
||||
let subjectFlags: TelegramChatBannedRightsFlags = .banSendMedia
|
||||
|
||||
let text: String
|
||||
let moreInfo: Bool
|
||||
switch reason {
|
||||
case .flood:
|
||||
text = strongSelf.presentationData.strings.Conversation_SendMessageErrorFlood
|
||||
moreInfo = true
|
||||
case .publicBan:
|
||||
text = strongSelf.presentationData.strings.Conversation_SendMessageErrorGroupRestricted
|
||||
moreInfo = true
|
||||
case .mediaRestricted:
|
||||
strongSelf.interfaceInteraction?.displayRestrictedInfo(.mediaRecording, .alert)
|
||||
return
|
||||
case .flood:
|
||||
text = strongSelf.presentationData.strings.Conversation_SendMessageErrorFlood
|
||||
moreInfo = true
|
||||
case .publicBan:
|
||||
text = strongSelf.presentationData.strings.Conversation_SendMessageErrorGroupRestricted
|
||||
moreInfo = true
|
||||
case .mediaRestricted:
|
||||
strongSelf.interfaceInteraction?.displayRestrictedInfo(.mediaRecording, .alert)
|
||||
return
|
||||
case .slowmodeActive:
|
||||
text = strongSelf.presentationData.strings.Chat_SlowmodeSendError
|
||||
moreInfo = false
|
||||
}
|
||||
let actions: [TextAlertAction]
|
||||
if moreInfo {
|
||||
@ -5826,7 +5827,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
||||
return nil
|
||||
}
|
||||
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|
||||
|> mapToSignal { status -> Signal<Bool, NoError> in
|
||||
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
|
||||
if status != nil {
|
||||
return .never()
|
||||
} else {
|
||||
|
@ -195,7 +195,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
|
||||
var updatedPlaybackStatus: Signal<FileMediaResourceStatus, NoError>?
|
||||
if let updatedFile = updatedFile, updatedMedia || updatedMessageId {
|
||||
updatedPlaybackStatus = combineLatest(messageFileMediaResourceStatus(context: item.context, file: updatedFile, message: item.message, isRecentActions: item.associatedData.isRecentActions), item.context.account.pendingMessageManager.pendingMessageStatus(item.message.id))
|
||||
updatedPlaybackStatus = combineLatest(messageFileMediaResourceStatus(context: item.context, file: updatedFile, message: item.message, isRecentActions: item.associatedData.isRecentActions), item.context.account.pendingMessageManager.pendingMessageStatus(item.message.id) |> map { $0.0 })
|
||||
|> map { resourceStatus, pendingStatus -> FileMediaResourceStatus in
|
||||
if let pendingStatus = pendingStatus {
|
||||
var progress = pendingStatus.progress
|
||||
|
@ -555,7 +555,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
if statusUpdated {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
if message.flags.isSending {
|
||||
updatedStatusSignal = combineLatest(chatMessagePhotoStatus(context: context, messageId: message.id, photoReference: .message(message: MessageReference(message), media: image)), context.account.pendingMessageManager.pendingMessageStatus(message.id))
|
||||
updatedStatusSignal = combineLatest(chatMessagePhotoStatus(context: context, messageId: message.id, photoReference: .message(message: MessageReference(message), media: image)), context.account.pendingMessageManager.pendingMessageStatus(message.id) |> map { $0.0 })
|
||||
|> map { resourceStatus, pendingStatus -> (MediaResourceStatus, MediaResourceStatus?) in
|
||||
if let pendingStatus = pendingStatus {
|
||||
let adjustedProgress = max(pendingStatus.progress, 0.027)
|
||||
@ -571,7 +571,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
updatedStatusSignal = combineLatest(messageMediaFileStatus(context: context, messageId: message.id, file: file), context.account.pendingMessageManager.pendingMessageStatus(message.id))
|
||||
updatedStatusSignal = combineLatest(messageMediaFileStatus(context: context, messageId: message.id, file: file), context.account.pendingMessageManager.pendingMessageStatus(message.id) |> map { $0.0 })
|
||||
|> map { resourceStatus, pendingStatus -> (MediaResourceStatus, MediaResourceStatus?) in
|
||||
if let pendingStatus = pendingStatus {
|
||||
let adjustedProgress = max(pendingStatus.progress, 0.027)
|
||||
|
@ -52,7 +52,7 @@ func messageFileMediaResourceStatus(context: AccountContext, file: TelegramMedia
|
||||
}
|
||||
|
||||
if message.flags.isSending {
|
||||
return combineLatest(messageMediaFileStatus(context: context, messageId: message.id, file: file), context.account.pendingMessageManager.pendingMessageStatus(message.id), playbackStatus)
|
||||
return combineLatest(messageMediaFileStatus(context: context, messageId: message.id, file: file), context.account.pendingMessageManager.pendingMessageStatus(message.id) |> map { $0.0 }, playbackStatus)
|
||||
|> map { resourceStatus, pendingStatus, playbackStatus -> FileMediaResourceStatus in
|
||||
let mediaStatus: FileMediaResourceMediaStatus
|
||||
if let playbackStatus = playbackStatus {
|
||||
|
@ -663,7 +663,7 @@ public class PeerMediaCollectionController: TelegramController {
|
||||
return nil
|
||||
}
|
||||
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|
||||
|> mapToSignal { status -> Signal<Bool, NoError> in
|
||||
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
|
||||
if status != nil {
|
||||
return .never()
|
||||
} else {
|
||||
|
Binary file not shown.
@ -340,6 +340,11 @@ public final class ShareController: ViewController {
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = ShareControllerNode(sharedContext: self.sharedContext, defaultAction: self.defaultAction, requestLayout: { [weak self] transition in
|
||||
self?.requestLayout(transition: transition)
|
||||
}, presentError: { [weak self] title, text in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare)
|
||||
self.controllerNode.dismiss = { [weak self] shared in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
@ -353,98 +358,141 @@ public final class ShareController: ViewController {
|
||||
})
|
||||
}
|
||||
self.controllerNode.share = { [weak self] text, peerIds in
|
||||
if let strongSelf = self {
|
||||
switch strongSelf.subject {
|
||||
case let .url(url):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: url, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
return .complete()
|
||||
case let .text(string):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: string, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
return .complete()
|
||||
case let .quote(string, url):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber])
|
||||
attributedText.append(NSAttributedString(string: "\n\n\(url)"))
|
||||
let entities = generateChatInputTextEntities(attributedText)
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
return .complete()
|
||||
case let .image(representations):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil)), replyToMessageId: nil, localGroupingKey: nil))
|
||||
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
return .complete()
|
||||
case let .media(mediaReference):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil))
|
||||
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
return .complete()
|
||||
case let .mapMedia(media):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil))
|
||||
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
return .complete()
|
||||
case let .messages(messages):
|
||||
for peerId in peerIds {
|
||||
var messagesToEnqueue: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
for message in messages {
|
||||
messagesToEnqueue.append(.forward(source: message.id, grouping: .auto))
|
||||
}
|
||||
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messagesToEnqueue).start()
|
||||
}
|
||||
return .single(.done)
|
||||
case let .fromExternal(f):
|
||||
return f(peerIds, text, strongSelf.currentAccount)
|
||||
|> map { state -> ShareState in
|
||||
switch state {
|
||||
case .preparing:
|
||||
return .preparing
|
||||
case let .progress(value):
|
||||
return .progress(value)
|
||||
case .done:
|
||||
return .done
|
||||
}
|
||||
}
|
||||
guard let strongSelf = self else {
|
||||
return .complete()
|
||||
}
|
||||
var shareSignals: [Signal<[MessageId?], NoError>] = []
|
||||
switch strongSelf.subject {
|
||||
case let .url(url):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: url, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .text(string):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: string, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .quote(string, url):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber])
|
||||
attributedText.append(NSAttributedString(string: "\n\n\(url)"))
|
||||
let entities = generateChatInputTextEntities(attributedText)
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .image(representations):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil)), replyToMessageId: nil, localGroupingKey: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .media(mediaReference):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .mapMedia(media):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .messages(messages):
|
||||
for peerId in peerIds {
|
||||
var messagesToEnqueue: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
}
|
||||
for message in messages {
|
||||
messagesToEnqueue.append(.forward(source: message.id, grouping: .auto))
|
||||
}
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messagesToEnqueue))
|
||||
}
|
||||
case let .fromExternal(f):
|
||||
return f(peerIds, text, strongSelf.currentAccount)
|
||||
|> map { state -> ShareState in
|
||||
switch state {
|
||||
case .preparing:
|
||||
return .preparing
|
||||
case let .progress(value):
|
||||
return .progress(value)
|
||||
case .done:
|
||||
return .done
|
||||
}
|
||||
}
|
||||
}
|
||||
return .complete()
|
||||
let account = strongSelf.currentAccount
|
||||
let queue = Queue.mainQueue()
|
||||
var displayedError = false
|
||||
return combineLatest(queue: queue, shareSignals)
|
||||
|> mapToSignal { messageIdSets -> Signal<ShareState, NoError> in
|
||||
var statuses: [Signal<(MessageId, PendingMessageStatus?, PendingMessageFailureReason?), NoError>] = []
|
||||
for messageIds in messageIdSets {
|
||||
for case let id? in messageIds {
|
||||
statuses.append(account.pendingMessageManager.pendingMessageStatus(id)
|
||||
|> map { status, error -> (MessageId, PendingMessageStatus?, PendingMessageFailureReason?) in
|
||||
return (id, status, error)
|
||||
})
|
||||
}
|
||||
}
|
||||
return combineLatest(queue: queue, statuses)
|
||||
|> mapToSignal { statuses -> Signal<ShareState, NoError> in
|
||||
var hasStatuses = false
|
||||
for (id, status, error) in statuses {
|
||||
if let error = error {
|
||||
Queue.mainQueue().async {
|
||||
let _ = (account.postbox.transaction { transaction -> Peer? in
|
||||
transaction.deleteMessages([id])
|
||||
return transaction.getPeer(id.peerId)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
guard let strongSelf = self, let peer = peer else {
|
||||
return
|
||||
}
|
||||
if !displayedError, case .slowmodeActive = error {
|
||||
displayedError = true
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: peer.displayTitle, text: strongSelf.presentationData.strings.Chat_SlowmodeSendError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
let _ = account.postbox.transaction({ transaction in
|
||||
|
||||
}).start()
|
||||
if status != nil {
|
||||
hasStatuses = true
|
||||
}
|
||||
}
|
||||
if !hasStatuses {
|
||||
return .single(.done)
|
||||
}
|
||||
return .complete()
|
||||
}
|
||||
|> take(1)
|
||||
}
|
||||
}
|
||||
self.controllerNode.shareExternal = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
|
@ -30,6 +30,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
|
||||
private let defaultAction: ShareControllerAction?
|
||||
private let requestLayout: (ContainedViewLayoutTransition) -> Void
|
||||
private let presentError: (String?, String) -> Void
|
||||
|
||||
private var containerLayout: (ContainerViewLayout, CGFloat, CGFloat)?
|
||||
|
||||
@ -70,11 +71,12 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
|
||||
private var hapticFeedback: HapticFeedback?
|
||||
|
||||
init(sharedContext: SharedAccountContext, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, externalShare: Bool, immediateExternalShare: Bool) {
|
||||
init(sharedContext: SharedAccountContext, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool) {
|
||||
self.sharedContext = sharedContext
|
||||
self.presentationData = sharedContext.currentPresentationData.with { $0 }
|
||||
self.externalShare = externalShare
|
||||
self.immediateExternalShare = immediateExternalShare
|
||||
self.presentError = presentError
|
||||
|
||||
self.defaultAction = defaultAction
|
||||
self.requestLayout = requestLayout
|
||||
@ -500,6 +502,15 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
defaultAction.action()
|
||||
}
|
||||
} else {
|
||||
if !self.inputFieldNode.text.isEmpty {
|
||||
for peer in self.controllerInteraction!.selectedPeers {
|
||||
if let channel = peer.peer as? TelegramChannel, channel.isRestrictedBySlowmode {
|
||||
self.presentError(channel.title, self.presentationData.strings.Share_MultipleMessagesDisabled)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.inputFieldNode.deactivateInput()
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.12, curve: .easeInOut)
|
||||
transition.updateAlpha(node: self.actionButtonNode, alpha: 0.0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user