mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Video avatar fixes
This commit is contained in:
parent
ab41dbe22a
commit
b51dd938f4
@ -23,12 +23,12 @@ public enum AvatarGalleryEntryId: Hashable {
|
||||
}
|
||||
|
||||
public enum AvatarGalleryEntry: Equatable {
|
||||
case topImage([ImageRepresentationWithReference], GalleryItemIndexData?, Data?, String?)
|
||||
case topImage([ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], GalleryItemIndexData?, Data?, String?)
|
||||
case image(MediaId, TelegramMediaImageReference?, [ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], Peer?, Int32, GalleryItemIndexData?, MessageId?, Data?, String?)
|
||||
|
||||
public var id: AvatarGalleryEntryId {
|
||||
switch self {
|
||||
case let .topImage(representations, _, _, _):
|
||||
case let .topImage(representations, _, _, _, _):
|
||||
if let last = representations.last {
|
||||
return .resource(last.representation.resource.id.uniqueId)
|
||||
}
|
||||
@ -43,7 +43,7 @@ public enum AvatarGalleryEntry: Equatable {
|
||||
|
||||
public var representations: [ImageRepresentationWithReference] {
|
||||
switch self {
|
||||
case let .topImage(representations, _, _, _):
|
||||
case let .topImage(representations, _, _, _, _):
|
||||
return representations
|
||||
case let .image(_, _, representations, _, _, _, _, _, _, _):
|
||||
return representations
|
||||
@ -52,8 +52,8 @@ public enum AvatarGalleryEntry: Equatable {
|
||||
|
||||
public var videoRepresentations: [TelegramMediaImage.VideoRepresentation] {
|
||||
switch self {
|
||||
case .topImage:
|
||||
return []
|
||||
case let .topImage(_, videoRepresentations, _, _, _):
|
||||
return videoRepresentations
|
||||
case let .image(_, _, _, videoRepresentations, _, _, _, _, _, _):
|
||||
return videoRepresentations
|
||||
}
|
||||
@ -61,7 +61,7 @@ public enum AvatarGalleryEntry: Equatable {
|
||||
|
||||
public var indexData: GalleryItemIndexData? {
|
||||
switch self {
|
||||
case let .topImage(_, indexData, _, _):
|
||||
case let .topImage(_, _, indexData, _, _):
|
||||
return indexData
|
||||
case let .image(_, _, _, _, _, _, indexData, _, _, _):
|
||||
return indexData
|
||||
@ -70,8 +70,8 @@ public enum AvatarGalleryEntry: Equatable {
|
||||
|
||||
public static func ==(lhs: AvatarGalleryEntry, rhs: AvatarGalleryEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .topImage(lhsRepresentations, lhsIndexData, lhsImmediateThumbnailData, lhsCategory):
|
||||
if case let .topImage(rhsRepresentations, rhsIndexData, rhsImmediateThumbnailData, rhsCategory) = rhs, lhsRepresentations == rhsRepresentations, lhsIndexData == rhsIndexData, lhsImmediateThumbnailData == rhsImmediateThumbnailData, lhsCategory == rhsCategory {
|
||||
case let .topImage(lhsRepresentations, lhsVideoRepresentations, lhsIndexData, lhsImmediateThumbnailData, lhsCategory):
|
||||
if case let .topImage(rhsRepresentations, rhsVideoRepresentations, rhsIndexData, rhsImmediateThumbnailData, rhsCategory) = rhs, lhsRepresentations == rhsRepresentations, lhsVideoRepresentations == rhsVideoRepresentations, lhsIndexData == rhsIndexData, lhsImmediateThumbnailData == rhsImmediateThumbnailData, lhsCategory == rhsCategory {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -102,8 +102,8 @@ public func normalizeEntries(_ entries: [AvatarGalleryEntry]) -> [AvatarGalleryE
|
||||
var index: Int32 = 0
|
||||
for entry in entries {
|
||||
let indexData = GalleryItemIndexData(position: index, totalCount: count)
|
||||
if case let .topImage(representations, _, immediateThumbnailData, category) = entry {
|
||||
updatedEntries.append(.topImage(representations, indexData, immediateThumbnailData, category))
|
||||
if case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, category) = entry {
|
||||
updatedEntries.append(.topImage(representations, videoRepresentations, indexData, immediateThumbnailData, category))
|
||||
} else if case let .image(id, reference, representations, videoRepresentations, peer, date, _, messageId, immediateThumbnailData, category) = entry {
|
||||
updatedEntries.append(.image(id, reference, representations, videoRepresentations, peer, date, indexData, messageId, immediateThumbnailData, category))
|
||||
}
|
||||
@ -115,15 +115,24 @@ public func normalizeEntries(_ entries: [AvatarGalleryEntry]) -> [AvatarGalleryE
|
||||
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))
|
||||
initialEntries.append(.topImage(peer.profileImageRepresentations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatar(peer: peerReference, resource: $0.resource)) }), [], nil, nil, nil))
|
||||
}
|
||||
|
||||
if let peer = peer as? TelegramChannel {
|
||||
if peer is TelegramChannel || peer is TelegramGroup {
|
||||
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)]
|
||||
var initialPhoto: TelegramMediaImage?
|
||||
if let cachedData = cachedData as? CachedGroupData, let photo = cachedData.photo {
|
||||
initialPhoto = photo
|
||||
}
|
||||
else if let cachedData = cachedData as? CachedChannelData, let photo = cachedData.photo {
|
||||
initialPhoto = photo
|
||||
}
|
||||
|
||||
if let photo = initialPhoto {
|
||||
return [.topImage(photo.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.standalone(resource: $0.resource)) }), photo.videoRepresentations, nil, nil, nil)]
|
||||
// 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
|
||||
}
|
||||
@ -233,7 +242,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
||||
|
||||
private let editDisposable = MetaDisposable ()
|
||||
|
||||
public init(context: AccountContext, peer: Peer, sourceHasRoundCorners: Bool = true, remoteEntries: Promise<[AvatarGalleryEntry]>? = nil, centralEntryIndex: Int? = nil, replaceRootController: @escaping (ViewController, Promise<Bool>?) -> Void, synchronousLoad: Bool = false) {
|
||||
public init(context: AccountContext, peer: Peer, sourceHasRoundCorners: Bool = true, remoteEntries: Promise<[AvatarGalleryEntry]>? = nil, skipInitial: Bool = false, centralEntryIndex: Int? = nil, replaceRootController: @escaping (ViewController, Promise<Bool>?) -> Void, synchronousLoad: Bool = false) {
|
||||
self.context = context
|
||||
self.peer = peer
|
||||
self.sourceHasRoundCorners = sourceHasRoundCorners
|
||||
@ -256,7 +265,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
||||
remoteEntriesSignal = fetchedAvatarGalleryEntries(account: context.account, peer: peer)
|
||||
}
|
||||
|
||||
let entriesSignal: Signal<[AvatarGalleryEntry], NoError> = initialAvatarGalleryEntries(account: context.account, peer: peer) |> then(remoteEntriesSignal)
|
||||
let entriesSignal: Signal<[AvatarGalleryEntry], NoError> = skipInitial ? remoteEntriesSignal : (initialAvatarGalleryEntries(account: context.account, peer: peer) |> then(remoteEntriesSignal))
|
||||
|
||||
let presentationData = self.presentationData
|
||||
|
||||
|
@ -104,7 +104,7 @@ class PeerAvatarImageGalleryItem: GalleryItem {
|
||||
func thumbnailItem() -> (Int64, GalleryThumbnailItem)? {
|
||||
let content: [ImageRepresentationWithReference]
|
||||
switch self.entry {
|
||||
case let .topImage(representations, _, _, _):
|
||||
case let .topImage(representations, _, _, _, _):
|
||||
content = representations
|
||||
case let .image(_, _, representations, _, _, _, _, _, _, _):
|
||||
content = representations
|
||||
@ -256,6 +256,8 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
if case let .image(image) = entry {
|
||||
id = image.0.id
|
||||
category = image.9
|
||||
} else {
|
||||
id = 1
|
||||
}
|
||||
if let video = entry.videoRepresentations.last, let id = id {
|
||||
if video != previousVideoRepresentations?.last {
|
||||
@ -551,7 +553,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
case .Remote:
|
||||
let representations: [ImageRepresentationWithReference]
|
||||
switch entry {
|
||||
case let .topImage(topRepresentations, _, _, _):
|
||||
case let .topImage(topRepresentations, _, _, _, _):
|
||||
representations = topRepresentations
|
||||
case let .image(_, _, imageRepresentations, _, _, _, _, _, _, _):
|
||||
representations = imageRepresentations
|
||||
|
@ -49,6 +49,7 @@ public final class CachedGroupData: CachedPeerData {
|
||||
public let flags: CachedGroupFlags
|
||||
public let hasScheduledMessages: Bool
|
||||
public let invitedBy: PeerId?
|
||||
public let photo: TelegramMediaImage?
|
||||
|
||||
public let peerIds: Set<PeerId>
|
||||
public let messageIds: Set<MessageId>
|
||||
@ -66,9 +67,10 @@ public final class CachedGroupData: CachedPeerData {
|
||||
self.flags = CachedGroupFlags()
|
||||
self.hasScheduledMessages = false
|
||||
self.invitedBy = nil
|
||||
self.photo = nil
|
||||
}
|
||||
|
||||
public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, about: String?, flags: CachedGroupFlags, hasScheduledMessages: Bool, invitedBy: PeerId?) {
|
||||
public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, about: String?, flags: CachedGroupFlags, hasScheduledMessages: Bool, invitedBy: PeerId?, photo: TelegramMediaImage?) {
|
||||
self.participants = participants
|
||||
self.exportedInvitation = exportedInvitation
|
||||
self.botInfos = botInfos
|
||||
@ -78,6 +80,7 @@ public final class CachedGroupData: CachedPeerData {
|
||||
self.flags = flags
|
||||
self.hasScheduledMessages = hasScheduledMessages
|
||||
self.invitedBy = invitedBy
|
||||
self.photo = photo
|
||||
|
||||
var messageIds = Set<MessageId>()
|
||||
if let pinnedMessageId = self.pinnedMessageId {
|
||||
@ -123,6 +126,12 @@ public final class CachedGroupData: 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
|
||||
}
|
||||
|
||||
var messageIds = Set<MessageId>()
|
||||
if let pinnedMessageId = self.pinnedMessageId {
|
||||
messageIds.insert(pinnedMessageId)
|
||||
@ -181,6 +190,12 @@ public final class CachedGroupData: 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 {
|
||||
@ -192,38 +207,42 @@ public final class CachedGroupData: CachedPeerData {
|
||||
}
|
||||
|
||||
public func withUpdatedParticipants(_ participants: CachedGroupParticipants?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedAbout(_ about: String?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedFlags(_ flags: CachedGroupFlags) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: hasScheduledMessages, invitedBy: self.invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: invitedBy)
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: invitedBy, photo: self.photo)
|
||||
}
|
||||
|
||||
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedGroupData {
|
||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: photo)
|
||||
}
|
||||
}
|
||||
|
@ -250,6 +250,8 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
}
|
||||
}
|
||||
|
||||
let photo: TelegramMediaImage? = chatFull.chatPhoto.flatMap(telegramMediaImageFromApiPhoto)
|
||||
|
||||
let exportedInvitation = ExportedInvitation(apiExportedInvite: chatFull.exportedInvite)
|
||||
let pinnedMessageId = chatFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
|
||||
|
||||
@ -300,6 +302,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
.withUpdatedFlags(flags)
|
||||
.withUpdatedHasScheduledMessages(hasScheduledMessages)
|
||||
.withUpdatedInvitedBy(invitedBy)
|
||||
.withUpdatedPhoto(photo)
|
||||
})
|
||||
case .channelFull:
|
||||
break
|
||||
|
@ -158,12 +158,12 @@ final class PeerInfoHeaderNavigationTransition {
|
||||
}
|
||||
|
||||
enum PeerInfoAvatarListItem: Equatable {
|
||||
case topImage([ImageRepresentationWithReference], Data?)
|
||||
case topImage([ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], Data?)
|
||||
case image(TelegramMediaImageReference?, [ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], Data?)
|
||||
|
||||
var id: WrappedMediaResourceId {
|
||||
switch self {
|
||||
case let .topImage(representations, _):
|
||||
case let .topImage(representations, _, _):
|
||||
let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation
|
||||
return WrappedMediaResourceId(representation.resource.id)
|
||||
case let .image(_, representations, _, _):
|
||||
@ -171,6 +171,15 @@ enum PeerInfoAvatarListItem: Equatable {
|
||||
return WrappedMediaResourceId(representation.resource.id)
|
||||
}
|
||||
}
|
||||
|
||||
var videoRepresentations: [TelegramMediaImage.VideoRepresentation] {
|
||||
switch self {
|
||||
case let .topImage(_, videoRepresentations, _):
|
||||
return videoRepresentations
|
||||
case let .image(_, _, videoRepresentations, _):
|
||||
return videoRepresentations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
||||
@ -250,15 +259,15 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
||||
let immediateThumbnailData: Data?
|
||||
var id: Int64?
|
||||
switch item {
|
||||
case let .topImage(topRepresentations, immediateThumbnail):
|
||||
case let .topImage(topRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||
representations = topRepresentations
|
||||
videoRepresentations = []
|
||||
videoRepresentations = videoRepresentationsValue
|
||||
immediateThumbnailData = immediateThumbnail
|
||||
id = 1
|
||||
case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||
representations = imageRepresentations
|
||||
videoRepresentations = videoRepresentationsValue
|
||||
immediateThumbnailData = immediateThumbnail
|
||||
|
||||
if case let .cloud(imageId, _, _) = reference {
|
||||
id = imageId
|
||||
}
|
||||
@ -761,9 +770,9 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
var entries: [AvatarGalleryEntry] = []
|
||||
for entry in self.galleryEntries {
|
||||
switch entry {
|
||||
case let .topImage(representations, _, immediateThumbnailData, _):
|
||||
case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, _):
|
||||
entries.append(entry)
|
||||
items.append(.topImage(representations, immediateThumbnailData))
|
||||
items.append(.topImage(representations, videoRepresentations, immediateThumbnailData))
|
||||
case let .image(id, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
||||
if image.0 == reference {
|
||||
entries.insert(entry, at: 0)
|
||||
@ -797,9 +806,9 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
let previousIndex = self.currentIndex
|
||||
for entry in self.galleryEntries {
|
||||
switch entry {
|
||||
case let .topImage(representations, _, immediateThumbnailData, _):
|
||||
case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, _):
|
||||
entries.append(entry)
|
||||
items.append(.topImage(representations, immediateThumbnailData))
|
||||
items.append(.topImage(representations, videoRepresentations, immediateThumbnailData))
|
||||
case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
||||
if image.0 != reference {
|
||||
entries.append(entry)
|
||||
@ -861,8 +870,8 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
var items: [PeerInfoAvatarListItem] = []
|
||||
for entry in entries {
|
||||
switch entry {
|
||||
case let .topImage(representations, _, immediateThumbnailData, _):
|
||||
items.append(.topImage(representations, immediateThumbnailData))
|
||||
case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, _):
|
||||
items.append(.topImage(representations, videoRepresentations, immediateThumbnailData))
|
||||
case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
||||
items.append(.image(reference, representations, videoRepresentations, immediateThumbnailData))
|
||||
}
|
||||
@ -1112,53 +1121,78 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
||||
|
||||
self.avatarNode.frame = CGRect(origin: CGPoint(x: -avatarSize / 2.0, y: -avatarSize / 2.0), size: CGSize(width: avatarSize, height: avatarSize))
|
||||
self.avatarNode.font = avatarPlaceholderFont(size: floor(avatarSize * 16.0 / 37.0))
|
||||
|
||||
if let item = item, case let .image(reference, representations, videoRepresentations, immediateThumbnailData) = item, let video = videoRepresentations.last, case let .cloud(imageId, _, _) = reference {
|
||||
let id = imageId
|
||||
let videoFileReference = FileMediaReference.standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
|
||||
if videoContent.id != self.videoContent?.id {
|
||||
let mediaManager = self.context.sharedContext.mediaManager
|
||||
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .embedded)
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
videoNode.isHidden = true
|
||||
|
||||
if let startTimestamp = video.startTimestamp {
|
||||
self.videoStartTimestamp = startTimestamp
|
||||
self.playbackStatusDisposable.set((videoNode.status
|
||||
|> map { status -> Bool in
|
||||
if let status = status, case .playing = status.status {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|> filter { playing in
|
||||
return playing
|
||||
}
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
Queue.mainQueue().after(0.15) {
|
||||
strongSelf.videoNode?.isHidden = false
|
||||
|
||||
if let item = item {
|
||||
let representations: [ImageRepresentationWithReference]
|
||||
let videoRepresentations: [TelegramMediaImage.VideoRepresentation]
|
||||
let immediateThumbnailData: Data?
|
||||
var id: Int64?
|
||||
switch item {
|
||||
case let .topImage(topRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||
representations = topRepresentations
|
||||
videoRepresentations = videoRepresentationsValue
|
||||
immediateThumbnailData = immediateThumbnail
|
||||
id = 1
|
||||
case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||
representations = imageRepresentations
|
||||
videoRepresentations = videoRepresentationsValue
|
||||
immediateThumbnailData = immediateThumbnail
|
||||
if case let .cloud(imageId, _, _) = reference {
|
||||
id = imageId
|
||||
}
|
||||
}
|
||||
|
||||
if let video = videoRepresentations.last, let id = id {
|
||||
let videoFileReference = FileMediaReference.standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
|
||||
if videoContent.id != self.videoContent?.id {
|
||||
let mediaManager = self.context.sharedContext.mediaManager
|
||||
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .embedded)
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
videoNode.isHidden = true
|
||||
|
||||
if let startTimestamp = video.startTimestamp {
|
||||
self.videoStartTimestamp = startTimestamp
|
||||
self.playbackStatusDisposable.set((videoNode.status
|
||||
|> map { status -> Bool in
|
||||
if let status = status, case .playing = status.status {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.videoStartTimestamp = nil
|
||||
self.playbackStatusDisposable.set(nil)
|
||||
videoNode.isHidden = false
|
||||
|> filter { playing in
|
||||
return playing
|
||||
}
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
Queue.mainQueue().after(0.15) {
|
||||
strongSelf.videoNode?.isHidden = false
|
||||
}
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.videoStartTimestamp = nil
|
||||
self.playbackStatusDisposable.set(nil)
|
||||
videoNode.isHidden = false
|
||||
}
|
||||
|
||||
self.videoContent = videoContent
|
||||
self.videoNode = videoNode
|
||||
|
||||
let maskPath = UIBezierPath(ovalIn: CGRect(origin: CGPoint(), size: self.avatarNode.frame.size))
|
||||
let shape = CAShapeLayer()
|
||||
shape.path = maskPath.cgPath
|
||||
videoNode.layer.mask = shape
|
||||
|
||||
self.addSubnode(videoNode)
|
||||
}
|
||||
} else if let videoNode = self.videoNode {
|
||||
self.videoContent = nil
|
||||
self.videoNode = nil
|
||||
|
||||
self.videoContent = videoContent
|
||||
self.videoNode = videoNode
|
||||
|
||||
let maskPath = UIBezierPath(ovalIn: CGRect(origin: CGPoint(), size: self.avatarNode.frame.size))
|
||||
let shape = CAShapeLayer()
|
||||
shape.path = maskPath.cgPath
|
||||
videoNode.layer.mask = shape
|
||||
|
||||
self.addSubnode(videoNode)
|
||||
videoNode.removeFromSupernode()
|
||||
}
|
||||
} else if let videoNode = self.videoNode {
|
||||
self.videoContent = nil
|
||||
@ -1283,7 +1317,7 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode {
|
||||
iconHidden = true
|
||||
overlayHidden = true
|
||||
}
|
||||
Queue.mainQueue().after(0.15) { [weak self] in
|
||||
Queue.mainQueue().after(0.3) { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -1351,28 +1385,53 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode {
|
||||
self.avatarNode.setPeer(context: self.context, theme: theme, peer: peer, overrideImage: overrideImage, synchronousLoad: false, displayDimensions: CGSize(width: avatarSize, height: avatarSize))
|
||||
self.avatarNode.frame = CGRect(origin: CGPoint(x: -avatarSize / 2.0, y: -avatarSize / 2.0), size: CGSize(width: avatarSize, height: avatarSize))
|
||||
|
||||
if let item = item, case let .image(reference, representations, videoRepresentations, immediateThumbnailData) = item, let video = videoRepresentations.last, case let .cloud(imageId, _, _) = reference {
|
||||
let id = imageId
|
||||
let videoFileReference = FileMediaReference.standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
|
||||
if videoContent.id != self.videoContent?.id {
|
||||
let mediaManager = self.context.sharedContext.mediaManager
|
||||
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .overlay)
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
videoNode.ownsContentNodeUpdated = { [weak self] owns in
|
||||
if let strongSelf = self {
|
||||
strongSelf.videoNode?.isHidden = !owns
|
||||
}
|
||||
if let item = item {
|
||||
let representations: [ImageRepresentationWithReference]
|
||||
let videoRepresentations: [TelegramMediaImage.VideoRepresentation]
|
||||
let immediateThumbnailData: Data?
|
||||
var id: Int64?
|
||||
switch item {
|
||||
case let .topImage(topRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||
representations = topRepresentations
|
||||
videoRepresentations = videoRepresentationsValue
|
||||
immediateThumbnailData = immediateThumbnail
|
||||
id = 1
|
||||
case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||
representations = imageRepresentations
|
||||
videoRepresentations = videoRepresentationsValue
|
||||
immediateThumbnailData = immediateThumbnail
|
||||
if case let .cloud(imageId, _, _) = reference {
|
||||
id = imageId
|
||||
}
|
||||
self.videoContent = videoContent
|
||||
self.videoNode = videoNode
|
||||
}
|
||||
|
||||
if let video = videoRepresentations.last, let id = id {
|
||||
let videoFileReference = FileMediaReference.standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
|
||||
if videoContent.id != self.videoContent?.id {
|
||||
let mediaManager = self.context.sharedContext.mediaManager
|
||||
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .overlay)
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
videoNode.ownsContentNodeUpdated = { [weak self] owns in
|
||||
if let strongSelf = self {
|
||||
strongSelf.videoNode?.isHidden = !owns
|
||||
}
|
||||
}
|
||||
self.videoContent = videoContent
|
||||
self.videoNode = videoNode
|
||||
|
||||
let maskPath = UIBezierPath(ovalIn: CGRect(origin: CGPoint(), size: self.avatarNode.frame.size))
|
||||
let shape = CAShapeLayer()
|
||||
shape.path = maskPath.cgPath
|
||||
videoNode.layer.mask = shape
|
||||
|
||||
self.insertSubnode(videoNode, aboveSubnode: self.avatarNode)
|
||||
}
|
||||
} else if let videoNode = self.videoNode {
|
||||
self.videoContent = nil
|
||||
self.videoNode = nil
|
||||
|
||||
let maskPath = UIBezierPath(ovalIn: CGRect(origin: CGPoint(), size: self.avatarNode.frame.size))
|
||||
let shape = CAShapeLayer()
|
||||
shape.path = maskPath.cgPath
|
||||
videoNode.layer.mask = shape
|
||||
|
||||
self.insertSubnode(videoNode, aboveSubnode: self.avatarNode)
|
||||
videoNode.removeFromSupernode()
|
||||
}
|
||||
} else if let videoNode = self.videoNode {
|
||||
self.videoContent = nil
|
||||
|
@ -2086,7 +2086,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}
|
||||
|
||||
let entriesPromise = Promise<[AvatarGalleryEntry]>(entries)
|
||||
let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, sourceHasRoundCorners: !strongSelf.headerNode.isAvatarExpanded, remoteEntries: entriesPromise, centralEntryIndex: centralEntry.flatMap { entries.firstIndex(of: $0) }, replaceRootController: { controller, ready in
|
||||
let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, sourceHasRoundCorners: !strongSelf.headerNode.isAvatarExpanded, remoteEntries: entriesPromise, skipInitial: true, centralEntryIndex: centralEntry.flatMap { entries.firstIndex(of: $0) }, replaceRootController: { controller, ready in
|
||||
})
|
||||
galleryController.openAvatarSetup = { [weak self] completion in
|
||||
self?.openAvatarForEditing(hasRemove: false, completion: completion)
|
||||
|
@ -43,8 +43,12 @@ final class GenericEmbedImplementation: WebEmbedImplementation {
|
||||
self.onPlaybackStarted = onPlaybackStarted
|
||||
updateStatus(self.status)
|
||||
|
||||
let html = String(format: htmlTemplate, self.url)
|
||||
webView.loadHTMLString(html, baseURL: URL(string: "about:blank"))
|
||||
if self.url.contains("player.twitch.tv/"), let url = URL(string: self.url) {
|
||||
webView.load(URLRequest(url: url))
|
||||
} else {
|
||||
let html = String(format: htmlTemplate, self.url)
|
||||
webView.loadHTMLString(html, baseURL: URL(string: "about:blank"))
|
||||
}
|
||||
|
||||
userContentController.addUserScript(WKUserScript(source: userScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user