diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 380f21eac..8338c2225 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -87,6 +87,7 @@ 62FD27D32893707B00B205C5 /* BookmarkViewController+DataSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D22893707B00B205C5 /* BookmarkViewController+DataSourceProvider.swift */; }; 62FD27D52893708A00B205C5 /* BookmarkViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D42893708A00B205C5 /* BookmarkViewModel+Diffable.swift */; }; 87FFDA5D898A5C42ADCB35E7 /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4ABE34829701A4496C5BB64 /* Pods_Mastodon.framework */; }; + C24C97032922F30500BAE8CB /* RefreshControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = C24C97022922F30500BAE8CB /* RefreshControl.swift */; }; DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; settings = {ATTRIBUTES = (codegen, ); }; }; DB0009A726AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; }; DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0140CE25C42AEE00F9F3CF /* OSLog.swift */; }; @@ -610,6 +611,7 @@ B44342AC2B6585F8295F1DDF /* Pods-Mastodon-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-Mastodon-NotificationService/Pods-Mastodon-NotificationService.release.xcconfig"; sourceTree = ""; }; BB482D32A7B9825BF5327C4F /* Pods-Mastodon-MastodonUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.release.xcconfig"; sourceTree = ""; }; BD7598A87F4497045EDEF252 /* Pods-Mastodon.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk - release.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk - release.xcconfig"; sourceTree = ""; }; + C24C97022922F30500BAE8CB /* RefreshControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshControl.swift; sourceTree = ""; }; C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.asdk - debug.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.asdk - debug.xcconfig"; sourceTree = ""; }; CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D7D7CF93E262178800077512 /* Pods-Mastodon-AppShared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-AppShared.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-AppShared/Pods-Mastodon-AppShared.debug.xcconfig"; sourceTree = ""; }; @@ -2452,6 +2454,7 @@ isa = PBXGroup; children = ( DB02CDBE2625AE5000D0A2AF /* AdaptiveUserInterfaceStyleBarButtonItem.swift */, + C24C97022922F30500BAE8CB /* RefreshControl.swift */, ); path = Control; sourceTree = ""; @@ -3520,6 +3523,7 @@ 5BB04FF5262F0E6D0043BFF6 /* ReportSection.swift in Sources */, DBEFCD82282A2AB100C0ABEA /* ReportServerRulesView.swift in Sources */, DBA94436265CBB7400C537E1 /* ProfileFieldItem.swift in Sources */, + C24C97032922F30500BAE8CB /* RefreshControl.swift in Sources */, DB023D2A27A0FE5C005AC798 /* DataSourceProvider+NotificationTableViewCellDelegate.swift in Sources */, DB98EB6027B10E150082E365 /* ReportCommentTableViewCell.swift in Sources */, DB0FCB962797E6C2006C02E2 /* SearchResultViewController+DataSourceProvider.swift in Sources */, diff --git a/Mastodon/Scene/Discovery/Community/DiscoveryCommunityViewController.swift b/Mastodon/Scene/Discovery/Community/DiscoveryCommunityViewController.swift index d592c3033..31635dc85 100644 --- a/Mastodon/Scene/Discovery/Community/DiscoveryCommunityViewController.swift +++ b/Mastodon/Scene/Discovery/Community/DiscoveryCommunityViewController.swift @@ -33,7 +33,7 @@ final class DiscoveryCommunityViewController: UIViewController, NeedsDependency, return tableView }() - let refreshControl = UIRefreshControl() + let refreshControl = RefreshControl() deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) @@ -108,7 +108,7 @@ extension DiscoveryCommunityViewController { extension DiscoveryCommunityViewController { - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { if !viewModel.stateMachine.enter(DiscoveryCommunityViewModel.State.Reloading.self) { refreshControl.endRefreshing() } diff --git a/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift b/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift index ce1aadbb4..52e5e1856 100644 --- a/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift +++ b/Mastodon/Scene/Discovery/ForYou/DiscoveryForYouViewController.swift @@ -32,7 +32,7 @@ final class DiscoveryForYouViewController: UIViewController, NeedsDependency, Me return tableView }() - let refreshControl = UIRefreshControl() + let refreshControl = RefreshControl() deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) @@ -93,7 +93,7 @@ extension DiscoveryForYouViewController { extension DiscoveryForYouViewController { - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { Task { try await viewModel.fetch() } diff --git a/Mastodon/Scene/Discovery/Hashtags/DiscoveryHashtagsViewController.swift b/Mastodon/Scene/Discovery/Hashtags/DiscoveryHashtagsViewController.swift index e315f04ee..1c855c254 100644 --- a/Mastodon/Scene/Discovery/Hashtags/DiscoveryHashtagsViewController.swift +++ b/Mastodon/Scene/Discovery/Hashtags/DiscoveryHashtagsViewController.swift @@ -32,7 +32,7 @@ final class DiscoveryHashtagsViewController: UIViewController, NeedsDependency, return tableView }() - let refreshControl = UIRefreshControl() + let refreshControl = RefreshControl() deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) @@ -88,7 +88,7 @@ extension DiscoveryHashtagsViewController { extension DiscoveryHashtagsViewController { - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { Task { @MainActor in do { try await viewModel.fetch() diff --git a/Mastodon/Scene/Discovery/News/DiscoveryNewsViewController.swift b/Mastodon/Scene/Discovery/News/DiscoveryNewsViewController.swift index 7f9efb0d9..d1634db82 100644 --- a/Mastodon/Scene/Discovery/News/DiscoveryNewsViewController.swift +++ b/Mastodon/Scene/Discovery/News/DiscoveryNewsViewController.swift @@ -32,7 +32,7 @@ final class DiscoveryNewsViewController: UIViewController, NeedsDependency, Medi return tableView }() - let refreshControl = UIRefreshControl() + let refreshControl = RefreshControl() deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) @@ -101,7 +101,7 @@ extension DiscoveryNewsViewController { extension DiscoveryNewsViewController { - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { guard viewModel.stateMachine.enter(DiscoveryNewsViewModel.State.Reloading.self) else { sender.endRefreshing() return diff --git a/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewController.swift b/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewController.swift index ee3538885..893f564a3 100644 --- a/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewController.swift +++ b/Mastodon/Scene/Discovery/Posts/DiscoveryPostsViewController.swift @@ -32,7 +32,7 @@ final class DiscoveryPostsViewController: UIViewController, NeedsDependency, Med return tableView }() - let refreshControl = UIRefreshControl() + let refreshControl = RefreshControl() let discoveryIntroBannerView = DiscoveryIntroBannerView() @@ -119,7 +119,7 @@ extension DiscoveryPostsViewController { extension DiscoveryPostsViewController { - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { guard viewModel.stateMachine.enter(DiscoveryPostsViewModel.State.Reloading.self) else { sender.endRefreshing() return diff --git a/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift b/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift index 42079a91e..aad97283c 100644 --- a/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift +++ b/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewController.swift @@ -48,7 +48,7 @@ final class HashtagTimelineViewController: UIViewController, NeedsDependency, Me return tableView }() - let refreshControl = UIRefreshControl() + let refreshControl = RefreshControl() deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", ((#file as NSString).lastPathComponent), #line, #function) @@ -158,7 +158,7 @@ extension HashtagTimelineViewController { extension HashtagTimelineViewController { - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { guard viewModel.stateMachine.enter(HashtagTimelineViewModel.State.Reloading.self) else { sender.endRefreshing() return diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index 3efcd5cbe..e83101796 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -74,7 +74,7 @@ final class HomeTimelineViewController: UIViewController, NeedsDependency, Media return progressView }() - let refreshControl = UIRefreshControl() + let refreshControl = RefreshControl() deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", ((#file as NSString).lastPathComponent), #line, #function) @@ -398,7 +398,7 @@ extension HomeTimelineViewController { coordinator.present(scene: .settings(viewModel: settingsViewModel), from: self, transition: .modal(animated: true, completion: nil)) } - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { guard viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.Loading.self) else { sender.endRefreshing() return diff --git a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift index 00e2a9fc8..d088bb783 100644 --- a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift +++ b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift @@ -26,8 +26,8 @@ final class NotificationTimelineViewController: UIViewController, NeedsDependenc var viewModel: NotificationTimelineViewModel! - private(set) lazy var refreshControl: UIRefreshControl = { - let refreshControl = UIRefreshControl() + private(set) lazy var refreshControl: RefreshControl = { + let refreshControl = RefreshControl() refreshControl.addTarget(self, action: #selector(NotificationTimelineViewController.refreshControlValueChanged(_:)), for: .valueChanged) return refreshControl }() @@ -137,7 +137,7 @@ extension NotificationTimelineViewController: CellFrameCacheContainer { extension NotificationTimelineViewController { - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") Task { diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 3ce1fd33a..99f3042aa 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -99,8 +99,8 @@ final class ProfileViewController: UIViewController, NeedsDependency, MediaPrevi return barButtonItem }() - let refreshControl: UIRefreshControl = { - let refreshControl = UIRefreshControl() + let refreshControl: RefreshControl = { + let refreshControl = RefreshControl() refreshControl.tintColor = .white return refreshControl }() @@ -545,7 +545,7 @@ extension ProfileViewController { _ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil)) } - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { + @objc private func refreshControlValueChanged(_ sender: RefreshControl) { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) if let userTimelineViewController = profilePagingViewController.currentViewController as? UserTimelineViewController { diff --git a/Mastodon/Scene/Share/View/Control/RefreshControl.swift b/Mastodon/Scene/Share/View/Control/RefreshControl.swift new file mode 100644 index 000000000..afac5a1a1 --- /dev/null +++ b/Mastodon/Scene/Share/View/Control/RefreshControl.swift @@ -0,0 +1,28 @@ +// +// RefreshControl.swift +// Mastodon +// +// Created by Kyle Bashour on 11/14/22. +// + +import UIKit + +/// RefreshControl subclass that properly displays itself behind table view contents. +class RefreshControl: UIRefreshControl { + override init() { + super.init() + } + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func didMoveToSuperview() { + super.didMoveToSuperview() + layer.zPosition = -1 + } +}