From 7ea47b8105b5fa9d73ace3eb4e402c2db818922a Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 30 Mar 2026 17:23:39 +0200 Subject: [PATCH] Various fixes --- .../GalleryData/Sources/GalleryData.swift | 29 +++++++++++++++---- .../GalleryUI/Sources/GalleryController.swift | 13 +++++++-- .../Items/UniversalVideoGalleryItem.swift | 4 ++- .../MediaPlaybackHeaderPanelComponent.swift | 6 ++-- .../ChatControllerOpenPollOptionMedia.swift | 17 ++--------- .../OverlayAudioPlayerControllerNode.swift | 25 ++++++++++++++-- 6 files changed, 66 insertions(+), 28 deletions(-) diff --git a/submodules/GalleryData/Sources/GalleryData.swift b/submodules/GalleryData/Sources/GalleryData.swift index f948ee945c..91ed759a29 100644 --- a/submodules/GalleryData/Sources/GalleryData.swift +++ b/submodules/GalleryData/Sources/GalleryData.swift @@ -129,11 +129,7 @@ public func chatMessageGalleryControllerData( for media in message.media { if let poll = media as? TelegramMediaPoll { standalone = true - if let attachedMedia = poll.attachedMedia as? TelegramMediaMap { - galleryMedia = attachedMedia - } else { - galleryMedia = poll - } + galleryMedia = poll } else if let paidContent = media as? TelegramMediaPaidContent, let extendedMedia = paidContent.extendedMedia.first, case .full = extendedMedia { standalone = true galleryMedia = paidContent @@ -231,6 +227,29 @@ public func chatMessageGalleryControllerData( }, baseNavigationController: navigationController) return .instantPage(gallery, centralIndex, galleryMedia) } else if let galleryMedia = galleryMedia { + var galleryMedia = galleryMedia + if let poll = galleryMedia as? TelegramMediaPoll { + if mediaSubject == nil || mediaSubject == .pollDescription, let attachedMedia = poll.attachedMedia { + if let file = attachedMedia as? TelegramMediaFile, file.isMusic { + galleryMedia = file + } else if let map = attachedMedia as? TelegramMediaMap { + galleryMedia = map + } + } else if case let .pollOption(opaqueIdentifier) = mediaSubject, let optionMedia = poll.options.first(where: { $0.opaqueIdentifier == opaqueIdentifier })?.media { + if let file = optionMedia as? TelegramMediaFile, file.isMusic { + galleryMedia = file + } else if let map = optionMedia as? TelegramMediaMap { + galleryMedia = map + } + } else if case .pollSolution = mediaSubject, let solutionMedia = poll.results.solution?.media { + if let file = solutionMedia as? TelegramMediaFile, file.isMusic { + galleryMedia = file + } else if let map = solutionMedia as? TelegramMediaMap { + galleryMedia = map + } + } + } + if let mapMedia = galleryMedia as? TelegramMediaMap { return .map(mapMedia) } else if let file = galleryMedia as? TelegramMediaFile, (file.isSticker || file.isAnimatedSticker) { diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index ab140949c9..343071ab31 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -436,6 +436,7 @@ public func galleryItemForEntry( context: context, presentationData: presentationData, message: message, + mediaSubject: entry.mediaSubject, location: location, translateToLanguage: translateToLanguage, peerIsCopyProtected: peerIsCopyProtected, @@ -664,8 +665,16 @@ private func galleryEntriesForMessageHistoryEntries(_ entries: [MessageHistoryEn case .pollOption: if let poll = entry.message.media.first(where: { $0 is TelegramMediaPoll }) as? TelegramMediaPoll { for option in poll.options { - if let _ = option.media { - results.append(GalleryEntry(entry: entry, mediaSubject: .pollOption(option.opaqueIdentifier))) + if let optionMedia = option.media { + var isGalleryMedia = false + if optionMedia is TelegramMediaImage { + isGalleryMedia = true + } else if let file = optionMedia as? TelegramMediaFile, file.isVideo || file.mimeType.hasPrefix("image/") { + isGalleryMedia = true + } + if isGalleryMedia { + results.append(GalleryEntry(entry: entry, mediaSubject: .pollOption(option.opaqueIdentifier))) + } } } } diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 007a2f5b50..b5773cc16c 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -3288,7 +3288,6 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { guard let (message, _, _) = self.contentInfo() else { return false } - var canDelete = false if let peer = message.peers[message.id.peerId] { if peer is TelegramUser || peer is TelegramSecretChat { @@ -3307,6 +3306,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } else { canDelete = false } + if let _ = message.media.first(where: { $0 is TelegramMediaPoll }) { + canDelete = false + } return canDelete } diff --git a/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaPlaybackHeaderPanelComponent.swift b/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaPlaybackHeaderPanelComponent.swift index c8275e6994..3899788a34 100644 --- a/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaPlaybackHeaderPanelComponent.swift +++ b/submodules/TelegramUI/Components/MediaPlaybackHeaderPanelComponent/Sources/MediaPlaybackHeaderPanelComponent.swift @@ -254,7 +254,8 @@ public final class MediaPlaybackHeaderPanelComponent: Component { } let playerController = component.context.sharedContext.makeOverlayAudioPlayerController(context: controllerContext, chatLocation: .peer(id: id.messageId.peerId), type: component.data.kind, initialMessageId: id.messageId, initialOrder: component.data.playbackOrder, playlistLocation: playlistLocation, parentNavigationController: navigationController) self.window?.endEditing(true) - controller.present(playerController, in: .window(.root)) + playerController.navigationPresentation = .flatModal + controller.push(playerController) case let .messages(chatLocation, _, _): let signal = component.context.sharedContext.messageFromPreloadedChatHistoryViewForLocation(id: id.messageId, location: ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: .id(id.messageId)), count: 60, highlight: true, setupReply: false), id: 0), context: component.context, chatLocation: chatLocation, subject: nil, chatLocationContextHolder: Atomic(value: nil), tag: .tag(MessageTags.music)) @@ -295,7 +296,8 @@ public final class MediaPlaybackHeaderPanelComponent: Component { } let playerController = component.context.sharedContext.makeOverlayAudioPlayerController(context: controllerContext, chatLocation: chatLocation, type: component.data.kind, initialMessageId: id.messageId, initialOrder: component.data.playbackOrder, playlistLocation: nil, parentNavigationController: navigationController) self.window?.endEditing(true) - controller.present(playerController, in: .window(.root)) + playerController.navigationPresentation = .flatModal + controller.push(playerController) } else if index.1 { if !progressStarted { progressStarted = true diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenPollOptionMedia.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenPollOptionMedia.swift index fcb1a9dc31..7989c608ac 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenPollOptionMedia.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenPollOptionMedia.swift @@ -18,24 +18,18 @@ import StickerPackPreviewUI extension ChatControllerImpl { func openPollMedia(message: Message, subject: ChatControllerInteraction.PollMediaSubject) -> Void { - var media: Media? - var text: String? - var entities: [MessageTextEntity] = [] let mediaSubject: GalleryMediaSubject + var media: Media? switch subject { case let .option(option): - text = option.text - entities = option.entities media = option.media mediaSubject = .pollOption(option.opaqueIdentifier) case let .solution(solution): - text = solution.text - entities = solution.entities media = solution.media mediaSubject = .pollSolution } - guard let _ = text, let media else { + guard let media else { return } @@ -112,13 +106,6 @@ extension ChatControllerImpl { }) } else { - var attributes = message.attributes - attributes.removeAll(where: { $0 is TextEntitiesMessageAttribute }) - if !entities.isEmpty { - attributes.append(TextEntitiesMessageAttribute(entities: entities)) - } - - let message = message //.withUpdatedText(text).withUpdatedAttributes(attributes) let _ = self.context.sharedContext.openChatMessage(OpenChatMessageParams( context: self.context, updatedPresentationData: self.controllerInteraction?.updatedPresentationData, diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 1324d32411..2862519fe9 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -293,7 +293,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu self.historyFrameTopMaskNode = ASImageNode() self.historyFrameTopMaskNode.displaysAsynchronously = false - self.historyFrameTopMaskNode.image = PresentationResourcesItemList.cornersImage(self.presentationData.theme.withModalBlocksBackground(), top: true, bottom: false, glass: true) + self.historyFrameTopMaskNode.image = generateCornersImage(theme: self.presentationData.theme) self.historyFrameTopMaskNode.isUserInteractionEnabled = false let tagMask: MessageTags @@ -633,7 +633,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu self.historyFrameLeftOverlayNode.backgroundColor = self.hasAnyHistoryMessages == true ? self.presentationData.theme.list.modalBlocksBackgroundColor : self.presentationData.theme.list.modalPlainBackgroundColor self.historyFrameRightOverlayNode.backgroundColor = self.hasAnyHistoryMessages == true ? self.presentationData.theme.list.modalBlocksBackgroundColor : self.presentationData.theme.list.modalPlainBackgroundColor self.historyFrameTopOverlayNode.backgroundColor = self.hasAnyHistoryMessages == true ? self.presentationData.theme.list.modalBlocksBackgroundColor : self.presentationData.theme.list.modalPlainBackgroundColor - self.historyFrameTopMaskNode.image = PresentationResourcesItemList.cornersImage(self.presentationData.theme.withModalBlocksBackground(), top: true, bottom: false, glass: true) + self.historyFrameTopMaskNode.image = generateCornersImage(theme: self.presentationData.theme) self.collapseNode.setImage(generateCollapseIcon(theme: self.presentationData.theme), for: []) @@ -1098,7 +1098,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu self.historyFrameLeftOverlayNode.frame = leftOverlayFrame self.historyFrameRightOverlayNode.frame = rightOverlayFrame if let image = self.historyFrameTopMaskNode.image { - self.historyFrameTopMaskNode.frame = CGRect(origin: CGPoint(x: sideInset, y: topOverlayFrame.maxY - UIScreenPixel), size: CGSize(width: layout.size.width - sideInset * 2.0, height: image.size.height)) + self.historyFrameTopMaskNode.frame = CGRect(origin: CGPoint(x: sideInset, y: topOverlayFrame.maxY - 1.0), size: CGSize(width: layout.size.width - sideInset * 2.0, height: image.size.height)) } self.historyFrameTopMaskNode.isHidden = self.controlsNode.hasPlainBackground @@ -1562,3 +1562,22 @@ private func generateCollapseIcon(theme: PresentationTheme) -> UIImage? { context.fillPath() }) } + +private func generateCornersImage(theme: PresentationTheme) -> UIImage? { + return generateImage(CGSize(width: 56.0, height: 56.0), rotatedContext: { (size, context) in + let bounds = CGRect(origin: CGPoint(), size: size) + context.setFillColor(theme.list.blocksBackgroundColor.cgColor) + context.fill(bounds) + + context.setBlendMode(.clear) + + var corners: UIRectCorner = [] + corners.insert(.topLeft) + corners.insert(.topRight) + + let cornerRadius: CGFloat = 26.0 + let path = UIBezierPath(roundedRect: bounds.offsetBy(dx: 0.0, dy: 1.0), byRoundingCorners: corners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)) + context.addPath(path.cgPath) + context.fillPath() + })?.stretchableImage(withLeftCapWidth: 28, topCapHeight: 28) +}