Merge pull request #595 from mastodon/more_obvious_account_switcher

Add Account Toggle Indicator to make Account Switch Feature more obvious
This commit is contained in:
Marcus Kida 2022-11-18 10:12:12 +01:00 committed by GitHub
commit 91bb3f3627
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 4 deletions

View File

@ -24,6 +24,7 @@
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 */; };
2AE244482927831100BDBF7C /* UIImage+SFSymbols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE244472927831100BDBF7C /* UIImage+SFSymbols.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 */; };
@ -520,6 +521,7 @@
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>"; };
2AE244472927831100BDBF7C /* UIImage+SFSymbols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+SFSymbols.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>"; };
@ -2244,6 +2246,7 @@
2D3F9E0325DFA133004262D9 /* UITapGestureRecognizer.swift */,
2D84350425FF858100EECE90 /* UIScrollView.swift */,
DB9E0D6E25EE008500CFDD76 /* UIInterpolatingMotionEffect.swift */,
2AE244472927831100BDBF7C /* UIImage+SFSymbols.swift */,
DBCC3B2F261440A50045B23D /* UITabBarController.swift */,
DB73BF4827140BA300781945 /* UICollectionViewDiffableDataSource.swift */,
DB73BF4A27140C0800781945 /* UITableViewDiffableDataSource.swift */,
@ -3273,6 +3276,7 @@
DB73BF4927140BA300781945 /* UICollectionViewDiffableDataSource.swift in Sources */,
DBA5E7AB263BD3F5004598BB /* TimelineTableViewCellContextMenuConfiguration.swift in Sources */,
DB73B490261F030A002E9E9F /* SafariActivity.swift in Sources */,
2AE244482927831100BDBF7C /* UIImage+SFSymbols.swift in Sources */,
DB63F7492799126300455B82 /* FollowerListViewController+DataSourceProvider.swift in Sources */,
2D198643261BF09500F0B013 /* SearchResultItem.swift in Sources */,
2DAC9E38262FC2320062E1A6 /* SuggestionAccountViewController.swift in Sources */,

View File

@ -0,0 +1,12 @@
//
// UIImage+SFSymbols.swift
// Mastodon
//
// Created by Marcus Kida on 18.11.22.
//
import UIKit
extension UIImage {
static let chevronUpChevronDown = UIImage(systemName: "chevron.up.chevron.down")
}

View File

@ -43,6 +43,7 @@ class MainTabBarController: UITabBarController {
static let avatarButtonSize = CGSize(width: 25, height: 25)
let avatarButton = CircleAvatarButton()
let accountSwitcherChevron = UIImageView(image: .chevronUpChevronDown)
@Published var currentTab: Tab = .home
@ -506,13 +507,20 @@ extension MainTabBarController {
}
anchorImageView.alpha = 0
accountSwitcherChevron.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(accountSwitcherChevron)
self.avatarButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(self.avatarButton)
NSLayoutConstraint.activate([
self.avatarButton.centerXAnchor.constraint(equalTo: anchorImageView.centerXAnchor),
self.avatarButton.centerXAnchor.constraint(equalTo: anchorImageView.centerXAnchor, constant: -16),
self.avatarButton.centerYAnchor.constraint(equalTo: anchorImageView.centerYAnchor),
self.avatarButton.widthAnchor.constraint(equalToConstant: MainTabBarController.avatarButtonSize.width).priority(.required - 1),
self.avatarButton.heightAnchor.constraint(equalToConstant: MainTabBarController.avatarButtonSize.height).priority(.required - 1),
accountSwitcherChevron.widthAnchor.constraint(equalToConstant: 10),
accountSwitcherChevron.heightAnchor.constraint(equalToConstant: 18),
accountSwitcherChevron.leadingAnchor.constraint(equalTo: avatarButton.trailingAnchor, constant: 8),
accountSwitcherChevron.centerYAnchor.constraint(equalTo: avatarButton.centerYAnchor)
])
self.avatarButton.setContentHuggingPriority(.required - 1, for: .horizontal)
self.avatarButton.setContentHuggingPriority(.required - 1, for: .vertical)
@ -520,6 +528,7 @@ extension MainTabBarController {
}
private func updateAvatarButtonAppearance() {
accountSwitcherChevron.tintColor = currentTab == .me ? .label : .secondaryLabel
avatarButton.borderColor = currentTab == .me ? .label : .systemFill
avatarButton.setNeedsLayout()
}

View File

@ -16,7 +16,6 @@ import MastodonCore
import MastodonLocalization
final class SidebarViewModel {
var disposeBag = Set<AnyCancellable>()
// input
@ -80,6 +79,7 @@ extension SidebarViewModel {
}()
cell.item = SidebarListContentView.Item(
isActive: false,
accessoryImage: item == .me ? .chevronUpChevronDown : nil,
title: item.title,
image: item.image,
activeImage: item.selectedImage,
@ -166,6 +166,7 @@ extension SidebarViewModel {
case .compose:
let item = SidebarListContentView.Item(
isActive: false,
accessoryImage: self.currentTab == .me ? .chevronUpChevronDown : nil,
title: L10n.Common.Controls.Actions.compose,
image: Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate),
activeImage: Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate),

View File

@ -23,7 +23,8 @@ final class SidebarListContentView: UIView, UIContentView {
button.borderColor = UIColor.label
return button
}()
private let accessoryImageView = UIImageView(image: nil)
private var currentConfiguration: ContentConfiguration!
var configuration: UIContentConfiguration {
get {
@ -60,6 +61,9 @@ extension SidebarListContentView {
imageView.widthAnchor.constraint(equalToConstant: 40).priority(.required - 1),
imageView.heightAnchor.constraint(equalToConstant: 40).priority(.required - 1),
])
accessoryImageView.translatesAutoresizingMaskIntoConstraints = false
addSubview(accessoryImageView)
avatarButton.translatesAutoresizingMaskIntoConstraints = false
addSubview(avatarButton)
@ -68,6 +72,10 @@ extension SidebarListContentView {
avatarButton.centerYAnchor.constraint(equalTo: imageView.centerYAnchor),
avatarButton.widthAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 1.0).priority(.required - 2),
avatarButton.heightAnchor.constraint(equalTo: imageView.heightAnchor, multiplier: 1.0).priority(.required - 2),
accessoryImageView.widthAnchor.constraint(equalToConstant: 12),
accessoryImageView.heightAnchor.constraint(equalToConstant: 22),
accessoryImageView.leadingAnchor.constraint(equalTo: avatarButton.trailingAnchor, constant: 4),
accessoryImageView.centerYAnchor.constraint(equalTo: avatarButton.centerYAnchor)
])
avatarButton.setContentHuggingPriority(.defaultLow - 10, for: .vertical)
avatarButton.setContentHuggingPriority(.defaultLow - 10, for: .horizontal)
@ -96,6 +104,9 @@ extension SidebarListContentView {
imageView.isHidden = item.imageURL != nil
avatarButton.isHidden = item.imageURL == nil
imageView.image = item.isActive ? item.activeImage.withRenderingMode(.alwaysTemplate) : item.image.withRenderingMode(.alwaysTemplate)
accessoryImageView.image = item.accessoryImage
accessoryImageView.isHidden = item.accessoryImage == nil
accessoryImageView.tintColor = item.isActive ? .label : .secondaryLabel
avatarButton.avatarImageView.setImage(
url: item.imageURL,
placeholder: avatarButton.avatarImageView.image ?? .placeholder(color: .systemFill), // reuse to avoid blink
@ -112,7 +123,8 @@ extension SidebarListContentView {
var isSelected: Bool = false
var isHighlighted: Bool = false
var isActive: Bool
var accessoryImage: UIImage? = nil
// model
let title: String
var image: UIImage
@ -124,6 +136,7 @@ extension SidebarListContentView {
return lhs.isSelected == rhs.isSelected
&& lhs.isHighlighted == rhs.isHighlighted
&& lhs.isActive == rhs.isActive
&& lhs.accessoryImage == rhs.accessoryImage
&& lhs.title == rhs.title
&& lhs.image == rhs.image
&& lhs.activeImage == rhs.activeImage
@ -134,6 +147,7 @@ extension SidebarListContentView {
hasher.combine(isSelected)
hasher.combine(isHighlighted)
hasher.combine(isActive)
hasher.combine(accessoryImage)
hasher.combine(title)
hasher.combine(image)
hasher.combine(activeImage)