diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 478a802666..188dbc95c9 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7057,6 +7057,11 @@ Sorry for the inconvenience."; "Conversation.CopyProtectionInfoGroup" = "Admins restricted members to copy or forward content from this group."; "Conversation.CopyProtectionInfoChannel" = "Admins restricted members to copy or forward content from this channel."; +"Conversation.CopyProtectionForwardingDisabledGroup" = "Forwards from this group are restricted"; +"Conversation.CopyProtectionForwardingDisabledChannel" = "Forwards from this channel are restricted"; +"Conversation.CopyProtectionSavingDisabledGroup" = "Saving from this group is restricted"; +"Conversation.CopyProtectionSavingDisabledChannel" = "Saving from this channel is restricted"; + "Channel.AdminLog.MessageToggleNoForwardsOn" = "%@ restricted message forwarding"; "Channel.AdminLog.MessageToggleNoForwardsOff" = "%@ allowed message forwarding"; diff --git a/submodules/AccountContext/Sources/SharedMediaPlayer.swift b/submodules/AccountContext/Sources/SharedMediaPlayer.swift index 6217d6f815..584461a252 100644 --- a/submodules/AccountContext/Sources/SharedMediaPlayer.swift +++ b/submodules/AccountContext/Sources/SharedMediaPlayer.swift @@ -13,15 +13,18 @@ public enum SharedMediaPlaybackDataType { } public enum SharedMediaPlaybackDataSource: Equatable { - case telegramFile(FileMediaReference) + case telegramFile(reference: FileMediaReference, isCopyProtected: Bool) public static func ==(lhs: SharedMediaPlaybackDataSource, rhs: SharedMediaPlaybackDataSource) -> Bool { switch lhs { - case let .telegramFile(lhsFileReference): - if case let .telegramFile(rhsFileReference) = rhs { + case let .telegramFile(lhsFileReference, lhsIsCopyProtected): + if case let .telegramFile(rhsFileReference, rhsIsCopyProtected) = rhs { if !lhsFileReference.media.isEqual(to: rhsFileReference.media) { return false } + if lhsIsCopyProtected != rhsIsCopyProtected { + return false + } return true } else { return false diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 7da6c75921..1506aa3f98 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -2423,8 +2423,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { let url = content.url let item = OpenInItem.url(url: url) - let canOpenIn = availableOpenInOptions(context: strongSelf.context, item: item).count > 1 - let openText = canOpenIn ? strongSelf.presentationData.strings.Conversation_FileOpenIn : strongSelf.presentationData.strings.Conversation_LinkDialogOpen + let openText = strongSelf.presentationData.strings.Conversation_FileOpenIn items.append(.action(ContextMenuActionItem(text: openText, textColor: .primary, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Share"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) @@ -2446,7 +2445,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } } - if let (message, maybeFile, _) = strongSelf.contentInfo(), let file = maybeFile { + if let (message, maybeFile, _) = strongSelf.contentInfo(), let file = maybeFile, !message.isCopyProtected() { items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Gallery_SaveVideo, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Download"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in f(.default) diff --git a/submodules/InstantPageUI/Sources/InstantPageMediaPlaylist.swift b/submodules/InstantPageUI/Sources/InstantPageMediaPlaylist.swift index 25fdfb9d3c..c7e42e2916 100644 --- a/submodules/InstantPageUI/Sources/InstantPageMediaPlaylist.swift +++ b/submodules/InstantPageUI/Sources/InstantPageMediaPlaylist.swift @@ -46,13 +46,13 @@ final class InstantPageMediaPlaylistItem: SharedMediaPlaylistItem { switch attribute { case let .Audio(isVoice, _, _, _, _): if isVoice { - return SharedMediaPlaybackData(type: .voice, source: .telegramFile(.webPage(webPage: WebpageReference(self.webPage), media: file))) + return SharedMediaPlaybackData(type: .voice, source: .telegramFile(reference: .webPage(webPage: WebpageReference(self.webPage), media: file), isCopyProtected: false)) } else { - return SharedMediaPlaybackData(type: .music, source: .telegramFile(.webPage(webPage: WebpageReference(self.webPage), media: file))) + return SharedMediaPlaybackData(type: .music, source: .telegramFile(reference: .webPage(webPage: WebpageReference(self.webPage), media: file), isCopyProtected: false)) } case let .Video(_, _, flags): if flags.contains(.instantRoundVideo) { - return SharedMediaPlaybackData(type: .instantVideo, source: .telegramFile(.webPage(webPage: WebpageReference(self.webPage), media: file))) + return SharedMediaPlaybackData(type: .instantVideo, source: .telegramFile(reference: .webPage(webPage: WebpageReference(self.webPage), media: file), isCopyProtected: false)) } else { return nil } @@ -61,12 +61,12 @@ final class InstantPageMediaPlaylistItem: SharedMediaPlaylistItem { } } if file.mimeType.hasPrefix("audio/") { - return SharedMediaPlaybackData(type: .music, source: .telegramFile(.webPage(webPage: WebpageReference(self.webPage), media: file))) + return SharedMediaPlaybackData(type: .music, source: .telegramFile(reference: .webPage(webPage: WebpageReference(self.webPage), media: file), isCopyProtected: false)) } if let fileName = file.fileName { let ext = (fileName as NSString).pathExtension.lowercased() if ext == "wav" || ext == "opus" { - return SharedMediaPlaybackData(type: .music, source: .telegramFile(.webPage(webPage: WebpageReference(self.webPage), media: file))) + return SharedMediaPlaybackData(type: .music, source: .telegramFile(reference: .webPage(webPage: WebpageReference(self.webPage), media: file), isCopyProtected: false)) } } } diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift index c75cba79f5..2f36df53a5 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift @@ -105,6 +105,7 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode { var dateText: String? var typeText: String? var buttonText: String? + var canShare = true switch entry { case let .image(_, _, _, videoRepresentations, peer, date, _, _, _, _): nameText = peer.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "" @@ -119,6 +120,10 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode { typeText = self.strings.ProfilePhoto_MainPhoto buttonText = self.strings.ProfilePhoto_SetMainPhoto } + + if let peer = peer { + canShare = !peer.isCopyProtectionEnabled + } default: break } @@ -151,6 +156,8 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode { } } + self.actionButton.isHidden = !canShare + switch content { case .info: self.nameNode.isHidden = false diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift index 5ce9e6415a..01dece6d67 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift @@ -757,7 +757,7 @@ public func recentSessionsController(context: AccountContext, activeSessionsCont pushControllerImpl?(AuthTransferScanScreen(context: context, activeSessionsContext: activeSessionsContext)) }) }, openOtherAppsUrl: { - context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: "https://desktop.telegram.org", forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {}) + context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: "https://getdesktop.telegram.org", forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {}) }, setupAuthorizationTTL: { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let controller = ActionSheetController(presentationData: presentationData) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsHeaderItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsHeaderItem.swift index 27d913d50b..aa61efb90e 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsHeaderItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsHeaderItem.swift @@ -131,7 +131,7 @@ class RecentSessionsHeaderItemNode: ListViewItemNode { let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) - let contentSize = CGSize(width: params.width, height: topInset + titleLayout.size.height + 85.0) + let contentSize = CGSize(width: params.width, height: topInset + titleLayout.size.height + 69.0) let insets = itemListNeighborsGroupedInsets(neighbors, params) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) @@ -150,9 +150,9 @@ class RecentSessionsHeaderItemNode: ListViewItemNode { strongSelf.buttonNode.updateTheme(SolidRoundedButtonTheme(theme: item.theme)) } - let buttonWidth = contentSize.width - 32.0 + let buttonWidth = min(375, contentSize.width - params.leftInset - params.rightInset) let buttonHeight = strongSelf.buttonNode.updateLayout(width: buttonWidth, transition: .immediate) - let buttonFrame = CGRect(x: 16.0, y: contentSize.height - buttonHeight - 12.0, width: buttonWidth, height: buttonHeight) + let buttonFrame = CGRect(x: params.leftInset, y: contentSize.height - buttonHeight + 4.0, width: buttonWidth, height: buttonHeight) strongSelf.buttonNode.frame = buttonFrame strongSelf.accessibilityLabel = attributedText.string diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 974b32a0dc..620bc7c79a 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -782,15 +782,15 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp()) - var needShareButton = false + var needsShareButton = false if case .pinnedMessages = item.associatedData.subject { - needShareButton = true + needsShareButton = true } else if isFailed || Namespaces.Message.allScheduled.contains(item.message.id.namespace) { - needShareButton = false + needsShareButton = false } else if item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) { for attribute in item.content.firstMessage.attributes { if let _ = attribute as? SourceReferenceMessageAttribute { - needShareButton = true + needsShareButton = true break } } @@ -798,31 +798,35 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let peer = item.message.peers[item.message.id.peerId] { if let channel = peer as? TelegramChannel { if case .broadcast = channel.info { - needShareButton = true + needsShareButton = true } } } - if !needShareButton, let author = item.message.author as? TelegramUser, let _ = author.botInfo, !item.message.media.isEmpty { - needShareButton = true + if !needsShareButton, let author = item.message.author as? TelegramUser, let _ = author.botInfo, !item.message.media.isEmpty { + needsShareButton = true } - if !needShareButton { + if !needsShareButton { loop: for media in item.message.media { if media is TelegramMediaGame || media is TelegramMediaInvoice { - needShareButton = true + needsShareButton = true break loop } else if let media = media as? TelegramMediaWebpage, case .Loaded = media.content { - needShareButton = true + needsShareButton = true break loop } } } else { loop: for media in item.message.media { if media is TelegramMediaAction { - needShareButton = false + needsShareButton = false break loop } } } + + if item.associatedData.isCopyProtectionEnabled { + needsShareButton = false + } } var layoutInsets = UIEdgeInsets(top: mergedTop.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, left: 0.0, bottom: mergedBottom.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, right: 0.0) @@ -955,7 +959,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } var updatedShareButtonNode: ChatMessageShareButton? - if needShareButton { + if needsShareButton { if let currentShareButtonNode = currentShareButtonNode { updatedShareButtonNode = currentShareButtonNode } else { diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 5596d847e6..1e6e68a410 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -1118,6 +1118,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode tmpWidth = baseWidth if needsShareButton || isAd { tmpWidth -= 38.0 + } else { + tmpWidth -= 4.0 } } else { tmpWidth = layoutConstants.bubble.maximumWidthFill.widthFor(baseWidth) diff --git a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift index 64f871ad5b..ac3c179125 100644 --- a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift @@ -501,7 +501,11 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode { if self.peerId.namespace == Namespaces.Peer.Empty, case let .message(_, id, _, _, _) = self.messageReference?.content { self.controllerInteraction.displayMessageTooltip(id, self.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, self.avatarNode.frame) } else { - self.controllerInteraction.openPeer(self.peerId, .info, nil) + if let channel = self.peer as? TelegramChannel, case .broadcast = channel.info { + self.controllerInteraction.openPeer(self.peerId, .chat(textInputState: nil, subject: nil, peekData: nil), nil) + } else { + self.controllerInteraction.openPeer(self.peerId, .info, nil) + } } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index 357d80fae9..2e84df6df2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -306,16 +306,16 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp()) - var needShareButton = false + var needsShareButton = false if case .pinnedMessages = item.associatedData.subject { - needShareButton = true + needsShareButton = true } else if isFailed || Namespaces.Message.allScheduled.contains(item.message.id.namespace) { - needShareButton = false + needsShareButton = false } else if item.message.id.peerId == item.context.account.peerId { for attribute in item.content.firstMessage.attributes { if let _ = attribute as? SourceReferenceMessageAttribute { - needShareButton = true + needsShareButton = true break } } @@ -323,31 +323,35 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD if let peer = item.message.peers[item.message.id.peerId] { if let channel = peer as? TelegramChannel { if case .broadcast = channel.info { - needShareButton = true + needsShareButton = true } } } - if !needShareButton, let author = item.message.author as? TelegramUser, let _ = author.botInfo, !item.message.media.isEmpty { - needShareButton = true + if !needsShareButton, let author = item.message.author as? TelegramUser, let _ = author.botInfo, !item.message.media.isEmpty { + needsShareButton = true } - if !needShareButton { + if !needsShareButton { loop: for media in item.message.media { if media is TelegramMediaGame || media is TelegramMediaInvoice { - needShareButton = true + needsShareButton = true break loop } else if let media = media as? TelegramMediaWebpage, case .Loaded = media.content { - needShareButton = true + needsShareButton = true break loop } } } else { loop: for media in item.message.media { if media is TelegramMediaAction { - needShareButton = false + needsShareButton = false break loop } } } + + if item.associatedData.isCopyProtectionEnabled { + needsShareButton = false + } } var layoutInsets = layoutConstants.instantVideo.insets @@ -472,7 +476,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD } var updatedShareButtonNode: ChatMessageShareButton? - if needShareButton { + if needsShareButton { if currentShareButtonNode != nil { updatedShareButtonNode = currentShareButtonNode } else { diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 2fa451dd9b..244c5c0fc8 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -380,15 +380,15 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp()) - var needShareButton = false + var needsShareButton = false if case .pinnedMessages = item.associatedData.subject { - needShareButton = true + needsShareButton = true } else if isFailed || Namespaces.Message.allScheduled.contains(item.message.id.namespace) { - needShareButton = false + needsShareButton = false } else if item.message.id.peerId == item.context.account.peerId { for attribute in item.content.firstMessage.attributes { if let _ = attribute as? SourceReferenceMessageAttribute { - needShareButton = true + needsShareButton = true break } } @@ -396,31 +396,35 @@ class ChatMessageStickerItemNode: ChatMessageItemView { if let peer = item.message.peers[item.message.id.peerId] { if let channel = peer as? TelegramChannel { if case .broadcast = channel.info { - needShareButton = true + needsShareButton = true } } } - if !needShareButton, let author = item.message.author as? TelegramUser, let _ = author.botInfo, !item.message.media.isEmpty { - needShareButton = true + if !needsShareButton, let author = item.message.author as? TelegramUser, let _ = author.botInfo, !item.message.media.isEmpty { + needsShareButton = true } - if !needShareButton { + if !needsShareButton { loop: for media in item.message.media { if media is TelegramMediaGame || media is TelegramMediaInvoice { - needShareButton = true + needsShareButton = true break loop } else if let media = media as? TelegramMediaWebpage, case .Loaded = media.content { - needShareButton = true + needsShareButton = true break loop } } } else { loop: for media in item.message.media { if media is TelegramMediaAction { - needShareButton = false + needsShareButton = false break loop } } } + + if item.associatedData.isCopyProtectionEnabled { + needsShareButton = false + } } var layoutInsets = UIEdgeInsets(top: mergedTop.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, left: 0.0, bottom: mergedBottom.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, right: 0.0) @@ -553,7 +557,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } var updatedShareButtonNode: ChatMessageShareButton? - if needShareButton { + if needsShareButton { if let currentShareButtonNode = currentShareButtonNode { updatedShareButtonNode = currentShareButtonNode } else { diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index d36c5ecdb3..57e3745aad 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -1115,7 +1115,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { var hasMenuButton = false var menuButtonExpanded = false var isSendAsButton = false - if let sendAsPeers = interfaceState.sendAsPeers, !sendAsPeers.isEmpty { + if let sendAsPeers = interfaceState.sendAsPeers, !sendAsPeers.isEmpty && interfaceState.editMessageState == nil { hasMenuButton = true menuButtonExpanded = false isSendAsButton = true diff --git a/submodules/TelegramUI/Sources/DocumentPreviewController.swift b/submodules/TelegramUI/Sources/DocumentPreviewController.swift index 186561cdd0..04ba8eff94 100644 --- a/submodules/TelegramUI/Sources/DocumentPreviewController.swift +++ b/submodules/TelegramUI/Sources/DocumentPreviewController.swift @@ -111,14 +111,16 @@ final class DocumentPreviewController: UINavigationController, QLPreviewControll final class CompactDocumentPreviewController: QLPreviewController, QLPreviewControllerDelegate, QLPreviewControllerDataSource { private let postbox: Postbox private let file: TelegramMediaFile + private let canShare: Bool private var item: DocumentPreviewItem? private var tempFile: TempBoxFile? - init(theme: PresentationTheme, strings: PresentationStrings, postbox: Postbox, file: TelegramMediaFile) { + init(theme: PresentationTheme, strings: PresentationStrings, postbox: Postbox, file: TelegramMediaFile, canShare: Bool = true) { self.postbox = postbox self.file = file + self.canShare = canShare super.init(nibName: nil, bundle: nil) @@ -144,6 +146,7 @@ final class CompactDocumentPreviewController: QLPreviewController, QLPreviewCont if let tempFile = self.tempFile { TempBox.shared.dispose(tempFile) } + self.timer?.invalidate() } @objc private func cancelPressed() { @@ -174,9 +177,51 @@ final class CompactDocumentPreviewController: QLPreviewController, QLPreviewCont func previewControllerDidDismiss(_ controller: QLPreviewController) { //self.cancelPressed() } + + private var toolbars: [UIView] = [] + private var observations : [NSKeyValueObservation] = [] + + private var initialized = false + private var timer: SwiftSignalKit.Timer? + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + if !self.canShare && !self.initialized { + self.initialized = true + + self.timer = SwiftSignalKit.Timer(timeout: 0.01, repeat: true, completion: { [weak self] in + self?.tick() + }, queue: Queue.mainQueue()) + self.timer?.start() + } + } + + private func tick() { + self.navigationItem.rightBarButtonItems?[0] = UIBarButtonItem() + self.navigationItem.setRightBarButton(UIBarButtonItem(), animated: false) + + self.navigationController?.toolbar.isHidden = true + + self.toolbars = self.toolbarsInSubviews(forView: self.view) + + for toolbar in self.toolbars { + toolbar.isHidden = true + } + } + + private func toolbarsInSubviews(forView view: UIView) -> [UIView] { + var toolbars: [UIView] = [] + for subview in view.subviews { + if subview is UIToolbar { + toolbars.append(subview) + } + toolbars.append(contentsOf: toolbarsInSubviews(forView: subview)) + } + return toolbars + } } -func presentDocumentPreviewController(rootController: UIViewController, theme: PresentationTheme, strings: PresentationStrings, postbox: Postbox, file: TelegramMediaFile) { +func presentDocumentPreviewController(rootController: UIViewController, theme: PresentationTheme, strings: PresentationStrings, postbox: Postbox, file: TelegramMediaFile, canShare: Bool) { if #available(iOSApplicationExtension 9.0, iOS 9.0, *) { let navigationBar = UINavigationBar.appearance(whenContainedInInstancesOf: [QLPreviewController.self]) navigationBar.barTintColor = theme.rootController.navigationBar.opaqueBackgroundColor @@ -194,5 +239,5 @@ func presentDocumentPreviewController(rootController: UIViewController, theme: P navigationBar.titleTextAttributes = [NSAttributedString.Key.font: Font.semibold(17.0), NSAttributedString.Key.foregroundColor: theme.rootController.navigationBar.primaryTextColor] } - rootController.present(CompactDocumentPreviewController(theme: theme, strings: strings, postbox: postbox, file: file), animated: true, completion: nil) + rootController.present(CompactDocumentPreviewController(theme: theme, strings: strings, postbox: postbox, file: file, canShare: canShare), animated: true, completion: nil) } diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index dca61c8c93..94bdfdb06d 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -114,7 +114,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { params.present(controller, nil) } else if let rootController = params.navigationController?.view.window?.rootViewController { let proceed = { - presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file) + presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file, canShare: !params.message.isCopyProtected()) } if file.mimeType.contains("image/svg") { let presentationData = params.context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift b/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift index 9c1a301fc8..4a28ef7c0c 100644 --- a/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift +++ b/submodules/TelegramUI/Sources/OverlayPlayerControlsNode.swift @@ -393,10 +393,12 @@ final class OverlayPlayerControlsNode: ASDisplayNode { if strongSelf.displayData != displayData { strongSelf.displayData = displayData - + + var canShare = true if let (_, valueOrLoading, _) = value, case let .state(value) = valueOrLoading, let source = value.item.playbackData?.source { switch source { - case let .telegramFile(fileReference): + case let .telegramFile(fileReference, isCopyProtected): + canShare = !isCopyProtected strongSelf.currentFileReference = fileReference if let size = fileReference.media.size { strongSelf.scrubberNode.bufferingStatus = strongSelf.postbox.mediaBox.resourceRangesStatus(fileReference.media.resource) @@ -411,6 +413,8 @@ final class OverlayPlayerControlsNode: ASDisplayNode { strongSelf.scrubberNode.bufferingStatus = nil } strongSelf.updateLabels(transition: .immediate) + + strongSelf.shareNode.isHidden = !canShare } }) diff --git a/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift b/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift index a53e1eb2eb..6396344dc5 100644 --- a/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift +++ b/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift @@ -61,7 +61,7 @@ final class MessageMediaPlaylistItem: SharedMediaPlaylistItem { var playbackData: SharedMediaPlaybackData? { if let file = extractFileMedia(self.message) { let fileReference = FileMediaReference.message(message: MessageReference(self.message), media: file) - let source = SharedMediaPlaybackDataSource.telegramFile(fileReference) + let source = SharedMediaPlaybackDataSource.telegramFile(reference: fileReference, isCopyProtected: self.message.isCopyProtected()) for attribute in file.attributes { switch attribute { case let .Audio(isVoice, _, _, _, _): diff --git a/submodules/TelegramUI/Sources/SharedMediaPlayer.swift b/submodules/TelegramUI/Sources/SharedMediaPlayer.swift index d235274ce2..21c4e4bd4d 100644 --- a/submodules/TelegramUI/Sources/SharedMediaPlayer.swift +++ b/submodules/TelegramUI/Sources/SharedMediaPlayer.swift @@ -227,13 +227,13 @@ final class SharedMediaPlayer { switch playbackData.type { case .voice, .music: switch playbackData.source { - case let .telegramFile(fileReference): + case let .telegramFile(fileReference, _): strongSelf.playbackItem = .audio(MediaPlayer(audioSessionManager: strongSelf.audioSession, postbox: strongSelf.account.postbox, resourceReference: fileReference.resourceReference(fileReference.media.resource), streamable: playbackData.type == .music ? .conservative : .none, video: false, preferSoftwareDecoding: false, enableSound: true, baseRate: rateValue, fetchAutomatically: true, playAndRecord: controlPlaybackWithProximity)) } case .instantVideo: if let mediaManager = strongSelf.mediaManager, let item = item as? MessageMediaPlaylistItem { switch playbackData.source { - case let .telegramFile(fileReference): + case let .telegramFile(fileReference, _): let videoNode = OverlayInstantVideoNode(postbox: strongSelf.account.postbox, audioSession: strongSelf.audioSession, manager: mediaManager.universalVideoManager, content: NativeVideoContent(id: .message(item.message.stableId, fileReference.media.fileId), fileReference: fileReference, enableSound: false, baseRate: rateValue), close: { [weak mediaManager] in mediaManager?.setPlaylist(nil, type: .voice, control: .playback(.pause)) }) @@ -483,7 +483,7 @@ final class SharedMediaPlayer { let fetchedCurrentSignal: Signal let fetchedNextSignal: Signal switch current { - case let .telegramFile(file): + case let .telegramFile(file, _): fetchedCurrentSignal = self.account.postbox.mediaBox.resourceData(file.media.resource) |> mapToSignal { data -> Signal in if data.complete { @@ -496,7 +496,7 @@ final class SharedMediaPlayer { |> ignoreValues } switch next { - case let .telegramFile(file): + case let .telegramFile(file, _): fetchedNextSignal = fetchedMediaResource(mediaBox: self.account.postbox.mediaBox, reference: file.resourceReference(file.media.resource)) |> ignoreValues |> `catch` { _ -> Signal in