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 {
|
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?)
|
case image(MediaId, TelegramMediaImageReference?, [ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], Peer?, Int32, GalleryItemIndexData?, MessageId?, Data?, String?)
|
||||||
|
|
||||||
public var id: AvatarGalleryEntryId {
|
public var id: AvatarGalleryEntryId {
|
||||||
switch self {
|
switch self {
|
||||||
case let .topImage(representations, _, _, _):
|
case let .topImage(representations, _, _, _, _):
|
||||||
if let last = representations.last {
|
if let last = representations.last {
|
||||||
return .resource(last.representation.resource.id.uniqueId)
|
return .resource(last.representation.resource.id.uniqueId)
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ public enum AvatarGalleryEntry: Equatable {
|
|||||||
|
|
||||||
public var representations: [ImageRepresentationWithReference] {
|
public var representations: [ImageRepresentationWithReference] {
|
||||||
switch self {
|
switch self {
|
||||||
case let .topImage(representations, _, _, _):
|
case let .topImage(representations, _, _, _, _):
|
||||||
return representations
|
return representations
|
||||||
case let .image(_, _, representations, _, _, _, _, _, _, _):
|
case let .image(_, _, representations, _, _, _, _, _, _, _):
|
||||||
return representations
|
return representations
|
||||||
@ -52,8 +52,8 @@ public enum AvatarGalleryEntry: Equatable {
|
|||||||
|
|
||||||
public var videoRepresentations: [TelegramMediaImage.VideoRepresentation] {
|
public var videoRepresentations: [TelegramMediaImage.VideoRepresentation] {
|
||||||
switch self {
|
switch self {
|
||||||
case .topImage:
|
case let .topImage(_, videoRepresentations, _, _, _):
|
||||||
return []
|
return videoRepresentations
|
||||||
case let .image(_, _, _, videoRepresentations, _, _, _, _, _, _):
|
case let .image(_, _, _, videoRepresentations, _, _, _, _, _, _):
|
||||||
return videoRepresentations
|
return videoRepresentations
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ public enum AvatarGalleryEntry: Equatable {
|
|||||||
|
|
||||||
public var indexData: GalleryItemIndexData? {
|
public var indexData: GalleryItemIndexData? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .topImage(_, indexData, _, _):
|
case let .topImage(_, _, indexData, _, _):
|
||||||
return indexData
|
return indexData
|
||||||
case let .image(_, _, _, _, _, _, indexData, _, _, _):
|
case let .image(_, _, _, _, _, _, indexData, _, _, _):
|
||||||
return indexData
|
return indexData
|
||||||
@ -70,8 +70,8 @@ public enum AvatarGalleryEntry: Equatable {
|
|||||||
|
|
||||||
public static func ==(lhs: AvatarGalleryEntry, rhs: AvatarGalleryEntry) -> Bool {
|
public static func ==(lhs: AvatarGalleryEntry, rhs: AvatarGalleryEntry) -> Bool {
|
||||||
switch lhs {
|
switch lhs {
|
||||||
case let .topImage(lhsRepresentations, lhsIndexData, lhsImmediateThumbnailData, lhsCategory):
|
case let .topImage(lhsRepresentations, lhsVideoRepresentations, lhsIndexData, lhsImmediateThumbnailData, lhsCategory):
|
||||||
if case let .topImage(rhsRepresentations, rhsIndexData, rhsImmediateThumbnailData, rhsCategory) = rhs, lhsRepresentations == rhsRepresentations, lhsIndexData == rhsIndexData, lhsImmediateThumbnailData == rhsImmediateThumbnailData, lhsCategory == rhsCategory {
|
if case let .topImage(rhsRepresentations, rhsVideoRepresentations, rhsIndexData, rhsImmediateThumbnailData, rhsCategory) = rhs, lhsRepresentations == rhsRepresentations, lhsVideoRepresentations == rhsVideoRepresentations, lhsIndexData == rhsIndexData, lhsImmediateThumbnailData == rhsImmediateThumbnailData, lhsCategory == rhsCategory {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -102,8 +102,8 @@ public func normalizeEntries(_ entries: [AvatarGalleryEntry]) -> [AvatarGalleryE
|
|||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let indexData = GalleryItemIndexData(position: index, totalCount: count)
|
let indexData = GalleryItemIndexData(position: index, totalCount: count)
|
||||||
if case let .topImage(representations, _, immediateThumbnailData, category) = entry {
|
if case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, category) = entry {
|
||||||
updatedEntries.append(.topImage(representations, indexData, immediateThumbnailData, category))
|
updatedEntries.append(.topImage(representations, videoRepresentations, indexData, immediateThumbnailData, category))
|
||||||
} else if case let .image(id, reference, representations, videoRepresentations, peer, date, _, messageId, immediateThumbnailData, category) = entry {
|
} 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))
|
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> {
|
public func initialAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<[AvatarGalleryEntry], NoError> {
|
||||||
var initialEntries: [AvatarGalleryEntry] = []
|
var initialEntries: [AvatarGalleryEntry] = []
|
||||||
if !peer.profileImageRepresentations.isEmpty, let peerReference = PeerReference(peer) {
|
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 account.postbox.transaction { transaction in
|
||||||
return transaction.getPeerCachedData(peerId: peer.id)
|
return transaction.getPeerCachedData(peerId: peer.id)
|
||||||
} |> map { cachedData in
|
} |> map { cachedData in
|
||||||
if let cachedData = cachedData as? CachedChannelData, let photo = cachedData.photo {
|
var initialPhoto: TelegramMediaImage?
|
||||||
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)]
|
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 {
|
} else {
|
||||||
return initialEntries
|
return initialEntries
|
||||||
}
|
}
|
||||||
@ -233,7 +242,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||||||
|
|
||||||
private let editDisposable = MetaDisposable ()
|
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.context = context
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.sourceHasRoundCorners = sourceHasRoundCorners
|
self.sourceHasRoundCorners = sourceHasRoundCorners
|
||||||
@ -256,7 +265,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||||||
remoteEntriesSignal = fetchedAvatarGalleryEntries(account: context.account, peer: peer)
|
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
|
let presentationData = self.presentationData
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ class PeerAvatarImageGalleryItem: GalleryItem {
|
|||||||
func thumbnailItem() -> (Int64, GalleryThumbnailItem)? {
|
func thumbnailItem() -> (Int64, GalleryThumbnailItem)? {
|
||||||
let content: [ImageRepresentationWithReference]
|
let content: [ImageRepresentationWithReference]
|
||||||
switch self.entry {
|
switch self.entry {
|
||||||
case let .topImage(representations, _, _, _):
|
case let .topImage(representations, _, _, _, _):
|
||||||
content = representations
|
content = representations
|
||||||
case let .image(_, _, representations, _, _, _, _, _, _, _):
|
case let .image(_, _, representations, _, _, _, _, _, _, _):
|
||||||
content = representations
|
content = representations
|
||||||
@ -256,6 +256,8 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
if case let .image(image) = entry {
|
if case let .image(image) = entry {
|
||||||
id = image.0.id
|
id = image.0.id
|
||||||
category = image.9
|
category = image.9
|
||||||
|
} else {
|
||||||
|
id = 1
|
||||||
}
|
}
|
||||||
if let video = entry.videoRepresentations.last, let id = id {
|
if let video = entry.videoRepresentations.last, let id = id {
|
||||||
if video != previousVideoRepresentations?.last {
|
if video != previousVideoRepresentations?.last {
|
||||||
@ -551,7 +553,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
case .Remote:
|
case .Remote:
|
||||||
let representations: [ImageRepresentationWithReference]
|
let representations: [ImageRepresentationWithReference]
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .topImage(topRepresentations, _, _, _):
|
case let .topImage(topRepresentations, _, _, _, _):
|
||||||
representations = topRepresentations
|
representations = topRepresentations
|
||||||
case let .image(_, _, imageRepresentations, _, _, _, _, _, _, _):
|
case let .image(_, _, imageRepresentations, _, _, _, _, _, _, _):
|
||||||
representations = imageRepresentations
|
representations = imageRepresentations
|
||||||
|
@ -49,6 +49,7 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
public let flags: CachedGroupFlags
|
public let flags: CachedGroupFlags
|
||||||
public let hasScheduledMessages: Bool
|
public let hasScheduledMessages: Bool
|
||||||
public let invitedBy: PeerId?
|
public let invitedBy: PeerId?
|
||||||
|
public let photo: TelegramMediaImage?
|
||||||
|
|
||||||
public let peerIds: Set<PeerId>
|
public let peerIds: Set<PeerId>
|
||||||
public let messageIds: Set<MessageId>
|
public let messageIds: Set<MessageId>
|
||||||
@ -66,9 +67,10 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
self.flags = CachedGroupFlags()
|
self.flags = CachedGroupFlags()
|
||||||
self.hasScheduledMessages = false
|
self.hasScheduledMessages = false
|
||||||
self.invitedBy = nil
|
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.participants = participants
|
||||||
self.exportedInvitation = exportedInvitation
|
self.exportedInvitation = exportedInvitation
|
||||||
self.botInfos = botInfos
|
self.botInfos = botInfos
|
||||||
@ -78,6 +80,7 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
self.flags = flags
|
self.flags = flags
|
||||||
self.hasScheduledMessages = hasScheduledMessages
|
self.hasScheduledMessages = hasScheduledMessages
|
||||||
self.invitedBy = invitedBy
|
self.invitedBy = invitedBy
|
||||||
|
self.photo = photo
|
||||||
|
|
||||||
var messageIds = Set<MessageId>()
|
var messageIds = Set<MessageId>()
|
||||||
if let pinnedMessageId = self.pinnedMessageId {
|
if let pinnedMessageId = self.pinnedMessageId {
|
||||||
@ -123,6 +126,12 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
|
|
||||||
self.invitedBy = decoder.decodeOptionalInt64ForKey("invBy").flatMap(PeerId.init)
|
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>()
|
var messageIds = Set<MessageId>()
|
||||||
if let pinnedMessageId = self.pinnedMessageId {
|
if let pinnedMessageId = self.pinnedMessageId {
|
||||||
messageIds.insert(pinnedMessageId)
|
messageIds.insert(pinnedMessageId)
|
||||||
@ -181,6 +190,12 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "invBy")
|
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 {
|
public func isEqual(to: CachedPeerData) -> Bool {
|
||||||
@ -192,38 +207,42 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedParticipants(_ participants: CachedGroupParticipants?) -> CachedGroupData {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 exportedInvitation = ExportedInvitation(apiExportedInvite: chatFull.exportedInvite)
|
||||||
let pinnedMessageId = chatFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
|
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)
|
.withUpdatedFlags(flags)
|
||||||
.withUpdatedHasScheduledMessages(hasScheduledMessages)
|
.withUpdatedHasScheduledMessages(hasScheduledMessages)
|
||||||
.withUpdatedInvitedBy(invitedBy)
|
.withUpdatedInvitedBy(invitedBy)
|
||||||
|
.withUpdatedPhoto(photo)
|
||||||
})
|
})
|
||||||
case .channelFull:
|
case .channelFull:
|
||||||
break
|
break
|
||||||
|
@ -158,12 +158,12 @@ final class PeerInfoHeaderNavigationTransition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum PeerInfoAvatarListItem: Equatable {
|
enum PeerInfoAvatarListItem: Equatable {
|
||||||
case topImage([ImageRepresentationWithReference], Data?)
|
case topImage([ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], Data?)
|
||||||
case image(TelegramMediaImageReference?, [ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], Data?)
|
case image(TelegramMediaImageReference?, [ImageRepresentationWithReference], [TelegramMediaImage.VideoRepresentation], Data?)
|
||||||
|
|
||||||
var id: WrappedMediaResourceId {
|
var id: WrappedMediaResourceId {
|
||||||
switch self {
|
switch self {
|
||||||
case let .topImage(representations, _):
|
case let .topImage(representations, _, _):
|
||||||
let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation
|
let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation
|
||||||
return WrappedMediaResourceId(representation.resource.id)
|
return WrappedMediaResourceId(representation.resource.id)
|
||||||
case let .image(_, representations, _, _):
|
case let .image(_, representations, _, _):
|
||||||
@ -171,6 +171,15 @@ enum PeerInfoAvatarListItem: Equatable {
|
|||||||
return WrappedMediaResourceId(representation.resource.id)
|
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 {
|
final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
||||||
@ -250,15 +259,15 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
|||||||
let immediateThumbnailData: Data?
|
let immediateThumbnailData: Data?
|
||||||
var id: Int64?
|
var id: Int64?
|
||||||
switch item {
|
switch item {
|
||||||
case let .topImage(topRepresentations, immediateThumbnail):
|
case let .topImage(topRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||||
representations = topRepresentations
|
representations = topRepresentations
|
||||||
videoRepresentations = []
|
videoRepresentations = videoRepresentationsValue
|
||||||
immediateThumbnailData = immediateThumbnail
|
immediateThumbnailData = immediateThumbnail
|
||||||
|
id = 1
|
||||||
case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail):
|
case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||||
representations = imageRepresentations
|
representations = imageRepresentations
|
||||||
videoRepresentations = videoRepresentationsValue
|
videoRepresentations = videoRepresentationsValue
|
||||||
immediateThumbnailData = immediateThumbnail
|
immediateThumbnailData = immediateThumbnail
|
||||||
|
|
||||||
if case let .cloud(imageId, _, _) = reference {
|
if case let .cloud(imageId, _, _) = reference {
|
||||||
id = imageId
|
id = imageId
|
||||||
}
|
}
|
||||||
@ -761,9 +770,9 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
var entries: [AvatarGalleryEntry] = []
|
var entries: [AvatarGalleryEntry] = []
|
||||||
for entry in self.galleryEntries {
|
for entry in self.galleryEntries {
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .topImage(representations, _, immediateThumbnailData, _):
|
case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, _):
|
||||||
entries.append(entry)
|
entries.append(entry)
|
||||||
items.append(.topImage(representations, immediateThumbnailData))
|
items.append(.topImage(representations, videoRepresentations, immediateThumbnailData))
|
||||||
case let .image(id, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
case let .image(id, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
||||||
if image.0 == reference {
|
if image.0 == reference {
|
||||||
entries.insert(entry, at: 0)
|
entries.insert(entry, at: 0)
|
||||||
@ -797,9 +806,9 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
let previousIndex = self.currentIndex
|
let previousIndex = self.currentIndex
|
||||||
for entry in self.galleryEntries {
|
for entry in self.galleryEntries {
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .topImage(representations, _, immediateThumbnailData, _):
|
case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, _):
|
||||||
entries.append(entry)
|
entries.append(entry)
|
||||||
items.append(.topImage(representations, immediateThumbnailData))
|
items.append(.topImage(representations, videoRepresentations, immediateThumbnailData))
|
||||||
case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
||||||
if image.0 != reference {
|
if image.0 != reference {
|
||||||
entries.append(entry)
|
entries.append(entry)
|
||||||
@ -861,8 +870,8 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
|||||||
var items: [PeerInfoAvatarListItem] = []
|
var items: [PeerInfoAvatarListItem] = []
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .topImage(representations, _, immediateThumbnailData, _):
|
case let .topImage(representations, videoRepresentations, _, immediateThumbnailData, _):
|
||||||
items.append(.topImage(representations, immediateThumbnailData))
|
items.append(.topImage(representations, videoRepresentations, immediateThumbnailData))
|
||||||
case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _):
|
||||||
items.append(.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.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))
|
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 {
|
if let item = item {
|
||||||
let id = imageId
|
let representations: [ImageRepresentationWithReference]
|
||||||
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 videoRepresentations: [TelegramMediaImage.VideoRepresentation]
|
||||||
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)
|
let immediateThumbnailData: Data?
|
||||||
if videoContent.id != self.videoContent?.id {
|
var id: Int64?
|
||||||
let mediaManager = self.context.sharedContext.mediaManager
|
switch item {
|
||||||
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .embedded)
|
case let .topImage(topRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||||
videoNode.isUserInteractionEnabled = false
|
representations = topRepresentations
|
||||||
videoNode.isHidden = true
|
videoRepresentations = videoRepresentationsValue
|
||||||
|
immediateThumbnailData = immediateThumbnail
|
||||||
if let startTimestamp = video.startTimestamp {
|
id = 1
|
||||||
self.videoStartTimestamp = startTimestamp
|
case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||||
self.playbackStatusDisposable.set((videoNode.status
|
representations = imageRepresentations
|
||||||
|> map { status -> Bool in
|
videoRepresentations = videoRepresentationsValue
|
||||||
if let status = status, case .playing = status.status {
|
immediateThumbnailData = immediateThumbnail
|
||||||
return true
|
if case let .cloud(imageId, _, _) = reference {
|
||||||
} else {
|
id = imageId
|
||||||
return false
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|> filter { playing in
|
if let video = videoRepresentations.last, let id = id {
|
||||||
return playing
|
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)
|
||||||
|> take(1)
|
if videoContent.id != self.videoContent?.id {
|
||||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
let mediaManager = self.context.sharedContext.mediaManager
|
||||||
if let strongSelf = self {
|
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .embedded)
|
||||||
Queue.mainQueue().after(0.15) {
|
videoNode.isUserInteractionEnabled = false
|
||||||
strongSelf.videoNode?.isHidden = 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
|
||||||
} else {
|
return playing
|
||||||
self.videoStartTimestamp = nil
|
}
|
||||||
self.playbackStatusDisposable.set(nil)
|
|> take(1)
|
||||||
videoNode.isHidden = false
|
|> 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
|
videoNode.removeFromSupernode()
|
||||||
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 {
|
} else if let videoNode = self.videoNode {
|
||||||
self.videoContent = nil
|
self.videoContent = nil
|
||||||
@ -1283,7 +1317,7 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode {
|
|||||||
iconHidden = true
|
iconHidden = true
|
||||||
overlayHidden = true
|
overlayHidden = true
|
||||||
}
|
}
|
||||||
Queue.mainQueue().after(0.15) { [weak self] in
|
Queue.mainQueue().after(0.3) { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
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.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))
|
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 {
|
if let item = item {
|
||||||
let id = imageId
|
let representations: [ImageRepresentationWithReference]
|
||||||
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 videoRepresentations: [TelegramMediaImage.VideoRepresentation]
|
||||||
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)
|
let immediateThumbnailData: Data?
|
||||||
if videoContent.id != self.videoContent?.id {
|
var id: Int64?
|
||||||
let mediaManager = self.context.sharedContext.mediaManager
|
switch item {
|
||||||
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .overlay)
|
case let .topImage(topRepresentations, videoRepresentationsValue, immediateThumbnail):
|
||||||
videoNode.isUserInteractionEnabled = false
|
representations = topRepresentations
|
||||||
videoNode.ownsContentNodeUpdated = { [weak self] owns in
|
videoRepresentations = videoRepresentationsValue
|
||||||
if let strongSelf = self {
|
immediateThumbnailData = immediateThumbnail
|
||||||
strongSelf.videoNode?.isHidden = !owns
|
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))
|
videoNode.removeFromSupernode()
|
||||||
let shape = CAShapeLayer()
|
|
||||||
shape.path = maskPath.cgPath
|
|
||||||
videoNode.layer.mask = shape
|
|
||||||
|
|
||||||
self.insertSubnode(videoNode, aboveSubnode: self.avatarNode)
|
|
||||||
}
|
}
|
||||||
} else if let videoNode = self.videoNode {
|
} else if let videoNode = self.videoNode {
|
||||||
self.videoContent = nil
|
self.videoContent = nil
|
||||||
|
@ -2086,7 +2086,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
}
|
}
|
||||||
|
|
||||||
let entriesPromise = Promise<[AvatarGalleryEntry]>(entries)
|
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
|
galleryController.openAvatarSetup = { [weak self] completion in
|
||||||
self?.openAvatarForEditing(hasRemove: false, completion: completion)
|
self?.openAvatarForEditing(hasRemove: false, completion: completion)
|
||||||
|
@ -43,8 +43,12 @@ final class GenericEmbedImplementation: WebEmbedImplementation {
|
|||||||
self.onPlaybackStarted = onPlaybackStarted
|
self.onPlaybackStarted = onPlaybackStarted
|
||||||
updateStatus(self.status)
|
updateStatus(self.status)
|
||||||
|
|
||||||
let html = String(format: htmlTemplate, self.url)
|
if self.url.contains("player.twitch.tv/"), let url = URL(string: self.url) {
|
||||||
webView.loadHTMLString(html, baseURL: URL(string: "about:blank"))
|
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))
|
userContentController.addUserScript(WKUserScript(source: userScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user