forked from shadowfacts/Tusker
Fix profile header images being blurry
Due to the old method using ImageCache.avatars for the headers 🤦 Closes #494
This commit is contained in:
parent
908b499f8f
commit
5cf2bc4fbf
|
@ -33,6 +33,11 @@ class CachedImageView: UIImageView {
|
||||||
commonInit()
|
commonInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
fetchTask?.cancel()
|
||||||
|
blurHashTask?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
private func commonInit() {
|
private func commonInit() {
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@ class ProfileHeaderView: UIView {
|
||||||
weak var delegate: ProfileHeaderViewDelegate?
|
weak var delegate: ProfileHeaderViewDelegate?
|
||||||
var mastodonController: MastodonController! { delegate?.apiController }
|
var mastodonController: MastodonController! { delegate?.apiController }
|
||||||
|
|
||||||
@IBOutlet weak var headerImageView: UIImageView!
|
@IBOutlet weak var headerImageView: CachedImageView!
|
||||||
@IBOutlet weak var avatarContainerView: UIView!
|
@IBOutlet weak var avatarContainerView: UIView!
|
||||||
@IBOutlet weak var avatarImageView: UIImageView!
|
@IBOutlet weak var avatarImageView: CachedImageView!
|
||||||
@IBOutlet weak var moreButton: ProfileHeaderButton!
|
@IBOutlet weak var moreButton: ProfileHeaderButton!
|
||||||
@IBOutlet weak var followButton: ProfileHeaderButton!
|
@IBOutlet weak var followButton: ProfileHeaderButton!
|
||||||
@IBOutlet weak var displayNameLabel: AccountDisplayNameLabel!
|
@IBOutlet weak var displayNameLabel: AccountDisplayNameLabel!
|
||||||
|
@ -44,8 +44,6 @@ class ProfileHeaderView: UIView {
|
||||||
|
|
||||||
var accountID: String!
|
var accountID: String!
|
||||||
|
|
||||||
private var imagesTask: Task<Void, Never>?
|
|
||||||
|
|
||||||
private var isGrayscale = false
|
private var isGrayscale = false
|
||||||
private var followButtonMode = FollowButtonMode.follow {
|
private var followButtonMode = FollowButtonMode.follow {
|
||||||
didSet {
|
didSet {
|
||||||
|
@ -56,10 +54,6 @@ class ProfileHeaderView: UIView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
|
||||||
imagesTask?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func awakeFromNib() {
|
override func awakeFromNib() {
|
||||||
super.awakeFromNib()
|
super.awakeFromNib()
|
||||||
|
|
||||||
|
@ -69,11 +63,13 @@ class ProfileHeaderView: UIView {
|
||||||
avatarContainerView.layer.cornerCurve = .continuous
|
avatarContainerView.layer.cornerCurve = .continuous
|
||||||
// Set zPositions so the gallery presentation/dismissal animation looks correct.
|
// Set zPositions so the gallery presentation/dismissal animation looks correct.
|
||||||
avatarContainerView.layer.zPosition = 2
|
avatarContainerView.layer.zPosition = 2
|
||||||
|
avatarImageView.cache = .avatars
|
||||||
avatarImageView.layer.masksToBounds = true
|
avatarImageView.layer.masksToBounds = true
|
||||||
avatarImageView.layer.cornerCurve = .continuous
|
avatarImageView.layer.cornerCurve = .continuous
|
||||||
avatarImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(avatarPressed)))
|
avatarImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(avatarPressed)))
|
||||||
avatarImageView.isUserInteractionEnabled = true
|
avatarImageView.isUserInteractionEnabled = true
|
||||||
|
|
||||||
|
headerImageView.cache = .headers
|
||||||
headerImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(headerPressed)))
|
headerImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(headerPressed)))
|
||||||
headerImageView.isUserInteractionEnabled = true
|
headerImageView.isUserInteractionEnabled = true
|
||||||
headerImageView.layer.zPosition = 1
|
headerImageView.layer.zPosition = 1
|
||||||
|
@ -138,11 +134,11 @@ class ProfileHeaderView: UIView {
|
||||||
usernameLabel.text = "@\(account.acct)"
|
usernameLabel.text = "@\(account.acct)"
|
||||||
lockImageView.isHidden = !account.locked
|
lockImageView.isHidden = !account.locked
|
||||||
|
|
||||||
imagesTask?.cancel()
|
if let avatar = account.avatar {
|
||||||
let avatar = account.avatar
|
avatarImageView.update(for: avatar)
|
||||||
let header = account.header
|
}
|
||||||
imagesTask = Task {
|
if let header = account.header {
|
||||||
await updateImages(avatar: avatar, header: header)
|
headerImageView.update(for: header)
|
||||||
}
|
}
|
||||||
|
|
||||||
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForProfile(accountID: accountID, source: .view(moreButton), fetchRelationship: false) ?? [])
|
moreButton.menu = UIMenu(title: "", image: nil, identifier: nil, options: [], children: delegate?.actionsForProfile(accountID: accountID, source: .view(moreButton), fetchRelationship: false) ?? [])
|
||||||
|
@ -294,44 +290,6 @@ class ProfileHeaderView: UIView {
|
||||||
avatarContainerView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarContainerView)
|
avatarContainerView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarContainerView)
|
||||||
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView)
|
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView)
|
||||||
displayNameLabel.updateForAccountDisplayName(account: account)
|
displayNameLabel.updateForAccountDisplayName(account: account)
|
||||||
|
|
||||||
if isGrayscale != Preferences.shared.grayscaleImages {
|
|
||||||
isGrayscale = Preferences.shared.grayscaleImages
|
|
||||||
imagesTask?.cancel()
|
|
||||||
let avatar = account.avatar
|
|
||||||
let header = account.header
|
|
||||||
imagesTask = Task {
|
|
||||||
await updateImages(avatar: avatar, header: header)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private nonisolated func updateImages(avatar: URL?, header: URL?) async {
|
|
||||||
await withTaskGroup(of: Void.self) { group in
|
|
||||||
group.addTask {
|
|
||||||
guard let avatar,
|
|
||||||
let image = await ImageCache.avatars.get(avatar, loadOriginal: true).1,
|
|
||||||
let transformedImage = await ImageGrayscalifier.convertIfNecessary(url: avatar, image: image),
|
|
||||||
!Task.isCancelled else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await MainActor.run {
|
|
||||||
self.avatarImageView.image = transformedImage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
group.addTask {
|
|
||||||
guard let header,
|
|
||||||
let image = await ImageCache.avatars.get(header, loadOriginal: true).1,
|
|
||||||
let transformedImage = await ImageGrayscalifier.convertIfNecessary(url: header, image: image),
|
|
||||||
!Task.isCancelled else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await MainActor.run {
|
|
||||||
self.headerImageView.image = transformedImage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await group.waitForAll()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func formatBigNumber(_ value: Int) -> (String, String) {
|
private func formatBigNumber(_ value: Int) -> (String, String) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iN0-l3-epB" customClass="ProfileHeaderView" customModule="Tusker" customModuleProvider="target">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iN0-l3-epB" customClass="ProfileHeaderView" customModule="Tusker" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dgG-dR-lSv">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dgG-dR-lSv" customClass="CachedImageView" customModule="Tusker" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="48" width="414" height="150"/>
|
<rect key="frame" x="0.0" y="48" width="414" height="150"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="150" id="aCE-CA-XWm"/>
|
<constraint firstAttribute="height" constant="150" id="aCE-CA-XWm"/>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wT9-2J-uSY">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wT9-2J-uSY">
|
||||||
<rect key="frame" x="16" y="138" width="120" height="120"/>
|
<rect key="frame" x="16" y="138" width="120" height="120"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="TkY-oK-if4">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="TkY-oK-if4" customClass="CachedImageView" customModule="Tusker" customModuleProvider="target">
|
||||||
<rect key="frame" x="2" y="2" width="116" height="116"/>
|
<rect key="frame" x="2" y="2" width="116" height="116"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="116" id="eDg-Vc-o8R"/>
|
<constraint firstAttribute="height" constant="116" id="eDg-Vc-o8R"/>
|
||||||
|
|
Loading…
Reference in New Issue