feat: Implement double-tap account switching on iPad
This commit is contained in:
parent
cf28286d89
commit
60d9d3537d
|
@ -23,6 +23,7 @@
|
|||
0FB3D33825E6401400AAD544 /* PickServerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D33725E6401400AAD544 /* PickServerCell.swift */; };
|
||||
164F0EBC267D4FE400249499 /* BoopSound.caf in Resources */ = {isa = PBXBuildFile; fileRef = 164F0EBB267D4FE400249499 /* BoopSound.caf */; };
|
||||
18BC7629F65E6DB12CB8416D /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */; };
|
||||
2A82294F29262EE000D2A1F7 /* AppContext+NextAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A82294E29262EE000D2A1F7 /* AppContext+NextAccount.swift */; };
|
||||
2D198643261BF09500F0B013 /* SearchResultItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198642261BF09500F0B013 /* SearchResultItem.swift */; };
|
||||
2D198649261C0B8500F0B013 /* SearchResultSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198648261C0B8500F0B013 /* SearchResultSection.swift */; };
|
||||
2D206B8625F5FB0900143C56 /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D206B8525F5FB0900143C56 /* Double.swift */; };
|
||||
|
@ -518,6 +519,7 @@
|
|||
0FB3D33725E6401400AAD544 /* PickServerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerCell.swift; sourceTree = "<group>"; };
|
||||
164F0EBB267D4FE400249499 /* BoopSound.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = BoopSound.caf; sourceTree = "<group>"; };
|
||||
1D6D967E77A5357E2C6110D9 /* Pods-Mastodon.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk - debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk - debug.xcconfig"; sourceTree = "<group>"; };
|
||||
2A82294E29262EE000D2A1F7 /* AppContext+NextAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppContext+NextAccount.swift"; sourceTree = "<group>"; };
|
||||
2D198642261BF09500F0B013 /* SearchResultItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultItem.swift; sourceTree = "<group>"; };
|
||||
2D198648261C0B8500F0B013 /* SearchResultSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultSection.swift; sourceTree = "<group>"; };
|
||||
2D206B8525F5FB0900143C56 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = "<group>"; };
|
||||
|
@ -2222,6 +2224,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
2DF123A625C3B0210020F248 /* ActiveLabel.swift */,
|
||||
2A82294E29262EE000D2A1F7 /* AppContext+NextAccount.swift */,
|
||||
5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */,
|
||||
2D206B8525F5FB0900143C56 /* Double.swift */,
|
||||
DBB3BA2926A81C020004F2D4 /* FLAnimatedImageView.swift */,
|
||||
|
@ -3465,6 +3468,7 @@
|
|||
DBFEEC99279BDCDE004F81DD /* ProfileAboutViewModel.swift in Sources */,
|
||||
2D198649261C0B8500F0B013 /* SearchResultSection.swift in Sources */,
|
||||
DB4F097B26A039FF00D62E92 /* SearchHistorySection.swift in Sources */,
|
||||
2A82294F29262EE000D2A1F7 /* AppContext+NextAccount.swift in Sources */,
|
||||
DBB525302611EBF3002F1F29 /* ProfilePagingViewModel.swift in Sources */,
|
||||
DB9F58EC26EF435000E7BBE9 /* AccountViewController.swift in Sources */,
|
||||
2D5A3D6225CFD9CB002347D6 /* HomeTimelineViewController+DebugAction.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// AppContext+NextAccount.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by Marcus Kida on 17.11.22.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import CoreDataStack
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
extension AppContext {
|
||||
func nextAccount(in authContext: AuthContext) -> MastodonAuthentication? {
|
||||
let request = MastodonAuthentication.sortedFetchRequest
|
||||
guard
|
||||
let accounts = try? managedObjectContext.fetch(request),
|
||||
accounts.count > 1
|
||||
else { return nil }
|
||||
|
||||
let nextSelectedAccountIndex: Int? = {
|
||||
for (index, account) in accounts.enumerated() {
|
||||
guard account == authContext.mastodonAuthenticationBox
|
||||
.authenticationRecord
|
||||
.object(in: managedObjectContext)
|
||||
else { continue }
|
||||
|
||||
let nextAccountIndex = index + 1
|
||||
|
||||
if accounts.count > nextAccountIndex {
|
||||
return nextAccountIndex
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
guard
|
||||
let nextSelectedAccountIndex = nextSelectedAccountIndex,
|
||||
accounts.count > nextSelectedAccountIndex
|
||||
else { return nil }
|
||||
|
||||
return accounts[nextSelectedAccountIndex]
|
||||
}
|
||||
}
|
|
@ -124,4 +124,17 @@ extension ContentSplitViewController: SidebarViewControllerDelegate {
|
|||
accountListViewController.preferredContentSize = CGSize(width: 375, height: 400)
|
||||
}
|
||||
|
||||
func sidebarViewController(_ sidebarViewController: SidebarViewController, didDoubleTapItem item: SidebarViewModel.Item, sourceView: UIView) {
|
||||
guard case let .tab(tab) = item, tab == .me else { return }
|
||||
guard let authContext = authContext else { return }
|
||||
assert(Thread.isMainThread)
|
||||
|
||||
guard let nextAccount = context.nextAccount(in: authContext) else { return }
|
||||
|
||||
Task { @MainActor in
|
||||
let isActive = try await context.authenticationService.activeMastodonUser(domain: nextAccount.domain, userID: nextAccount.userID)
|
||||
guard isActive else { return }
|
||||
self.coordinator.setup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -406,30 +406,7 @@ extension MainTabBarController {
|
|||
guard let authContext = authContext else { return }
|
||||
assert(Thread.isMainThread)
|
||||
|
||||
let request = MastodonAuthentication.sortedFetchRequest
|
||||
guard let accounts = try? context.managedObjectContext.fetch(request), accounts.count > 1 else { return }
|
||||
|
||||
let nextSelectedAccountIndex: Int? = {
|
||||
for (index, account) in accounts.enumerated() {
|
||||
guard account == authContext.mastodonAuthenticationBox
|
||||
.authenticationRecord
|
||||
.object(in: context.managedObjectContext)
|
||||
else { continue }
|
||||
|
||||
let nextAccountIndex = index + 1
|
||||
|
||||
if accounts.count > nextAccountIndex {
|
||||
return nextAccountIndex
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
guard let nextSelectedAccountIndex = nextSelectedAccountIndex, accounts.count > nextSelectedAccountIndex else { return }
|
||||
let nextAccount = accounts[nextSelectedAccountIndex]
|
||||
guard let nextAccount = context.nextAccount(in: authContext) else { return }
|
||||
|
||||
Task { @MainActor in
|
||||
let isActive = try await context.authenticationService.activeMastodonUser(domain: nextAccount.domain, userID: nextAccount.userID)
|
||||
|
|
|
@ -15,6 +15,7 @@ import MastodonUI
|
|||
protocol SidebarViewControllerDelegate: AnyObject {
|
||||
func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab)
|
||||
func sidebarViewController(_ sidebarViewController: SidebarViewController, didLongPressItem item: SidebarViewModel.Item, sourceView: UIView)
|
||||
func sidebarViewController(_ sidebarViewController: SidebarViewController, didDoubleTapItem item: SidebarViewModel.Item, sourceView: UIView)
|
||||
}
|
||||
|
||||
final class SidebarViewController: UIViewController, NeedsDependency {
|
||||
|
@ -143,6 +144,14 @@ extension SidebarViewController {
|
|||
let sidebarLongPressGestureRecognizer = UILongPressGestureRecognizer()
|
||||
sidebarLongPressGestureRecognizer.addTarget(self, action: #selector(SidebarViewController.sidebarLongPressGestureRecognizerHandler(_:)))
|
||||
collectionView.addGestureRecognizer(sidebarLongPressGestureRecognizer)
|
||||
|
||||
let sidebarDoubleTapGestureRecognizer = UITapGestureRecognizer()
|
||||
sidebarDoubleTapGestureRecognizer.numberOfTapsRequired = 2
|
||||
sidebarDoubleTapGestureRecognizer.addTarget(self, action: #selector(SidebarViewController.sidebarDoubleTapGestureRecognizerHandler(_:)))
|
||||
sidebarDoubleTapGestureRecognizer.delaysTouchesBegan = true
|
||||
sidebarDoubleTapGestureRecognizer.cancelsTouchesInView = true
|
||||
collectionView.addGestureRecognizer(sidebarDoubleTapGestureRecognizer)
|
||||
|
||||
}
|
||||
|
||||
private func setupBackground(theme: Theme) {
|
||||
|
@ -177,6 +186,20 @@ extension SidebarViewController {
|
|||
delegate?.sidebarViewController(self, didLongPressItem: item, sourceView: cell)
|
||||
}
|
||||
|
||||
@objc private func sidebarDoubleTapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) {
|
||||
guard sender.state == .ended else { return }
|
||||
|
||||
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
|
||||
assert(sender.view === collectionView)
|
||||
|
||||
let position = sender.location(in: collectionView)
|
||||
guard let indexPath = collectionView.indexPathForItem(at: position) else { return }
|
||||
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
|
||||
delegate?.sidebarViewController(self, didDoubleTapItem: item, sourceView: cell)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDelegate
|
||||
|
|
Loading…
Reference in New Issue