mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Video improvements
This commit is contained in:
parent
2f9d5c41e3
commit
817e189709
@ -58,7 +58,9 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/RasterizedCompositionComponent",
|
||||
"//submodules/TelegramUI/Components/BadgeComponent",
|
||||
"//submodules/TelegramUI/Components/AnimatedTextComponent",
|
||||
"//submodules/TelegramUI/Components/LottieComponent",
|
||||
"//submodules/Components/MultilineTextComponent",
|
||||
"//submodules/Components/BalancedTextComponent",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
"//submodules/ComponentFlow",
|
||||
],
|
||||
|
@ -5,10 +5,16 @@ import ComponentFlow
|
||||
import AppBundle
|
||||
|
||||
final class GalleryRateToastAnimationComponent: Component {
|
||||
init() {
|
||||
let speedFraction: CGFloat
|
||||
|
||||
init(speedFraction: CGFloat) {
|
||||
self.speedFraction = speedFraction
|
||||
}
|
||||
|
||||
static func ==(lhs: GalleryRateToastAnimationComponent, rhs: GalleryRateToastAnimationComponent) -> Bool {
|
||||
if lhs.speedFraction != rhs.speedFraction {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -16,6 +22,10 @@ final class GalleryRateToastAnimationComponent: Component {
|
||||
private let itemViewContainer: UIView
|
||||
private var itemViews: [UIImageView] = []
|
||||
|
||||
private var link: SharedDisplayLinkDriver.Link?
|
||||
private var timeValue: CGFloat = 0.0
|
||||
private var speedFraction: CGFloat = 1.0
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.itemViewContainer = UIView()
|
||||
|
||||
@ -36,41 +46,49 @@ final class GalleryRateToastAnimationComponent: Component {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.link?.invalidate()
|
||||
}
|
||||
|
||||
private func setupAnimations() {
|
||||
let beginTime = self.layer.convertTime(CACurrentMediaTime(), from: nil)
|
||||
|
||||
for i in 0 ..< self.itemViews.count {
|
||||
if self.itemViews[i].layer.animation(forKey: "idle-opacity") != nil {
|
||||
continue
|
||||
if self.link == nil {
|
||||
var previousTimestamp = CACurrentMediaTime()
|
||||
self.link = SharedDisplayLinkDriver.shared.add { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let timestamp = CACurrentMediaTime()
|
||||
let deltaMultiplier = 1.0 * (1.0 - self.speedFraction) + 3.0 * self.speedFraction
|
||||
let deltaTime = (timestamp - previousTimestamp) * deltaMultiplier
|
||||
previousTimestamp = timestamp
|
||||
|
||||
self.timeValue += deltaTime
|
||||
|
||||
let duration: CGFloat = 1.2
|
||||
|
||||
for i in 0 ..< self.itemViews.count {
|
||||
var itemFraction = (self.timeValue + CGFloat(i) * 0.1).truncatingRemainder(dividingBy: duration) / duration
|
||||
|
||||
if itemFraction >= 0.5 {
|
||||
itemFraction = (1.0 - itemFraction) / 0.5
|
||||
} else {
|
||||
itemFraction = itemFraction / 0.5
|
||||
}
|
||||
|
||||
let itemAlpha = 0.6 * (1.0 - itemFraction) + 1.0 * itemFraction
|
||||
let itemScale = 0.9 * (1.0 - itemFraction) + 1.1 * itemFraction
|
||||
|
||||
self.itemViews[i].alpha = itemAlpha
|
||||
self.itemViews[i].transform = CGAffineTransformMakeScale(itemScale, itemScale)
|
||||
}
|
||||
}
|
||||
|
||||
let delay = Double(i) * 0.1
|
||||
|
||||
let animation = CABasicAnimation(keyPath: "opacity")
|
||||
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||
animation.beginTime = beginTime + delay
|
||||
animation.fromValue = 0.6 as NSNumber
|
||||
animation.toValue = 1.0 as NSNumber
|
||||
animation.repeatCount = Float.infinity
|
||||
animation.autoreverses = true
|
||||
animation.fillMode = .both
|
||||
animation.duration = 0.4
|
||||
self.itemViews[i].layer.add(animation, forKey: "idle-opacity")
|
||||
|
||||
let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
|
||||
scaleAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||
scaleAnimation.beginTime = beginTime + delay
|
||||
scaleAnimation.fromValue = 0.9 as NSNumber
|
||||
scaleAnimation.toValue = 1.1 as NSNumber
|
||||
scaleAnimation.repeatCount = Float.infinity
|
||||
scaleAnimation.autoreverses = true
|
||||
scaleAnimation.fillMode = .both
|
||||
scaleAnimation.duration = 0.4
|
||||
self.itemViews[i].layer.add(scaleAnimation, forKey: "idle-scale")
|
||||
}
|
||||
}
|
||||
|
||||
func update(component: GalleryRateToastAnimationComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.speedFraction = component.speedFraction
|
||||
|
||||
let itemSize = self.itemViews[0].image?.size ?? CGSize(width: 10.0, height: 10.0)
|
||||
let itemSpacing: CGFloat = 1.0
|
||||
|
||||
@ -78,7 +96,10 @@ final class GalleryRateToastAnimationComponent: Component {
|
||||
|
||||
for i in 0 ..< self.itemViews.count {
|
||||
let itemFrame = CGRect(origin: CGPoint(x: CGFloat(i) * (itemSize.width + itemSpacing), y: UIScreenPixel), size: itemSize)
|
||||
self.itemViews[i].frame = itemFrame
|
||||
self.itemViews[i].center = itemFrame.center
|
||||
self.itemViews[i].bounds = CGRect(origin: CGPoint(), size: itemFrame.size)
|
||||
|
||||
self.itemViews[i].layer.speed = Float(1.0 * (1.0 - component.speedFraction) + 2.0 * component.speedFraction)
|
||||
}
|
||||
|
||||
self.setupAnimations()
|
||||
|
@ -3,20 +3,26 @@ import UIKit
|
||||
import Display
|
||||
import ComponentFlow
|
||||
import AppBundle
|
||||
import MultilineTextComponent
|
||||
import BalancedTextComponent
|
||||
import AnimatedTextComponent
|
||||
import LottieComponent
|
||||
|
||||
final class GalleryRateToastComponent: Component {
|
||||
let rate: Double
|
||||
let displayTooltip: String?
|
||||
|
||||
init(rate: Double) {
|
||||
init(rate: Double, displayTooltip: String?) {
|
||||
self.rate = rate
|
||||
self.displayTooltip = displayTooltip
|
||||
}
|
||||
|
||||
static func ==(lhs: GalleryRateToastComponent, rhs: GalleryRateToastComponent) -> Bool {
|
||||
if lhs.rate != rhs.rate {
|
||||
return false
|
||||
}
|
||||
if lhs.displayTooltip != rhs.displayTooltip {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -25,6 +31,14 @@ final class GalleryRateToastComponent: Component {
|
||||
private let text = ComponentView<Empty>()
|
||||
private let arrows = ComponentView<Empty>()
|
||||
|
||||
private var tooltipText: ComponentView<Empty>?
|
||||
private var tooltipAnimation: ComponentView<Empty>?
|
||||
|
||||
private var tooltipIsHidden: Bool = false
|
||||
private var tooltipTimer: Foundation.Timer?
|
||||
|
||||
private weak var state: EmptyComponentState?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
@ -33,7 +47,13 @@ final class GalleryRateToastComponent: Component {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.tooltipTimer?.invalidate()
|
||||
}
|
||||
|
||||
func update(component: GalleryRateToastComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.state = state
|
||||
|
||||
let insets = UIEdgeInsets(top: 5.0, left: 11.0, bottom: 5.0, right: 16.0)
|
||||
let spacing: CGFloat = 5.0
|
||||
|
||||
@ -55,7 +75,7 @@ final class GalleryRateToastComponent: Component {
|
||||
let textSize = self.text.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(AnimatedTextComponent(
|
||||
font: Font.semibold(17.0),
|
||||
font: Font.with(size: 17.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]),
|
||||
color: .white,
|
||||
items: textItems
|
||||
)),
|
||||
@ -63,9 +83,11 @@ final class GalleryRateToastComponent: Component {
|
||||
containerSize: CGSize(width: 100.0, height: 100.0)
|
||||
)
|
||||
|
||||
var speedFraction = (component.rate - 1.0) / (2.5 - 1.0)
|
||||
speedFraction = max(0.0, min(1.0, speedFraction))
|
||||
let arrowsSize = self.arrows.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(GalleryRateToastAnimationComponent()),
|
||||
component: AnyComponent(GalleryRateToastAnimationComponent(speedFraction: speedFraction)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 200.0, height: 100.0)
|
||||
)
|
||||
@ -82,7 +104,7 @@ final class GalleryRateToastComponent: Component {
|
||||
environment: {},
|
||||
containerSize: size
|
||||
)
|
||||
let backgroundFrame = CGRect(origin: CGPoint(), size: size)
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - size.width) * 0.5), y: 0.0), size: size)
|
||||
if let backgroundView = self.background.view {
|
||||
if backgroundView.superview == nil {
|
||||
self.addSubview(backgroundView)
|
||||
@ -90,7 +112,7 @@ final class GalleryRateToastComponent: Component {
|
||||
transition.setFrame(view: backgroundView, frame: backgroundFrame)
|
||||
}
|
||||
|
||||
let textFrame = CGRect(origin: CGPoint(x: insets.left, y: floorToScreenPixels((size.height - textSize.height) * 0.5)), size: textSize)
|
||||
let textFrame = CGRect(origin: CGPoint(x: backgroundFrame.minX + insets.left, y: backgroundFrame.minY + floorToScreenPixels((size.height - textSize.height) * 0.5)), size: textSize)
|
||||
if let textView = self.text.view {
|
||||
if textView.superview == nil {
|
||||
textView.layer.anchorPoint = CGPoint()
|
||||
@ -100,7 +122,7 @@ final class GalleryRateToastComponent: Component {
|
||||
textView.bounds = CGRect(origin: CGPoint(), size: textFrame.size)
|
||||
}
|
||||
|
||||
let arrowsFrame = CGRect(origin: CGPoint(x: textFrame.maxX + spacing, y: floorToScreenPixels((size.height - arrowsSize.height) * 0.5)), size: arrowsSize)
|
||||
let arrowsFrame = CGRect(origin: CGPoint(x: textFrame.maxX + spacing, y: backgroundFrame.minY + floorToScreenPixels((size.height - arrowsSize.height) * 0.5)), size: arrowsSize)
|
||||
if let arrowsView = self.arrows.view {
|
||||
if arrowsView.superview == nil {
|
||||
self.addSubview(arrowsView)
|
||||
@ -108,7 +130,97 @@ final class GalleryRateToastComponent: Component {
|
||||
transition.setFrame(view: arrowsView, frame: arrowsFrame)
|
||||
}
|
||||
|
||||
return size
|
||||
if let displayTooltip = component.displayTooltip {
|
||||
var tooltipTransition = transition
|
||||
|
||||
let tooltipText: ComponentView<Empty>
|
||||
if let current = self.tooltipText {
|
||||
tooltipText = current
|
||||
} else {
|
||||
tooltipText = ComponentView()
|
||||
self.tooltipText = tooltipText
|
||||
tooltipTransition = tooltipTransition.withAnimation(.none)
|
||||
}
|
||||
|
||||
let tooltipAnimation: ComponentView<Empty>
|
||||
if let current = self.tooltipAnimation {
|
||||
tooltipAnimation = current
|
||||
} else {
|
||||
tooltipAnimation = ComponentView()
|
||||
self.tooltipAnimation = tooltipAnimation
|
||||
}
|
||||
|
||||
let tooltipTextSize = tooltipText.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(BalancedTextComponent(
|
||||
text: .plain(NSAttributedString(string: displayTooltip, font: Font.regular(15.0), textColor: UIColor(white: 1.0, alpha: 0.8))),
|
||||
horizontalAlignment: .center,
|
||||
maximumNumberOfLines: 0
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - 8.0 * 2.0, height: 1000.0)
|
||||
)
|
||||
let tooltipTextFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - tooltipTextSize.width) * 0.5), y: backgroundFrame.maxY + 10.0), size: tooltipTextSize)
|
||||
if let tooltipTextView = tooltipText.view {
|
||||
if tooltipTextView.superview == nil {
|
||||
self.addSubview(tooltipTextView)
|
||||
}
|
||||
tooltipTransition.setPosition(view: tooltipTextView, position: tooltipTextFrame.center)
|
||||
tooltipTextView.bounds = CGRect(origin: CGPoint(), size: tooltipTextFrame.size)
|
||||
|
||||
transition.setAlpha(view: tooltipTextView, alpha: self.tooltipIsHidden ? 0.0 : 1.0)
|
||||
}
|
||||
|
||||
let tooltipAnimationSize = tooltipAnimation.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(LottieComponent(
|
||||
content: LottieComponent.AppBundleContent(name: "video_toast_speedup"),
|
||||
color: .white,
|
||||
startingPosition: .begin,
|
||||
loop: true
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 60.0, height: 60.0)
|
||||
)
|
||||
let tooltipAnimationFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - tooltipAnimationSize.width) * 0.5), y: tooltipTextFrame.maxY + 10.0), size: tooltipAnimationSize)
|
||||
if let tooltipAnimationView = tooltipAnimation.view {
|
||||
if tooltipAnimationView.superview == nil {
|
||||
self.addSubview(tooltipAnimationView)
|
||||
}
|
||||
tooltipTransition.setFrame(view: tooltipAnimationView, frame: tooltipAnimationFrame)
|
||||
|
||||
transition.setAlpha(view: tooltipAnimationView, alpha: self.tooltipIsHidden ? 0.0 : 0.8)
|
||||
}
|
||||
} else {
|
||||
if let tooltipText = self.tooltipText {
|
||||
self.tooltipText = nil
|
||||
if let tooltipTextView = tooltipText.view {
|
||||
transition.setAlpha(view: tooltipTextView, alpha: 0.0, completion: { [weak tooltipTextView] _ in
|
||||
tooltipTextView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
}
|
||||
if let tooltipAnimation = self.tooltipAnimation {
|
||||
self.tooltipAnimation = nil
|
||||
if let tooltipAnimationView = tooltipAnimation.view {
|
||||
transition.setAlpha(view: tooltipAnimationView, alpha: 0.0, completion: { [weak tooltipAnimationView] _ in
|
||||
tooltipAnimationView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.tooltipTimer == nil {
|
||||
self.tooltipTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false, block: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.tooltipIsHidden = true
|
||||
self.state?.updated(transition: .easeInOut(duration: 0.25), isLocal: true)
|
||||
})
|
||||
}
|
||||
|
||||
return CGSize(width: availableSize.width, height: size.height)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1619,13 +1619,15 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
activeEdgeRateIndicatorTransition = .immediate
|
||||
}
|
||||
|
||||
//TODO:localize
|
||||
let activeEdgeRateIndicatorSize = activeEdgeRateIndicator.update(
|
||||
transition: ComponentTransition(activeEdgeRateIndicatorTransition),
|
||||
component: AnyComponent(GalleryRateToastComponent(
|
||||
rate: activeEdgeRateState.currentRate
|
||||
rate: activeEdgeRateState.currentRate,
|
||||
displayTooltip: "Swipe sideways to adjust speed."
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 200.0, height: 100.0)
|
||||
containerSize: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: 100.0)
|
||||
)
|
||||
let activeEdgeRateIndicatorFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - activeEdgeRateIndicatorSize.width) * 0.5), y: max(navigationBarHeight, layout.statusBarHeight ?? 0.0) + 8.0), size: activeEdgeRateIndicatorSize)
|
||||
if let activeEdgeRateIndicatorView = activeEdgeRateIndicator.view {
|
||||
|
@ -362,7 +362,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode {
|
||||
selectedStarsForeground: themeColors.reactionStarsActiveForeground.argb,
|
||||
extractedBackground: arguments.presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
||||
extractedForeground: arguments.presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
extractedSelectedForeground: arguments.presentationData.theme.theme.overallDarkAppearance ? themeColors.reactionActiveForeground.argb : arguments.presentationData.theme.theme.list.itemCheckColors.foregroundColor.argb,
|
||||
extractedSelectedForeground: arguments.presentationData.theme.theme.overallDarkAppearance ? themeColors.reactionActiveForeground.argb : arguments.presentationData.theme.theme.contextMenu.primaryColor.argb,
|
||||
deselectedMediaPlaceholder: themeColors.reactionInactiveMediaPlaceholder.argb,
|
||||
selectedMediaPlaceholder: themeColors.reactionActiveMediaPlaceholder.argb
|
||||
)
|
||||
|
File diff suppressed because one or more lines are too long
@ -4613,7 +4613,7 @@ extension ChatControllerImpl {
|
||||
title: "Improving video...",
|
||||
text: "The video will be published after it's optimized for the bese viewing experience.",
|
||||
customUndoText: nil,
|
||||
timeout: 3.5
|
||||
timeout: 5.0
|
||||
),
|
||||
elevatedLayout: false,
|
||||
position: .top,
|
||||
|
@ -10358,7 +10358,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let location = CGPoint(x: bounds.midX, y: bounds.minY - 8.0)
|
||||
|
||||
//TODO:localize
|
||||
let tooltipController = TooltipController(content: .text("Processing video may take a few minutes."), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, balancedTextLayout: true, isBlurred: true, timeout: 3.5, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
let tooltipController = TooltipController(content: .text("Processing video may take a few minutes."), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, balancedTextLayout: true, isBlurred: true, timeout: 4.5, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
self.checksTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak self, weak tooltipController] _ in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.checksTooltipController === tooltipController {
|
||||
|
@ -223,23 +223,6 @@ func chatHistoryEntriesForView(
|
||||
}
|
||||
|
||||
if groupMessages || reverseGroupedMessages {
|
||||
/*if !groupBucket.isEmpty && message.groupInfo != groupBucket[0].0.groupInfo {
|
||||
if reverseGroupedMessages {
|
||||
groupBucket.reverse()
|
||||
}
|
||||
if groupMessages {
|
||||
let groupStableId = groupBucket[0].0.groupInfo!.stableId
|
||||
if !existingGroupStableIds.contains(groupStableId) {
|
||||
existingGroupStableIds.append(groupStableId)
|
||||
entries.append(.MessageGroupEntry(groupBucket[0].0.groupInfo!, groupBucket, presentationData))
|
||||
}
|
||||
} else {
|
||||
for (message, isRead, selection, attributes, location) in groupBucket {
|
||||
entries.append(.MessageEntry(message, presentationData, isRead, location, selection, attributes))
|
||||
}
|
||||
}
|
||||
groupBucket.removeAll()
|
||||
}*/
|
||||
if let messageGroupingKey = message.groupingKey, (groupMessages || reverseGroupedMessages) {
|
||||
let selection: ChatHistoryMessageSelection
|
||||
if let selectedMessages = selectedMessages {
|
||||
@ -286,14 +269,6 @@ func chatHistoryEntriesForView(
|
||||
if !found {
|
||||
entries.append(.MessageEntry(message, presentationData, isRead, entry.location, selection, attributes))
|
||||
}
|
||||
|
||||
/*let selection: ChatHistoryMessageSelection
|
||||
if let selectedMessages = selectedMessages {
|
||||
selection = .selectable(selected: selectedMessages.contains(message.id))
|
||||
} else {
|
||||
selection = .none
|
||||
}
|
||||
groupBucket.append((message, isRead, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: false, isCentered: false, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] }), entry.location))*/
|
||||
} else {
|
||||
let selection: ChatHistoryMessageSelection
|
||||
if let selectedMessages = selectedMessages {
|
||||
@ -316,27 +291,64 @@ func chatHistoryEntriesForView(
|
||||
} else {
|
||||
selection = .none
|
||||
}
|
||||
|
||||
entries.append(.MessageEntry(message, presentationData, isRead, entry.location, selection, ChatMessageEntryAttributes(rank: adminRank, isContact: entry.attributes.authorIsContact, contentTypeHint: contentTypeHint, updatingMedia: updatingMedia[message.id], isPlaying: message.index == associatedData.currentlyPlayingMessageId, isCentered: false, authorStoryStats: message.author.flatMap { view.peerStoryStats[$0.id] })))
|
||||
}
|
||||
}
|
||||
|
||||
/*if !groupBucket.isEmpty {
|
||||
assert(groupMessages || reverseGroupedMessages)
|
||||
if reverseGroupedMessages {
|
||||
groupBucket.reverse()
|
||||
}
|
||||
if groupMessages {
|
||||
let groupStableId = groupBucket[0].0.groupInfo!.stableId
|
||||
if !existingGroupStableIds.contains(groupStableId) {
|
||||
existingGroupStableIds.append(groupStableId)
|
||||
entries.append(.MessageGroupEntry(groupBucket[0].0.groupInfo!, groupBucket, presentationData))
|
||||
|
||||
let insertPendingProcessingMessage: ([Message], Int) -> Void = { messages, index in
|
||||
//TODO:localize
|
||||
let serviceMessage = Message(
|
||||
stableId: UInt32.max - messages[0].stableId,
|
||||
stableVersion: 0,
|
||||
id: MessageId(peerId: messages[0].id.peerId, namespace: -1, id: messages[0].id.id),
|
||||
globallyUniqueId: nil,
|
||||
groupingKey: nil,
|
||||
groupInfo: nil,
|
||||
threadId: nil,
|
||||
timestamp: messages[0].timestamp,
|
||||
flags: [.Incoming],
|
||||
tags: [],
|
||||
globalTags: [],
|
||||
localTags: [],
|
||||
customTags: [],
|
||||
forwardInfo: nil,
|
||||
author: nil,
|
||||
text: "",
|
||||
attributes: [],
|
||||
media: [TelegramMediaAction(action: .customText(text: "This video will be published once converted and optimized", entities: [], additionalAttributes: nil))],
|
||||
peers: SimpleDictionary<PeerId, Peer>(),
|
||||
associatedMessages: SimpleDictionary<MessageId, Message>(),
|
||||
associatedMessageIds: [],
|
||||
associatedMedia: [:],
|
||||
associatedThreadInfo: nil,
|
||||
associatedStories: [:]
|
||||
)
|
||||
entries.insert(.MessageEntry(serviceMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false, authorStoryStats: nil)), at: index)
|
||||
}
|
||||
|
||||
for i in (0 ..< entries.count).reversed() {
|
||||
switch entries[i] {
|
||||
case let .MessageEntry(message, _, _, _, _, _):
|
||||
if message.id.namespace == Namespaces.Message.ScheduledCloud && message.pendingProcessingAttribute != nil {
|
||||
insertPendingProcessingMessage([message], i)
|
||||
}
|
||||
} else {
|
||||
for (message, isRead, selection, attributes, location) in groupBucket {
|
||||
entries.append(.MessageEntry(message, presentationData, isRead, location, selection, attributes))
|
||||
case let .MessageGroupEntry(_, messages, _):
|
||||
if !messages.isEmpty && messages[0].0.id.namespace == Namespaces.Message.ScheduledCloud {
|
||||
var videoCount = 0
|
||||
for message in messages {
|
||||
if message.0.pendingProcessingAttribute != nil {
|
||||
videoCount += 1
|
||||
}
|
||||
}
|
||||
if videoCount != 0 {
|
||||
insertPendingProcessingMessage(messages.map(\.0), i)
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if let lowerTimestamp = view.entries.last?.message.timestamp, let upperTimestamp = view.entries.first?.message.timestamp {
|
||||
if let joinMessage {
|
||||
@ -657,6 +669,9 @@ func chatHistoryEntriesForView(
|
||||
if reverse {
|
||||
return (entries.reversed(), currentState)
|
||||
} else {
|
||||
#if DEBUG
|
||||
assert(entries.map(\.stableId) == entries.sorted().map(\.stableId))
|
||||
#endif
|
||||
return (entries, currentState)
|
||||
}
|
||||
}
|
||||
|
@ -476,6 +476,9 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
guard let interfaceInteraction = interfaceInteraction, let controllerInteraction = controllerInteraction else {
|
||||
return .single(ContextController.Items(content: .list([])))
|
||||
}
|
||||
if let message = messages.first, message.id.namespace < 0 {
|
||||
return .single(ContextController.Items(content: .list([])))
|
||||
}
|
||||
|
||||
var isEmbeddedMode = false
|
||||
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
||||
|
Loading…
x
Reference in New Issue
Block a user