diff --git a/submodules/AvatarNode/Sources/AvatarNode.swift b/submodules/AvatarNode/Sources/AvatarNode.swift index 355af220c2..5a6714f198 100644 --- a/submodules/AvatarNode/Sources/AvatarNode.swift +++ b/submodules/AvatarNode/Sources/AvatarNode.swift @@ -936,6 +936,12 @@ public final class AvatarNode: ASDisplayNode { public func pushLoadingStatus(signal: Signal) -> Disposable { let disposable = MetaDisposable() + + for d in self.loadingStatuses.copyItems() { + d.dispose() + } + self.loadingStatuses.removeAll() + let index = self.loadingStatuses.add(disposable) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { [weak self] in diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index 82bd74f871..b90784cb0b 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -1064,4 +1064,18 @@ public struct Transition { ) } } + + public func animateContentsImage(layer: CALayer, from fromImage: CGImage, to toImage: CGImage, duration: Double, curve: Transition.Animation.Curve, completion: ((Bool) -> Void)? = nil) { + layer.animate( + from: fromImage, + to: toImage, + keyPath: "contents", + duration: duration, + delay: 0.0, + curve: .easeInOut, + removeOnCompletion: true, + additive: false, + completion: completion + ) + } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentCaptionComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentCaptionComponent.swift index f029700d2d..482b437abb 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentCaptionComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContentCaptionComponent.swift @@ -125,10 +125,10 @@ final class StoryContentCaptionComponent: Component { private let scrollFullMaskView: UIView private let scrollCenterMaskView: UIView private let scrollBottomMaskView: UIImageView + private let scrollBottomFullMaskView: UIView private let scrollTopMaskView: UIImageView - private let shadowGradientLayer: SimpleGradientLayer - private let shadowPlainLayer: SimpleLayer + private let shadowGradientView: UIImageView private var component: StoryContentCaptionComponent? private weak var state: EmptyComponentState? @@ -140,9 +140,15 @@ final class StoryContentCaptionComponent: Component { private var isExpanded: Bool = false + private static let shadowImage: UIImage? = { + UIImage(named: "Stories/PanelGradient") + }() + override init(frame: CGRect) { - self.shadowGradientLayer = SimpleGradientLayer() - self.shadowPlainLayer = SimpleLayer() + self.shadowGradientView = UIImageView() + if let image = StoryContentCaptionComponent.View.shadowImage { + self.shadowGradientView.image = image.stretchableImage(withLeftCapWidth: 0, topCapHeight: Int(image.size.height - 1.0)) + } self.scrollViewContainer = UIView() @@ -170,6 +176,10 @@ final class StoryContentCaptionComponent: Component { ], locations: [0.0, 1.0])) self.scrollMaskContainer.addSubview(self.scrollBottomMaskView) + self.scrollBottomFullMaskView = UIView() + self.scrollBottomFullMaskView.backgroundColor = .white + self.scrollMaskContainer.addSubview(self.scrollBottomFullMaskView) + self.scrollTopMaskView = UIImageView(image: generateGradientImage(size: CGSize(width: 8.0, height: 8.0), colors: [ UIColor(white: 1.0, alpha: 0.0), UIColor(white: 1.0, alpha: 1.0) @@ -181,8 +191,7 @@ final class StoryContentCaptionComponent: Component { super.init(frame: frame) - self.layer.addSublayer(self.shadowGradientLayer) - self.layer.addSublayer(self.shadowPlainLayer) + self.addSubview(self.shadowGradientView) self.scrollViewContainer.addSubview(self.scrollView) self.scrollView.delegate = self @@ -258,8 +267,7 @@ final class StoryContentCaptionComponent: Component { let shadowOverflow: CGFloat = 58.0 let shadowFrame = CGRect(origin: CGPoint(x: 0.0, y: -self.scrollView.contentOffset.y + itemLayout.containerSize.height - itemLayout.visibleTextHeight - itemLayout.verticalInset - shadowOverflow), size: CGSize(width: itemLayout.containerSize.width, height: itemLayout.visibleTextHeight + itemLayout.verticalInset + shadowOverflow)) - transition.setFrame(layer: self.shadowGradientLayer, frame: shadowFrame) - transition.setFrame(layer: self.shadowPlainLayer, frame: CGRect(origin: CGPoint(x: shadowFrame.minX, y: shadowFrame.maxY), size: CGSize(width: shadowFrame.width, height: self.scrollView.contentSize.height + 1000.0))) + transition.setFrame(view: self.shadowGradientView, frame: CGRect(origin: CGPoint(x: shadowFrame.minX, y: shadowFrame.minY), size: CGSize(width: shadowFrame.width, height: self.scrollView.contentSize.height + 1000.0))) let expandDistance: CGFloat = 50.0 var expandFraction: CGFloat = self.scrollView.contentOffset.y / expandDistance @@ -626,7 +634,7 @@ final class StoryContentCaptionComponent: Component { transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: availableSize.height))) transition.setFrame(view: self.scrollViewContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: availableSize.height))) - if self.shadowGradientLayer.colors == nil { + /*if self.shadowGradientLayer.colors == nil { var locations: [NSNumber] = [] var colors: [CGColor] = [] let numStops = 10 @@ -646,7 +654,7 @@ final class StoryContentCaptionComponent: Component { self.shadowGradientLayer.type = .axial self.shadowPlainLayer.backgroundColor = UIColor(white: 0.0, alpha: baseAlpha).cgColor - } + }*/ self.ignoreScrolling = false self.updateScrolling(transition: transition) @@ -656,6 +664,7 @@ final class StoryContentCaptionComponent: Component { transition.setFrame(view: self.scrollFullMaskView, frame: CGRect(origin: CGPoint(x: 0.0, y: gradientEdgeHeight), size: CGSize(width: availableSize.width, height: availableSize.height - gradientEdgeHeight))) transition.setFrame(view: self.scrollCenterMaskView, frame: CGRect(origin: CGPoint(x: 0.0, y: gradientEdgeHeight), size: CGSize(width: availableSize.width, height: availableSize.height - gradientEdgeHeight * 2.0))) transition.setFrame(view: self.scrollBottomMaskView, frame: CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - gradientEdgeHeight), size: CGSize(width: availableSize.width, height: gradientEdgeHeight))) + transition.setFrame(view: self.scrollBottomFullMaskView, frame: CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - gradientEdgeHeight), size: CGSize(width: availableSize.width, height: gradientEdgeHeight))) transition.setFrame(view: self.scrollTopMaskView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: gradientEdgeHeight))) self.ignoreExternalState = false @@ -685,8 +694,10 @@ final class StoryContentCaptionComponent: Component { isExpandedTransition.setAlpha(view: dustNode.view, alpha: !self.isExpanded ? 0.0 : 1.0) } - isExpandedTransition.setAlpha(layer: self.shadowPlainLayer, alpha: self.isExpanded ? 0.0 : 1.0) - isExpandedTransition.setAlpha(layer: self.shadowGradientLayer, alpha: self.isExpanded ? 0.0 : 1.0) + isExpandedTransition.setAlpha(view: self.shadowGradientView, alpha: self.isExpanded ? 0.0 : 1.0) + + isExpandedTransition.setAlpha(view: self.scrollBottomMaskView, alpha: self.isExpanded ? 1.0 : 0.0) + isExpandedTransition.setAlpha(view: self.scrollBottomFullMaskView, alpha: self.isExpanded ? 0.0 : 1.0) return availableSize } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 3d64deac60..7b947725d9 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -327,6 +327,10 @@ public final class StoryItemSetContainerComponent: Component { } } + private static let shadowImage: UIImage? = { + UIImage(named: "Stories/PanelGradient") + }() + public final class View: UIView, UIScrollViewDelegate, UIGestureRecognizerDelegate { let sendMessageContext: StoryItemSetContainerSendMessage @@ -334,7 +338,7 @@ public final class StoryItemSetContainerComponent: Component { let itemsContainerView: UIView let controlsContainerView: UIView - let topContentGradientLayer: SimpleGradientLayer + let topContentGradientView: UIImageView let bottomContentGradientLayer: SimpleGradientLayer let contentDimView: UIView @@ -416,7 +420,12 @@ public final class StoryItemSetContainerComponent: Component { self.controlsContainerView.layer.cornerCurve = .continuous } - self.topContentGradientLayer = SimpleGradientLayer() + self.topContentGradientView = UIImageView() + if let image = StoryItemSetContainerComponent.shadowImage { + self.topContentGradientView.image = image.stretchableImage(withLeftCapWidth: 0, topCapHeight: Int(image.size.height - 1.0)) + self.topContentGradientView.transform = CGAffineTransformMakeScale(1.0, -1.0) + } + self.bottomContentGradientLayer = SimpleGradientLayer() self.contentDimView = UIView() @@ -437,7 +446,7 @@ public final class StoryItemSetContainerComponent: Component { self.addSubview(self.controlsContainerView) self.controlsContainerView.addSubview(self.contentDimView) - self.controlsContainerView.layer.addSublayer(self.topContentGradientLayer) + self.controlsContainerView.addSubview(self.topContentGradientView) self.layer.addSublayer(self.bottomContentGradientLayer) self.closeButton.addSubview(self.closeButtonIconView) @@ -1253,7 +1262,7 @@ public final class StoryItemSetContainerComponent: Component { } self.closeButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) - self.topContentGradientLayer.animateAlpha(from: 0.0, to: CGFloat(self.topContentGradientLayer.opacity), duration: 0.25) + self.topContentGradientView.layer.animateAlpha(from: 0.0, to: self.topContentGradientView.alpha, duration: 0.25) let sourceLocalFrame = sourceView.convert(transitionIn.sourceRect, to: self) let innerSourceLocalFrame = CGRect(origin: CGPoint(x: sourceLocalFrame.minX - contentContainerView.frame.minX, y: sourceLocalFrame.minY - contentContainerView.frame.minY), size: sourceLocalFrame.size) @@ -1381,7 +1390,7 @@ public final class StoryItemSetContainerComponent: Component { captionView.layer.animateAlpha(from: captionView.alpha, to: 0.0, duration: 0.25, removeOnCompletion: false) } self.closeButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false) - self.topContentGradientLayer.animateAlpha(from: CGFloat(self.topContentGradientLayer.opacity), to: 0.0, duration: 0.25, removeOnCompletion: false) + self.topContentGradientView.layer.animateAlpha(from: self.topContentGradientView.alpha, to: 0.0, duration: 0.25, removeOnCompletion: false) if let leftInfoView = self.leftInfoItem?.view.view { if transitionOut.destinationIsAvatar { @@ -1610,7 +1619,7 @@ public final class StoryItemSetContainerComponent: Component { resetScrollingOffsetWithItemTransition = true } - if self.topContentGradientLayer.colors == nil { + /*if self.topContentGradientLayer.colors == nil { var locations: [NSNumber] = [] var colors: [CGColor] = [] let numStops = 4 @@ -1628,7 +1637,7 @@ public final class StoryItemSetContainerComponent: Component { self.topContentGradientLayer.locations = locations self.topContentGradientLayer.colors = colors self.topContentGradientLayer.type = .axial - } + }*/ if self.bottomContentGradientLayer.colors == nil { var locations: [NSNumber] = [] var colors: [CGColor] = [] @@ -1648,7 +1657,7 @@ public final class StoryItemSetContainerComponent: Component { self.bottomContentGradientLayer.colors = colors self.bottomContentGradientLayer.type = .axial - self.contentDimView.backgroundColor = UIColor(white: 0.0, alpha: 0.3) + self.contentDimView.backgroundColor = UIColor(white: 0.0, alpha: 0.6) } let wasPanning = self.component?.isPanning ?? false @@ -2552,9 +2561,10 @@ public final class StoryItemSetContainerComponent: Component { } } - let gradientHeight: CGFloat = 74.0 - transition.setFrame(layer: self.topContentGradientLayer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: contentFrame.width, height: gradientHeight))) - transition.setAlpha(layer: self.topContentGradientLayer, alpha: (component.hideUI || self.displayViewList || self.isEditingStory) ? 0.0 : 1.0) + let topGradientHeight: CGFloat = 90.0 + let topContentGradientRect = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: contentFrame.width, height: topGradientHeight)) + transition.setPosition(view: self.topContentGradientView, position: topContentGradientRect.center) + transition.setBounds(view: self.topContentGradientView, bounds: CGRect(origin: CGPoint(), size: topContentGradientRect.size)) let inputPanelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - inputPanelSize.width) / 2.0), y: availableSize.height - inputPanelBottomInset - inputPanelSize.height), size: inputPanelSize) var inputPanelAlpha: CGFloat = component.slice.peer.id == component.context.account.peerId || component.hideUI || self.isEditingStory ? 0.0 : 1.0 @@ -2959,9 +2969,13 @@ public final class StoryItemSetContainerComponent: Component { //transition.setAlpha(layer: self.bottomContentGradientLayer, alpha: inputPanelIsOverlay ? 1.0 : 0.0) transition.setAlpha(layer: self.bottomContentGradientLayer, alpha: 0.0) + var topGradientAlpha: CGFloat = (component.hideUI || self.displayViewList || self.isEditingStory) ? 0.0 : 1.0 var normalDimAlpha: CGFloat = 0.0 var forceDimAnimation = false if let captionItem = self.captionItem { + if captionItem.externalState.isExpanded { + topGradientAlpha = 0.0 + } normalDimAlpha = captionItem.externalState.isExpanded ? 1.0 : 0.0 if transition.animation.isImmediate && transition.userData(StoryContentCaptionComponent.TransitionHint.self)?.kind == .isExpandedUpdated { forceDimAnimation = true @@ -2974,6 +2988,12 @@ public final class StoryItemSetContainerComponent: Component { transition.setFrame(view: self.contentDimView, frame: CGRect(origin: CGPoint(), size: contentFrame.size)) + if transition.animation.isImmediate && forceDimAnimation && self.topContentGradientView.alpha != topGradientAlpha { + Transition(animation: .curve(duration: 0.25, curve: .easeInOut)).setAlpha(view: self.topContentGradientView, alpha: topGradientAlpha) + } else { + transition.setAlpha(view: self.topContentGradientView, alpha: topGradientAlpha) + } + if transition.animation.isImmediate && forceDimAnimation && self.contentDimView.alpha != dimAlpha { Transition(animation: .curve(duration: 0.25, curve: .easeInOut)).setAlpha(view: self.contentDimView, alpha: dimAlpha) } else { diff --git a/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/Contents.json index 54905e0f8b..0d1e12bb58 100644 --- a/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "smoothGradient.png", + "filename" : "smoothGradient 0.4.png", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/smoothGradient 0.4.png b/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/smoothGradient 0.4.png new file mode 100644 index 0000000000..49a5faf1c2 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/smoothGradient 0.4.png differ diff --git a/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/smoothGradient.png b/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/smoothGradient.png deleted file mode 100644 index ae7189a9cf..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Stories/PanelGradient.imageset/smoothGradient.png and /dev/null differ