mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-19 17:51:29 +00:00
Merge branch 'todo' of gitlab.com:peter-iakovlev/telegram-ios into todo
This commit is contained in:
commit
562c621ec4
@ -14383,7 +14383,7 @@ Sorry for the inconvenience.";
|
||||
"ChannelMessages.PriceSectionTitle" = "PRICE FOR EACH MESSAGE";
|
||||
"ChannelMessages.PriceSectionFooter" = "You will receive 85% of the selected fee for each incoming message.";
|
||||
|
||||
"ChatList.MonoforumLabel" = "MESSAGES";
|
||||
"ChatList.MonoforumLabel" = "DIRECT";
|
||||
"ChatList.MonoforumEmptyText" = "No messages here yet...";
|
||||
|
||||
"Chat.InlineTopicMenu.Reorder" = "Reorder";
|
||||
@ -14400,6 +14400,7 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Chat.EmptyStateMonoforum.Text" = "Send a direct message to the administrator of **%@**.";
|
||||
"Chat.EmptyStateMonoforumPaid.Text" = "**%1$@** charges **%2$@**\nper message to its admin.";
|
||||
"Chat.Monoforum.Subtitle" = "Direct messages";
|
||||
|
||||
"Monoforum.NameFormat" = "%@ Messages";
|
||||
|
||||
@ -14409,3 +14410,5 @@ Sorry for the inconvenience.";
|
||||
"Stars.SendMessage.AdjustmentSectionFooterValue" = "You will receive **%@ Stars**.";
|
||||
"Stars.SendMessage.AdjustmentSectionFooterEmpty" = "You will receive **80%**.";
|
||||
"Stars.SendMessage.AdjustmentAction" = "OK";
|
||||
|
||||
"Stars.SendMessage.PriceFree" = "Free";
|
||||
|
@ -97,22 +97,14 @@ open class TransformImageNode: ASDisplayNode {
|
||||
self.disposable.set((result |> deliverOnMainQueue).start(next: { [weak self] next in
|
||||
let apply: () -> Void = {
|
||||
if let strongSelf = self {
|
||||
var animateFromContents: Any?
|
||||
|
||||
if strongSelf.contents == nil {
|
||||
if strongSelf.contentAnimations.contains(.firstUpdate) && !attemptSynchronously {
|
||||
strongSelf.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||
}
|
||||
} else if strongSelf.contentAnimations.contains(.subsequentUpdates) {
|
||||
let tempLayer = CALayer()
|
||||
if strongSelf.captureProtected {
|
||||
setLayerDisableScreenshots(tempLayer, strongSelf.captureProtected)
|
||||
}
|
||||
tempLayer.frame = strongSelf.bounds
|
||||
tempLayer.contentsGravity = strongSelf.layer.contentsGravity
|
||||
tempLayer.contents = strongSelf.contents
|
||||
strongSelf.layer.addSublayer(tempLayer)
|
||||
tempLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak tempLayer] _ in
|
||||
tempLayer?.removeFromSuperlayer()
|
||||
})
|
||||
animateFromContents = strongSelf.contents
|
||||
}
|
||||
|
||||
var imageUpdate: UIImage?
|
||||
@ -129,6 +121,23 @@ open class TransformImageNode: ASDisplayNode {
|
||||
if let imageUpdated = strongSelf.imageUpdated {
|
||||
imageUpdated(imageUpdate)
|
||||
}
|
||||
|
||||
if let animateFromContents {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .linear)
|
||||
transition.animateContents(layer: strongSelf.layer, from: animateFromContents)
|
||||
|
||||
/*let tempLayer = CALayer()
|
||||
if strongSelf.captureProtected {
|
||||
setLayerDisableScreenshots(tempLayer, strongSelf.captureProtected)
|
||||
}
|
||||
tempLayer.frame = strongSelf.bounds
|
||||
tempLayer.contentsGravity = strongSelf.layer.contentsGravity
|
||||
tempLayer.contents = animateFromContents
|
||||
strongSelf.layer.addSublayer(tempLayer)
|
||||
tempLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak tempLayer] _ in
|
||||
tempLayer?.removeFromSuperlayer()
|
||||
})*/
|
||||
}
|
||||
}
|
||||
}
|
||||
if dispatchOnDisplayLink && !attemptSynchronously {
|
||||
@ -168,6 +177,34 @@ open class TransformImageNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
public func asyncLayoutWithAnimation() -> (TransformImageArguments) -> ((ListViewItemUpdateAnimation) -> Void) {
|
||||
let currentTransform = self.currentTransform
|
||||
let currentArguments = self.currentArguments
|
||||
return { [weak self] arguments in
|
||||
let updatedImage: UIImage?
|
||||
|
||||
if currentArguments != arguments {
|
||||
updatedImage = currentTransform?(arguments)?.generateImage()
|
||||
} else {
|
||||
updatedImage = nil
|
||||
}
|
||||
return { animation in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let image = updatedImage {
|
||||
self.contents = image.cgImage
|
||||
self.image = image
|
||||
self.currentArguments = arguments
|
||||
if let _ = self.overlayColor {
|
||||
self.applyOverlayColor(animated: false)
|
||||
}
|
||||
}
|
||||
self.argumentsPromise.set(arguments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class func asyncLayout(_ maybeNode: TransformImageNode?) -> (TransformImageArguments) -> (() -> TransformImageNode) {
|
||||
return { arguments in
|
||||
let node: TransformImageNode
|
||||
|
@ -402,7 +402,7 @@ public final class MediaPlayerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
private func updateLayout() {
|
||||
public func updateLayout() {
|
||||
let bounds = self.bounds
|
||||
if bounds.isEmpty {
|
||||
return
|
||||
|
@ -313,6 +313,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
||||
private let clipHoles: Bool
|
||||
private let trackHoles: Bool
|
||||
private let anchor: HistoryViewInputAnchor
|
||||
fileprivate var mapReadStatesFromThreads: Bool = false
|
||||
|
||||
fileprivate var combinedReadStates: MessageHistoryViewReadState?
|
||||
fileprivate var transientReadStates: MessageHistoryViewReadState?
|
||||
@ -322,6 +323,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
||||
|
||||
fileprivate var topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?]
|
||||
fileprivate var additionalDatas: [AdditionalMessageHistoryViewDataEntry]
|
||||
fileprivate var threadMaxOutgoingReadId: [Int64: Int32] = [:]
|
||||
|
||||
fileprivate(set) var sampledState: HistoryViewSample
|
||||
|
||||
@ -373,8 +375,14 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
||||
switch peerIds {
|
||||
case let .associated(peerId, _):
|
||||
self.isAddedToChatList = postbox.chatListTable.getPeerChatListIndex(peerId: peerId) != nil
|
||||
case let .single(peerId, _):
|
||||
case let .single(peerId, threadId):
|
||||
self.isAddedToChatList = postbox.chatListTable.getPeerChatListIndex(peerId: peerId) != nil
|
||||
if threadId == nil, let peer = postbox.peerTable.get(peerId) {
|
||||
let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get))
|
||||
if value.value && value.threadsArePeers {
|
||||
self.mapReadStatesFromThreads = true
|
||||
}
|
||||
}
|
||||
case let .external(input):
|
||||
switch input.content {
|
||||
case let .thread(peerId, _, _):
|
||||
@ -401,6 +409,8 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
||||
|
||||
self.render(postbox: postbox)
|
||||
let _ = self.updateStoryStats(postbox: postbox)
|
||||
|
||||
let _ = self.updateThreadInfos(postbox: postbox, updatedIds: nil)
|
||||
}
|
||||
|
||||
private func reset(postbox: PostboxImpl) {
|
||||
@ -1023,9 +1033,81 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
||||
}
|
||||
}
|
||||
|
||||
if !transaction.updatedPeerThreadInfos.isEmpty {
|
||||
if self.updateThreadInfos(postbox: postbox, updatedIds: transaction.updatedPeerThreadInfos) {
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
|
||||
return hasChanges
|
||||
}
|
||||
|
||||
private func updateThreadInfos(postbox: PostboxImpl, updatedIds: Set<MessageHistoryThreadsTable.ItemId>?) -> Bool {
|
||||
if self.mapReadStatesFromThreads, case let .single(peerId, peerThreadId) = self.peerIds, peerThreadId == nil {
|
||||
switch self.sampledState {
|
||||
case .loading:
|
||||
if !self.threadMaxOutgoingReadId.isEmpty {
|
||||
self.threadMaxOutgoingReadId.removeAll()
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .loaded(loaded):
|
||||
//TODO:release
|
||||
let currentIds = Set<Int64>(self.threadMaxOutgoingReadId.keys)
|
||||
|
||||
var threadIds: Set<Int64> = []
|
||||
for entry in loaded.entries {
|
||||
if let threadId = entry.message.threadId {
|
||||
threadIds.insert(threadId)
|
||||
}
|
||||
}
|
||||
|
||||
var updated = false
|
||||
if currentIds != threadIds {
|
||||
updated = true
|
||||
|
||||
for id in currentIds.subtracting(threadIds) {
|
||||
self.threadMaxOutgoingReadId.removeValue(forKey: id)
|
||||
}
|
||||
}
|
||||
|
||||
for threadId in threadIds {
|
||||
var fetch = false
|
||||
if let updatedIds {
|
||||
if updatedIds.contains(MessageHistoryThreadsTable.ItemId(peerId: peerId, threadId: threadId)) {
|
||||
fetch = true
|
||||
}
|
||||
} else {
|
||||
fetch = self.threadMaxOutgoingReadId[threadId] == nil
|
||||
}
|
||||
|
||||
if fetch {
|
||||
var maxOutgoingReadId: Int32?
|
||||
if let threadData = postbox.messageHistoryThreadIndexTable.get(peerId: peerId, threadId: threadId) {
|
||||
maxOutgoingReadId = threadData.summary.maxOutgoingReadId
|
||||
}
|
||||
|
||||
let current = self.threadMaxOutgoingReadId[threadId]
|
||||
if let maxOutgoingReadId {
|
||||
if current != maxOutgoingReadId {
|
||||
self.threadMaxOutgoingReadId[threadId] = maxOutgoingReadId
|
||||
updated = true
|
||||
}
|
||||
} else if current != nil {
|
||||
self.threadMaxOutgoingReadId.removeValue(forKey: threadId)
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updated
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private func render(postbox: PostboxImpl) {
|
||||
for namespace in self.topTaggedMessages.keys {
|
||||
if let entry = self.topTaggedMessages[namespace]!, case let .intermediate(message) = entry {
|
||||
@ -1166,7 +1248,20 @@ public final class MessageHistoryView: PostboxView {
|
||||
}
|
||||
self.isLoadingEarlier = isLoadingEarlier
|
||||
entries = []
|
||||
if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates {
|
||||
if mutableView.mapReadStatesFromThreads {
|
||||
for entry in state.entries {
|
||||
if mutableView.namespaces.contains(entry.message.id.namespace) {
|
||||
var read = false
|
||||
if let threadId = entry.message.threadId {
|
||||
if let maxId = mutableView.threadMaxOutgoingReadId[threadId] {
|
||||
read = entry.message.id.id <= maxId
|
||||
}
|
||||
}
|
||||
|
||||
entries.append(MessageHistoryEntry(message: entry.message, isRead: read, location: entry.location, monthLocation: entry.monthLocation, attributes: entry.attributes))
|
||||
}
|
||||
}
|
||||
} else if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates {
|
||||
for entry in state.entries {
|
||||
if mutableView.namespaces.contains(entry.message.id.namespace) {
|
||||
let read: Bool
|
||||
|
@ -1308,6 +1308,7 @@ final class HistoryViewLoadedState {
|
||||
let halfLimit: Int
|
||||
let seedConfiguration: SeedConfiguration
|
||||
var orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries]
|
||||
var threadSummaries: [Int64: Int32]
|
||||
var holes: HistoryViewHoles
|
||||
var spacesWithRemovals = Set<PeerIdAndNamespace>()
|
||||
|
||||
@ -1321,6 +1322,7 @@ final class HistoryViewLoadedState {
|
||||
self.halfLimit = halfLimit
|
||||
self.seedConfiguration = postbox.seedConfiguration
|
||||
self.orderedEntriesBySpace = [:]
|
||||
self.threadSummaries = [:]
|
||||
self.holes = holes
|
||||
|
||||
var peerIds: [PeerId] = []
|
||||
@ -1854,6 +1856,7 @@ final class HistoryViewLoadedState {
|
||||
var holesToLower = false
|
||||
var holesToHigher = false
|
||||
var result: [MessageHistoryMessageEntry] = []
|
||||
|
||||
if combinedSpacesAndIndicesByDirection.lowerOrAtAnchor.isEmpty && combinedSpacesAndIndicesByDirection.higherThanAnchor.isEmpty {
|
||||
if !clipRanges.isEmpty {
|
||||
holesToLower = true
|
||||
|
@ -559,7 +559,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-808853502] = { return Api.MediaAreaCoordinates.parse_mediaAreaCoordinates($0) }
|
||||
dict[-356721331] = { return Api.Message.parse_message($0) }
|
||||
dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) }
|
||||
dict[-741178048] = { return Api.Message.parse_messageService($0) }
|
||||
dict[2055212554] = { return Api.Message.parse_messageService($0) }
|
||||
dict[-872240531] = { return Api.MessageAction.parse_messageActionBoostApply($0) }
|
||||
dict[-988359047] = { return Api.MessageAction.parse_messageActionBotAllowed($0) }
|
||||
dict[-1781355374] = { return Api.MessageAction.parse_messageActionChannelCreate($0) }
|
||||
|
@ -62,7 +62,7 @@ public extension Api {
|
||||
indirect enum Message: TypeConstructorDescription {
|
||||
case message(flags: Int32, flags2: Int32, id: Int32, fromId: Api.Peer?, fromBoostsApplied: Int32?, peerId: Api.Peer, savedPeerId: Api.Peer?, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, viaBusinessBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?, quickReplyShortcutId: Int32?, effect: Int64?, factcheck: Api.FactCheck?, reportDeliveryUntilDate: Int32?, paidMessageStars: Int64?)
|
||||
case messageEmpty(flags: Int32, id: Int32, peerId: Api.Peer?)
|
||||
case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, reactions: Api.MessageReactions?, ttlPeriod: Int32?)
|
||||
case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, savedPeerId: Api.Peer?, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, reactions: Api.MessageReactions?, ttlPeriod: Int32?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -117,14 +117,15 @@ public extension Api {
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {peerId!.serialize(buffer, true)}
|
||||
break
|
||||
case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let reactions, let ttlPeriod):
|
||||
case .messageService(let flags, let id, let fromId, let peerId, let savedPeerId, let replyTo, let date, let action, let reactions, let ttlPeriod):
|
||||
if boxed {
|
||||
buffer.appendInt32(-741178048)
|
||||
buffer.appendInt32(2055212554)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 8) != 0 {fromId!.serialize(buffer, true)}
|
||||
peerId.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 28) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)}
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
action.serialize(buffer, true)
|
||||
@ -140,8 +141,8 @@ public extension Api {
|
||||
return ("message", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("fromId", fromId as Any), ("fromBoostsApplied", fromBoostsApplied as Any), ("peerId", peerId as Any), ("savedPeerId", savedPeerId as Any), ("fwdFrom", fwdFrom as Any), ("viaBotId", viaBotId as Any), ("viaBusinessBotId", viaBusinessBotId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("message", message as Any), ("media", media as Any), ("replyMarkup", replyMarkup as Any), ("entities", entities as Any), ("views", views as Any), ("forwards", forwards as Any), ("replies", replies as Any), ("editDate", editDate as Any), ("postAuthor", postAuthor as Any), ("groupedId", groupedId as Any), ("reactions", reactions as Any), ("restrictionReason", restrictionReason as Any), ("ttlPeriod", ttlPeriod as Any), ("quickReplyShortcutId", quickReplyShortcutId as Any), ("effect", effect as Any), ("factcheck", factcheck as Any), ("reportDeliveryUntilDate", reportDeliveryUntilDate as Any), ("paidMessageStars", paidMessageStars as Any)])
|
||||
case .messageEmpty(let flags, let id, let peerId):
|
||||
return ("messageEmpty", [("flags", flags as Any), ("id", id as Any), ("peerId", peerId as Any)])
|
||||
case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let reactions, let ttlPeriod):
|
||||
return ("messageService", [("flags", flags as Any), ("id", id as Any), ("fromId", fromId as Any), ("peerId", peerId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("action", action as Any), ("reactions", reactions as Any), ("ttlPeriod", ttlPeriod as Any)])
|
||||
case .messageService(let flags, let id, let fromId, let peerId, let savedPeerId, let replyTo, let date, let action, let reactions, let ttlPeriod):
|
||||
return ("messageService", [("flags", flags as Any), ("id", id as Any), ("fromId", fromId as Any), ("peerId", peerId as Any), ("savedPeerId", savedPeerId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("action", action as Any), ("reactions", reactions as Any), ("ttlPeriod", ttlPeriod as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,33 +300,38 @@ public extension Api {
|
||||
if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _5: Api.MessageReplyHeader?
|
||||
var _5: Api.Peer?
|
||||
if Int(_1!) & Int(1 << 28) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
} }
|
||||
var _6: Api.MessageReplyHeader?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader
|
||||
} }
|
||||
var _6: Int32?
|
||||
_6 = reader.readInt32()
|
||||
var _7: Api.MessageAction?
|
||||
var _7: Int32?
|
||||
_7 = reader.readInt32()
|
||||
var _8: Api.MessageAction?
|
||||
if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.MessageAction
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.MessageAction
|
||||
}
|
||||
var _8: Api.MessageReactions?
|
||||
var _9: Api.MessageReactions?
|
||||
if Int(_1!) & Int(1 << 20) != 0 {if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.MessageReactions
|
||||
_9 = Api.parse(reader, signature: signature) as? Api.MessageReactions
|
||||
} }
|
||||
var _9: Int32?
|
||||
if Int(_1!) & Int(1 << 25) != 0 {_9 = reader.readInt32() }
|
||||
var _10: Int32?
|
||||
if Int(_1!) & Int(1 << 25) != 0 {_10 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 8) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 28) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 20) == 0) || _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 25) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.Message.messageService(flags: _1!, id: _2!, fromId: _3, peerId: _4!, replyTo: _5, date: _6!, action: _7!, reactions: _8, ttlPeriod: _9)
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 20) == 0) || _9 != nil
|
||||
let _c10 = (Int(_1!) & Int(1 << 25) == 0) || _10 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
||||
return Api.Message.messageService(flags: _1!, id: _2!, fromId: _3, peerId: _4!, savedPeerId: _5, replyTo: _6, date: _7!, action: _8!, reactions: _9, ttlPeriod: _10)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -137,7 +137,7 @@ func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case let .messageService(_, _, _, chatPeerId, _, _, _, _, _):
|
||||
case let .messageService(_, _, _, chatPeerId, _, _, _, _, _, _):
|
||||
return chatPeerId.peerId
|
||||
}
|
||||
}
|
||||
@ -218,7 +218,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
return result
|
||||
case .messageEmpty:
|
||||
return []
|
||||
case let .messageService(_, _, fromId, chatPeerId, _, _, action, _, _):
|
||||
case let .messageService(_, _, fromId, chatPeerId, savedPeerId, _, _, action, _, _):
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
var result = [peerId]
|
||||
|
||||
@ -227,6 +227,9 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
if resolvedFromId != peerId {
|
||||
result.append(resolvedFromId)
|
||||
}
|
||||
if let savedPeerId, resolvedFromId != savedPeerId.peerId {
|
||||
result.append(savedPeerId.peerId)
|
||||
}
|
||||
|
||||
switch action {
|
||||
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks:
|
||||
@ -301,7 +304,7 @@ func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: Refere
|
||||
}
|
||||
case .messageEmpty:
|
||||
break
|
||||
case let .messageService(_, id, _, chatPeerId, replyHeader, _, _, _, _):
|
||||
case let .messageService(_, id, _, chatPeerId, _, replyHeader, _, _, _, _):
|
||||
if let replyHeader = replyHeader {
|
||||
switch replyHeader {
|
||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset):
|
||||
@ -1061,14 +1064,16 @@ extension StoreMessage {
|
||||
self.init(id: MessageId(peerId: peerId, namespace: namespace, id: id), globallyUniqueId: nil, groupingKey: groupingId, threadId: threadId, timestamp: date, flags: storeFlags, tags: tags, globalTags: globalTags, localTags: [], forwardInfo: forwardInfo, authorId: authorId, text: messageText, attributes: attributes, media: medias)
|
||||
case .messageEmpty:
|
||||
return nil
|
||||
case let .messageService(flags, id, fromId, chatPeerId, replyTo, date, action, reactions, ttlPeriod):
|
||||
case let .messageService(flags, id, fromId, chatPeerId, savedPeerId, replyTo, date, action, reactions, ttlPeriod):
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
let authorId: PeerId? = fromId?.peerId ?? chatPeerId.peerId
|
||||
|
||||
var attributes: [MessageAttribute] = []
|
||||
|
||||
var threadId: Int64?
|
||||
if let replyTo = replyTo {
|
||||
if let savedPeerId {
|
||||
threadId = savedPeerId.peerId.toInt64()
|
||||
} else if let replyTo = replyTo {
|
||||
var threadMessageId: MessageId?
|
||||
switch replyTo {
|
||||
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset):
|
||||
|
@ -108,7 +108,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
|
||||
updatedTimestamp = date
|
||||
case .messageEmpty:
|
||||
break
|
||||
case let .messageService(_, _, _, _, _, date, _, _, _):
|
||||
case let .messageService(_, _, _, _, _, _, date, _, _, _):
|
||||
updatedTimestamp = date
|
||||
}
|
||||
} else {
|
||||
|
@ -108,7 +108,7 @@ extension Api.Message {
|
||||
return id
|
||||
case let .messageEmpty(_, id, _):
|
||||
return id
|
||||
case let .messageService(_, id, _, _, _, _, _, _, _):
|
||||
case let .messageService(_, id, _, _, _, _, _, _, _, _):
|
||||
return id
|
||||
}
|
||||
}
|
||||
@ -128,7 +128,7 @@ extension Api.Message {
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case let .messageService(_, id, _, chatPeerId, _, _, _, _, _):
|
||||
case let .messageService(_, id, _, chatPeerId, _, _, _, _, _, _):
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
return MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)
|
||||
}
|
||||
@ -141,7 +141,7 @@ extension Api.Message {
|
||||
return peerId
|
||||
case let .messageEmpty(_, _, peerId):
|
||||
return peerId?.peerId
|
||||
case let .messageService(_, _, _, chatPeerId, _, _, _, _, _):
|
||||
case let .messageService(_, _, _, chatPeerId, _, _, _, _, _, _):
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
return peerId
|
||||
}
|
||||
@ -151,7 +151,7 @@ extension Api.Message {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return date
|
||||
case let .messageService(_, _, _, _, _, date, _, _, _):
|
||||
case let .messageService(_, _, _, _, _, _, date, _, _, _):
|
||||
return date
|
||||
case .messageEmpty:
|
||||
return nil
|
||||
|
@ -1288,6 +1288,11 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
}
|
||||
case .unknown:
|
||||
attributedString = nil
|
||||
case let .todoCompletions(completed, incompleted):
|
||||
//TODO:release
|
||||
let _ = completed
|
||||
let _ = incompleted
|
||||
attributedString = nil
|
||||
}
|
||||
break
|
||||
} else if let expiredMedia = media as? TelegramMediaExpiredContent {
|
||||
|
@ -858,7 +858,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
||||
public func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ dateTimeFormat: PresentationDateTimeFormat, _ message: Message, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ media: Media, _ mediaIndex: Int?, _ dateAndStatus: ChatMessageDateAndStatus?, _ automaticDownload: InteractiveMediaNodeAutodownloadMode, _ peerType: MediaAutoDownloadPeerType, _ peerId: EnginePeer.Id?, _ sizeCalculation: InteractiveMediaNodeSizeCalculation, _ layoutConstants: ChatMessageItemLayoutConstants, _ contentMode: InteractiveMediaNodeContentMode, _ presentationContext: ChatPresentationContext) -> (CGSize, CGFloat, (CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))) {
|
||||
let currentMessage = self.message
|
||||
let currentMedia = self.media
|
||||
let imageLayout = self.imageNode.asyncLayout()
|
||||
let imageLayout = self.imageNode.asyncLayoutWithAnimation()
|
||||
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
||||
|
||||
let currentVideoNode = self.videoNode
|
||||
@ -1894,7 +1894,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
||||
timestampMaskView.image = strongSelf.generateTimestampMaskImage(corners: arguments.corners)
|
||||
}
|
||||
strongSelf.currentImageArguments = arguments
|
||||
imageApply()
|
||||
imageApply(transition)
|
||||
|
||||
if let statusApply = statusApply {
|
||||
let dateAndStatusFrame = CGRect(origin: CGPoint(x: cleanImageFrame.width - layoutConstants.image.statusInsets.right - statusSize.width, y: cleanImageFrame.height - layoutConstants.image.statusInsets.bottom - statusSize.height), size: statusSize)
|
||||
@ -2084,8 +2084,13 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
||||
strongSelf.imageNode.cornerRadius = 0.0
|
||||
}
|
||||
|
||||
videoNode.updateLayout(size: arguments.drawingSize, transition: .immediate)
|
||||
videoNode.frame = CGRect(origin: CGPoint(), size: imageFrame.size)
|
||||
if videoNode.bounds.isEmpty {
|
||||
videoNode.updateLayout(size: arguments.drawingSize, transition: .immediate)
|
||||
videoNode.frame = CGRect(origin: CGPoint(), size: imageFrame.size)
|
||||
} else {
|
||||
videoNode.updateLayout(size: arguments.drawingSize, transition: transition.transition)
|
||||
transition.animator.updateFrame(layer: videoNode.layer, frame: CGRect(origin: CGPoint(), size: imageFrame.size), completion: nil)
|
||||
}
|
||||
|
||||
if strongSelf.visibility && strongSelf.internallyVisible && !presentationData.isPreview {
|
||||
if !videoNode.canAttachContent {
|
||||
|
@ -1359,7 +1359,7 @@ public final class ChatSideTopicsPanel: Component {
|
||||
maximumNumberOfLines: 2
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 200.0, height: 200.0)
|
||||
containerSize: CGSize(width: 400.0, height: 200.0)
|
||||
)
|
||||
|
||||
let contentSize: CGFloat = leftInset + rightInset + titleSize.height
|
||||
|
@ -68,6 +68,8 @@ public enum ChatTitleContent: Equatable {
|
||||
return false
|
||||
}
|
||||
if lhs.peerPresences.count != rhs.peerPresences.count {
|
||||
return false
|
||||
} else {
|
||||
for (key, value) in lhs.peerPresences {
|
||||
if let rhsValue = rhs.peerPresences[key] {
|
||||
if !value.isEqual(to: rhsValue) {
|
||||
|
@ -368,8 +368,7 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
strongSelf.leftTextNode.attributedText = NSAttributedString(string: "\(item.minValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
||||
strongSelf.rightTextNode.attributedText = NSAttributedString(string: "\(item.maxValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
||||
|
||||
//TODO:localize
|
||||
let centralLeftText = item.value == 0 ? "Free" : item.strings.Privacy_Messages_Stars(Int32(item.value))
|
||||
let centralLeftText = item.value == 0 ? item.strings.Stars_SendMessage_PriceFree : item.strings.Privacy_Messages_Stars(Int32(item.value))
|
||||
|
||||
strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor.withMultipliedAlpha(0.5) : item.theme.list.itemSecondaryTextColor)
|
||||
|
@ -397,21 +397,30 @@ extension ChatControllerImpl {
|
||||
self.navigationActionDisposable.set((peerView.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] peerView in
|
||||
if let strongSelf = self, let peer = peerView.peers[peerView.peerId], peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && !strongSelf.presentationInterfaceState.isNotAccessible {
|
||||
|
||||
if peer.id == strongSelf.context.account.peerId {
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) {
|
||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard var peer = peerView.peers[peerView.peerId] else {
|
||||
return
|
||||
}
|
||||
if let channel = peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainPeer = peerView.peers[linkedMonoforumId] {
|
||||
peer = mainPeer
|
||||
}
|
||||
|
||||
if peer.restrictionText(platform: "ios", contentSettings: self.context.currentContentSettings.with { $0 }) == nil && !self.presentationInterfaceState.isNotAccessible {
|
||||
if peer.id == self.context.account.peerId {
|
||||
if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) {
|
||||
self.effectiveNavigationController?.pushViewController(infoController)
|
||||
}
|
||||
} else {
|
||||
var expandAvatar = expandAvatar
|
||||
if peer.smallProfileImage == nil {
|
||||
expandAvatar = false
|
||||
}
|
||||
if let validLayout = strongSelf.validLayout, validLayout.deviceMetrics.type == .tablet {
|
||||
if let validLayout = self.validLayout, validLayout.deviceMetrics.type == .tablet {
|
||||
expandAvatar = false
|
||||
}
|
||||
let mode: PeerInfoControllerMode
|
||||
let mode: PeerInfoControllerMode
|
||||
switch section {
|
||||
case .groupsInCommon:
|
||||
mode = .groupsInCommon
|
||||
@ -420,12 +429,12 @@ extension ChatControllerImpl {
|
||||
default:
|
||||
mode = .generic
|
||||
}
|
||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: mode, avatarInitiallyExpanded: expandAvatar, fromChat: true, requestsContext: strongSelf.contentData?.inviteRequestsContext) {
|
||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
||||
if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: peer, mode: mode, avatarInitiallyExpanded: expandAvatar, fromChat: true, requestsContext: self.contentData?.inviteRequestsContext) {
|
||||
self.effectiveNavigationController?.pushViewController(infoController)
|
||||
}
|
||||
}
|
||||
|
||||
let _ = strongSelf.dismissPreviewing?(false)
|
||||
let _ = self.dismissPreviewing?(false)
|
||||
}
|
||||
}))
|
||||
case .replyThread:
|
||||
|
@ -548,9 +548,9 @@ extension ChatControllerImpl {
|
||||
strongSelf.state.chatTitleContent = .custom(strings.Chat_TitlePinnedMessages(Int32(displayedCount ?? 1)), nil, false)
|
||||
} else if let channel = peer as? TelegramChannel, channel.isMonoForum {
|
||||
if let linkedMonoforumId = channel.linkedMonoforumId, let mainPeer = peerView.peers[linkedMonoforumId] {
|
||||
strongSelf.state.chatTitleContent = .custom(mainPeer.debugDisplayTitle, "Direct messages", false)
|
||||
strongSelf.state.chatTitleContent = .custom(mainPeer.debugDisplayTitle, strings.Chat_Monoforum_Subtitle, true)
|
||||
} else {
|
||||
strongSelf.state.chatTitleContent = .custom(channel.debugDisplayTitle, nil, false)
|
||||
strongSelf.state.chatTitleContent = .custom(channel.debugDisplayTitle, nil, true)
|
||||
}
|
||||
} else {
|
||||
strongSelf.state.chatTitleContent = .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages, isMuted: nil, customMessageCount: nil, isEnabled: hasPeerInfo)
|
||||
|
@ -2552,17 +2552,9 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
if self.leftPanel != nil || dismissedLeftPanel != nil {
|
||||
titleTopicsAccessoryPanelNode.updateGlobalOffset(globalOffset: -titleTopicsAccessoryPanelFrame.height, transition: .immediate)
|
||||
}
|
||||
|
||||
let topPanelTransition = ComponentTransition(transition)
|
||||
/*switch topPanelTransition.animation {
|
||||
case let .curve(duration, _):
|
||||
topPanelTransition = topPanelTransition.withAnimation(.curve(duration: duration, curve: ComponentTransition.Animation.Curve(ChatMessageTransitionNodeImpl.verticalAnimationCurve)))
|
||||
default:
|
||||
break
|
||||
}*/
|
||||
|
||||
topPanelTransition.setFrame(view: titleTopicsAccessoryPanelNode.view, frame: titleTopicsAccessoryPanelFrame)
|
||||
titleTopicsAccessoryPanelNode.updateGlobalOffset(globalOffset: 0.0, transition: topPanelTransition)
|
||||
ComponentTransition(transition).setFrame(view: titleTopicsAccessoryPanelNode.view, frame: titleTopicsAccessoryPanelFrame)
|
||||
titleTopicsAccessoryPanelNode.updateGlobalOffset(globalOffset: 0.0, transition: ComponentTransition(transition))
|
||||
} else {
|
||||
let previousFrame = titleTopicsAccessoryPanelNode.frame
|
||||
titleTopicsAccessoryPanelNode.frame = titleTopicsAccessoryPanelFrame
|
||||
|
@ -681,6 +681,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
|
||||
private var loadedMessagesFromCachedDataDisposable: Disposable?
|
||||
|
||||
private var isSettingTopReplyThreadMessageShown: Bool = false
|
||||
let isTopReplyThreadMessageShown = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
|
||||
private var topVisibleMessageRangeValueInitialized: Bool = false
|
||||
@ -3178,8 +3179,15 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.isTopReplyThreadMessageShown.set(isTopReplyThreadMessageShownValue)
|
||||
if !self.isSettingTopReplyThreadMessageShown {
|
||||
self.isSettingTopReplyThreadMessageShown = true
|
||||
self.isTopReplyThreadMessageShown.set(isTopReplyThreadMessageShownValue)
|
||||
self.isSettingTopReplyThreadMessageShown = false
|
||||
} else {
|
||||
#if DEBUG
|
||||
print("Ignore repeated isTopReplyThreadMessageShown update")
|
||||
#endif
|
||||
}
|
||||
self.updateTopVisibleMessageRange(topVisibleMessageRange)
|
||||
let _ = self.visibleMessageRange.swap(topVisibleMessageRange.flatMap { range in
|
||||
return VisibleMessageRange(lowerBound: range.lowerBound, upperBound: range.upperBound)
|
||||
|
@ -1591,7 +1591,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
}
|
||||
}
|
||||
|
||||
if let message = messages.first, message.id.namespace == Namespaces.Message.Cloud, let channel = message.peers[message.id.peerId] as? TelegramChannel, !(message.media.first is TelegramMediaAction), !isReplyThreadHead, !isMigrated {
|
||||
if let message = messages.first, message.id.namespace == Namespaces.Message.Cloud, let channel = message.peers[message.id.peerId] as? TelegramChannel, !channel.isMonoForum, !(message.media.first is TelegramMediaAction), !isReplyThreadHead, !isMigrated {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopyLink, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
@ -1893,8 +1893,8 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
|
||||
var canViewStats = false
|
||||
var canViewAuthor = false
|
||||
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum {
|
||||
if message.effectivelyIncoming(context.account.peerId) {
|
||||
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let associatedPeerId = channel.associatedPeerId {
|
||||
if message.effectivelyIncoming(context.account.peerId), message.author?.id == associatedPeerId {
|
||||
canViewAuthor = true
|
||||
}
|
||||
} else if let messageReadStatsAreHidden = infoSummaryData.messageReadStatsAreHidden, !messageReadStatsAreHidden {
|
||||
|
@ -690,22 +690,34 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
|
||||
if let dimensions = self.dimensions {
|
||||
let imageSize = CGSize(width: floor(dimensions.width / 2.0), height: floor(dimensions.height / 2.0))
|
||||
let makeLayout = self.imageNode.asyncLayout()
|
||||
let makeLayout = self.imageNode.asyncLayoutWithAnimation()
|
||||
let applyLayout = makeLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: self.fileReference.media.isInstantVideo ? .clear : self.placeholderColor))
|
||||
applyLayout()
|
||||
let mappedAnimation: ListViewItemUpdateAnimation
|
||||
if case let .animated(duration, curve) = transition {
|
||||
mappedAnimation = .System(duration: duration, transition: ControlledTransition(duration: duration, curve: curve, interactive: false))
|
||||
} else {
|
||||
mappedAnimation = .None
|
||||
}
|
||||
applyLayout(mappedAnimation)
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
let fromFrame = self.playerNode.frame
|
||||
let toFrame = CGRect(origin: CGPoint(), size: size).insetBy(dx: -1.0, dy: -1.0)
|
||||
if case let .animated(duration, curve) = transition, fromFrame != toFrame, !fromFrame.width.isZero, !fromFrame.height.isZero, !toFrame.width.isZero, !toFrame.height.isZero {
|
||||
self.playerNode.frame = toFrame
|
||||
transition.animatePosition(node: self.playerNode, from: CGPoint(x: fromFrame.center.x - toFrame.center.x, y: fromFrame.center.y - toFrame.center.y))
|
||||
let _ = duration
|
||||
let _ = curve
|
||||
self.playerNode.position = toFrame.center
|
||||
self.playerNode.bounds = CGRect(origin: CGPoint(), size: toFrame.size)
|
||||
self.playerNode.updateLayout()
|
||||
transition.animatePosition(node: self.playerNode, from: CGPoint(x: fromFrame.center.x, y: fromFrame.center.y))
|
||||
|
||||
let transform = CATransform3DScale(CATransform3DIdentity, fromFrame.width / toFrame.width, fromFrame.height / toFrame.height, 1.0)
|
||||
self.playerNode.layer.animate(from: NSValue(caTransform3D: transform), to: NSValue(caTransform3D: CATransform3DIdentity), keyPath: "transform", timingFunction: curve.timingFunction, duration: duration)
|
||||
} else {
|
||||
transition.updateFrame(node: self.playerNode, frame: toFrame)
|
||||
transition.updatePosition(node: self.playerNode, position: toFrame.center)
|
||||
transition.updateBounds(node: self.playerNode, bounds: CGRect(origin: CGPoint(), size: toFrame.size))
|
||||
self.playerNode.updateLayout()
|
||||
}
|
||||
if let thumbnailNode = self.thumbnailNode {
|
||||
transition.updateFrame(node: thumbnailNode, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: -1.0, dy: -1.0))
|
||||
|
Loading…
x
Reference in New Issue
Block a user