diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 29c7f55f..8ced2977 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -235,6 +235,7 @@ D6B81F3C2560365300F6E31D /* RefreshableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B81F3B2560365300F6E31D /* RefreshableViewController.swift */; }; D6B81F442560390300F6E31D /* MenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B81F432560390300F6E31D /* MenuController.swift */; }; D6B8DB342182A59300424AF7 /* UIAlertController+Visibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */; }; + D6B93667281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B93666281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift */; }; D6BC8748219738E1006163F1 /* EnhancedTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC8747219738E1006163F1 /* EnhancedTableViewController.swift */; }; D6BC9DB1232C61BC002CA326 /* NotificationsPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9DB0232C61BC002CA326 /* NotificationsPageViewController.swift */; }; D6BC9DB3232D4C07002CA326 /* WellnessPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9DB2232D4C07002CA326 /* WellnessPrefsView.swift */; }; @@ -575,6 +576,7 @@ D6B81F3B2560365300F6E31D /* RefreshableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshableViewController.swift; sourceTree = ""; }; D6B81F432560390300F6E31D /* MenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuController.swift; sourceTree = ""; }; D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Visibility.swift"; sourceTree = ""; }; + D6B93666281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainSidebarMyProfileCollectionViewCell.swift; sourceTree = ""; }; D6BC8747219738E1006163F1 /* EnhancedTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnhancedTableViewController.swift; sourceTree = ""; }; D6BC9DB0232C61BC002CA326 /* NotificationsPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsPageViewController.swift; sourceTree = ""; }; D6BC9DB2232D4C07002CA326 /* WellnessPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WellnessPrefsView.swift; sourceTree = ""; }; @@ -893,6 +895,7 @@ D6F0B12A24A3071C001E48C3 /* MainSplitViewController.swift */, 04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */, D6F0B17424A3A1AA001E48C3 /* MainSidebarViewController.swift */, + D6B93666281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift */, D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */, ); path = Main; @@ -1855,6 +1858,7 @@ D64AAE9526C88C5000FC57FB /* ToastableViewController.swift in Sources */, D6420AEE26BED18B00ED8175 /* PublicTimelineDescriptionTableViewCell.swift in Sources */, D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */, + D6B93667281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift in Sources */, D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */, D69693F42585941A00F4E116 /* UIWindowSceneDelegate+Close.swift in Sources */, D6C143DA253510F4007DC240 /* ComposeEmojiTextField.swift in Sources */, diff --git a/Tusker/Screens/Main/MainSidebarMyProfileCollectionViewCell.swift b/Tusker/Screens/Main/MainSidebarMyProfileCollectionViewCell.swift new file mode 100644 index 00000000..da49a34c --- /dev/null +++ b/Tusker/Screens/Main/MainSidebarMyProfileCollectionViewCell.swift @@ -0,0 +1,78 @@ +// +// MainSidebarMyProfileCollectionViewCell.swift +// Tusker +// +// Created by Shadowfacts on 4/30/22. +// Copyright © 2022 Shadowfacts. All rights reserved. +// + +import UIKit + +class MainSidebarMyProfileCollectionViewCell: UICollectionViewListCell { + + private var verticalImageInset: CGFloat { + if UIDevice.current.userInterfaceIdiom == .mac { + return (28 - avatarImageSize) / 2 + } else { + return (44 - avatarImageSize) / 2 + } + } + private var avatarImageSize: CGFloat { + if UIDevice.current.userInterfaceIdiom == .mac { + return 20 + } else { + return 28 + } + } + + override init(frame: CGRect) { + super.init(frame: frame) + + NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func updateUI(item: MainSidebarViewController.Item, account: LocalData.UserAccountInfo) async { + var config = defaultContentConfiguration() + config.text = item.title + config.image = UIImage(systemName: item.imageName!) + self.contentConfiguration = config + + let mastodonController = MastodonController.getForAccount(account) + guard let account = try? await mastodonController.getOwnAccount(), + let avatar = account.avatar else { + return + } + _ = ImageCache.avatars.get(avatar, loadOriginal: false) { [weak self] _, image in + guard let self = self, + let image = image else { + return + } + + DispatchQueue.main.async { + guard var config = self.contentConfiguration as? UIListContentConfiguration else { + return + } + config.image = image + config.directionalLayoutMargins.top = self.verticalImageInset + config.directionalLayoutMargins.bottom = self.verticalImageInset + config.imageProperties.maximumSize = CGSize(width: self.avatarImageSize, height: self.avatarImageSize) + config.imageProperties.reservedLayoutSize = CGSize(width: UIListContentConfiguration.ImageProperties.standardDimension, height: 0) + config.imageProperties.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * self.avatarImageSize + self.contentConfiguration = config + } + } + } + + @objc private func preferencesChanged() { + guard var config = self.contentConfiguration as? UIListContentConfiguration else { + return + } + config.imageProperties.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * avatarImageSize + self.contentConfiguration = contentConfiguration + } + +} diff --git a/Tusker/Screens/Main/MainSidebarViewController.swift b/Tusker/Screens/Main/MainSidebarViewController.swift index 5cf4ec3d..ae0c25cc 100644 --- a/Tusker/Screens/Main/MainSidebarViewController.swift +++ b/Tusker/Screens/Main/MainSidebarViewController.swift @@ -115,6 +115,12 @@ class MainSidebarViewController: UIViewController { cell.contentConfiguration = config } + let myProfileCell = UICollectionView.CellRegistration { [unowned self] cell, indexPath, item in + Task { + await cell.updateUI(item: item, account: self.mastodonController.accountInfo!) + } + } + let outlineHeaderCell = UICollectionView.CellRegistration { (cell, indexPath, item) in var config = cell.defaultContentConfiguration() config.attributedText = NSAttributedString(string: item.title, attributes: [ @@ -125,7 +131,9 @@ class MainSidebarViewController: UIViewController { } return UICollectionViewDiffableDataSource(collectionView: collectionView, cellProvider: { (collectionView, indexPath, item) -> UICollectionViewCell? in - if item.hasChildren { + if case .tab(.myProfile) = item { + return collectionView.dequeueConfiguredReusableCell(using: myProfileCell, for: indexPath, item: item) + } else if item.hasChildren { return collectionView.dequeueConfiguredReusableCell(using: outlineHeaderCell, for: indexPath, item: item) } else { return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: item)