Add saved instances to new sidebar
This commit is contained in:
parent
0d9eed73dd
commit
1817247077
|
@ -371,7 +371,7 @@ extension MainSidebarViewController {
|
||||||
case let .savedInstance(url):
|
case let .savedInstance(url):
|
||||||
return url.host!
|
return url.host!
|
||||||
case .addSavedInstance:
|
case .addSavedInstance:
|
||||||
return "Find An Instance..."
|
return "Find an Instance..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
private var myProfileTab: UITab!
|
private var myProfileTab: UITab!
|
||||||
private var listsGroup: UITabGroup!
|
private var listsGroup: UITabGroup!
|
||||||
private var hashtagsGroup: UITabGroup!
|
private var hashtagsGroup: UITabGroup!
|
||||||
|
private var instancesGroup: UITabGroup!
|
||||||
|
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
@ -79,6 +80,17 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
]
|
]
|
||||||
reloadHashtags()
|
reloadHashtags()
|
||||||
|
|
||||||
|
instancesGroup = UITabGroup(title: "Instance Timelines", image: nil, identifier: Tab.instances.rawValue, children: []) { _ in
|
||||||
|
return AdaptableNavigationController()
|
||||||
|
}
|
||||||
|
instancesGroup.preferredPlacement = .sidebarOnly
|
||||||
|
instancesGroup.sidebarActions = [
|
||||||
|
UIAction(title: "Find an Instance…", image: UIImage(systemName: "plus"), handler: { [unowned self] _ in
|
||||||
|
self.showAddSavedInstance()
|
||||||
|
})
|
||||||
|
]
|
||||||
|
reloadSavedInstances()
|
||||||
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||||
self.tabs = [
|
self.tabs = [
|
||||||
homeTab,
|
homeTab,
|
||||||
|
@ -105,6 +117,8 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
.merge(with: NotificationCenter.default.publisher(for: .savedHashtagsChanged).map { _ in () })
|
.merge(with: NotificationCenter.default.publisher(for: .savedHashtagsChanged).map { _ in () })
|
||||||
.sink { [unowned self] in self.reloadHashtags() }
|
.sink { [unowned self] in self.reloadHashtags() }
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(reloadSavedInstances), name: .savedInstancesChanged, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
setupFastAccountSwitcher()
|
setupFastAccountSwitcher()
|
||||||
|
@ -118,7 +132,7 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
|
|
||||||
var exploreNavStack: [UIViewController]? = nil
|
var exploreNavStack: [UIViewController]? = nil
|
||||||
if let parent = selectedTab?.parent,
|
if let parent = selectedTab?.parent,
|
||||||
parent === listsGroup || parent === hashtagsGroup {
|
parent === listsGroup || parent === hashtagsGroup || parent === instancesGroup {
|
||||||
let nav = parent.viewController as! any NavigationControllerProtocol
|
let nav = parent.viewController as! any NavigationControllerProtocol
|
||||||
exploreNavStack = nav.viewControllers
|
exploreNavStack = nav.viewControllers
|
||||||
nav.viewControllers = []
|
nav.viewControllers = []
|
||||||
|
@ -180,6 +194,7 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
composeTab,
|
composeTab,
|
||||||
listsGroup,
|
listsGroup,
|
||||||
hashtagsGroup,
|
hashtagsGroup,
|
||||||
|
instancesGroup,
|
||||||
]
|
]
|
||||||
|
|
||||||
if let (tab, navStack) = newTabAndNavigationStack {
|
if let (tab, navStack) = newTabAndNavigationStack {
|
||||||
|
@ -222,7 +237,7 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
root = FavoritesViewController(mastodonController: mastodonController)
|
root = FavoritesViewController(mastodonController: mastodonController)
|
||||||
case .myProfile:
|
case .myProfile:
|
||||||
root = MyProfileViewController(mastodonController: mastodonController)
|
root = MyProfileViewController(mastodonController: mastodonController)
|
||||||
case .lists, .hashtags:
|
case .lists, .hashtags, .instances:
|
||||||
fatalError("unreachable")
|
fatalError("unreachable")
|
||||||
}
|
}
|
||||||
return embedInNavigationController(root)
|
return embedInNavigationController(root)
|
||||||
|
@ -279,6 +294,19 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
hashtagsGroup.children = tabs
|
hashtagsGroup.children = tabs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func reloadSavedInstances() {
|
||||||
|
let viewControllerProvider = { [unowned self] (tab: UITab) in
|
||||||
|
let tab = tab as! InstanceTab
|
||||||
|
return InstanceTimelineViewController(for: tab.instance.url, parentMastodonController: self.mastodonController)
|
||||||
|
}
|
||||||
|
let req = SavedInstance.fetchRequest(account: mastodonController.accountInfo!)
|
||||||
|
req.sortDescriptors = [NSSortDescriptor(key: "url.host", ascending: true)]
|
||||||
|
let instances = (try? mastodonController.persistentContainer.viewContext.fetch(req).uniques(by: \.url)) ?? []
|
||||||
|
instancesGroup.children = instances.map {
|
||||||
|
InstanceTab(instance: $0, viewControllerProvider: viewControllerProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc func handleComposeKeyCommand() {
|
@objc func handleComposeKeyCommand() {
|
||||||
compose(editing: nil)
|
compose(editing: nil)
|
||||||
}
|
}
|
||||||
|
@ -305,6 +333,13 @@ final class NewMainTabBarViewController: BaseMainTabBarViewController {
|
||||||
present(nav, animated: true)
|
present(nav, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func showAddSavedInstance() {
|
||||||
|
let findController = FindInstanceViewController(parentMastodonController: mastodonController)
|
||||||
|
findController.instanceTimelineDelegate = self
|
||||||
|
let nav = EnhancedNavigationViewController(rootViewController: findController)
|
||||||
|
present(nav, animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate func updateViewControllerSafeAreaInsets(_ vc: UIViewController) {
|
fileprivate func updateViewControllerSafeAreaInsets(_ vc: UIViewController) {
|
||||||
guard vc is MultiColumnNavigationController || (vc as? AdaptableNavigationController)?.current is MultiColumnNavigationController else {
|
guard vc is MultiColumnNavigationController || (vc as? AdaptableNavigationController)?.current is MultiColumnNavigationController else {
|
||||||
return
|
return
|
||||||
|
@ -379,6 +414,7 @@ extension NewMainTabBarViewController {
|
||||||
|
|
||||||
case lists
|
case lists
|
||||||
case hashtags
|
case hashtags
|
||||||
|
case instances
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +454,7 @@ extension NewMainTabBarViewController: UITabBarControllerDelegate {
|
||||||
// get the new transition animation.
|
// get the new transition animation.
|
||||||
// This would be much less complicated if the controller just used the individual VCs of items in a group.
|
// This would be much less complicated if the controller just used the individual VCs of items in a group.
|
||||||
if let group = newTab.parent,
|
if let group = newTab.parent,
|
||||||
group === listsGroup || group === hashtagsGroup,
|
group === listsGroup || group === hashtagsGroup || group === instancesGroup,
|
||||||
let nav = group.viewController as? any NavigationControllerProtocol {
|
let nav = group.viewController as? any NavigationControllerProtocol {
|
||||||
updateViewControllerSafeAreaInsets(nav)
|
updateViewControllerSafeAreaInsets(nav)
|
||||||
|
|
||||||
|
@ -499,6 +535,9 @@ extension NewMainTabBarViewController: UITabBarController.Sidebar.Delegate {
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
} else if tab is InstanceTab {
|
||||||
|
// don't currently have a scene type for this
|
||||||
|
return nil
|
||||||
} else if let tabID = Tab(rawValue: tab.identifier) {
|
} else if let tabID = Tab(rawValue: tab.identifier) {
|
||||||
switch tabID {
|
switch tabID {
|
||||||
case .home:
|
case .home:
|
||||||
|
@ -517,7 +556,7 @@ extension NewMainTabBarViewController: UITabBarController.Sidebar.Delegate {
|
||||||
return nil
|
return nil
|
||||||
case .compose:
|
case .compose:
|
||||||
activity = UserActivityManager.newPostActivity(accountID: id)
|
activity = UserActivityManager.newPostActivity(accountID: id)
|
||||||
case .lists, .hashtags:
|
case .lists, .hashtags, .instances:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -638,6 +677,20 @@ extension NewMainTabBarViewController: AccountSwitchableViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 18.0, *)
|
||||||
|
extension NewMainTabBarViewController: InstanceTimelineViewControllerDelegate {
|
||||||
|
func didSaveInstance(url: URL) {
|
||||||
|
dismiss(animated: true) {
|
||||||
|
let tab = self.instancesGroup.tab(forIdentifier: InstanceTab.identifier(for: url))!
|
||||||
|
self.selectedTab = tab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func didUnsaveInstance(url: URL) {
|
||||||
|
dismiss(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private struct MyProfileContentConfiguration: UIContentConfiguration {
|
private struct MyProfileContentConfiguration: UIContentConfiguration {
|
||||||
let wrapped: any UIContentConfiguration
|
let wrapped: any UIContentConfiguration
|
||||||
@Box var view: UIView?
|
@Box var view: UIView?
|
||||||
|
@ -754,3 +807,21 @@ private class HashtagTab: UITab {
|
||||||
"hashtag:\(name)"
|
"hashtag:\(name)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 18.0, *)
|
||||||
|
private class InstanceTab: UITab {
|
||||||
|
let instance: SavedInstance
|
||||||
|
|
||||||
|
init(instance: SavedInstance, viewControllerProvider: @escaping (UITab) -> UIViewController) {
|
||||||
|
self.instance = instance
|
||||||
|
super.init(title: instance.url.host!, image: UIImage(systemName: "globe"), identifier: Self.identifier(for: instance), viewControllerProvider: viewControllerProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func identifier(for instance: SavedInstance) -> String {
|
||||||
|
"instance:\(instance.url.host!)"
|
||||||
|
}
|
||||||
|
|
||||||
|
static func identifier(for instanceURL: URL) -> String {
|
||||||
|
"instance:\(instanceURL.host!)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue