Fix tabbar avatar not visible (IOS-176)

This commit is contained in:
Marcus Kida 2023-11-27 14:19:17 +01:00
parent cc3f1d030f
commit 831665141c
No known key found for this signature in database
GPG Key ID: 19FF64E08013CA40
1 changed files with 117 additions and 115 deletions

View File

@ -190,131 +190,133 @@ extension MainTabBarController {
_viewControllers = viewControllers _viewControllers = viewControllers
setViewControllers(viewControllers, animated: false) setViewControllers(viewControllers, animated: false)
selectedIndex = 0 selectedIndex = 0
}
// hacky workaround for FB11986255 (Setting accessibilityUserInputLabels on a UITabBarItem has no effect)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(50)) {
if let searchItem = self.tabBar.subviews.first(where: { $0.accessibilityLabel == Tab.search.title }) {
searchItem.accessibilityUserInputLabels = Tab.search.inputLabels
}
}
context.apiService.error // hacky workaround for FB11986255 (Setting accessibilityUserInputLabels on a UITabBarItem has no effect)
.receive(on: DispatchQueue.main) DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(50)) {
.sink { [weak self] error in if let searchItem = self.tabBar.subviews.first(where: { $0.accessibilityLabel == Tab.search.title }) {
guard let self = self, let coordinator = self.coordinator else { return } searchItem.accessibilityUserInputLabels = Tab.search.inputLabels
switch error {
case .implicit:
break
case .explicit:
let alertController = UIAlertController(for: error, title: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(okAction)
_ = coordinator.present(
scene: .alertController(alertController: alertController),
from: nil,
transition: .alertController(animated: true, completion: nil)
)
} }
} }
.store(in: &disposeBag)
// handle post failure context.apiService.error
.receive(on: DispatchQueue.main)
.sink { [weak self] error in
guard let self = self, let coordinator = self.coordinator else { return }
switch error {
case .implicit:
break
case .explicit:
let alertController = UIAlertController(for: error, title: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(okAction)
_ = coordinator.present(
scene: .alertController(alertController: alertController),
from: nil,
transition: .alertController(animated: true, completion: nil)
)
}
}
.store(in: &disposeBag)
// handle push notification. // handle post failure
// toggle entry when finish fetch latest notification
Publishers.CombineLatest(
context.notificationService.unreadNotificationCountDidUpdate,
$currentTab
)
.receive(on: DispatchQueue.main)
.sink { [weak self] authentication, currentTab in
guard let self = self else { return }
guard let notificationViewController = self.notificationViewController else { return }
let authentication = self.authContext?.mastodonAuthenticationBox.userAuthorization // handle push notification.
let hasUnreadPushNotification: Bool = authentication.flatMap { authentication in // toggle entry when finish fetch latest notification
let count = UserDefaults.shared.getNotificationCountWithAccessToken(accessToken: authentication.accessToken) Publishers.CombineLatest(
return count > 0 context.notificationService.unreadNotificationCountDidUpdate,
} ?? false $currentTab
)
let image: UIImage
if hasUnreadPushNotification {
let imageConfiguration = UIImage.SymbolConfiguration(paletteColors: [.red, SystemTheme.tabBarItemNormalIconColor])
image = UIImage(systemName: "bell.badge", withConfiguration: imageConfiguration)!
} else {
image = Tab.notifications.image
}
notificationViewController.tabBarItem.image = image.imageWithoutBaseline()
notificationViewController.navigationController?.tabBarItem.image = image.imageWithoutBaseline()
}
.store(in: &disposeBag)
layoutAvatarButton()
$avatarURL
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] avatarURL in .sink { [weak self] authentication, currentTab in
guard let self = self else { return } guard let self = self else { return }
self.avatarButton.avatarImageView.setImage( guard let notificationViewController = self.notificationViewController else { return }
url: avatarURL,
placeholder: .placeholder(color: .systemFill),
scaleToSize: MainTabBarController.avatarButtonSize
)
}
.store(in: &disposeBag)
NotificationCenter.default.publisher(for: .userFetched) let authentication = self.authContext?.mastodonAuthenticationBox.userAuthorization
.receive(on: DispatchQueue.main) let hasUnreadPushNotification: Bool = authentication.flatMap { authentication in
.sink { [weak self] _ in let count = UserDefaults.shared.getNotificationCountWithAccessToken(accessToken: authentication.accessToken)
guard let self = self else { return } return count > 0
if let user = self.authContext?.mastodonAuthenticationBox.authentication.user(in: self.context.managedObjectContext) { } ?? false
self.avatarURLObserver = user.publisher(for: \.avatar)
.sink { [weak self, weak user] _ in
guard let self = self else { return }
guard let user = user else { return }
guard user.managedObjectContext != nil else { return }
self.avatarURL = user.avatarImageURL()
}
// a11y let image: UIImage
let _profileTabItem = self.tabBar.items?.first { item in item.tag == Tab.me.tag } if hasUnreadPushNotification {
guard let profileTabItem = _profileTabItem else { return } let imageConfiguration = UIImage.SymbolConfiguration(paletteColors: [.red, SystemTheme.tabBarItemNormalIconColor])
profileTabItem.accessibilityHint = L10n.Scene.AccountList.tabBarHint(user.displayNameWithFallback) image = UIImage(systemName: "bell.badge", withConfiguration: imageConfiguration)!
self.context.authenticationService.updateActiveUserAccountPublisher
.sink { [weak self] in
self?.updateUserAccount()
}
.store(in: &self.disposeBag)
} else { } else {
self.avatarURLObserver = nil image = Tab.notifications.image
} }
notificationViewController.tabBarItem.image = image.imageWithoutBaseline()
notificationViewController.navigationController?.tabBarItem.image = image.imageWithoutBaseline()
} }
.store(in: &disposeBag) .store(in: &disposeBag)
layoutAvatarButton()
let tabBarLongPressGestureRecognizer = UILongPressGestureRecognizer() $avatarURL
tabBarLongPressGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.tabBarLongPressGestureRecognizerHandler(_:))) .receive(on: DispatchQueue.main)
tabBarLongPressGestureRecognizer.delegate = self .sink { [weak self] avatarURL in
tabBar.addGestureRecognizer(tabBarLongPressGestureRecognizer) guard let self = self else { return }
self.avatarButton.avatarImageView.setImage(
url: avatarURL,
placeholder: .placeholder(color: .systemFill),
scaleToSize: MainTabBarController.avatarButtonSize
)
// self.avatarButton.avatarImageView.image = UIImage(named: "AppIcon")
}
.store(in: &disposeBag)
let tabBarDoubleTapGestureRecognizer = UITapGestureRecognizer() NotificationCenter.default.publisher(for: .userFetched)
tabBarDoubleTapGestureRecognizer.numberOfTapsRequired = 2 .receive(on: DispatchQueue.main)
tabBarDoubleTapGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.tabBarDoubleTapGestureRecognizerHandler(_:))) .sink { [weak self] _ in
tabBarDoubleTapGestureRecognizer.delaysTouchesEnded = false guard let self = self else { return }
tabBar.addGestureRecognizer(tabBarDoubleTapGestureRecognizer) if let user = self.authContext?.mastodonAuthenticationBox.authentication.user(in: self.context.managedObjectContext) {
self.avatarURLObserver = user.publisher(for: \.avatar)
.sink { [weak self, weak user] _ in
guard let self = self else { return }
guard let user = user else { return }
guard user.managedObjectContext != nil else { return }
self.avatarURL = user.avatarImageURL()
}
self.isReadyForWizardAvatarButton = authContext != nil // a11y
let _profileTabItem = self.tabBar.items?.first { item in item.tag == Tab.me.tag }
guard let profileTabItem = _profileTabItem else { return }
profileTabItem.accessibilityHint = L10n.Scene.AccountList.tabBarHint(user.displayNameWithFallback)
$currentTab self.context.authenticationService.updateActiveUserAccountPublisher
.receive(on: DispatchQueue.main) .sink { [weak self] in
.sink { [weak self] tab in self?.updateUserAccount()
guard let self = self else { return } }
self.updateAvatarButtonAppearance() .store(in: &self.disposeBag)
} } else {
.store(in: &disposeBag) self.avatarURLObserver = nil
}
}
.store(in: &disposeBag)
updateTabBarDisplay() let tabBarLongPressGestureRecognizer = UILongPressGestureRecognizer()
tabBarLongPressGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.tabBarLongPressGestureRecognizerHandler(_:)))
tabBarLongPressGestureRecognizer.delegate = self
tabBar.addGestureRecognizer(tabBarLongPressGestureRecognizer)
let tabBarDoubleTapGestureRecognizer = UITapGestureRecognizer()
tabBarDoubleTapGestureRecognizer.numberOfTapsRequired = 2
tabBarDoubleTapGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.tabBarDoubleTapGestureRecognizerHandler(_:)))
tabBarDoubleTapGestureRecognizer.delaysTouchesEnded = false
tabBar.addGestureRecognizer(tabBarDoubleTapGestureRecognizer)
self.isReadyForWizardAvatarButton = authContext != nil
$currentTab
.receive(on: DispatchQueue.main)
.sink { [weak self] tab in
guard let self = self else { return }
self.updateAvatarButtonAppearance()
}
.store(in: &disposeBag)
updateTabBarDisplay()
}
} }
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {