Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/Signal/src/ViewControllers/MediaGallery/WideMediaTileViewLayout.swift
1 views
//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import SignalServiceKit
import UIKit

// Accommodates remaining scrolled to the same "apparent" position when new content is inserted
// into the top of a collectionView. There are multiple ways to solve this problem, but this
// is the only one which avoided a perceptible flicker.
protocol ScrollPositionPreserving: AnyObject {
    func recordContentSizeBeforeInsertingToTop()
}

class WideMediaTileViewLayout: UICollectionViewFlowLayout, ScrollPositionPreserving {

    private var contentSizeBeforeInsertingToTop: CGSize?

    let contentCardVerticalInset: CGFloat

    func recordContentSizeBeforeInsertingToTop() {
        contentSizeBeforeInsertingToTop = collectionViewContentSize
    }

    override func prepare() {
        super.prepare()

        if let collectionView, let oldContentSize = contentSizeBeforeInsertingToTop {
            let newContentSize = collectionViewContentSize
            collectionView.contentOffset.y += newContentSize.height - oldContentSize.height
            contentSizeBeforeInsertingToTop = nil
        }
    }

    init(contentCardVerticalInset inset: CGFloat) {
        contentCardVerticalInset = inset

        super.init()

        scrollDirection = .vertical
        minimumInteritemSpacing = 0
        minimumLineSpacing = 0
    }

    required init?(coder: NSCoder) {
        owsFail("init(coder:) has not been implemented")
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true
    }
}