From aaff05021d3fe545ca5c934591d9d3bcaf360a68 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 10 Jul 2020 05:31:32 +0300 Subject: [PATCH] Video avatar fixes --- .../Items/UniversalVideoGalleryItem.swift | 8 +- .../Sources/TGPhotoEditorController.m | 2 +- .../Sources/AvatarGalleryController.swift | 62 ++++++++----- .../Sources/PeerAvatarImageGalleryItem.swift | 5 +- .../SyncCore/Sources/CachedChannelData.swift | 61 +++++++++---- .../Sources/ChannelAdminEventLogs.swift | 6 +- .../Sources/UpdateCachedPeerData.swift | 5 +- .../Sources/ChatMessageActionItemNode.swift | 26 +++++- .../ChatRecentActionsControllerNode.swift | 24 ++++- .../ChatRecentActionsHistoryTransition.swift | 5 +- .../Sources/CreateGroupController.swift | 91 ++++++++++++++++++- .../Sources/PeerInfo/PeerInfoData.swift | 9 +- .../Sources/PeerInfo/PeerInfoHeaderNode.swift | 86 ++++++++++++++---- .../Sources/PeerInfo/PeerInfoScreen.swift | 18 +++- 14 files changed, 320 insertions(+), 88 deletions(-) diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 75bda68d39..819e30f4ed 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -928,8 +928,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { let transformedCopyViewFinalFrame = videoNode.view.convert(videoNode.view.bounds, to: self.view) let (maybeSurfaceCopyView, _) = node.2() - let (maybeCopyView, copyViewBackgrond) = node.2() - copyViewBackgrond?.alpha = 0.0 + let (maybeCopyView, copyViewBackground) = node.2() + copyViewBackground?.alpha = 0.0 let surfaceCopyView = maybeSurfaceCopyView! let copyView = maybeCopyView! @@ -1032,8 +1032,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { var copyCompleted = false let (maybeSurfaceCopyView, _) = node.2() - let (maybeCopyView, copyViewBackgrond) = node.2() - copyViewBackgrond?.alpha = 0.0 + let (maybeCopyView, copyViewBackground) = node.2() + copyViewBackground?.alpha = 0.0 let surfaceCopyView = maybeSurfaceCopyView! let copyView = maybeCopyView! diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorController.m b/submodules/LegacyComponents/Sources/TGPhotoEditorController.m index a3297538d9..24ed610fcc 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorController.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorController.m @@ -1716,7 +1716,7 @@ CGFloat duration = self.view.frame.size.height / velocity; CGRect targetFrame = CGRectOffset(self.view.frame, 0, self.view.frame.size.height); - [UIView animateWithDuration:duration animations:^ + [UIView animateWithDuration:duration delay:0.4 options:kNilOptions animations:^ { self.view.frame = targetFrame; } completion:^(__unused BOOL finished) diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index 583c0b98a6..31c75ac133 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -112,39 +112,53 @@ public func normalizeEntries(_ entries: [AvatarGalleryEntry]) -> [AvatarGalleryE return updatedEntries } -public func initialAvatarGalleryEntries(peer: Peer) -> [AvatarGalleryEntry] { +public func initialAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<[AvatarGalleryEntry], NoError> { var initialEntries: [AvatarGalleryEntry] = [] if !peer.profileImageRepresentations.isEmpty, let peerReference = PeerReference(peer) { initialEntries.append(.topImage(peer.profileImageRepresentations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatar(peer: peerReference, resource: $0.resource)) }), nil, nil, nil)) } - return initialEntries + + if let peer = peer as? TelegramChannel { + return account.postbox.transaction { transaction in + return transaction.getPeerCachedData(peerId: peer.id) + } |> map { cachedData in + if let cachedData = cachedData as? CachedChannelData, let photo = cachedData.photo { + return [.image(photo.imageId, photo.reference, photo.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.standalone(resource: $0.resource)) }), photo.videoRepresentations, peer, 0, nil, nil, photo.immediateThumbnailData, nil)] + } else { + return initialEntries + } + } + } else { + return .single(initialEntries) + } } public func fetchedAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<[AvatarGalleryEntry], NoError> { - let initialEntries = initialAvatarGalleryEntries(peer: peer) - return Signal<[AvatarGalleryEntry], NoError>.single(initialEntries) - |> then( - requestPeerPhotos(account: account, peerId: peer.id) - |> map { photos -> [AvatarGalleryEntry] in - var result: [AvatarGalleryEntry] = [] - let initialEntries = initialAvatarGalleryEntries(peer: peer) - if photos.isEmpty { - result = initialEntries - } else { - var index: Int32 = 0 - for photo in photos { - let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photos.count)) - if result.isEmpty, let first = initialEntries.first { - result.append(.image(photo.image.imageId, photo.image.reference, first.representations, photo.image.videoRepresentations, peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil)) - } else { - result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.standalone(resource: $0.resource)) }), photo.image.videoRepresentations, peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil)) + return initialAvatarGalleryEntries(account: account, peer: peer) + |> mapToSignal { initialEntries in + return .single(initialEntries) + |> then( + requestPeerPhotos(account: account, peerId: peer.id) + |> map { photos -> [AvatarGalleryEntry] in + var result: [AvatarGalleryEntry] = [] + if photos.isEmpty { + result = initialEntries + } else { + var index: Int32 = 0 + for photo in photos { + let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photos.count)) + if result.isEmpty, let first = initialEntries.first { + result.append(.image(photo.image.imageId, photo.image.reference, first.representations, photo.image.videoRepresentations, peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil)) + } else { + result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.standalone(resource: $0.resource)) }), photo.image.videoRepresentations, peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil)) + } + index += 1 } - index += 1 } + return result } - return result - } - ) + ) + } } public func fetchedAvatarGalleryEntries(account: Account, peer: Peer, firstEntry: AvatarGalleryEntry) -> Signal<[AvatarGalleryEntry], NoError> { @@ -242,7 +256,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr remoteEntriesSignal = fetchedAvatarGalleryEntries(account: context.account, peer: peer) } - let entriesSignal: Signal<[AvatarGalleryEntry], NoError> = .single(initialAvatarGalleryEntries(peer: peer)) |> then(remoteEntriesSignal) + let entriesSignal: Signal<[AvatarGalleryEntry], NoError> = initialAvatarGalleryEntries(account: context.account, peer: peer) |> then(remoteEntriesSignal) let presentationData = self.presentationData diff --git a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift index 7582258cc4..12fe994097 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift @@ -449,7 +449,10 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode { var copyCompleted = false var surfaceCopyCompleted = false - let copyView = node.2().0! + let (maybeCopyView, copyViewBackground) = node.2() + copyViewBackground?.alpha = 1.0 + + let copyView = maybeCopyView! if self.sourceHasRoundCorners { self.view.insertSubview(copyView, belowSubview: self.scrollNode.view) diff --git a/submodules/SyncCore/Sources/CachedChannelData.swift b/submodules/SyncCore/Sources/CachedChannelData.swift index ec04d09ffe..79019c8c40 100644 --- a/submodules/SyncCore/Sources/CachedChannelData.swift +++ b/submodules/SyncCore/Sources/CachedChannelData.swift @@ -168,6 +168,7 @@ public final class CachedChannelData: CachedPeerData { public let hasScheduledMessages: Bool public let statsDatacenterId: Int32 public let invitedBy: PeerId? + public let photo: TelegramMediaImage? public let peerIds: Set public let messageIds: Set @@ -196,9 +197,10 @@ public final class CachedChannelData: CachedPeerData { self.hasScheduledMessages = false self.statsDatacenterId = 0 self.invitedBy = nil + self.photo = nil } - public init(isNotAccessible: Bool, flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?, minAvailableMessageId: MessageId?, migrationReference: ChannelMigrationReference?, linkedDiscussionPeerId: PeerId?, peerGeoLocation: PeerGeoLocation?, slowModeTimeout: Int32?, slowModeValidUntilTimestamp: Int32?, hasScheduledMessages: Bool, statsDatacenterId: Int32, invitedBy: PeerId?) { + public init(isNotAccessible: Bool, flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?, minAvailableMessageId: MessageId?, migrationReference: ChannelMigrationReference?, linkedDiscussionPeerId: PeerId?, peerGeoLocation: PeerGeoLocation?, slowModeTimeout: Int32?, slowModeValidUntilTimestamp: Int32?, hasScheduledMessages: Bool, statsDatacenterId: Int32, invitedBy: PeerId?, photo: TelegramMediaImage?) { self.isNotAccessible = isNotAccessible self.flags = flags self.about = about @@ -217,6 +219,7 @@ public final class CachedChannelData: CachedPeerData { self.hasScheduledMessages = hasScheduledMessages self.statsDatacenterId = statsDatacenterId self.invitedBy = invitedBy + self.photo = photo var peerIds = Set() for botInfo in botInfos { @@ -242,75 +245,79 @@ public final class CachedChannelData: CachedPeerData { } public func withUpdatedIsNotAccessible(_ isNotAccessible: Bool) -> CachedChannelData { - return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedAbout(_ about: String?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedParticipantsSummary(_ participantsSummary: CachedChannelParticipantsSummary) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedStickerPack(_ stickerPack: StickerPackCollectionInfo?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedMinAvailableMessageId(_ minAvailableMessageId: MessageId?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedMigrationReference(_ migrationReference: ChannelMigrationReference?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedLinkedDiscussionPeerId(_ linkedDiscussionPeerId: PeerId?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedSlowModeTimeout(_ slowModeTimeout: Int32?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedSlowModeValidUntilTimestamp(_ slowModeValidUntilTimestamp: Int32?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedStatsDatacenterId(_ statsDatacenterId: Int32) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo) } public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedChannelData { - return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy) + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy, photo: self.photo) + } + + public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedChannelData { + return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: photo) } public init(decoder: PostboxDecoder) { @@ -372,6 +379,12 @@ public final class CachedChannelData: CachedPeerData { self.invitedBy = decoder.decodeOptionalInt64ForKey("invBy").flatMap(PeerId.init) + if let photo = decoder.decodeObjectForKey("ph", decoder: { TelegramMediaImage(decoder: $0) }) as? TelegramMediaImage { + self.photo = photo + } else { + self.photo = nil + } + if let linkedDiscussionPeerId = self.linkedDiscussionPeerId { peerIds.insert(linkedDiscussionPeerId) } @@ -462,6 +475,12 @@ public final class CachedChannelData: CachedPeerData { } else { encoder.encodeNil(forKey: "invBy") } + + if let photo = self.photo { + encoder.encodeObject(photo, forKey: "ph") + } else { + encoder.encodeNil(forKey: "ph") + } } public func isEqual(to: CachedPeerData) -> Bool { @@ -541,6 +560,10 @@ public final class CachedChannelData: CachedPeerData { return false } + if other.photo != self.photo { + return false + } + return true } } diff --git a/submodules/TelegramCore/Sources/ChannelAdminEventLogs.swift b/submodules/TelegramCore/Sources/ChannelAdminEventLogs.swift index 5d3ec84adc..247a8ecf3c 100644 --- a/submodules/TelegramCore/Sources/ChannelAdminEventLogs.swift +++ b/submodules/TelegramCore/Sources/ChannelAdminEventLogs.swift @@ -36,7 +36,7 @@ public enum AdminLogEventAction { case changeTitle(prev: String, new: String) case changeAbout(prev: String, new: String) case changeUsername(prev: String, new: String) - case changePhoto(prev: [TelegramMediaImageRepresentation], new: [TelegramMediaImageRepresentation]) + case changePhoto(prev: ([TelegramMediaImageRepresentation], [TelegramMediaImage.VideoRepresentation]), new: ([TelegramMediaImageRepresentation], [TelegramMediaImage.VideoRepresentation])) case toggleInvites(Bool) case toggleSignatures(Bool) case updatePinned(Message?) @@ -149,7 +149,9 @@ public func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: Pe case let .channelAdminLogEventActionChangeUsername(prev, new): action = .changeUsername(prev: prev, new: new) case let .channelAdminLogEventActionChangePhoto(prev, new): - action = .changePhoto(prev: telegramMediaImageFromApiPhoto(prev)?.representations ?? [], new: telegramMediaImageFromApiPhoto(new)?.representations ?? []) + let previousImage = telegramMediaImageFromApiPhoto(prev) + let newImage = telegramMediaImageFromApiPhoto(new) + action = .changePhoto(prev: (previousImage?.representations ?? [], previousImage?.videoRepresentations ?? []) , new: (newImage?.representations ?? [], newImage?.videoRepresentations ?? [])) case let .channelAdminLogEventActionToggleInvites(new): action = .toggleInvites(boolFromApiValue(new)) case let .channelAdminLogEventActionToggleSignatures(new): diff --git a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift index 2bc2af0ad8..07a5eed43d 100644 --- a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift @@ -337,7 +337,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI } switch fullChat { - case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, pts): + case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, pts): var channelFlags = CachedChannelFlags() if (flags & (1 << 3)) != 0 { channelFlags.insert(.canDisplayParticipants) @@ -467,6 +467,8 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI } } + let photo = telegramMediaImageFromApiPhoto(chatPhoto) + var minAvailableMessageIdUpdated = false transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current in var previous: CachedChannelData @@ -496,6 +498,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI .withUpdatedHasScheduledMessages(hasScheduledMessages) .withUpdatedStatsDatacenterId(statsDc ?? 0) .withUpdatedInvitedBy(invitedBy) + .withUpdatedPhoto(photo) }) if let minAvailableMessageId = minAvailableMessageId, minAvailableMessageIdUpdated { diff --git a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift index 159926012d..3e8a2f5eda 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift @@ -65,9 +65,28 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if let imageNode = self.imageNode, self.item?.message.id == messageId { - return (imageNode, imageNode.bounds, { [weak imageNode] in - let snapshot = imageNode?.view.snapshotContentTree(unhide: true) - return (snapshot, nil) + return (imageNode, imageNode.bounds, { [weak self] in + guard let strongSelf = self, let imageNode = strongSelf.imageNode else { + return (nil, nil) + } + + let resultView = imageNode.view.snapshotContentTree(unhide: true) + if let resultView = resultView, strongSelf.mediaBackgroundNode.supernode != nil, let backgroundView = strongSelf.mediaBackgroundNode.view.snapshotContentTree(unhide: true) { + let backgroundContainer = UIView() + + backgroundContainer.addSubview(backgroundView) + let backgroundFrame = strongSelf.mediaBackgroundNode.layer.convert(strongSelf.mediaBackgroundNode.bounds, to: resultView.layer) + backgroundContainer.frame = CGRect(origin: CGPoint(x: -2.0, y: -2.0), size: CGSize(width: resultView.frame.width + 4.0, height: resultView.frame.height + 4.0)) + backgroundView.frame = backgroundContainer.bounds + let viewWithBackground = UIView() + viewWithBackground.addSubview(backgroundContainer) + viewWithBackground.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: resultView.frame.size) + resultView.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: resultView.frame.size) + viewWithBackground.addSubview(resultView) + return (viewWithBackground, backgroundContainer) + } + + return (resultView, nil) }) } else { return nil @@ -100,6 +119,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { } self.imageNode?.isHidden = mediaHidden + self.mediaBackgroundNode.isHidden = mediaHidden return mediaHidden } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index e2fd4e5317..959ea86be8 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -44,6 +44,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { private var controllerInteraction: ChatControllerInteraction! private let galleryHiddenMesageAndMediaDisposable = MetaDisposable() + private let temporaryHiddenGalleryMediaDisposable = MetaDisposable() private var chatPresentationDataPromise: Promise private var presentationDataDisposable: Disposable? @@ -183,7 +184,27 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, callPeer: { peerId, isVideo in self?.controllerInteraction?.callPeer(peerId, isVideo) }, enqueueMessage: { _ in - }, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in })) + }, sendSticker: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { signal, media in + if let strongSelf = self { + strongSelf.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).start(next: { messageId in + if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { + var messageIdAndMedia: [MessageId: [Media]] = [:] + + if let messageId = messageId { + messageIdAndMedia[messageId] = [media] + } + + controllerInteraction.hiddenMedia = messageIdAndMedia + + strongSelf.listNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ChatMessageItemView { + itemNode.updateHiddenMedia() + } + } + } + })) + } + })) } return false }, openPeer: { [weak self] peerId, _, message in @@ -516,6 +537,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { self.historyDisposable?.dispose() self.navigationActionDisposable.dispose() self.galleryHiddenMesageAndMediaDisposable.dispose() + self.temporaryHiddenGalleryMediaDisposable.dispose() self.resolvePeerByNameDisposable.dispose() self.adminsDisposable?.dispose() self.banDisposables.dispose() diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift index f4aa666109..72086329da 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift @@ -219,8 +219,9 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { peers[peer.id] = peer var photo: TelegramMediaImage? - if !new.isEmpty { - photo = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: new, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) + let (newPhoto, newVideo) = new + if !newPhoto.isEmpty || !newVideo.isEmpty { + photo = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: newPhoto, videoRepresentations: newVideo, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) } let action = TelegramMediaActionType.photoUpdated(image: photo) diff --git a/submodules/TelegramUI/Sources/CreateGroupController.swift b/submodules/TelegramUI/Sources/CreateGroupController.swift index fb8fbaa78c..fbab9422f0 100644 --- a/submodules/TelegramUI/Sources/CreateGroupController.swift +++ b/submodules/TelegramUI/Sources/CreateGroupController.swift @@ -26,6 +26,7 @@ import PeerInfoUI import MapResourceToAvatarSizes import ItemListAddressItem import ItemListVenueItem +import LegacyMediaPickerUI private struct CreateGroupArguments { let context: AccountContext @@ -383,6 +384,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] let currentAvatarMixin = Atomic(value: nil) let uploadedAvatar = Promise() + var uploadedVideoAvatar: Promise? = nil let addressPromise = Promise(nil) let venuesPromise = Promise<[TelegramMediaMap]?>(nil) @@ -480,7 +482,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] return $0.avatar } if let _ = updatingAvatar { - return updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), mapResourceToAvatarSizes: { resource, representations in + return updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.get(), mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) }) |> ignoreValues @@ -569,12 +571,13 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] endEditingImpl?() presentControllerImpl?(legacyController, nil) - let completedImpl: (UIImage) -> Void = { image in + let completedGroupPhotoImpl: (UIImage) -> Void = { image in if let data = image.jpegData(compressionQuality: 0.6) { let resource = LocalFileMediaResource(fileId: arc4random64()) context.account.postbox.mediaBox.storeResourceData(resource.id, data: data) let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource) uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: resource)) + uploadedVideoAvatar = nil updateState { current in var current = current current.avatar = .image(representation, false) @@ -583,19 +586,99 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] } } + let completedGroupVideoImpl: (UIImage, URL, TGVideoEditAdjustments?) -> Void = { image, url, adjustments in + if let data = image.jpegData(compressionQuality: 0.6) { + let photoResource = LocalFileMediaResource(fileId: arc4random64()) + context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data) + let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: photoResource) + updateState { state in + var state = state + state.avatar = .image(representation, true) + return state + } + + var videoStartTimestamp: Double? = nil + if let adjustments = adjustments, adjustments.videoStartValue > 0.0 { + videoStartTimestamp = adjustments.videoStartValue - adjustments.trimStartValue + } + + let signal = Signal { subscriber in + var filteredPath = url.path + if filteredPath.hasPrefix("file://") { + filteredPath = String(filteredPath[filteredPath.index(filteredPath.startIndex, offsetBy: "file://".count)]) + } + + let avAsset = AVURLAsset(url: URL(fileURLWithPath: filteredPath)) + let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in + if let paintingData = adjustments.paintingData, paintingData.hasAnimation { + return LegacyPaintEntityRenderer(account: context.account, adjustments: adjustments) + } else { + return nil + } + } + let uploadInterface = LegacyLiveUploadInterface(account: context.account) + let signal = TGMediaVideoConverter.convert(avAsset, adjustments: adjustments, watcher: uploadInterface, entityRenderer: entityRenderer)! + + let signalDisposable = signal.start(next: { next in + if let result = next as? TGMediaVideoConversionResult { + if let image = result.coverImage, let data = image.jpegData(compressionQuality: 0.7) { + context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data) + } + + var value = stat() + if stat(result.fileURL.path, &value) == 0 { + if let data = try? Data(contentsOf: result.fileURL) { + let resource: TelegramMediaResource + if let liveUploadData = result.liveUploadData as? LegacyLiveUploadInterfaceResult { + resource = LocalFileMediaResource(fileId: liveUploadData.id) + } else { + resource = LocalFileMediaResource(fileId: arc4random64()) + } + context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true) + subscriber.putNext(resource) + } + } + subscriber.putCompletion() + } + }, error: { _ in + }, completed: nil) + + let disposable = ActionDisposable { + signalDisposable?.dispose() + } + + return ActionDisposable { + disposable.dispose() + } + } + +// let promise = Promise() +// promise.set(signal |> mapToSignal { resource in +// return uploadedPeerVideo(postbox: context.account.postbox, network: context.account.network, messageMediaPreuploadManager: context.account.messageMediaPreuploadManager, resource: resource) |> map(Optional.init) +// |> `catch` { _ -> Signal in +// return .single(nil) +// } +// }) +// uploadedVideoAvatar = promise + } + } + let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)! let _ = currentAvatarMixin.swap(mixin) mixin.requestSearchController = { assetsController in let controller = WebSearchController(context: context, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in assetsController?.dismiss() - completedImpl(result) + completedGroupPhotoImpl(result) })) presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) } mixin.didFinishWithImage = { image in if let image = image { - completedImpl(image) + completedGroupPhotoImpl(image) } + } + mixin.didFinishWithVideo = { _, _, _ in + } if stateValue.with({ $0.avatar }) != nil { mixin.didFinishWithDelete = { diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift index 1d6a2903fa..83303351b7 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift @@ -318,11 +318,14 @@ private func peerInfoScreenInputData(context: AccountContext, peerId: PeerId, is private func peerInfoProfilePhotos(context: AccountContext, peerId: PeerId) -> Signal { return context.account.postbox.combinedView(keys: [.basicPeer(peerId)]) - |> map { view -> AvatarGalleryEntry? in + |> mapToSignal { view -> Signal in guard let peer = (view.views[.basicPeer(peerId)] as? BasicPeerView)?.peer else { - return nil + return .single(nil) + } + return initialAvatarGalleryEntries(account: context.account, peer: peer) + |> map { entries in + return entries.first } - return initialAvatarGalleryEntries(peer: peer).first } |> distinctUntilChanged |> mapToSignal { firstEntry -> Signal<[AvatarGalleryEntry], NoError> in diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index 1c57da0951..65c9ed0d92 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -273,7 +273,7 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode { videoNode.isUserInteractionEnabled = false videoNode.isHidden = true - if let _ = video.startTimestamp { + if let startTimestamp = video.startTimestamp { self.playbackStatusDisposable.set((videoNode.status |> map { status -> Bool in if let status = status, case .playing = status.status { @@ -288,20 +288,17 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode { |> take(1) |> deliverOnMainQueue).start(completed: { [weak self] in if let strongSelf = self { - Queue.mainQueue().after(0.1) { + Queue.mainQueue().after(0.15) { strongSelf.videoNode?.isHidden = false } } })) + videoNode.seek(startTimestamp) } else { self.playbackStatusDisposable.set(nil) videoNode.isHidden = false } - - if let startTimestamp = video.startTimestamp { - videoNode.seek(startTimestamp) - } - + self.videoContent = videoContent self.videoNode = videoNode self.statusPromise.set(videoNode.status |> map { ($0, video.startTimestamp) }) @@ -1035,6 +1032,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { var tapped: (() -> Void)? private var isFirstAvatarLoading = true + var item: PeerInfoAvatarListItem? private let playbackStatusDisposable = MetaDisposable() @@ -1090,11 +1088,22 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { } } + var removedPhotoResourceIds = Set() func update(peer: Peer?, item: PeerInfoAvatarListItem?, theme: PresentationTheme, avatarSize: CGFloat, isExpanded: Bool) { if let peer = peer { + let previousItem = self.item + self.item = item + var overrideImage: AvatarNodeImageOverride? if peer.isDeleted { overrideImage = .deletedIcon + } else if let previousItem = previousItem, item == nil { + if case let .image(image) = previousItem, let rep = image.1.last { + self.removedPhotoResourceIds.insert(rep.representation.resource.id.uniqueId) + } + overrideImage = AvatarNodeImageOverride.none + } else if let rep = peer.profileImageRepresentations.last, self.removedPhotoResourceIds.contains(rep.resource.id.uniqueId) { + overrideImage = AvatarNodeImageOverride.none } self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, overrideImage: overrideImage, synchronousLoad: self.isFirstAvatarLoading, displayDimensions: CGSize(width: avatarSize, height: avatarSize), storeUnrounded: true) self.isFirstAvatarLoading = false @@ -1128,7 +1137,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { |> take(1) |> deliverOnMainQueue).start(completed: { [weak self] in if let strongSelf = self { - Queue.mainQueue().after(0.1) { + Queue.mainQueue().after(0.15) { strongSelf.videoNode?.isHidden = false } } @@ -1213,6 +1222,7 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode { self.iconNode = ASImageNode() self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Avatar/EditAvatarIconLarge"), color: .white) + self.iconNode.isHidden = true super.init() @@ -1248,7 +1258,7 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode { overlayHidden = false iconHidden = true - self.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: uploadProgress ?? 0.0, cancelEnabled: true)) + self.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: max(0.027, uploadProgress ?? 0.0), cancelEnabled: true)) if case let .image(representation) = updatingAvatar { if representation != self.currentRepresentation { @@ -1262,12 +1272,13 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode { self.updatingAvatarOverlay.isHidden = overlayHidden } else { if isEditing { - iconHidden = false + iconHidden = peer.profileImageRepresentations.isEmpty + overlayHidden = peer.profileImageRepresentations.isEmpty } else { iconHidden = true overlayHidden = true } - Queue.mainQueue().after(0.1) { [weak self] in + Queue.mainQueue().after(0.15) { [weak self] in self?.statusNode.transitionToState(.none) self?.currentRepresentation = nil self?.imageNode.setSignal(.single(nil)) @@ -1283,7 +1294,6 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode { self.iconNode.isHidden = true self.updatingAvatarOverlay.isHidden = true self.currentRepresentation = nil - } } } @@ -1296,7 +1306,7 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode { private var videoStartTimestamp: Double? var tapped: ((Bool) -> Void)? - + var canAttachVideo: Bool = true init(context: AccountContext) { @@ -1322,7 +1332,7 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode { guard let peer = peer else { return } - + let overrideImage: AvatarNodeImageOverride? if canEditPeerInfo(context: self.context, peer: peer), peer.profileImageRepresentations.isEmpty { overrideImage = .editAvatarIcon @@ -1393,6 +1403,8 @@ final class PeerInfoAvatarListNode: ASDisplayNode { var arguments: (Peer?, PresentationTheme, CGFloat, Bool)? var item: PeerInfoAvatarListItem? + var itemsUpdated: (([PeerInfoAvatarListItem]) -> Void)? + init(context: AccountContext, readyWhenGalleryLoads: Bool) { self.avatarContainerNode = PeerInfoAvatarTransformContainerNode(context: context) self.listContainerTransformNode = ASDisplayNode() @@ -1440,6 +1452,7 @@ final class PeerInfoAvatarListNode: ASDisplayNode { self.listContainerNode.itemsUpdated = { [weak self] items in if let strongSelf = self { strongSelf.item = items.first + strongSelf.itemsUpdated?(items) if let (peer, theme, avatarSize, isExpanded) = strongSelf.arguments { strongSelf.avatarContainerNode.update(peer: peer, item: strongSelf.item, theme: theme, avatarSize: avatarSize, isExpanded: isExpanded) } @@ -2190,6 +2203,9 @@ private let TitleNodeStateExpanded = 1 final class PeerInfoHeaderNode: ASDisplayNode { private var context: AccountContext private var presentationData: PresentationData? + private var state: PeerInfoState? + private var peer: Peer? + private var avatarSize: CGFloat? private let isOpenedFromChat: Bool private let isSettings: Bool @@ -2218,6 +2234,10 @@ final class PeerInfoHeaderNode: ASDisplayNode { private let backgroundNode: ASDisplayNode private let expandedBackgroundNode: ASDisplayNode let separatorNode: ASDisplayNode + let navigationBackgroundNode: ASDisplayNode + var navigationTitle: String? + let navigationTitleNode: ImmediateTextNode + let navigationSeparatorNode: ASDisplayNode let navigationButtonContainer: PeerInfoHeaderNavigationButtonContainerNode var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? @@ -2272,6 +2292,13 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.avatarOverlayNode = PeerInfoEditingAvatarOverlayNode(context: context) + self.navigationBackgroundNode = ASDisplayNode() + self.navigationBackgroundNode.isUserInteractionEnabled = false + + self.navigationTitleNode = ImmediateTextNode() + + self.navigationSeparatorNode = ASDisplayNode() + self.navigationButtonContainer = PeerInfoHeaderNavigationButtonContainerNode() self.backgroundNode = ASDisplayNode() @@ -2303,6 +2330,9 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.addSubnode(self.regularContentNode) self.addSubnode(self.editingContentNode) self.addSubnode(self.avatarOverlayNode) + self.addSubnode(self.navigationBackgroundNode) + self.navigationBackgroundNode.addSubnode(self.navigationTitleNode) + self.navigationBackgroundNode.addSubnode(self.navigationSeparatorNode) self.addSubnode(self.navigationButtonContainer) self.addSubnode(self.separatorNode) @@ -2310,10 +2340,14 @@ final class PeerInfoHeaderNode: ASDisplayNode { self?.initiateAvatarExpansion() } self.editingContentNode.avatarNode.tapped = { [weak self] confirm in - guard let strongSelf = self else { + self?.requestOpenAvatarForEditing?(confirm) + } + + self.avatarListNode.itemsUpdated = { [weak self] items in + guard let strongSelf = self, let state = strongSelf.state, let peer = strongSelf.peer, let presentationData = strongSelf.presentationData, let avatarSize = strongSelf.avatarSize else { return } - strongSelf.requestOpenAvatarForEditing?(confirm) + strongSelf.editingContentNode.avatarNode.update(peer: peer, item: strongSelf.avatarListNode.item, updatingAvatar: state.updatingAvatar, uploadProgress: state.avatarUploadProgress, theme: presentationData.theme, avatarSize: avatarSize, isEditing: state.isEditing) } } @@ -2387,6 +2421,12 @@ final class PeerInfoHeaderNode: ASDisplayNode { } func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, statusData: PeerInfoStatusData?, isContact: Bool, isSettings: Bool, state: PeerInfoState, transition: ContainedViewLayoutTransition, additive: Bool) -> CGFloat { + self.state = state + self.peer = peer + + let avatarSize: CGFloat = isModalOverlay ? 200.0 : 100.0 + self.avatarSize = avatarSize + var contentOffset = contentOffset if isMediaOnly { @@ -2446,7 +2486,6 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.avatarListNode.animateAvatarCollapse(transition: transition) } } else { - let avatarSize: CGFloat = isModalOverlay ? 200.0 : 100.0 let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / (112.0 + avatarSize))) transition.updateAlpha(node: self.expandedBackgroundNode, alpha: backgroundTransitionFraction) } @@ -2454,6 +2493,18 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.avatarListNode.avatarContainerNode.updateTransitionFraction(transitionFraction, transition: transition) self.avatarListNode.listContainerNode.currentItemNode?.updateTransitionFraction(transitionFraction, transition: transition) + if self.navigationTitle != presentationData.strings.EditProfile_Title || themeUpdated { + self.navigationTitleNode.attributedText = NSAttributedString(string: presentationData.strings.EditProfile_Title, font: Font.bold(17.0), textColor: presentationData.theme.rootController.navigationBar.primaryTextColor) + } + + let navigationTitleSize = self.navigationTitleNode.updateLayout(CGSize(width: width, height: navigationHeight)) + self.navigationTitleNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - navigationTitleSize.width) / 2.0), y: navigationHeight - 44.0 + floorToScreenPixels((44.0 - navigationTitleSize.height) / 2.0)), size: navigationTitleSize) + + self.navigationBackgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: navigationHeight)) + self.navigationSeparatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: navigationHeight), size: CGSize(width: width, height: UIScreenPixel)) + self.navigationBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.backgroundColor + self.navigationSeparatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor + transition.updateAlpha(node: self.navigationBackgroundNode, alpha: state.isEditing && self.isSettings ? min(1.0, contentOffset / (navigationHeight * 0.5)) : 0.0) self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor let defaultButtonSize: CGFloat = 40.0 @@ -2521,7 +2572,6 @@ final class PeerInfoHeaderNode: ASDisplayNode { TitleNodeStateExpanded: MultiScaleTextState(attributedText: usernameString, constrainedSize: CGSize(width: width - titleNodeLayout[TitleNodeStateExpanded]!.size.width - 8.0, height: titleConstrainedSize.height)) ], mainState: TitleNodeStateRegular) - let avatarSize: CGFloat = isModalOverlay ? 200.0 : 100.0 let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize)) let avatarCenter = CGPoint(x: (1.0 - transitionFraction) * avatarFrame.midX + transitionFraction * transitionSourceAvatarFrame.midX, y: (1.0 - transitionFraction) * avatarFrame.midY + transitionFraction * transitionSourceAvatarFrame.midY) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index e6dab217ea..86ba52b5bc 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -5415,11 +5415,19 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let (_, navigationHeight) = self.validLayout else { return } - var height: CGFloat = self.isSettings ? 140.0 : 212.0 - if self.headerNode.twoLineInfo { - height += 17.0 - } - if !self.state.isEditing { + if self.state.isEditing && self.isSettings { + if targetContentOffset.pointee.y < navigationHeight { + if targetContentOffset.pointee.y < navigationHeight / 2.0 { + targetContentOffset.pointee.y = 0.0 + } else { + targetContentOffset.pointee.y = navigationHeight + } + } + } else { + var height: CGFloat = self.isSettings ? 140.0 : 212.0 + if self.headerNode.twoLineInfo { + height += 17.0 + } if targetContentOffset.pointee.y < height { if targetContentOffset.pointee.y < height / 2.0 { targetContentOffset.pointee.y = 0.0