diff --git a/Tusker/Screens/Main/NewMainTabBarViewController.swift b/Tusker/Screens/Main/NewMainTabBarViewController.swift index ebfbc6bd..c0a7f02f 100644 --- a/Tusker/Screens/Main/NewMainTabBarViewController.swift +++ b/Tusker/Screens/Main/NewMainTabBarViewController.swift @@ -129,7 +129,7 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController { if nav.viewControllers.count > 1 { switch nav.viewControllers[1] { case let listVC as ListTimelineViewController: - if let tab = listsGroup.tab(forIdentifier: Self.listTabIdentifier(listVC.list)) { + if let tab = listsGroup.tab(forIdentifier: ListTab.identifier(for: listVC.list)) { newTab = (tab, Array(nav.viewControllers[1...])) nav.viewControllers = [ nav.viewControllers[0], // leave the ExploreVC in place @@ -218,16 +218,12 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController { private func reloadLists(_ lists: [List]) { listsGroup.children = lists.map { list in - UITab(title: list.title, image: UIImage(systemName: "list.bullet"), identifier: Self.listTabIdentifier(list)) { [unowned self] _ in + ListTab(list: list) { [unowned self] _ in return ListTimelineViewController(for: list, mastodonController: self.mastodonController) } } } - private static func listTabIdentifier(_ list: List) -> String { - "list:\(list.id)" - } - @objc func handleComposeKeyCommand() { compose(editing: nil) } @@ -240,7 +236,7 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController { let service = CreateListService(mastodonController: mastodonController, present: { self.present($0, animated: true) }) { list in - let tab = self.listsGroup.tab(forIdentifier: Self.listTabIdentifier(list))! + let tab = self.listsGroup.tab(forIdentifier: ListTab.identifier(for: list))! let listVC = tab.viewController as! ListTimelineViewController listVC.presentEditOnAppear = true self.selectedTab = tab @@ -419,6 +415,69 @@ extension NewMainTabBarViewController: UITabBarController.Sidebar.Delegate { } return item } + + func tabBarController(_ tabBarController: UITabBarController, sidebar: UITabBarController.Sidebar, contextMenuConfigurationFor tab: UITab) -> UIContextMenuConfiguration? { + guard let id = mastodonController.accountInfo?.id else { + return nil + } + + let activity: NSUserActivity + + if let listTab = tab as? ListTab { + let timelineActivity = UserActivityManager.showTimelineActivity(timeline: .list(id: listTab.list.id), accountID: id) + if let timelineActivity { + activity = timelineActivity + } else { + return nil + } + } else if let tabID = Tab(rawValue: tab.identifier) { + switch tabID { + case .home: + return nil + case .notifications: + activity = UserActivityManager.checkNotificationsActivity(mode: Preferences.shared.defaultNotificationsMode, accountID: id) + case .explore: + activity = UserActivityManager.searchActivity(query: nil, accountID: id) + case .bookmarks: + activity = UserActivityManager.bookmarksActivity(accountID: id) + case .favorites: + // TODO + return nil + case .myProfile: + // no 'Open in New Window' activity for my profile, because the context menu clashes with the fast account switcher + return nil + case .compose: + activity = UserActivityManager.newPostActivity(accountID: id) + case .lists: + return nil + } + } else { + return nil + } + + activity.displaysAuxiliaryScene = true + + return UIContextMenuConfiguration(actionProvider: { _ in + var actions: [UIAction] = [ + UIWindowScene.ActivationAction({ action in + return UIWindowScene.ActivationConfiguration(userActivity: activity) + }) + ] + + if let listTab = tab as? ListTab { + actions.append(UIAction(title: "Delete List", image: UIImage(systemName: "trash"), attributes: .destructive, handler: { [unowned self] _ in + Task { + let service = DeleteListService(list: listTab.list, mastodonController: self.mastodonController) { + self.present($0, animated: true) + } + await service.run() + } + })) + } + + return UIMenu(children: actions) + }) + } } @available(iOS 18.0, *) @@ -597,5 +656,18 @@ private class MyProfileTab: UITab { } } } - +} + +@available(iOS 18.0, *) +private class ListTab: UITab { + let list: List + + init(list: List, viewControllerProvider: @escaping (UITab) -> UIViewController) { + self.list = list + super.init(title: list.title, image: UIImage(systemName: "list.bullet"), identifier: Self.identifier(for: list), viewControllerProvider: viewControllerProvider) + } + + static func identifier(for list: List) -> String { + "list:\(list.id)" + } }