Merge pull request #449 from mastodon/feature-following-indicator

Add follows you indicator. resolve #397
This commit is contained in:
CMK 2022-06-09 18:10:18 +08:00 committed by GitHub
commit 08d55dd419
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 10 deletions

View File

@ -24,17 +24,17 @@
<key>Mastodon - RTL.xcscheme_^#shared#^_</key> <key>Mastodon - RTL.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>11</integer> <integer>12</integer>
</dict> </dict>
<key>Mastodon - Release.xcscheme_^#shared#^_</key> <key>Mastodon - Release.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>4</integer> <integer>5</integer>
</dict> </dict>
<key>Mastodon - Snapshot.xcscheme_^#shared#^_</key> <key>Mastodon - Snapshot.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>6</integer> <integer>7</integer>
</dict> </dict>
<key>Mastodon - ar.xcscheme</key> <key>Mastodon - ar.xcscheme</key>
<dict> <dict>
@ -114,7 +114,7 @@
<key>MastodonIntent.xcscheme_^#shared#^_</key> <key>MastodonIntent.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>30</integer> <integer>23</integer>
</dict> </dict>
<key>MastodonIntents.xcscheme_^#shared#^_</key> <key>MastodonIntents.xcscheme_^#shared#^_</key>
<dict> <dict>
@ -129,12 +129,12 @@
<key>NotificationService.xcscheme_^#shared#^_</key> <key>NotificationService.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>29</integer> <integer>24</integer>
</dict> </dict>
<key>ShareActionExtension.xcscheme_^#shared#^_</key> <key>ShareActionExtension.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>31</integer> <integer>22</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>

View File

@ -88,6 +88,13 @@ extension ProfileHeaderView.ViewModel {
) )
} }
.store(in: &disposeBag) .store(in: &disposeBag)
// follows you
$relationshipActionOptionSet
.map { $0.contains(.followingBy) && !$0.contains(.isMyself) }
.sink { isFollowingBy in
view.followsYouBlurEffectView.isHidden = !isFollowingBy
}
.store(in: &disposeBag)
// avatar // avatar
Publishers.CombineLatest4( Publishers.CombineLatest4(
$avatarImageURL, $avatarImageURL,
@ -102,7 +109,7 @@ extension ProfileHeaderView.ViewModel {
)) ))
} }
.store(in: &disposeBag) .store(in: &disposeBag)
// blur // blur for blocking & blockingBy
$relationshipActionOptionSet $relationshipActionOptionSet
.map { $0.contains(.blocking) || $0.contains(.blockingBy) } .map { $0.contains(.blocking) || $0.contains(.blockingBy) }
.sink { needsImageOverlayBlurred in .sink { needsImageOverlayBlurred in

View File

@ -72,6 +72,16 @@ final class ProfileHeaderView: UIView {
var bannerImageViewTopLayoutConstraint: NSLayoutConstraint! var bannerImageViewTopLayoutConstraint: NSLayoutConstraint!
var bannerImageViewBottomLayoutConstraint: NSLayoutConstraint! var bannerImageViewBottomLayoutConstraint: NSLayoutConstraint!
let followsYouBlurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
let followsYouVibrantEffectView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: UIBlurEffect(style: .regular), style: .label))
let followsYouLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 15, weight: .regular)
label.text = "Follows You" // TODO: i18n
return label
}()
let followsYouMaskView = UIView()
let avatarImageViewBackgroundView: UIView = { let avatarImageViewBackgroundView: UIView = {
let view = UIView() let view = UIView()
view.layer.masksToBounds = true view.layer.masksToBounds = true
@ -174,9 +184,6 @@ final class ProfileHeaderView: UIView {
return button return button
}() }()
// let bioContainerView = UIView()
// let fieldContainerStackView = UIStackView()
let bioMetaText: MetaText = { let bioMetaText: MetaText = {
let metaText = MetaText() let metaText = MetaText()
metaText.textView.backgroundColor = .clear metaText.textView.backgroundColor = .clear
@ -263,6 +270,40 @@ extension ProfileHeaderView {
bannerImageViewOverlayVisualEffectView.bottomAnchor.constraint(equalTo: bannerImageView.bottomAnchor), bannerImageViewOverlayVisualEffectView.bottomAnchor.constraint(equalTo: bannerImageView.bottomAnchor),
]) ])
// follows you
followsYouBlurEffectView.translatesAutoresizingMaskIntoConstraints = false
addSubview(followsYouBlurEffectView)
NSLayoutConstraint.activate([
layoutMarginsGuide.trailingAnchor.constraint(equalTo: followsYouBlurEffectView.trailingAnchor),
bannerContainerView.bottomAnchor.constraint(equalTo: followsYouBlurEffectView.bottomAnchor, constant: 16),
])
followsYouBlurEffectView.layer.masksToBounds = true
followsYouBlurEffectView.layer.cornerRadius = 8
followsYouBlurEffectView.layer.cornerCurve = .continuous
followsYouBlurEffectView.isHidden = true
followsYouVibrantEffectView.translatesAutoresizingMaskIntoConstraints = false
followsYouBlurEffectView.contentView.addSubview(followsYouVibrantEffectView)
NSLayoutConstraint.activate([
followsYouVibrantEffectView.topAnchor.constraint(equalTo: followsYouBlurEffectView.topAnchor),
followsYouVibrantEffectView.leadingAnchor.constraint(equalTo: followsYouBlurEffectView.leadingAnchor),
followsYouVibrantEffectView.trailingAnchor.constraint(equalTo: followsYouBlurEffectView.trailingAnchor),
followsYouVibrantEffectView.bottomAnchor.constraint(equalTo: followsYouBlurEffectView.bottomAnchor),
])
followsYouLabel.translatesAutoresizingMaskIntoConstraints = false
followsYouVibrantEffectView.contentView.addSubview(followsYouLabel)
NSLayoutConstraint.activate([
followsYouLabel.topAnchor.constraint(equalTo: followsYouVibrantEffectView.topAnchor, constant: 4),
followsYouLabel.leadingAnchor.constraint(equalTo: followsYouVibrantEffectView.leadingAnchor, constant: 6),
followsYouVibrantEffectView.trailingAnchor.constraint(equalTo: followsYouLabel.trailingAnchor, constant: 6),
followsYouVibrantEffectView.bottomAnchor.constraint(equalTo: followsYouLabel.bottomAnchor, constant: 4),
])
followsYouMaskView.frame = CGRect(x: 0, y: 0, width: 1000, height: 1000)
followsYouMaskView.backgroundColor = .red
followsYouBlurEffectView.mask = followsYouMaskView
// avatar // avatar
avatarImageViewBackgroundView.translatesAutoresizingMaskIntoConstraints = false avatarImageViewBackgroundView.translatesAutoresizingMaskIntoConstraints = false
addSubview(avatarImageViewBackgroundView) addSubview(avatarImageViewBackgroundView)
@ -406,6 +447,7 @@ extension ProfileHeaderView {
container.addArrangedSubview(bioMetaText.textView) container.addArrangedSubview(bioMetaText.textView)
bringSubviewToFront(bannerContainerView) bringSubviewToFront(bannerContainerView)
bringSubviewToFront(followsYouBlurEffectView)
bringSubviewToFront(avatarImageViewBackgroundView) bringSubviewToFront(avatarImageViewBackgroundView)
statusDashboardView.delegate = self statusDashboardView.delegate = self

View File

@ -584,6 +584,22 @@ extension ProfileViewController: TabBarPagerDelegate {
progress = 0 progress = 0
} }
// setup follows you mask
// 1. set mask size
profileHeaderViewController.profileHeaderView.followsYouMaskView.frame = profileHeaderViewController.profileHeaderView.followsYouBlurEffectView.bounds
// 2. check follows you view overflow navigation bar or not
let followsYouBlurEffectViewInWindow = profileHeaderViewController.profileHeaderView.convert(
profileHeaderViewController.profileHeaderView.followsYouBlurEffectView.frame,
to: nil
)
if followsYouBlurEffectViewInWindow.minY < tabBarPagerController.containerScrollView.safeAreaInsets.top {
let offestY = tabBarPagerController.containerScrollView.safeAreaInsets.top - followsYouBlurEffectViewInWindow.minY
let height = profileHeaderViewController.profileHeaderView.followsYouMaskView.frame.height
profileHeaderViewController.profileHeaderView.followsYouMaskView.frame.origin.y = min(offestY, height)
} else {
profileHeaderViewController.profileHeaderView.followsYouMaskView.frame.origin.y = .zero
}
// setup titleView offset and fade avatar // setup titleView offset and fade avatar
profileHeaderViewController.updateHeaderScrollProgress(progress, throttle: throttle) profileHeaderViewController.updateHeaderScrollProgress(progress, throttle: throttle)