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/RasterizedCompositionComponent",
|
||||||
"//submodules/TelegramUI/Components/BadgeComponent",
|
"//submodules/TelegramUI/Components/BadgeComponent",
|
||||||
"//submodules/TelegramUI/Components/AnimatedTextComponent",
|
"//submodules/TelegramUI/Components/AnimatedTextComponent",
|
||||||
|
"//submodules/TelegramUI/Components/LottieComponent",
|
||||||
"//submodules/Components/MultilineTextComponent",
|
"//submodules/Components/MultilineTextComponent",
|
||||||
|
"//submodules/Components/BalancedTextComponent",
|
||||||
"//submodules/Components/ComponentDisplayAdapters",
|
"//submodules/Components/ComponentDisplayAdapters",
|
||||||
"//submodules/ComponentFlow",
|
"//submodules/ComponentFlow",
|
||||||
],
|
],
|
||||||
|
@ -5,10 +5,16 @@ import ComponentFlow
|
|||||||
import AppBundle
|
import AppBundle
|
||||||
|
|
||||||
final class GalleryRateToastAnimationComponent: Component {
|
final class GalleryRateToastAnimationComponent: Component {
|
||||||
init() {
|
let speedFraction: CGFloat
|
||||||
|
|
||||||
|
init(speedFraction: CGFloat) {
|
||||||
|
self.speedFraction = speedFraction
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: GalleryRateToastAnimationComponent, rhs: GalleryRateToastAnimationComponent) -> Bool {
|
static func ==(lhs: GalleryRateToastAnimationComponent, rhs: GalleryRateToastAnimationComponent) -> Bool {
|
||||||
|
if lhs.speedFraction != rhs.speedFraction {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,6 +22,10 @@ final class GalleryRateToastAnimationComponent: Component {
|
|||||||
private let itemViewContainer: UIView
|
private let itemViewContainer: UIView
|
||||||
private var itemViews: [UIImageView] = []
|
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) {
|
override init(frame: CGRect) {
|
||||||
self.itemViewContainer = UIView()
|
self.itemViewContainer = UIView()
|
||||||
|
|
||||||
@ -36,41 +46,49 @@ final class GalleryRateToastAnimationComponent: Component {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.link?.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
private func setupAnimations() {
|
private func setupAnimations() {
|
||||||
let beginTime = self.layer.convertTime(CACurrentMediaTime(), from: nil)
|
if self.link == nil {
|
||||||
|
var previousTimestamp = CACurrentMediaTime()
|
||||||
for i in 0 ..< self.itemViews.count {
|
self.link = SharedDisplayLinkDriver.shared.add { [weak self] _ in
|
||||||
if self.itemViews[i].layer.animation(forKey: "idle-opacity") != nil {
|
guard let self else {
|
||||||
continue
|
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 {
|
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 itemSize = self.itemViews[0].image?.size ?? CGSize(width: 10.0, height: 10.0)
|
||||||
let itemSpacing: CGFloat = 1.0
|
let itemSpacing: CGFloat = 1.0
|
||||||
|
|
||||||
@ -78,7 +96,10 @@ final class GalleryRateToastAnimationComponent: Component {
|
|||||||
|
|
||||||
for i in 0 ..< self.itemViews.count {
|
for i in 0 ..< self.itemViews.count {
|
||||||
let itemFrame = CGRect(origin: CGPoint(x: CGFloat(i) * (itemSize.width + itemSpacing), y: UIScreenPixel), size: itemSize)
|
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()
|
self.setupAnimations()
|
||||||
|
@ -3,20 +3,26 @@ import UIKit
|
|||||||
import Display
|
import Display
|
||||||
import ComponentFlow
|
import ComponentFlow
|
||||||
import AppBundle
|
import AppBundle
|
||||||
import MultilineTextComponent
|
import BalancedTextComponent
|
||||||
import AnimatedTextComponent
|
import AnimatedTextComponent
|
||||||
|
import LottieComponent
|
||||||
|
|
||||||
final class GalleryRateToastComponent: Component {
|
final class GalleryRateToastComponent: Component {
|
||||||
let rate: Double
|
let rate: Double
|
||||||
|
let displayTooltip: String?
|
||||||
|
|
||||||
init(rate: Double) {
|
init(rate: Double, displayTooltip: String?) {
|
||||||
self.rate = rate
|
self.rate = rate
|
||||||
|
self.displayTooltip = displayTooltip
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: GalleryRateToastComponent, rhs: GalleryRateToastComponent) -> Bool {
|
static func ==(lhs: GalleryRateToastComponent, rhs: GalleryRateToastComponent) -> Bool {
|
||||||
if lhs.rate != rhs.rate {
|
if lhs.rate != rhs.rate {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.displayTooltip != rhs.displayTooltip {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +31,14 @@ final class GalleryRateToastComponent: Component {
|
|||||||
private let text = ComponentView<Empty>()
|
private let text = ComponentView<Empty>()
|
||||||
private let arrows = 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) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
}
|
}
|
||||||
@ -33,7 +47,13 @@ final class GalleryRateToastComponent: Component {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
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 {
|
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 insets = UIEdgeInsets(top: 5.0, left: 11.0, bottom: 5.0, right: 16.0)
|
||||||
let spacing: CGFloat = 5.0
|
let spacing: CGFloat = 5.0
|
||||||
|
|
||||||
@ -55,7 +75,7 @@ final class GalleryRateToastComponent: Component {
|
|||||||
let textSize = self.text.update(
|
let textSize = self.text.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(AnimatedTextComponent(
|
component: AnyComponent(AnimatedTextComponent(
|
||||||
font: Font.semibold(17.0),
|
font: Font.with(size: 17.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]),
|
||||||
color: .white,
|
color: .white,
|
||||||
items: textItems
|
items: textItems
|
||||||
)),
|
)),
|
||||||
@ -63,9 +83,11 @@ final class GalleryRateToastComponent: Component {
|
|||||||
containerSize: CGSize(width: 100.0, height: 100.0)
|
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(
|
let arrowsSize = self.arrows.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(GalleryRateToastAnimationComponent()),
|
component: AnyComponent(GalleryRateToastAnimationComponent(speedFraction: speedFraction)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 200.0, height: 100.0)
|
containerSize: CGSize(width: 200.0, height: 100.0)
|
||||||
)
|
)
|
||||||
@ -82,7 +104,7 @@ final class GalleryRateToastComponent: Component {
|
|||||||
environment: {},
|
environment: {},
|
||||||
containerSize: size
|
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 let backgroundView = self.background.view {
|
||||||
if backgroundView.superview == nil {
|
if backgroundView.superview == nil {
|
||||||
self.addSubview(backgroundView)
|
self.addSubview(backgroundView)
|
||||||
@ -90,7 +112,7 @@ final class GalleryRateToastComponent: Component {
|
|||||||
transition.setFrame(view: backgroundView, frame: backgroundFrame)
|
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 let textView = self.text.view {
|
||||||
if textView.superview == nil {
|
if textView.superview == nil {
|
||||||
textView.layer.anchorPoint = CGPoint()
|
textView.layer.anchorPoint = CGPoint()
|
||||||
@ -100,7 +122,7 @@ final class GalleryRateToastComponent: Component {
|
|||||||
textView.bounds = CGRect(origin: CGPoint(), size: textFrame.size)
|
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 let arrowsView = self.arrows.view {
|
||||||
if arrowsView.superview == nil {
|
if arrowsView.superview == nil {
|
||||||
self.addSubview(arrowsView)
|
self.addSubview(arrowsView)
|
||||||
@ -108,7 +130,97 @@ final class GalleryRateToastComponent: Component {
|
|||||||
transition.setFrame(view: arrowsView, frame: arrowsFrame)
|
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
|
activeEdgeRateIndicatorTransition = .immediate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO:localize
|
||||||
let activeEdgeRateIndicatorSize = activeEdgeRateIndicator.update(
|
let activeEdgeRateIndicatorSize = activeEdgeRateIndicator.update(
|
||||||
transition: ComponentTransition(activeEdgeRateIndicatorTransition),
|
transition: ComponentTransition(activeEdgeRateIndicatorTransition),
|
||||||
component: AnyComponent(GalleryRateToastComponent(
|
component: AnyComponent(GalleryRateToastComponent(
|
||||||
rate: activeEdgeRateState.currentRate
|
rate: activeEdgeRateState.currentRate,
|
||||||
|
displayTooltip: "Swipe sideways to adjust speed."
|
||||||
)),
|
)),
|
||||||
environment: {},
|
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)
|
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 {
|
if let activeEdgeRateIndicatorView = activeEdgeRateIndicator.view {
|
||||||
|
@ -362,7 +362,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode {
|
|||||||
selectedStarsForeground: themeColors.reactionStarsActiveForeground.argb,
|
selectedStarsForeground: themeColors.reactionStarsActiveForeground.argb,
|
||||||
extractedBackground: arguments.presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
extractedBackground: arguments.presentationData.theme.theme.contextMenu.backgroundColor.argb,
|
||||||
extractedForeground: arguments.presentationData.theme.theme.contextMenu.primaryColor.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,
|
deselectedMediaPlaceholder: themeColors.reactionInactiveMediaPlaceholder.argb,
|
||||||
selectedMediaPlaceholder: themeColors.reactionActiveMediaPlaceholder.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...",
|
title: "Improving video...",
|
||||||
text: "The video will be published after it's optimized for the bese viewing experience.",
|
text: "The video will be published after it's optimized for the bese viewing experience.",
|
||||||
customUndoText: nil,
|
customUndoText: nil,
|
||||||
timeout: 3.5
|
timeout: 5.0
|
||||||
),
|
),
|
||||||
elevatedLayout: false,
|
elevatedLayout: false,
|
||||||
position: .top,
|
position: .top,
|
||||||
|
@ -10358,7 +10358,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
let location = CGPoint(x: bounds.midX, y: bounds.minY - 8.0)
|
let location = CGPoint(x: bounds.midX, y: bounds.minY - 8.0)
|
||||||
|
|
||||||
//TODO:localize
|
//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
|
self.checksTooltipController = tooltipController
|
||||||
tooltipController.dismissed = { [weak self, weak tooltipController] _ in
|
tooltipController.dismissed = { [weak self, weak tooltipController] _ in
|
||||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.checksTooltipController === tooltipController {
|
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.checksTooltipController === tooltipController {
|
||||||
|
@ -223,23 +223,6 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if groupMessages || reverseGroupedMessages {
|
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) {
|
if let messageGroupingKey = message.groupingKey, (groupMessages || reverseGroupedMessages) {
|
||||||
let selection: ChatHistoryMessageSelection
|
let selection: ChatHistoryMessageSelection
|
||||||
if let selectedMessages = selectedMessages {
|
if let selectedMessages = selectedMessages {
|
||||||
@ -286,14 +269,6 @@ func chatHistoryEntriesForView(
|
|||||||
if !found {
|
if !found {
|
||||||
entries.append(.MessageEntry(message, presentationData, isRead, entry.location, selection, attributes))
|
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 {
|
} else {
|
||||||
let selection: ChatHistoryMessageSelection
|
let selection: ChatHistoryMessageSelection
|
||||||
if let selectedMessages = selectedMessages {
|
if let selectedMessages = selectedMessages {
|
||||||
@ -316,27 +291,64 @@ func chatHistoryEntriesForView(
|
|||||||
} else {
|
} else {
|
||||||
selection = .none
|
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] })))
|
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 {
|
let insertPendingProcessingMessage: ([Message], Int) -> Void = { messages, index in
|
||||||
assert(groupMessages || reverseGroupedMessages)
|
//TODO:localize
|
||||||
if reverseGroupedMessages {
|
let serviceMessage = Message(
|
||||||
groupBucket.reverse()
|
stableId: UInt32.max - messages[0].stableId,
|
||||||
}
|
stableVersion: 0,
|
||||||
if groupMessages {
|
id: MessageId(peerId: messages[0].id.peerId, namespace: -1, id: messages[0].id.id),
|
||||||
let groupStableId = groupBucket[0].0.groupInfo!.stableId
|
globallyUniqueId: nil,
|
||||||
if !existingGroupStableIds.contains(groupStableId) {
|
groupingKey: nil,
|
||||||
existingGroupStableIds.append(groupStableId)
|
groupInfo: nil,
|
||||||
entries.append(.MessageGroupEntry(groupBucket[0].0.groupInfo!, groupBucket, presentationData))
|
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 {
|
case let .MessageGroupEntry(_, messages, _):
|
||||||
for (message, isRead, selection, attributes, location) in groupBucket {
|
if !messages.isEmpty && messages[0].0.id.namespace == Namespaces.Message.ScheduledCloud {
|
||||||
entries.append(.MessageEntry(message, presentationData, isRead, location, selection, attributes))
|
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 lowerTimestamp = view.entries.last?.message.timestamp, let upperTimestamp = view.entries.first?.message.timestamp {
|
||||||
if let joinMessage {
|
if let joinMessage {
|
||||||
@ -657,6 +669,9 @@ func chatHistoryEntriesForView(
|
|||||||
if reverse {
|
if reverse {
|
||||||
return (entries.reversed(), currentState)
|
return (entries.reversed(), currentState)
|
||||||
} else {
|
} else {
|
||||||
|
#if DEBUG
|
||||||
|
assert(entries.map(\.stableId) == entries.sorted().map(\.stableId))
|
||||||
|
#endif
|
||||||
return (entries, currentState)
|
return (entries, currentState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -476,6 +476,9 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
guard let interfaceInteraction = interfaceInteraction, let controllerInteraction = controllerInteraction else {
|
guard let interfaceInteraction = interfaceInteraction, let controllerInteraction = controllerInteraction else {
|
||||||
return .single(ContextController.Items(content: .list([])))
|
return .single(ContextController.Items(content: .list([])))
|
||||||
}
|
}
|
||||||
|
if let message = messages.first, message.id.namespace < 0 {
|
||||||
|
return .single(ContextController.Items(content: .list([])))
|
||||||
|
}
|
||||||
|
|
||||||
var isEmbeddedMode = false
|
var isEmbeddedMode = false
|
||||||
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user