diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index 696b211bc..10d6fb84f 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -90,45 +90,44 @@ final public class SceneCoordinator { // Delay in next run loop -// DispatchQueue.main.async { [weak self] in -// guard let self = self else { return } -// -// // Note: -// // show (push) on phone or pad (compact) -// // showDetail in .secondary in UISplitViewController on pad (expand) -// let from: UIViewController? = { -// if let splitViewController = self.splitViewController { -// if splitViewController.mainTabBarController.topMost?.view.window != nil { -// // compact -// return splitViewController.mainTabBarController.topMost -// } else { -// // expand -// return splitViewController.viewController(for: .supplementary) -// } -// } else { -// return self.tabBarController.topMost -// } -// }() -// -// // show notification related content -// guard let type = Mastodon.Entity.Notification.NotificationType(rawValue: pushNotification.notificationType) else { return } -// let notificationID = String(pushNotification.notificationID) -// -// switch type { -// case .follow: -// let profileViewModel = RemoteProfileViewModel(context: appContext, notificationID: notificationID) -// self.present(scene: .profile(viewModel: profileViewModel), from: from, transition: .show) -// case .followRequest: -// // do nothing -// break -// case .mention, .reblog, .favourite, .poll, .status: -// let threadViewModel = RemoteThreadViewModel(context: appContext, notificationID: notificationID) -// self.present(scene: .thread(viewModel: threadViewModel), from: from, transition: .show) -// case ._other: -// assertionFailure() -// break -// } -// } // end DispatchQueue.main.async + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + // Note: + // show (push) on phone and pad + let from: UIViewController? = { + if let splitViewController = self.splitViewController { + if splitViewController.compactMainTabBarViewController.topMost?.view.window != nil { + // compact + return splitViewController.compactMainTabBarViewController.topMost + } else { + // expand + return splitViewController.contentSplitViewController.mainTabBarController.topMost + } + } else { + return self.tabBarController.topMost + } + }() + + // show notification related content + guard let type = Mastodon.Entity.Notification.NotificationType(rawValue: pushNotification.notificationType) else { return } + let notificationID = String(pushNotification.notificationID) + + switch type { + case .follow: + let profileViewModel = RemoteProfileViewModel(context: appContext, notificationID: notificationID) + self.present(scene: .profile(viewModel: profileViewModel), from: from, transition: .show) + case .followRequest: + // do nothing + break + case .mention, .reblog, .favourite, .poll, .status: + let threadViewModel = RemoteThreadViewModel(context: appContext, notificationID: notificationID) + self.present(scene: .thread(viewModel: threadViewModel), from: from, transition: .show) + case ._other: + assertionFailure() + break + } + } // end DispatchQueue.main.async } .store(in: &disposeBag) } @@ -283,18 +282,6 @@ extension SceneCoordinator { switch transition { case .show: -// if let splitViewController = splitViewController, !splitViewController.isCollapsed, -// let supplementaryViewController = splitViewController.viewController(for: .supplementary) as? UINavigationController, -// (supplementaryViewController === presentingViewController || supplementaryViewController.viewControllers.contains(presentingViewController)) || -// (presentingViewController is UserTimelineViewController && presentingViewController.view.isDescendant(of: supplementaryViewController.view)) -// { -// fallthrough -// } else { -// if secondaryStackHashValues.contains(presentingViewController.hashValue) { -// secondaryStackHashValues.insert(viewController.hashValue) -// } -// presentingViewController.show(viewController, sender: sender) -// } presentingViewController.show(viewController, sender: sender) case .showDetail: secondaryStackHashValues.insert(viewController.hashValue) @@ -362,6 +349,11 @@ extension SceneCoordinator { } func switchToTabBar(tab: MainTabBarController.Tab) { + splitViewController?.contentSplitViewController.currentSupplementaryTab = tab + + splitViewController?.compactMainTabBarViewController.selectedIndex = tab.rawValue + splitViewController?.compactMainTabBarViewController.currentTab.value = tab + tabBarController.selectedIndex = tab.rawValue tabBarController.currentTab.value = tab } diff --git a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift index 716b62307..34716dde5 100644 --- a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift +++ b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift @@ -44,10 +44,11 @@ final class ProfileHeaderViewController: UIViewController { let profileHeaderView = ProfileHeaderView() let pageSegmentedControl: UISegmentedControl = { - let segmenetedControl = UISegmentedControl(items: ["A", "B"]) - segmenetedControl.selectedSegmentIndex = 0 - return segmenetedControl + let segmentedControl = UISegmentedControl(items: ["A", "B"]) + segmentedControl.selectedSegmentIndex = 0 + return segmentedControl }() + var pageSegmentedControlLeadingLayoutConstraint: NSLayoutConstraint! private var isBannerPinned = false private var bottomShadowAlpha: CGFloat = 0.0 @@ -118,9 +119,10 @@ extension ProfileHeaderViewController { pageSegmentedControl.translatesAutoresizingMaskIntoConstraints = false view.addSubview(pageSegmentedControl) + pageSegmentedControlLeadingLayoutConstraint = pageSegmentedControl.leadingAnchor.constraint(equalTo: view.leadingAnchor) NSLayoutConstraint.activate([ pageSegmentedControl.topAnchor.constraint(equalTo: profileHeaderView.bottomAnchor, constant: ProfileHeaderViewController.segmentedControlMarginHeight), - pageSegmentedControl.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), + pageSegmentedControlLeadingLayoutConstraint, // Fix iPad layout issue pageSegmentedControl.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor), view.bottomAnchor.constraint(equalTo: pageSegmentedControl.bottomAnchor, constant: ProfileHeaderViewController.segmentedControlMarginHeight), pageSegmentedControl.heightAnchor.constraint(equalToConstant: ProfileHeaderViewController.segmentedControlHeight).priority(.defaultHigh), @@ -133,10 +135,10 @@ extension ProfileHeaderViewController { viewModel.isTitleViewContentOffsetSet.eraseToAnyPublisher() ) .receive(on: DispatchQueue.main) - .sink { [weak self] viewDidAppear, isTitleViewContentOffsetDidSetted in + .sink { [weak self] viewDidAppear, isTitleViewContentOffsetDidSet in guard let self = self else { return } - self.titleView.titleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSetted ? 1 : 0 - self.titleView.subtitleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSetted ? 1 : 0 + self.titleView.titleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSet ? 1 : 0 + self.titleView.subtitleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSet ? 1 : 0 } .store(in: &disposeBag) @@ -283,6 +285,13 @@ extension ProfileHeaderViewController { setupBottomShadow() } + override func viewLayoutMarginsDidChange() { + super.viewLayoutMarginsDidChange() + + let margin = view.frame.maxX - view.readableContentGuide.layoutFrame.maxX + pageSegmentedControlLeadingLayoutConstraint.constant = margin + } + } extension ProfileHeaderViewController { diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 434836ab4..b864fc94c 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -517,6 +517,7 @@ extension ProfileViewController { .assign(to: \.value, on: profileHeaderViewController.viewModel.displayProfileInfo.note) .store(in: &disposeBag) viewModel.statusesCount + .receive(on: DispatchQueue.main) .sink { [weak self] count in guard let self = self else { return } let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-" @@ -526,6 +527,7 @@ extension ProfileViewController { } .store(in: &disposeBag) viewModel.followingCount + .receive(on: DispatchQueue.main) .sink { [weak self] count in guard let self = self else { return } let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-" @@ -535,6 +537,7 @@ extension ProfileViewController { } .store(in: &disposeBag) viewModel.followersCount + .receive(on: DispatchQueue.main) .sink { [weak self] count in guard let self = self else { return } let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-"