diff --git a/Tusker/Screens/Conversation/ConversationViewController.swift b/Tusker/Screens/Conversation/ConversationViewController.swift index 5b00a9d5e..53c8b92bc 100644 --- a/Tusker/Screens/Conversation/ConversationViewController.swift +++ b/Tusker/Screens/Conversation/ConversationViewController.swift @@ -484,3 +484,11 @@ extension ConversationViewController: StatusBarTappableViewController { } } } + +extension ConversationViewController: RefreshableViewController { + func refresh() { + Task { + await refreshContext() + } + } +} diff --git a/Tusker/Screens/Main/BaseMainTabBarViewController.swift b/Tusker/Screens/Main/BaseMainTabBarViewController.swift index 3019d6a41..f3eb83136 100644 --- a/Tusker/Screens/Main/BaseMainTabBarViewController.swift +++ b/Tusker/Screens/Main/BaseMainTabBarViewController.swift @@ -151,6 +151,22 @@ class BaseMainTabBarViewController: UITabBarController, FastAccountSwitcherViewC return false #endif // !os(visionOS) } + + // MARK: Keyboard shortcuts + + override func target(forAction action: Selector, withSender sender: Any?) -> Any? { + // This is a silly workaround for when the sidebar is focused (and therefore first responder), which, + // unfortunately, is almost always. Because the content view controller then isn't in the responder chain, + // we manually delegate to the top view controller if possible. + if action == #selector(RefreshableViewController.refresh), + let selected = selectedViewController as? NavigationControllerProtocol, + let top = selected.topViewController as? RefreshableViewController { + return top + } else { + return super.target(forAction: action, withSender: sender) + } + } + } extension BaseMainTabBarViewController: TuskerNavigationDelegate { diff --git a/Tusker/Screens/Main/MainSplitViewController.swift b/Tusker/Screens/Main/MainSplitViewController.swift index 687be122b..e1c37957f 100644 --- a/Tusker/Screens/Main/MainSplitViewController.swift +++ b/Tusker/Screens/Main/MainSplitViewController.swift @@ -219,6 +219,19 @@ class MainSplitViewController: UISplitViewController { @objc func handleComposeKeyCommand() { compose(editing: nil) } + + override func target(forAction action: Selector, withSender sender: Any?) -> Any? { + // This is a silly workaround for when the sidebar is focused (and therefore first responder), which, + // unfortunately, is almost always. Because the content view controller then isn't in the responder chain, + // we manually delegate to the top view controller if possible. + if action == #selector(RefreshableViewController.refresh), + traitCollection.horizontalSizeClass == .regular, + let top = secondaryNavController.topViewController as? RefreshableViewController { + return top + } else { + return super.target(forAction: action, withSender: sender) + } + } } diff --git a/Tusker/Screens/Notifications/NotificationsPageViewController.swift b/Tusker/Screens/Notifications/NotificationsPageViewController.swift index d40cf7094..500ebdc1f 100644 --- a/Tusker/Screens/Notifications/NotificationsPageViewController.swift +++ b/Tusker/Screens/Notifications/NotificationsPageViewController.swift @@ -180,3 +180,9 @@ extension NotificationsPageViewController: StateRestorableViewController { return currentPage.userActivity(accountID: mastodonController.accountInfo!.id) } } + +extension NotificationsPageViewController: RefreshableViewController { + func refresh() { + (currentViewController as? RefreshableViewController)?.refresh() + } +} diff --git a/Tusker/Screens/Profile/ProfileViewController.swift b/Tusker/Screens/Profile/ProfileViewController.swift index 70633e577..b6617dc1c 100644 --- a/Tusker/Screens/Profile/ProfileViewController.swift +++ b/Tusker/Screens/Profile/ProfileViewController.swift @@ -393,3 +393,9 @@ extension ProfileViewController: StatusBarTappableViewController { return currentViewController.handleStatusBarTapped(xPosition: xPosition) } } + +extension ProfileViewController: RefreshableViewController { + func refresh() { + currentViewController.refresh() + } +} diff --git a/Tusker/Screens/Timeline/TimelinesPageViewController.swift b/Tusker/Screens/Timeline/TimelinesPageViewController.swift index 7ebe5f9c8..81123ba7b 100644 --- a/Tusker/Screens/Timeline/TimelinesPageViewController.swift +++ b/Tusker/Screens/Timeline/TimelinesPageViewController.swift @@ -212,3 +212,9 @@ extension TimelinesPageViewController: StateRestorableViewController { return (currentViewController as? TimelineViewController)?.stateRestorationActivity() } } + +extension TimelinesPageViewController: RefreshableViewController { + func refresh() { + (currentViewController as? RefreshableViewController)?.refresh() + } +}