mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-02 04:38:33 +00:00
Merge commit 'cc6f7882f1c8307599ca4788ea751811ca97de4a'
This commit is contained in:
commit
9536cb0da0
@ -1708,11 +1708,10 @@ let setupFontFunctions = """
|
||||
"""
|
||||
|
||||
private let videoSource = """
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
function tgBrowserDisableWebkitEnterFullscreen(videoElement) {
|
||||
if (videoElement && videoElement.webkitEnterFullscreen) {
|
||||
Object.defineProperty(videoElement, 'webkitEnterFullscreen', {
|
||||
value: undefined
|
||||
});
|
||||
videoElement.setAttribute('playsinline', '');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1747,6 +1746,7 @@ _tgbrowser_observer.observe(document.body, {
|
||||
function tgBrowserDisconnectObserver() {
|
||||
_tgbrowser_observer.disconnect();
|
||||
}
|
||||
});
|
||||
"""
|
||||
|
||||
let setupTouchObservers =
|
||||
|
||||
@ -100,7 +100,7 @@ public final class DeviceAccess {
|
||||
public static func isCameraAccessAuthorized() -> Bool {
|
||||
return AVCaptureDevice.authorizationStatus(for: .video) == .authorized
|
||||
}
|
||||
|
||||
|
||||
public static func authorizationStatus(applicationInForeground: Signal<Bool, NoError>? = nil, siriAuthorization: (() -> AccessType)? = nil, subject: DeviceAccessSubject) -> Signal<AccessType, NoError> {
|
||||
switch subject {
|
||||
case .notifications:
|
||||
|
||||
@ -309,13 +309,16 @@ public func galleryItemForEntry(
|
||||
} else {
|
||||
if let fileName = file.fileName, (fileName as NSString).pathExtension.lowercased() == "json" {
|
||||
return ChatAnimationGalleryItem(context: context, presentationData: presentationData, message: message, location: location)
|
||||
}
|
||||
else if file.mimeType.hasPrefix("image/") && file.mimeType != "image/gif" {
|
||||
} else if file.mimeType.hasPrefix("image/") && file.mimeType != "image/gif" {
|
||||
var pixelsCount: Int = 0
|
||||
if let dimensions = file.dimensions {
|
||||
pixelsCount = Int(dimensions.width) * Int(dimensions.height)
|
||||
}
|
||||
if pixelsCount < 10000 * 10000 {
|
||||
var fileSize: Int64 = 0
|
||||
if let size = file.size {
|
||||
fileSize = size
|
||||
}
|
||||
if pixelsCount < 10000 * 10000 && fileSize < 16 * 1024 * 1024 {
|
||||
return ChatImageGalleryItem(
|
||||
context: context,
|
||||
presentationData: presentationData,
|
||||
|
||||
@ -1283,24 +1283,22 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
}
|
||||
}
|
||||
recognizer.highlight = { [weak self] point in
|
||||
if let strongSelf = self {
|
||||
if strongSelf.selectionNode == nil {
|
||||
if let replyInfoNode = strongSelf.replyInfoNode {
|
||||
var translatedPoint: CGPoint?
|
||||
let convertedNodeFrame = replyInfoNode.view.convert(replyInfoNode.bounds, to: strongSelf.view)
|
||||
if let point = point, convertedNodeFrame.insetBy(dx: -4.0, dy: -4.0).contains(point) {
|
||||
translatedPoint = strongSelf.view.convert(point, to: replyInfoNode.view)
|
||||
}
|
||||
replyInfoNode.updateTouchesAtPoint(translatedPoint)
|
||||
if let strongSelf = self, strongSelf.selectionNode == nil {
|
||||
if let replyInfoNode = strongSelf.replyInfoNode {
|
||||
var translatedPoint: CGPoint?
|
||||
let convertedNodeFrame = replyInfoNode.view.convert(replyInfoNode.bounds, to: strongSelf.view)
|
||||
if let point = point, convertedNodeFrame.insetBy(dx: -4.0, dy: -4.0).contains(point) {
|
||||
translatedPoint = strongSelf.view.convert(point, to: replyInfoNode.view)
|
||||
}
|
||||
if let forwardInfoNode = strongSelf.forwardInfoNode {
|
||||
var translatedPoint: CGPoint?
|
||||
let convertedNodeFrame = forwardInfoNode.view.convert(forwardInfoNode.bounds, to: strongSelf.view)
|
||||
if let point = point, convertedNodeFrame.insetBy(dx: -4.0, dy: -4.0).contains(point) {
|
||||
translatedPoint = strongSelf.view.convert(point, to: forwardInfoNode.view)
|
||||
}
|
||||
forwardInfoNode.updateTouchesAtPoint(translatedPoint)
|
||||
replyInfoNode.updateTouchesAtPoint(translatedPoint)
|
||||
}
|
||||
if let forwardInfoNode = strongSelf.forwardInfoNode {
|
||||
var translatedPoint: CGPoint?
|
||||
let convertedNodeFrame = forwardInfoNode.view.convert(forwardInfoNode.bounds, to: strongSelf.view)
|
||||
if let point = point, convertedNodeFrame.insetBy(dx: -4.0, dy: -4.0).contains(point) {
|
||||
translatedPoint = strongSelf.view.convert(point, to: forwardInfoNode.view)
|
||||
}
|
||||
forwardInfoNode.updateTouchesAtPoint(translatedPoint)
|
||||
}
|
||||
for contentNode in strongSelf.contentNodes {
|
||||
var translatedPoint: CGPoint?
|
||||
@ -5254,10 +5252,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
}
|
||||
|
||||
if let selectionNode = self.selectionNode {
|
||||
// if let replyInfoNode = self.replyInfoNode, replyInfoNode.frame.contains(point) {
|
||||
// return replyInfoNode.view.hitTest(self.view.convert(point, to: replyInfoNode.view), with: event)
|
||||
// }
|
||||
|
||||
if let result = self.traceSelectionNodes(parent: self, point: point.offsetBy(dx: -42.0, dy: 0.0)) {
|
||||
return result.view
|
||||
}
|
||||
|
||||
@ -628,10 +628,20 @@ public final class MediaEditor {
|
||||
case let .asset(asset):
|
||||
textureSource = Signal { subscriber in
|
||||
let isVideo = asset.mediaType == .video
|
||||
|
||||
|
||||
let targetSize = isVideo ? CGSize(width: 128.0, height: 128.0) : CGSize(width: 1920.0, height: 1920.0)
|
||||
let options = PHImageRequestOptions()
|
||||
options.deliveryMode = isVideo ? .fastFormat : .highQualityFormat
|
||||
let deliveryMode: PHImageRequestOptionsDeliveryMode
|
||||
if isVideo {
|
||||
if #available(iOS 14.0, *), PHPhotoLibrary.authorizationStatus(for: .readWrite) == .limited {
|
||||
deliveryMode = .highQualityFormat
|
||||
} else {
|
||||
deliveryMode = .fastFormat
|
||||
}
|
||||
} else {
|
||||
deliveryMode = .highQualityFormat
|
||||
}
|
||||
options.deliveryMode = deliveryMode
|
||||
options.isNetworkAccessAllowed = true
|
||||
|
||||
let requestId = PHImageManager.default().requestImage(
|
||||
|
||||
@ -569,7 +569,7 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
theme: environment.theme,
|
||||
strings: strings,
|
||||
dateTimeFormat: environment.dateTimeFormat,
|
||||
containerInsets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right),
|
||||
containerInsets: .zero,
|
||||
isScrollable: false,
|
||||
isCurrent: true,
|
||||
externalScrollBounds: self.lastScrollBounds ?? .zero,
|
||||
|
||||
@ -102,6 +102,12 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
}
|
||||
|
||||
private final class ScrollViewImpl: UIScrollView {
|
||||
var forceDecelerating = false
|
||||
|
||||
override var isDecelerating: Bool {
|
||||
return self.forceDecelerating || super.isDecelerating
|
||||
}
|
||||
|
||||
override func touchesShouldCancel(in view: UIView) -> Bool {
|
||||
return true
|
||||
}
|
||||
@ -111,8 +117,9 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
private let scrollView: ScrollViewImpl
|
||||
|
||||
private let measureItem = ComponentView<Empty>()
|
||||
private var visibleItems: [String: ComponentView<Empty>] = [:]
|
||||
private var separatorViews: [String: UIView] = [:]
|
||||
private var visibleItems: [AnyHashable: ComponentView<Empty>] = [:]
|
||||
private var separatorLayers: [AnyHashable: SimpleLayer] = [:]
|
||||
private var highlightLayer = SimpleLayer()
|
||||
|
||||
private var ignoreScrolling: Bool = false
|
||||
|
||||
@ -145,6 +152,8 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
self.scrollView.delegate = self
|
||||
self.scrollView.clipsToBounds = true
|
||||
self.addSubview(self.scrollView)
|
||||
|
||||
self.scrollView.layer.addSublayer(self.highlightLayer)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@ -163,6 +172,79 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
|
||||
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||
cancelContextGestures(view: scrollView)
|
||||
if let decelerationAnimator = self.decelerationAnimator {
|
||||
self.scrollView.forceDecelerating = false
|
||||
self.decelerationAnimator = nil
|
||||
decelerationAnimator.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
private var decelerationAnimator: ConstantDisplayLinkAnimator?
|
||||
func transferVelocity(_ velocity: CGFloat) {
|
||||
if velocity <= 0.0 {
|
||||
return
|
||||
}
|
||||
self.decelerationAnimator?.isPaused = true
|
||||
let startTime = CACurrentMediaTime()
|
||||
var currentOffset = self.scrollView.contentOffset
|
||||
let decelerationRate: CGFloat = 0.998
|
||||
self.scrollView.forceDecelerating = true
|
||||
//self.scrollViewDidEndDragging(self.scrollView, willDecelerate: true)
|
||||
self.decelerationAnimator = ConstantDisplayLinkAnimator(update: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let t = CACurrentMediaTime() - startTime
|
||||
var currentVelocity = velocity * 15.0 * CGFloat(pow(Double(decelerationRate), 1000.0 * t))
|
||||
currentOffset.y += currentVelocity
|
||||
let maxOffset = strongSelf.scrollView.contentSize.height - strongSelf.scrollView.bounds.height
|
||||
if currentOffset.y >= maxOffset {
|
||||
currentOffset.y = maxOffset
|
||||
currentVelocity = 0.0
|
||||
}
|
||||
if currentOffset.y < 0.0 {
|
||||
currentOffset.y = 0.0
|
||||
currentVelocity = 0.0
|
||||
}
|
||||
|
||||
var didEnd = false
|
||||
if abs(currentVelocity) < 0.1 {
|
||||
strongSelf.decelerationAnimator?.isPaused = true
|
||||
strongSelf.decelerationAnimator = nil
|
||||
didEnd = true
|
||||
}
|
||||
var contentOffset = strongSelf.scrollView.contentOffset
|
||||
contentOffset.y = floorToScreenPixels(currentOffset.y)
|
||||
strongSelf.scrollView.setContentOffset(contentOffset, animated: false)
|
||||
strongSelf.scrollViewDidScroll(strongSelf.scrollView)
|
||||
if didEnd {
|
||||
//strongSelf.scrollViewDidEndDecelerating(strongSelf.scrollView)
|
||||
strongSelf.scrollView.forceDecelerating = false
|
||||
}
|
||||
})
|
||||
self.decelerationAnimator?.isPaused = false
|
||||
}
|
||||
|
||||
private var highlightedItemId: AnyHashable?
|
||||
private func updateHighlightedItem(itemId: AnyHashable?) {
|
||||
guard let environment = self.environment else {
|
||||
return
|
||||
}
|
||||
if self.highlightedItemId == itemId {
|
||||
return
|
||||
}
|
||||
let previousHighlightedItemId = self.highlightedItemId
|
||||
self.highlightedItemId = itemId
|
||||
|
||||
if let _ = previousHighlightedItemId, itemId == nil {
|
||||
ComponentTransition.easeInOut(duration: 0.2).setBackgroundColor(layer: self.highlightLayer, color: .clear)
|
||||
}
|
||||
if let itemId, let itemView = self.visibleItems[itemId]?.view {
|
||||
var highlightFrame = itemView.frame
|
||||
highlightFrame.size.height += UIScreenPixel
|
||||
self.highlightLayer.frame = highlightFrame
|
||||
ComponentTransition.immediate.setBackgroundColor(layer: self.highlightLayer, color: environment.theme.list.itemHighlightedBackgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateScrolling(transition: ComponentTransition) {
|
||||
@ -173,34 +255,34 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
var visibleBounds = environment.externalScrollBounds ?? self.scrollView.bounds
|
||||
visibleBounds = visibleBounds.insetBy(dx: 0.0, dy: -100.0)
|
||||
|
||||
var validIds = Set<String>()
|
||||
var validIds = Set<AnyHashable>()
|
||||
if let visibleItems = itemLayout.visibleItems(for: visibleBounds) {
|
||||
for index in visibleItems.lowerBound ..< visibleItems.upperBound {
|
||||
if index >= self.items.count {
|
||||
continue
|
||||
}
|
||||
let item = self.items[index]
|
||||
let id = item.extendedId
|
||||
let id = AnyHashable(item.extendedId)
|
||||
validIds.insert(id)
|
||||
|
||||
var itemTransition = transition
|
||||
let itemView: ComponentView<Empty>
|
||||
let separatorView: UIView
|
||||
if let current = self.visibleItems[id], let currentSeparator = self.separatorViews[id] {
|
||||
let separatorLayer: SimpleLayer
|
||||
if let current = self.visibleItems[id], let currentSeparator = self.separatorLayers[id] {
|
||||
itemView = current
|
||||
separatorView = currentSeparator
|
||||
separatorLayer = currentSeparator
|
||||
} else {
|
||||
itemTransition = .immediate
|
||||
itemView = ComponentView()
|
||||
self.visibleItems[id] = itemView
|
||||
|
||||
separatorView = UIView()
|
||||
self.separatorViews[id] = separatorView
|
||||
self.scrollView.addSubview(separatorView)
|
||||
separatorLayer = SimpleLayer()
|
||||
self.separatorLayers[id] = separatorLayer
|
||||
self.scrollView.layer.addSublayer(separatorLayer)
|
||||
}
|
||||
|
||||
separatorView.backgroundColor = environment.theme.list.itemBlocksSeparatorColor
|
||||
separatorView.isHidden = index == self.items.count - 1
|
||||
separatorLayer.backgroundColor = environment.theme.list.itemBlocksSeparatorColor.cgColor
|
||||
separatorLayer.isHidden = index == self.items.count - 1
|
||||
|
||||
let fontBaseDisplaySize = 17.0
|
||||
|
||||
@ -367,12 +449,18 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
if !item.flags.contains(.isLocal) {
|
||||
component.action(item)
|
||||
}
|
||||
},
|
||||
updateIsHighlighted: { [weak self] _, highlighted in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.updateHighlightedItem(itemId: highlighted ? id : nil)
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: itemLayout.containerWidth, height: itemLayout.itemHeight)
|
||||
containerSize: CGSize(width: itemLayout.containerWidth - itemLayout.containerInsets.left - itemLayout.containerInsets.right, height: itemLayout.itemHeight)
|
||||
)
|
||||
let itemFrame = itemLayout.itemFrame(for: index)
|
||||
let itemFrame = itemLayout.itemFrame(for: index).offsetBy(dx: itemLayout.containerInsets.left, dy: 0.0)
|
||||
if let itemComponentView = itemView.view {
|
||||
if itemComponentView.superview == nil {
|
||||
if !transition.animation.isImmediate {
|
||||
@ -383,11 +471,11 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
itemTransition.setFrame(view: itemComponentView, frame: itemFrame)
|
||||
}
|
||||
let sideInset: CGFloat = 60.0 + environment.containerInsets.left
|
||||
itemTransition.setFrame(view: separatorView, frame: CGRect(x: sideInset, y: itemFrame.maxY, width: itemFrame.width - sideInset, height: UIScreenPixel))
|
||||
itemTransition.setFrame(layer: separatorLayer, frame: CGRect(x: sideInset, y: itemFrame.maxY, width: itemFrame.width - sideInset - environment.containerInsets.right, height: UIScreenPixel))
|
||||
}
|
||||
}
|
||||
|
||||
var removeIds: [String] = []
|
||||
var removeIds: [AnyHashable] = []
|
||||
for (id, itemView) in self.visibleItems {
|
||||
if !validIds.contains(id) {
|
||||
removeIds.append(id)
|
||||
@ -398,10 +486,10 @@ final class StarsTransactionsListPanelComponent: Component {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (id, separatorView) in self.separatorViews {
|
||||
for (id, separatorLayer) in self.separatorLayers {
|
||||
if !validIds.contains(id) {
|
||||
transition.setAlpha(view: separatorView, alpha: 0.0, completion: { [weak separatorView] _ in
|
||||
separatorView?.removeFromSuperview()
|
||||
transition.setAlpha(layer: separatorLayer, alpha: 0.0, completion: { [weak separatorLayer] _ in
|
||||
separatorLayer?.removeFromSuperlayer()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,6 +427,7 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
}
|
||||
|
||||
class View: UIView, UIGestureRecognizerDelegate {
|
||||
private let topPanelClippingView: UIView
|
||||
private let topPanelBackgroundView: UIView
|
||||
private let topPanelMergedBackgroundView: UIView
|
||||
private let topPanelSeparatorLayer: SimpleLayer
|
||||
@ -436,6 +437,7 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
private weak var state: EmptyComponentState?
|
||||
|
||||
private let panelsBackgroundLayer: SimpleLayer
|
||||
private let clippingView: UIView
|
||||
private var visiblePanels: [AnyHashable: ComponentView<StarsTransactionsPanelEnvironment>] = [:]
|
||||
private var actualVisibleIds = Set<AnyHashable>()
|
||||
private var currentId: AnyHashable?
|
||||
@ -443,6 +445,10 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
private var animatingTransition: Bool = false
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.topPanelClippingView = UIView()
|
||||
self.topPanelClippingView.clipsToBounds = true
|
||||
self.topPanelClippingView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||
|
||||
self.topPanelBackgroundView = UIView()
|
||||
|
||||
self.topPanelMergedBackgroundView = UIView()
|
||||
@ -452,11 +458,16 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
|
||||
self.panelsBackgroundLayer = SimpleLayer()
|
||||
|
||||
self.clippingView = UIView()
|
||||
self.clippingView.clipsToBounds = true
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.layer.addSublayer(self.panelsBackgroundLayer)
|
||||
self.addSubview(self.topPanelBackgroundView)
|
||||
self.addSubview(self.topPanelMergedBackgroundView)
|
||||
self.addSubview(self.clippingView)
|
||||
self.addSubview(self.topPanelClippingView)
|
||||
self.topPanelClippingView.addSubview(self.topPanelBackgroundView)
|
||||
self.topPanelClippingView.addSubview(self.topPanelMergedBackgroundView)
|
||||
self.layer.addSublayer(self.topPanelSeparatorLayer)
|
||||
|
||||
let panRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: #selector(self.panGesture(_:)), allowedDirections: { [weak self] point in
|
||||
@ -593,6 +604,12 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
transition.setAlpha(view: self.topPanelBackgroundView, alpha: 1.0 - value)
|
||||
}
|
||||
|
||||
func transferVelocity(_ velocity: CGFloat) {
|
||||
if let currentPanelView = self.currentPanelView as? StarsTransactionsListPanelComponent.View {
|
||||
currentPanelView.transferVelocity(velocity)
|
||||
}
|
||||
}
|
||||
|
||||
func update(component: StarsTransactionsPanelContainerComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<StarsTransactionsPanelContainerEnvironment>, transition: ComponentTransition) -> CGSize {
|
||||
let environment = environment[StarsTransactionsPanelContainerEnvironment.self].value
|
||||
|
||||
@ -610,13 +627,17 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
|
||||
let topPanelCoverHeight: CGFloat = 10.0
|
||||
|
||||
let topPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: -topPanelCoverHeight), size: CGSize(width: availableSize.width, height: 44.0))
|
||||
transition.setFrame(view: self.topPanelBackgroundView, frame: topPanelFrame)
|
||||
transition.setFrame(view: self.topPanelMergedBackgroundView, frame: topPanelFrame)
|
||||
let containerWidth = availableSize.width - component.insets.left - component.insets.right
|
||||
let topPanelFrame = CGRect(origin: CGPoint(x: component.insets.left, y: -topPanelCoverHeight), size: CGSize(width: containerWidth, height: 44.0))
|
||||
transition.setFrame(view: self.topPanelClippingView, frame: topPanelFrame)
|
||||
transition.setFrame(view: self.topPanelBackgroundView, frame: CGRect(origin: .zero, size: topPanelFrame.size))
|
||||
transition.setFrame(view: self.topPanelMergedBackgroundView, frame: CGRect(origin: .zero, size: topPanelFrame.size))
|
||||
|
||||
transition.setCornerRadius(layer: self.topPanelClippingView.layer, cornerRadius: component.insets.left > 0.0 ? 11.0 : 0.0)
|
||||
|
||||
transition.setFrame(layer: self.panelsBackgroundLayer, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: availableSize.width, height: availableSize.height - topPanelFrame.maxY)))
|
||||
transition.setFrame(layer: self.panelsBackgroundLayer, frame: CGRect(origin: CGPoint(x: component.insets.left, y: topPanelFrame.maxY), size: CGSize(width: containerWidth, height: availableSize.height - topPanelFrame.maxY)))
|
||||
|
||||
transition.setFrame(layer: self.topPanelSeparatorLayer, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: availableSize.width, height: UIScreenPixel)))
|
||||
transition.setFrame(layer: self.topPanelSeparatorLayer, frame: CGRect(origin: CGPoint(x: component.insets.left, y: topPanelFrame.maxY), size: CGSize(width: containerWidth, height: UIScreenPixel)))
|
||||
|
||||
if let currentIdValue = self.currentId, !component.items.contains(where: { $0.id == currentIdValue }) {
|
||||
self.currentId = nil
|
||||
@ -641,7 +662,7 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let sideInset: CGFloat = 16.0
|
||||
let sideInset: CGFloat = 16.0 + component.insets.left
|
||||
let condensedPanelWidth: CGFloat = availableSize.width - sideInset * 2.0
|
||||
let headerSize = self.header.update(
|
||||
transition: transition,
|
||||
@ -674,7 +695,7 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
if headerView.superview == nil {
|
||||
self.addSubview(headerView)
|
||||
}
|
||||
transition.setFrame(view: headerView, frame: CGRect(origin: topPanelFrame.origin.offsetBy(dx: sideInset, dy: 0.0), size: headerSize))
|
||||
transition.setFrame(view: headerView, frame: CGRect(origin: topPanelFrame.origin.offsetBy(dx: 16.0, dy: 0.0), size: headerSize))
|
||||
}
|
||||
|
||||
let centralPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: availableSize.width, height: availableSize.height - topPanelFrame.maxY))
|
||||
@ -688,7 +709,7 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
for (id, _) in self.visiblePanels {
|
||||
visibleIds.insert(id)
|
||||
}
|
||||
|
||||
|
||||
var validIds = Set<AnyHashable>()
|
||||
if let currentIndex {
|
||||
var anyAnchorOffset: CGFloat = 0.0
|
||||
@ -769,7 +790,7 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
)
|
||||
if let panelView = panel.view {
|
||||
if panelView.superview == nil {
|
||||
self.insertSubview(panelView, belowSubview: self.topPanelBackgroundView)
|
||||
self.clippingView.addSubview(panelView)
|
||||
}
|
||||
|
||||
panelTransition.setFrame(view: panelView, frame: itemFrame, completion: { [weak self] _ in
|
||||
@ -790,6 +811,11 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let clippingFrame = CGRect(origin: CGPoint(x: component.insets.left, y: 0.0), size: CGSize(width: availableSize.width - component.insets.left - component.insets.right, height: availableSize.height))
|
||||
|
||||
transition.setPosition(view: self.clippingView, position: clippingFrame.center)
|
||||
transition.setBounds(view: self.clippingView, bounds: CGRect(origin: CGPoint(x: component.insets.left, y: 0.0), size: clippingFrame.size))
|
||||
|
||||
var removeIds: [AnyHashable] = []
|
||||
for (id, panel) in self.visiblePanels {
|
||||
if !validIds.contains(id) {
|
||||
|
||||
@ -120,6 +120,8 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
private var previousVelocityM1: CGFloat = 0.0
|
||||
private var previousVelocity: CGFloat = 0.0
|
||||
|
||||
private var listIsExpanded = false
|
||||
|
||||
private var ignoreScrolling: Bool = false
|
||||
|
||||
private var stateDisposable: Disposable?
|
||||
@ -200,6 +202,19 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
|
||||
guard let navigationMetrics = self.navigationMetrics else {
|
||||
return
|
||||
}
|
||||
|
||||
if let panelContainerView = self.panelContainer.view as? StarsTransactionsPanelContainerComponent.View {
|
||||
let paneAreaExpansionFinalPoint: CGFloat = panelContainerView.frame.minY - navigationMetrics.navigationHeight
|
||||
if abs(scrollView.contentOffset.y - paneAreaExpansionFinalPoint) < .ulpOfOne {
|
||||
panelContainerView.transferVelocity(self.previousVelocityM1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
|
||||
guard let _ = self.navigationMetrics else {
|
||||
return
|
||||
@ -273,6 +288,14 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
if let view = self.topBalanceIconView.view {
|
||||
view.alpha = topBalanceAlpha
|
||||
}
|
||||
|
||||
let listIsExpanded = expansionDistanceFactor == 0.0
|
||||
if listIsExpanded != self.listIsExpanded {
|
||||
self.listIsExpanded = listIsExpanded
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .init(animation: .curve(duration: 0.25, curve: .slide)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = self.panelContainer.updateEnvironment(
|
||||
@ -362,7 +385,7 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
|
||||
var contentHeight: CGFloat = 0.0
|
||||
|
||||
let sideInsets: CGFloat = environment.safeInsets.left + environment.safeInsets.right + 16 * 2.0
|
||||
let sideInsets: CGFloat = environment.safeInsets.left + environment.safeInsets.right + 16.0 * 2.0
|
||||
let bottomInset: CGFloat = environment.safeInsets.bottom
|
||||
|
||||
contentHeight += environment.statusBarHeight
|
||||
@ -834,13 +857,16 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
}
|
||||
|
||||
if !panelItems.isEmpty {
|
||||
let panelContainerInset: CGFloat = self.listIsExpanded ? 0.0 : 16.0
|
||||
let panelContainerCornerRadius: CGFloat = self.listIsExpanded ? 0.0 : 11.0
|
||||
|
||||
let panelContainerSize = self.panelContainer.update(
|
||||
transition: panelTransition,
|
||||
component: AnyComponent(StarsTransactionsPanelContainerComponent(
|
||||
theme: environment.theme,
|
||||
strings: environment.strings,
|
||||
dateTimeFormat: environment.dateTimeFormat,
|
||||
insets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: bottomInset, right: environment.safeInsets.right),
|
||||
insets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left + panelContainerInset, bottom: bottomInset, right: environment.safeInsets.right + panelContainerInset),
|
||||
items: panelItems,
|
||||
currentPanelUpdated: { [weak self] id, transition in
|
||||
guard let self else {
|
||||
@ -859,7 +885,8 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
if panelContainerView.superview == nil {
|
||||
self.scrollContainerView.addSubview(panelContainerView)
|
||||
}
|
||||
transition.setFrame(view: panelContainerView, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: panelContainerSize))
|
||||
transition.setFrame(view: panelContainerView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - panelContainerSize.width) / 2.0), y: contentHeight), size: panelContainerSize))
|
||||
transition.setCornerRadius(layer: panelContainerView.layer, cornerRadius: panelContainerCornerRadius)
|
||||
}
|
||||
contentHeight += panelContainerSize.height
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user