diff --git a/Demo/SnapshotTests/Info.plist b/Demo/SnapshotTests/Info.plist index 31c2b1d950..56b4d4ce37 100644 --- a/Demo/SnapshotTests/Info.plist +++ b/Demo/SnapshotTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 139.2.0 + 139.3.0 CFBundleVersion 1 NSPrincipalClass diff --git a/Demo/Sources/Components/RefreshControl/RefreshControlDemo.swift b/Demo/Sources/Components/RefreshControl/RefreshControlDemo.swift index 1b0a6f7e22..bf18430655 100644 --- a/Demo/Sources/Components/RefreshControl/RefreshControlDemo.swift +++ b/Demo/Sources/Components/RefreshControl/RefreshControlDemo.swift @@ -17,8 +17,8 @@ class RefreshControlDemoView: UIView, Demoable { }() private lazy var refreshControl: UIRefreshControl = { - let refreshControl = RefreshControl(frame: .zero) - refreshControl.delegate = self + let refreshControl = UIRefreshControl(frame: .zero) + refreshControl.addTarget(self, action: #selector(handleRefreshBegan), for: .valueChanged) return refreshControl }() @@ -47,6 +47,13 @@ class RefreshControlDemoView: UIView, Demoable { tableView.bottomAnchor.constraint(equalTo: bottomAnchor) ]) } + + @objc private func handleRefreshBegan() { + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) { [weak self] in + self?.refreshControl.endRefreshing() + self?.tableView.reloadData() + } + } } // MARK: - UITableViewDataSource @@ -66,14 +73,3 @@ extension RefreshControlDemoView: UITableViewDataSource { return cell } } - -// MARK: - RefreshControlDelegate - -extension RefreshControlDemoView: RefreshControlDelegate { - func refreshControlDidBeginRefreshing(_ refreshControl: RefreshControl) { - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) { [weak self] in - self?.refreshControl.endRefreshing() - self?.tableView.reloadData() - } - } -} diff --git a/Demo/Sources/Info.plist b/Demo/Sources/Info.plist index 96271f97b2..420d45c2ca 100644 --- a/Demo/Sources/Info.plist +++ b/Demo/Sources/Info.plist @@ -21,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 139.2.0 + 139.3.0 CFBundleVersion 1 ITSAppUsesNonExemptEncryption diff --git a/FinniversKit.podspec b/FinniversKit.podspec index 7d25df95d1..4b03433660 100644 --- a/FinniversKit.podspec +++ b/FinniversKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FinniversKit' - s.version = '139.2.0' + s.version = '139.3.0' s.summary = "FINN's iOS Components" s.author = 'FINN.no' s.homepage = 'https://schibsted.frontify.com/d/oCLrx0cypXJM/design-system' diff --git a/FinniversKit/Sources/Components/LoadingIndicator/LoadingIndicatorView.swift b/FinniversKit/Sources/Components/LoadingIndicator/LoadingIndicatorView.swift index 19ebf472cb..f0997f5026 100644 --- a/FinniversKit/Sources/Components/LoadingIndicator/LoadingIndicatorView.swift +++ b/FinniversKit/Sources/Components/LoadingIndicator/LoadingIndicatorView.swift @@ -1,62 +1,15 @@ import UIKit -/// Branded replacement for UIActivityIndicatorView with possibility to use delayed start. -public class LoadingIndicatorView: UIView { +/// Currently not in use. Replaced with Native UIActivityIndicatorView. Still here in case we decide to go back +public class LoadingIndicatorView: UIActivityIndicatorView { public enum State { case delayedStart case started case stopped } - private let backgroundLayer = CAShapeLayer() - private let animatedLayer = CAShapeLayer() - private let duration: CGFloat = 2.5 - private let lineWidth: CGFloat = 4 - private let startAngle: CGFloat = 3 * .pi / 2 - - private var endAngle: CGFloat { - return startAngle + 2 * .pi - } public private(set) var state = State.stopped - public var progress: CGFloat { - get { return animatedLayer.strokeEnd } - set { - CATransaction.begin() - CATransaction.setDisableActions(true) - animatedLayer.strokeEnd = newValue - backgroundLayer.opacity = Float(newValue) - CATransaction.commit() - } - } - - public override init(frame: CGRect) { - super.init(frame: frame) - setup() - } - - public required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setup() - } - - public override func layoutSubviews() { - super.layoutSubviews() - - let center = CGPoint(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0) - let radius = min(bounds.size.width, bounds.size.height) / 2.0 - animatedLayer.lineWidth / 2.0 - - let bezierPath = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true) - - backgroundLayer.path = bezierPath.cgPath - animatedLayer.path = bezierPath.cgPath - backgroundLayer.frame = bounds - animatedLayer.frame = bounds - - layer.addSublayer(backgroundLayer) - layer.addSublayer(animatedLayer) - } - /// Starts the animation of the loading indicator after a short delay, unless it has already been stopped. /// - Parameters: /// - after: Seconds to wait until starting animation (approximately) @@ -70,91 +23,42 @@ public class LoadingIndicatorView: UIView { } } - /// Starts the animation of the loading indicator. - public func startAnimating() { - animateGroup() - isHidden = false - state = .started - } - - /// Stops the animation of the loading indicator. - public func stopAnimating() { - backgroundLayer.removeAllAnimations() - animatedLayer.removeAllAnimations() - isHidden = true - state = .stopped + public init() { + super.init(frame: .zero) + setup() } -} - -extension LoadingIndicatorView { - private func setup() { - backgroundColor = .clear - - backgroundLayer.fillColor = UIColor.clear.cgColor - backgroundLayer.strokeColor = UIColor.loadingIndicatorBackground.cgColor - backgroundLayer.strokeStart = 0 - backgroundLayer.strokeEnd = 1 - backgroundLayer.lineWidth = lineWidth - backgroundLayer.lineCap = .round - animatedLayer.fillColor = UIColor.clear.cgColor - animatedLayer.strokeColor = UIColor.loadingIndicator.cgColor - animatedLayer.strokeStart = 0 - animatedLayer.strokeEnd = 1 - animatedLayer.lineWidth = lineWidth - animatedLayer.lineCap = .round - - isHidden = true + public override init(style: UIActivityIndicatorView.Style = .large) { + super.init(frame: .zero) + setup(style: style) } - private func animateStrokeEnd() -> CABasicAnimation { - let animation = CABasicAnimation(keyPath: "strokeEnd") - animation.beginTime = 0 - animation.duration = CFTimeInterval(duration / 2.0) - animation.fromValue = 0 - animation.toValue = 1 - animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) - - return animation + public override init(frame: CGRect) { + super.init(frame: frame) + setup() } - private func animateStrokeStart() -> CABasicAnimation { - let animation = CABasicAnimation(keyPath: "strokeStart") - animation.beginTime = CFTimeInterval(duration / 2.0) - animation.duration = CFTimeInterval(duration / 2.0) - animation.fromValue = 0 - animation.toValue = 1 - animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) - - return animation + public required init(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() } - private func animateRotation() -> CABasicAnimation { - let animation = CABasicAnimation(keyPath: "transform.rotation.z") - animation.fromValue = 0 - animation.toValue = .pi * 2.0 - animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) - animation.repeatCount = .infinity - return animation + /// Starts the animation of the loading indicator. + public override func startAnimating() { + super.startAnimating() + isHidden = false + state = .started } - private func animateGroup() { - let animationGroup = CAAnimationGroup() - animationGroup.animations = [animateStrokeEnd(), animateStrokeStart(), animateRotation()] - animationGroup.duration = CFTimeInterval(duration) - animationGroup.fillMode = .both - animationGroup.isRemovedOnCompletion = false - animationGroup.repeatCount = .infinity - - animatedLayer.add(animationGroup, forKey: "loading") + /// Stops the animation of the loading indicator. + public override func stopAnimating() { + super.stopAnimating() + isHidden = true + state = .stopped } -} - -// MARK: - Private extensions -private extension UIColor { - static var loadingIndicatorBackground: UIColor { - return UIColor(r: 221, g: 232, b: 250) + private func setup(style: UIActivityIndicatorView.Style = .large) { + self.style = style } } diff --git a/FinniversKit/Sources/Components/RefreshControl/RefreshControl.swift b/FinniversKit/Sources/Components/RefreshControl/RefreshControl.swift index 95c4ad7743..eaa8b831ad 100644 --- a/FinniversKit/Sources/Components/RefreshControl/RefreshControl.swift +++ b/FinniversKit/Sources/Components/RefreshControl/RefreshControl.swift @@ -79,7 +79,6 @@ public class RefreshControl: UIRefreshControl { private func handleLoadingProgress() { let pullDistance = superview.flatMap({ $0.bounds.height / 5 }) ?? defaultPullDistance let progress = min(max(topOffset, 0.0), pullDistance) / pullDistance - loadingIndicatorView.progress = progress if topOffset >= pullDistance { beginRefreshing() @@ -105,7 +104,6 @@ public class RefreshControl: UIRefreshControl { private func startAnimatingLoadingIndicator() { isAnimating = true - loadingIndicatorView.progress = 1 loadingIndicatorView.startAnimating() delegate?.refreshControlDidBeginRefreshing(self) } diff --git a/FinniversKit/Sources/Fullscreen/LoadingView/LoadingSwiftUIView.swift b/FinniversKit/Sources/Fullscreen/LoadingView/LoadingSwiftUIView.swift index bf26194475..c46625c58e 100644 --- a/FinniversKit/Sources/Fullscreen/LoadingView/LoadingSwiftUIView.swift +++ b/FinniversKit/Sources/Fullscreen/LoadingView/LoadingSwiftUIView.swift @@ -50,7 +50,7 @@ public struct LoadingSwiftUIView: View { } } } else { - SwiftUILoadingIndicator() + ProgressView() .scaleEffect(loadingIndicatorScale) .onAppear { loadingIndicatorScale = initialScale diff --git a/FinniversKit/Sources/Fullscreen/LoadingView/LoadingView.swift b/FinniversKit/Sources/Fullscreen/LoadingView/LoadingView.swift index cb60e30813..d675e310e4 100644 --- a/FinniversKit/Sources/Fullscreen/LoadingView/LoadingView.swift +++ b/FinniversKit/Sources/Fullscreen/LoadingView/LoadingView.swift @@ -39,8 +39,7 @@ import UIKit private var loadingIndicatorCenterY: NSLayoutConstraint? private lazy var loadingIndicator: LoadingIndicatorView = { - let view = LoadingIndicatorView() - view.translatesAutoresizingMaskIntoConstraints = false + let view = LoadingIndicatorView(withAutoLayout: true) view.transform = loadingIndicatorInitialTransform return view }() diff --git a/FinniversKit/Sources/Info.plist b/FinniversKit/Sources/Info.plist index 2c63c95bd7..d3cf81fbdb 100644 --- a/FinniversKit/Sources/Info.plist +++ b/FinniversKit/Sources/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 139.2.0 + 139.3.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/FinniversKit/Sources/Recycling/GridViews/AdRecommendations/GridView/AdRecommendationsGridView.swift b/FinniversKit/Sources/Recycling/GridViews/AdRecommendations/GridView/AdRecommendationsGridView.swift index a09032d724..33d8c853a5 100644 --- a/FinniversKit/Sources/Recycling/GridViews/AdRecommendations/GridView/AdRecommendationsGridView.swift +++ b/FinniversKit/Sources/Recycling/GridViews/AdRecommendations/GridView/AdRecommendationsGridView.swift @@ -68,8 +68,8 @@ public class AdRecommendationsGridView: UIView { }() private lazy var refreshControl: UIRefreshControl = { - let refreshControl = RefreshControl(frame: .zero) - refreshControl.delegate = self + let refreshControl = UIRefreshControl(frame: .zero) + refreshControl.addTarget(self, action: #selector(handleRefreshBegan), for: .valueChanged) return refreshControl }() @@ -116,6 +116,10 @@ public class AdRecommendationsGridView: UIView { collectionView.collectionViewLayout.invalidateLayout() } + @objc private func handleRefreshBegan() { + delegate?.adRecommendationsGridViewDidStartRefreshing(self) + } + // MARK: - Public methods public func reloadData() { @@ -252,11 +256,3 @@ extension AdRecommendationsGridView: AdRecommendationsGridViewLayoutDelegate { return dataSource?.adRecommendationsGridView(self, heightForItemWithWidth: width, at: indexPath) ?? 0 } } - -// MARK: - RefreshControlDelegate - -extension AdRecommendationsGridView: RefreshControlDelegate { - public func refreshControlDidBeginRefreshing(_ refreshControl: RefreshControl) { - delegate?.adRecommendationsGridViewDidStartRefreshing(self) - } -} diff --git a/FinniversKit/Sources/Recycling/ListViews/FavoriteFolders/FavoriteFoldersListView.swift b/FinniversKit/Sources/Recycling/ListViews/FavoriteFolders/FavoriteFoldersListView.swift index 6dc98fdc83..e9a6881d74 100644 --- a/FinniversKit/Sources/Recycling/ListViews/FavoriteFolders/FavoriteFoldersListView.swift +++ b/FinniversKit/Sources/Recycling/ListViews/FavoriteFolders/FavoriteFoldersListView.swift @@ -78,8 +78,8 @@ public class FavoriteFoldersListView: UIView { }() private lazy var refreshControl: UIRefreshControl = { - let refreshControl = RefreshControl(frame: .zero) - refreshControl.delegate = self + let refreshControl = UIRefreshControl(frame: .zero) + refreshControl.addTarget(self, action: #selector(handleRefreshBegan), for: .valueChanged) return refreshControl }() @@ -366,6 +366,10 @@ public class FavoriteFoldersListView: UIView { @objc private func handleXmasButtonTap() { delegate?.favoriteFoldersListViewDidSelectXmasButton(self) } + + @objc private func handleRefreshBegan() { + delegate?.favoriteFoldersListViewDidBeginRefreshing(self) + } } // MARK: - UITableViewDataSource @@ -460,14 +464,6 @@ extension FavoriteFoldersListView: UITableViewDelegate { } } -// MARK: - RefreshControlDelegate - -extension FavoriteFoldersListView: RefreshControlDelegate { - public func refreshControlDidBeginRefreshing(_ refreshControl: RefreshControl) { - delegate?.favoriteFoldersListViewDidBeginRefreshing(self) - } -} - // MARK: - FavoriteFoldersFooterViewDelegate extension FavoriteFoldersListView: FavoriteFoldersFooterViewDelegate { diff --git a/FinniversKit/Sources/SwiftUI Components/SwiftUILoadingIndicator.swift b/FinniversKit/Sources/SwiftUI Components/SwiftUILoadingIndicator.swift index efdc7cbf5a..b5f5076c18 100644 --- a/FinniversKit/Sources/SwiftUI Components/SwiftUILoadingIndicator.swift +++ b/FinniversKit/Sources/SwiftUI Components/SwiftUILoadingIndicator.swift @@ -1,5 +1,6 @@ import SwiftUI +/// Currently not in use. Replaced with Native ProgressView. Still here in case we decide to go back public struct SwiftUILoadingIndicator: View { private struct ProgressCircle: Shape { var startAngle: Angle diff --git a/FinniversKit/UnitTests/Info.plist b/FinniversKit/UnitTests/Info.plist index 04b2b11c03..cb8236cd4f 100644 --- a/FinniversKit/UnitTests/Info.plist +++ b/FinniversKit/UnitTests/Info.plist @@ -15,6 +15,6 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 139.2.0 + 139.3.0