Compare commits

..

No commits in common. "8319935a3d1d00a8e3025b4a78fd80f9be144131" and "c94e60d49b05a1f8f36a3e224079506bb623471d" have entirely different histories.

23 changed files with 168 additions and 211 deletions

View File

@ -246,7 +246,7 @@
D6B17255254F88B800128392 /* OppositeCollapseKeywordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B17254254F88B800128392 /* OppositeCollapseKeywordsView.swift */; }; D6B17255254F88B800128392 /* OppositeCollapseKeywordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B17254254F88B800128392 /* OppositeCollapseKeywordsView.swift */; };
D6B22A0F2560D52D004D82EF /* TabbedPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B22A0E2560D52D004D82EF /* TabbedPageViewController.swift */; }; D6B22A0F2560D52D004D82EF /* TabbedPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B22A0E2560D52D004D82EF /* TabbedPageViewController.swift */; };
D6B30E09254BAF63009CAEE5 /* ImageGrayscalifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B30E08254BAF63009CAEE5 /* ImageGrayscalifier.swift */; }; D6B30E09254BAF63009CAEE5 /* ImageGrayscalifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B30E08254BAF63009CAEE5 /* ImageGrayscalifier.swift */; };
D6B4A4FF2506B81A000C81C1 /* AccountDisplayNameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameView.swift */; }; D6B4A4FF2506B81A000C81C1 /* AccountDisplayNameLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameLabel.swift */; };
D6B81F3C2560365300F6E31D /* RefreshableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B81F3B2560365300F6E31D /* RefreshableViewController.swift */; }; D6B81F3C2560365300F6E31D /* RefreshableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B81F3B2560365300F6E31D /* RefreshableViewController.swift */; };
D6B81F442560390300F6E31D /* MenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B81F432560390300F6E31D /* MenuController.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 */; }; D6B8DB342182A59300424AF7 /* UIAlertController+Visibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */; };
@ -302,7 +302,6 @@
D6D79F2D2A0D61B400AB2315 /* StatusEditContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F2C2A0D61B400AB2315 /* StatusEditContentTextView.swift */; }; D6D79F2D2A0D61B400AB2315 /* StatusEditContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F2C2A0D61B400AB2315 /* StatusEditContentTextView.swift */; };
D6D79F2F2A0D6A7F00AB2315 /* StatusEditPollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F2E2A0D6A7F00AB2315 /* StatusEditPollView.swift */; }; D6D79F2F2A0D6A7F00AB2315 /* StatusEditPollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F2E2A0D6A7F00AB2315 /* StatusEditPollView.swift */; };
D6D79F532A0FFE3200AB2315 /* ToggleableButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F522A0FFE3200AB2315 /* ToggleableButton.swift */; }; D6D79F532A0FFE3200AB2315 /* ToggleableButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F522A0FFE3200AB2315 /* ToggleableButton.swift */; };
D6D79F572A1160B800AB2315 /* AccountDisplayNameLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F562A1160B800AB2315 /* AccountDisplayNameLabel.swift */; };
D6D94955298963A900C59229 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D94954298963A900C59229 /* Colors.swift */; }; D6D94955298963A900C59229 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D94954298963A900C59229 /* Colors.swift */; };
D6D9498D298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */; }; D6D9498D298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */; };
D6D9498F298EB79400C59229 /* CopyableLable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498E298EB79400C59229 /* CopyableLable.swift */; }; D6D9498F298EB79400C59229 /* CopyableLable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498E298EB79400C59229 /* CopyableLable.swift */; };
@ -639,7 +638,7 @@
D6B17254254F88B800128392 /* OppositeCollapseKeywordsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OppositeCollapseKeywordsView.swift; sourceTree = "<group>"; }; D6B17254254F88B800128392 /* OppositeCollapseKeywordsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OppositeCollapseKeywordsView.swift; sourceTree = "<group>"; };
D6B22A0E2560D52D004D82EF /* TabbedPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabbedPageViewController.swift; sourceTree = "<group>"; }; D6B22A0E2560D52D004D82EF /* TabbedPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabbedPageViewController.swift; sourceTree = "<group>"; };
D6B30E08254BAF63009CAEE5 /* ImageGrayscalifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageGrayscalifier.swift; sourceTree = "<group>"; }; D6B30E08254BAF63009CAEE5 /* ImageGrayscalifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageGrayscalifier.swift; sourceTree = "<group>"; };
D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDisplayNameView.swift; sourceTree = "<group>"; }; D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDisplayNameLabel.swift; sourceTree = "<group>"; };
D6B81F3B2560365300F6E31D /* RefreshableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshableViewController.swift; sourceTree = "<group>"; }; D6B81F3B2560365300F6E31D /* RefreshableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshableViewController.swift; sourceTree = "<group>"; };
D6B81F432560390300F6E31D /* MenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuController.swift; sourceTree = "<group>"; }; D6B81F432560390300F6E31D /* MenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuController.swift; sourceTree = "<group>"; };
D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Visibility.swift"; sourceTree = "<group>"; }; D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Visibility.swift"; sourceTree = "<group>"; };
@ -703,7 +702,6 @@
D6D79F2C2A0D61B400AB2315 /* StatusEditContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditContentTextView.swift; sourceTree = "<group>"; }; D6D79F2C2A0D61B400AB2315 /* StatusEditContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditContentTextView.swift; sourceTree = "<group>"; };
D6D79F2E2A0D6A7F00AB2315 /* StatusEditPollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditPollView.swift; sourceTree = "<group>"; }; D6D79F2E2A0D6A7F00AB2315 /* StatusEditPollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditPollView.swift; sourceTree = "<group>"; };
D6D79F522A0FFE3200AB2315 /* ToggleableButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleableButton.swift; sourceTree = "<group>"; }; D6D79F522A0FFE3200AB2315 /* ToggleableButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleableButton.swift; sourceTree = "<group>"; };
D6D79F562A1160B800AB2315 /* AccountDisplayNameLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDisplayNameLabel.swift; sourceTree = "<group>"; };
D6D94954298963A900C59229 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; }; D6D94954298963A900C59229 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingStatusCollectionViewCell.swift; sourceTree = "<group>"; }; D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingStatusCollectionViewCell.swift; sourceTree = "<group>"; };
D6D9498E298EB79400C59229 /* CopyableLable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLable.swift; sourceTree = "<group>"; }; D6D9498E298EB79400C59229 /* CopyableLable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLable.swift; sourceTree = "<group>"; };
@ -1353,7 +1351,7 @@
D6BED1722126661300F02DA0 /* Views */ = { D6BED1722126661300F02DA0 /* Views */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameView.swift */, D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameLabel.swift */,
D68E6F5E253C9B2D001A1B4C /* BaseEmojiLabel.swift */, D68E6F5E253C9B2D001A1B4C /* BaseEmojiLabel.swift */,
D6ADB6EF28ED1F25009924AB /* CachedImageView.swift */, D6ADB6EF28ED1F25009924AB /* CachedImageView.swift */,
D6895DC328D65342006341DA /* ConfirmReblogStatusPreviewView.swift */, D6895DC328D65342006341DA /* ConfirmReblogStatusPreviewView.swift */,
@ -1388,7 +1386,6 @@
D641C78B213DD92F004B4513 /* Profile Header */, D641C78B213DD92F004B4513 /* Profile Header */,
D641C78A213DD926004B4513 /* Status */, D641C78A213DD926004B4513 /* Status */,
D64AAE8F26C80DB600FC57FB /* Toast */, D64AAE8F26C80DB600FC57FB /* Toast */,
D6D79F562A1160B800AB2315 /* AccountDisplayNameLabel.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2016,7 +2013,7 @@
D646C956213B365700269FB5 /* LargeImageExpandAnimationController.swift in Sources */, D646C956213B365700269FB5 /* LargeImageExpandAnimationController.swift in Sources */,
D646DCD22A06F2510059ECEB /* NotificationsCollectionViewController.swift in Sources */, D646DCD22A06F2510059ECEB /* NotificationsCollectionViewController.swift in Sources */,
D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */, D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */,
D6B4A4FF2506B81A000C81C1 /* AccountDisplayNameView.swift in Sources */, D6B4A4FF2506B81A000C81C1 /* AccountDisplayNameLabel.swift in Sources */,
D63D8DF42850FE7A008D95E1 /* ViewTags.swift in Sources */, D63D8DF42850FE7A008D95E1 /* ViewTags.swift in Sources */,
D61DC84B28F4FD2000B82C6E /* ProfileHeaderCollectionViewCell.swift in Sources */, D61DC84B28F4FD2000B82C6E /* ProfileHeaderCollectionViewCell.swift in Sources */,
D61A45E828DF477D002BE511 /* LoadingCollectionViewCell.swift in Sources */, D61A45E828DF477D002BE511 /* LoadingCollectionViewCell.swift in Sources */,
@ -2112,7 +2109,6 @@
D663626C21361C6700C9CBA2 /* Account+Preferences.swift in Sources */, D663626C21361C6700C9CBA2 /* Account+Preferences.swift in Sources */,
D67895C0246870DE00D4CD9E /* LocalAccountAvatarView.swift in Sources */, D67895C0246870DE00D4CD9E /* LocalAccountAvatarView.swift in Sources */,
D6ADB6E828E8C878009924AB /* PublicTimelineDescriptionCollectionViewCell.swift in Sources */, D6ADB6E828E8C878009924AB /* PublicTimelineDescriptionCollectionViewCell.swift in Sources */,
D6D79F572A1160B800AB2315 /* AccountDisplayNameLabel.swift in Sources */,
D646DCAC2A06C8840059ECEB /* ProfileFieldValueView.swift in Sources */, D646DCAC2A06C8840059ECEB /* ProfileFieldValueView.swift in Sources */,
D6F4D79429ECB0AF00351B87 /* UIBackgroundConfiguration+AppColors.swift in Sources */, D6F4D79429ECB0AF00351B87 /* UIBackgroundConfiguration+AppColors.swift in Sources */,
D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */, D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */,

View File

@ -37,20 +37,16 @@ class ImageCache {
completion?(entry.data, entry.image) completion?(entry.data, entry.image)
return nil return nil
} else { } else {
return getFromSource(url, completion: completion) return Task.detached(priority: .userInitiated) {
} let result = await self.fetch(url: url)
} switch result {
case .data(let data):
func getFromSource(_ url: URL, completion: ((Data?, UIImage?) -> Void)?) -> Request? { completion?(data, nil)
return Task.detached(priority: .userInitiated) { case .dataAndImage(let data, let image):
let result = await self.fetch(url: url) completion?(data, image)
switch result { case .none:
case .data(let data): completion?(nil, nil)
completion?(data, nil) }
case .dataAndImage(let data, let image):
completion?(data, image)
case .none:
completion?(nil, nil)
} }
} }
} }

View File

@ -10,7 +10,6 @@ import UIKit
extension NSTextAttachment { extension NSTextAttachment {
// Based on https://github.com/ReticentJohn/Amaroq/blob/7c5b7088eb9fd1611dcb0f47d43bf8df093e142c/DireFloof/InlineImageHelpers.m // Based on https://github.com/ReticentJohn/Amaroq/blob/7c5b7088eb9fd1611dcb0f47d43bf8df093e142c/DireFloof/InlineImageHelpers.m
@available(iOS, deprecated: 15.0)
convenience init(emojiImage image: UIImage, in font: UIFont, with textColor: UIColor = .label) { convenience init(emojiImage image: UIImage, in font: UIFont, with textColor: UIColor = .label) {
let adjustedCapHeight = font.capHeight - 1 let adjustedCapHeight = font.capHeight - 1
var imageSizeMatchingFontSize = CGSize(width: image.size.width * (adjustedCapHeight / image.size.height), height: adjustedCapHeight) var imageSizeMatchingFontSize = CGSize(width: image.size.width * (adjustedCapHeight / image.size.height), height: adjustedCapHeight)

View File

@ -41,7 +41,7 @@ class ComposeHostingController: UIHostingController<ComposeHostingController.Vie
fetchAvatar: { @MainActor in await ImageCache.avatars.get($0).1 }, fetchAvatar: { @MainActor in await ImageCache.avatars.get($0).1 },
fetchAttachment: { @MainActor in await ImageCache.attachments.get($0).1 }, fetchAttachment: { @MainActor in await ImageCache.attachments.get($0).1 },
fetchStatus: { mastodonController.persistentContainer.status(for: $0) }, fetchStatus: { mastodonController.persistentContainer.status(for: $0) },
displayNameLabel: { AnyView(AccountDisplayNameView(account: $0, textStyle: $1, emojiSize: $2)) }, displayNameLabel: { AnyView(AccountDisplayNameLabel(account: $0, textStyle: $1, emojiSize: $2)) },
replyContentView: { AnyView(ComposeReplyContentView(status: $0, mastodonController: mastodonController, heightChanged: $1)) }, replyContentView: { AnyView(ComposeReplyContentView(status: $0, mastodonController: mastodonController, heightChanged: $1)) },
emojiImageView: { AnyView(CustomEmojiImageView(emoji: $0)) } emojiImageView: { AnyView(CustomEmojiImageView(emoji: $0)) }
) )

View File

@ -15,7 +15,7 @@ class FeaturedProfileCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var headerImageView: UIImageView! @IBOutlet weak var headerImageView: UIImageView!
@IBOutlet weak var avatarContainerView: UIView! @IBOutlet weak var avatarContainerView: UIView!
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@IBOutlet weak var displayNameLabel: AccountDisplayNameLabel! @IBOutlet weak var displayNameLabel: EmojiLabel!
@IBOutlet weak var noteTextView: StatusContentTextView! @IBOutlet weak var noteTextView: StatusContentTextView!
var account: Account? var account: Account?

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<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="21678"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<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"/>
@ -47,7 +47,7 @@
<constraint firstItem="4wd-wq-Sh2" firstAttribute="centerX" secondItem="RQe-uE-TEv" secondAttribute="centerX" id="bRk-uJ-JGg"/> <constraint firstItem="4wd-wq-Sh2" firstAttribute="centerX" secondItem="RQe-uE-TEv" secondAttribute="centerX" id="bRk-uJ-JGg"/>
</constraints> </constraints>
</view> </view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="voW-Is-1b2" customClass="AccountDisplayNameLabel" customModule="Tusker" customModuleProvider="target"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="voW-Is-1b2" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="76" y="72" width="316" height="24"/> <rect key="frame" x="76" y="72" width="316" height="24"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="20"/> <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="20"/>
<nil key="textColor"/> <nil key="textColor"/>

View File

@ -21,7 +21,7 @@ class SuggestedProfileCardCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var headerImageView: CachedImageView! @IBOutlet weak var headerImageView: CachedImageView!
@IBOutlet weak var avatarContainerView: UIView! @IBOutlet weak var avatarContainerView: UIView!
@IBOutlet weak var avatarImageView: CachedImageView! @IBOutlet weak var avatarImageView: CachedImageView!
@IBOutlet weak var displayNameLabel: AccountDisplayNameLabel! @IBOutlet weak var displayNameLabel: EmojiLabel!
@IBOutlet weak var usernameLabel: UILabel! @IBOutlet weak var usernameLabel: UILabel!
@IBOutlet weak var noteTextView: StatusContentTextView! @IBOutlet weak var noteTextView: StatusContentTextView!
@IBOutlet weak var suggestionSourceButton: UIButton! @IBOutlet weak var suggestionSourceButton: UIButton!

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/> <device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="collection view cell content view" minToolsVersion="11.0"/> <capability name="collection view cell content view" 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"/>
@ -44,7 +44,7 @@
<constraint firstAttribute="width" constant="90" id="wav-YT-e4Y"/> <constraint firstAttribute="width" constant="90" id="wav-YT-e4Y"/>
</constraints> </constraints>
</view> </view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsLetterSpacingToFitWidth="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XCk-sZ-ujT" customClass="AccountDisplayNameLabel" customModule="Tusker" customModuleProvider="target"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsLetterSpacingToFitWidth="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XCk-sZ-ujT" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="106" y="100" width="333" height="29"/> <rect key="frame" x="106" y="100" width="333" height="29"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/> <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/>
<nil key="textColor"/> <nil key="textColor"/>

View File

@ -65,7 +65,7 @@ struct MuteAccountView: View {
) )
VStack(alignment: .leading) { VStack(alignment: .leading) {
AccountDisplayNameView(account: account, textStyle: .headline, emojiSize: 17) AccountDisplayNameLabel(account: account, textStyle: .headline, emojiSize: 17)
Text("@\(account.acct)") Text("@\(account.acct)")
.fontWeight(.light) .fontWeight(.light)
.foregroundColor(.secondary) .foregroundColor(.secondary)

View File

@ -55,7 +55,7 @@ struct ReportView: View {
) )
VStack(alignment: .leading) { VStack(alignment: .leading) {
AccountDisplayNameView(account: account, textStyle: .headline, emojiSize: 17) AccountDisplayNameLabel(account: account, textStyle: .headline, emojiSize: 17)
Text("@\(account.acct)") Text("@\(account.acct)")
.fontWeight(.light) .fontWeight(.light)
.foregroundColor(.secondary) .foregroundColor(.secondary)

View File

@ -15,7 +15,7 @@ class AccountTableViewCell: UITableViewCell {
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController! { delegate?.apiController }
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@IBOutlet weak var displayNameLabel: AccountDisplayNameLabel! @IBOutlet weak var displayNameLabel: EmojiLabel!
@IBOutlet weak var usernameLabel: UILabel! @IBOutlet weak var usernameLabel: UILabel!
@IBOutlet weak var noteLabel: EmojiLabel! @IBOutlet weak var noteLabel: EmojiLabel!

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<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="21678"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<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"/>
@ -28,7 +28,7 @@
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="Iif-9m-vM5"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="Iif-9m-vM5">
<rect key="frame" x="74" y="11" width="230" height="78"/> <rect key="frame" x="74" y="11" width="230" height="78"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fhc-bZ-lkB" customClass="AccountDisplayNameLabel" customModule="Tusker" customModuleProvider="target"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fhc-bZ-lkB" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="230" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="230" height="20.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/> <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/> <nil key="textColor"/>

View File

@ -12,7 +12,7 @@ import Pachyderm
class LargeAccountDetailView: UIView { class LargeAccountDetailView: UIView {
var avatarImageView = UIImageView() var avatarImageView = UIImageView()
var displayNameLabel = AccountDisplayNameLabel() var displayNameLabel = EmojiLabel()
var usernameLabel = UILabel() var usernameLabel = UILabel()
var avatarRequest: ImageCache.Request? var avatarRequest: ImageCache.Request?

View File

@ -2,31 +2,106 @@
// AccountDisplayNameLabel.swift // AccountDisplayNameLabel.swift
// Tusker // Tusker
// //
// Created by Shadowfacts on 5/14/23. // Created by Shadowfacts on 9/7/20.
// Copyright © 2023 Shadowfacts. All rights reserved. // Copyright © 2020 Shadowfacts. All rights reserved.
// //
import UIKit import SwiftUI
import Pachyderm import Pachyderm
import WebURLFoundationExtras
class AccountDisplayNameLabel: EmojiLabel { private let emojiRegex = try! NSRegularExpression(pattern: ":(\\w+):", options: [])
private var accountID: String? struct AccountDisplayNameLabel: View {
// store the display name, so that if it changes the label updates w/o changing the id let account: any AccountProtocol
private var accountDisplayName: String? let textStyle: Font.TextStyle
@ScaledMetric var emojiSize: CGFloat
@State var text: Text
@State var emojiRequests = [ImageCache.Request]()
func updateForAccountDisplayName(account: some AccountProtocol) { init(account: any AccountProtocol, textStyle: Font.TextStyle, emojiSize: CGFloat) {
guard accountID != account.id || accountDisplayName != account.displayName || Preferences.shared.hideCustomEmojiInUsernames == hasEmojis else { self.account = account
return self.textStyle = textStyle
} self._emojiSize = ScaledMetric(wrappedValue: emojiSize, relativeTo: textStyle)
accountID = account.id let name = account.displayName.isEmpty ? account.username : account.displayName
accountDisplayName = account.displayName self._text = State(initialValue: Text(verbatim: name))
self.text = accountDisplayName
if Preferences.shared.hideCustomEmojiInUsernames {
self.removeEmojis()
} else {
self.setEmojis(account.emojis, identifier: account.id)
}
} }
var body: some View {
text
.font(.system(textStyle).weight(.semibold))
.onAppear(perform: self.loadEmojis)
}
private func loadEmojis() {
let fullRange = NSRange(account.displayName.startIndex..., in: account.displayName)
let matches = emojiRegex.matches(in: account.displayName, options: [], range: fullRange)
guard !matches.isEmpty else { return }
let emojiImages = MultiThreadDictionary<String, Image>()
let group = DispatchGroup()
for emoji in account.emojis {
guard matches.contains(where: { (match) in
let matchShortcode = (account.displayName as NSString).substring(with: match.range(at: 1))
return emoji.shortcode == matchShortcode
}) else {
continue
}
group.enter()
let request = ImageCache.emojis.get(URL(emoji.url)!) { (_, image) in
defer { group.leave() }
guard let image = image else { return }
let size = CGSize(width: emojiSize, height: emojiSize)
let renderer = UIGraphicsImageRenderer(size: size)
let resized = renderer.image { (ctx) in
image.draw(in: CGRect(origin: .zero, size: size))
}
emojiImages[emoji.shortcode] = Image(uiImage: resized)
}
if let request = request {
emojiRequests.append(request)
}
}
group.notify(queue: .main) {
var text: Text?
var endIndex = account.displayName.utf16.count
// iterate backwards as to not alter the indices of earlier matches
for match in matches.reversed() {
let shortcode = (account.displayName as NSString).substring(with: match.range(at: 1))
guard let image = emojiImages[shortcode] else { continue }
let afterCurrentMatch = (account.displayName as NSString).substring(with: NSRange(location: match.range.upperBound, length: endIndex - match.range.upperBound))
if let subsequent = text {
text = Text(image) + Text(verbatim: afterCurrentMatch) + subsequent
} else {
text = Text(image) + Text(verbatim: afterCurrentMatch)
}
endIndex = match.range.lowerBound
}
let beforeLastMatch = (account.displayName as NSString).substring(to: endIndex)
if let text = text {
self.text = Text(verbatim: beforeLastMatch) + text
} else {
self.text = Text(verbatim: beforeLastMatch)
}
}
}
} }
//struct AccountDisplayNameLabel_Previews: PreviewProvider {
// static var previews: some View {
// AccountDisplayNameLabel()
// }
//}

View File

@ -1,107 +0,0 @@
//
// AccountDisplayNameView.swift
// Tusker
//
// Created by Shadowfacts on 9/7/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import SwiftUI
import Pachyderm
import WebURLFoundationExtras
private let emojiRegex = try! NSRegularExpression(pattern: ":(\\w+):", options: [])
struct AccountDisplayNameView: View {
let account: any AccountProtocol
let textStyle: Font.TextStyle
@ScaledMetric var emojiSize: CGFloat
@State var text: Text
@State var emojiRequests = [ImageCache.Request]()
init(account: any AccountProtocol, textStyle: Font.TextStyle, emojiSize: CGFloat) {
self.account = account
self.textStyle = textStyle
self._emojiSize = ScaledMetric(wrappedValue: emojiSize, relativeTo: textStyle)
let name = account.displayName.isEmpty ? account.username : account.displayName
self._text = State(initialValue: Text(verbatim: name))
}
var body: some View {
text
.font(.system(textStyle).weight(.semibold))
.onAppear(perform: self.loadEmojis)
}
private func loadEmojis() {
let fullRange = NSRange(account.displayName.startIndex..., in: account.displayName)
let matches = emojiRegex.matches(in: account.displayName, options: [], range: fullRange)
guard !matches.isEmpty else { return }
let emojiImages = MultiThreadDictionary<String, Image>()
let group = DispatchGroup()
for emoji in account.emojis {
guard matches.contains(where: { (match) in
let matchShortcode = (account.displayName as NSString).substring(with: match.range(at: 1))
return emoji.shortcode == matchShortcode
}) else {
continue
}
group.enter()
let request = ImageCache.emojis.get(URL(emoji.url)!) { (_, image) in
defer { group.leave() }
guard let image = image else { return }
let size = CGSize(width: emojiSize, height: emojiSize)
let renderer = UIGraphicsImageRenderer(size: size)
let resized = renderer.image { (ctx) in
image.draw(in: CGRect(origin: .zero, size: size))
}
emojiImages[emoji.shortcode] = Image(uiImage: resized)
}
if let request = request {
emojiRequests.append(request)
}
}
group.notify(queue: .main) {
var text: Text?
var endIndex = account.displayName.utf16.count
// iterate backwards as to not alter the indices of earlier matches
for match in matches.reversed() {
let shortcode = (account.displayName as NSString).substring(with: match.range(at: 1))
guard let image = emojiImages[shortcode] else { continue }
let afterCurrentMatch = (account.displayName as NSString).substring(with: NSRange(location: match.range.upperBound, length: endIndex - match.range.upperBound))
if let subsequent = text {
text = Text(image) + Text(verbatim: afterCurrentMatch) + subsequent
} else {
text = Text(image) + Text(verbatim: afterCurrentMatch)
}
endIndex = match.range.lowerBound
}
let beforeLastMatch = (account.displayName as NSString).substring(to: endIndex)
if let text = text {
self.text = Text(verbatim: beforeLastMatch) + text
} else {
self.text = Text(verbatim: beforeLastMatch)
}
}
}
}
//struct AccountDisplayNameLabel_Previews: PreviewProvider {
// static var previews: some View {
// AccountDisplayNameView()
// }
//}

View File

@ -40,16 +40,6 @@ extension BaseEmojiLabel {
return return
} }
// Based on https://github.com/ReticentJohn/Amaroq/blob/7c5b7088eb9fd1611dcb0f47d43bf8df093e142c/DireFloof/InlineImageHelpers.m
let adjustedCapHeight = emojiFont.capHeight - 1
func emojiImageSize(_ image: UIImage) -> CGSize {
var imageSizeMatchingFontSize = CGSize(width: image.size.width * (adjustedCapHeight / image.size.height), height: adjustedCapHeight)
var scale: CGFloat = 1.4
scale *= UIScreen.main.scale
imageSizeMatchingFontSize = CGSize(width: imageSizeMatchingFontSize.width * scale, height: imageSizeMatchingFontSize.height * scale)
return imageSizeMatchingFontSize
}
let emojiImages = MultiThreadDictionary<String, UIImage>() let emojiImages = MultiThreadDictionary<String, UIImage>()
var foundEmojis = false var foundEmojis = false
@ -67,35 +57,21 @@ extension BaseEmojiLabel {
foundEmojis = true foundEmojis = true
if let image = ImageCache.emojis.get(URL(emoji.url)!)?.image { if let image = ImageCache.emojis.get(URL(emoji.url)!)?.image {
// if the image is cached, add it immediately. // if the image is cached, add it immediately
// we generate the thumbnail on the main thread, because it's usually fast enough emojiImages[emoji.shortcode] = image
// and the delay caused by doing it asynchronously looks works.
// todo: consider caching these somewhere? the cache needs to take into account both the url and the font size, which may vary across labels, so can't just use ImageCache
if let thumbnail = image.preparingThumbnail(of: emojiImageSize(image)),
let cgImage = thumbnail.cgImage {
// the thumbnail API takes a pixel size and returns an image with scale 1, but we want the actual screen scale, so convert
// see FB12187798
emojiImages[emoji.shortcode] = UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up)
}
} else { } else {
// otherwise, perform the network request // otherwise, perform the network request
group.enter() group.enter()
let request = ImageCache.emojis.getFromSource(URL(emoji.url)!) { (_, image) in // todo: ImageCache.emojis.get here will re-check the memory and disk caches, there should be another method to force-refetch
guard let image else { let request = ImageCache.emojis.get(URL(emoji.url)!) { (_, image) in
group.leave() guard let image = image,
return let transformedImage = ImageGrayscalifier.convertIfNecessary(url: URL(emoji.url)!, image: image) else {
} group.leave()
image.prepareThumbnail(of: emojiImageSize(image)) { thumbnail in return
guard let thumbnail = thumbnail?.cgImage,
case let rescaled = UIImage(cgImage: thumbnail, scale: UIScreen.main.scale, orientation: .up),
let transformedImage = ImageGrayscalifier.convertIfNecessary(url: URL(emoji.url)!, image: rescaled) else {
group.leave()
return
}
emojiImages[emoji.shortcode] = transformedImage
group.leave()
} }
emojiImages[emoji.shortcode] = transformedImage
group.leave()
} }
if let request = request { if let request = request {
emojiRequests.append(request) emojiRequests.append(request)
@ -115,8 +91,10 @@ extension BaseEmojiLabel {
// even though the closures is invoked on the same thread that withLock is called, so it's unclear why it needs to be @Sendable (FB11494878) // even though the closures is invoked on the same thread that withLock is called, so it's unclear why it needs to be @Sendable (FB11494878)
// so, just ignore the warnings // so, just ignore the warnings
let emojiAttachments = emojiImages.withLock { let emojiAttachments = emojiImages.withLock {
let emojiFont = self.emojiFont
let emojiTextColor = self.emojiTextColor
return $0.mapValues { image in return $0.mapValues { image in
NSTextAttachment(image: image) NSTextAttachment(emojiImage: image, in: emojiFont, with: emojiTextColor)
} }
} }
let placeholder = usePlaceholders ? NSTextAttachment(emojiPlaceholderIn: self.emojiFont) : nil let placeholder = usePlaceholders ? NSTextAttachment(emojiPlaceholderIn: self.emojiFont) : nil

View File

@ -52,7 +52,7 @@ class ConfirmReblogStatusPreviewView: UIView {
vStack.setContentHuggingPriority(.defaultLow, for: .horizontal) vStack.setContentHuggingPriority(.defaultLow, for: .horizontal)
hStack.addArrangedSubview(vStack) hStack.addArrangedSubview(vStack)
let displayNameLabel = AccountDisplayNameLabel() let displayNameLabel = EmojiLabel()
displayNameLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .caption1).addingAttributes([.traits: [UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold]]), size: 0) displayNameLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .caption1).addingAttributes([.traits: [UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold]]), size: 0)
displayNameLabel.adjustsFontSizeToFitWidth = true displayNameLabel.adjustsFontSizeToFitWidth = true
displayNameLabel.adjustsFontForContentSizeCategory = true displayNameLabel.adjustsFontForContentSizeCategory = true

View File

@ -38,3 +38,24 @@ class EmojiLabel: UILabel, BaseEmojiLabel {
} }
} }
extension EmojiLabel {
func updateForAccountDisplayName(account: Account) {
if Preferences.shared.hideCustomEmojiInUsernames {
self.text = account.displayName
self.removeEmojis()
} else {
self.text = account.displayName
self.setEmojis(account.emojis, identifier: account.id)
}
}
func updateForAccountDisplayName(account: AccountMO) {
if Preferences.shared.hideCustomEmojiInUsernames {
self.text = account.displayNameWithoutCustomEmoji
self.removeEmojis()
} else {
self.text = account.displayOrUserName
self.setEmojis(account.emojis, identifier: account.id)
}
}
}

View File

@ -28,7 +28,7 @@ class ProfileHeaderView: UIView {
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@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: EmojiLabel!
@IBOutlet weak var usernameLabel: UILabel! @IBOutlet weak var usernameLabel: UILabel!
@IBOutlet weak var lockImageView: UIImageView! @IBOutlet weak var lockImageView: UIImageView!
@IBOutlet weak var vStack: UIStackView! @IBOutlet weak var vStack: UIStackView!

View File

@ -39,7 +39,7 @@
<constraint firstItem="TkY-oK-if4" firstAttribute="centerX" secondItem="wT9-2J-uSY" secondAttribute="centerX" id="ozz-sa-gSc"/> <constraint firstItem="TkY-oK-if4" firstAttribute="centerX" secondItem="wT9-2J-uSY" secondAttribute="centerX" id="ozz-sa-gSc"/>
</constraints> </constraints>
</view> </view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vcl-Gl-kXl" customClass="AccountDisplayNameLabel" customModule="Tusker" customModuleProvider="target"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vcl-Gl-kXl" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="144" y="206" width="254" height="29"/> <rect key="frame" x="144" y="206" width="254" height="29"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/> <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/>
<nil key="textColor"/> <nil key="textColor"/>

View File

@ -39,7 +39,7 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
$0.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(accountPressed))) $0.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(accountPressed)))
} }
let displayNameLabel = AccountDisplayNameLabel().configure { let displayNameLabel = EmojiLabel().configure {
$0.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: .systemFont(ofSize: 24, weight: .semibold)) $0.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: .systemFont(ofSize: 24, weight: .semibold))
$0.adjustsFontForContentSizeCategory = true $0.adjustsFontForContentSizeCategory = true
} }

View File

@ -20,7 +20,7 @@ protocol StatusCollectionViewCellDelegate: AnyObject, TuskerNavigationDelegate,
protocol StatusCollectionViewCell: UICollectionViewCell, AttachmentViewDelegate { protocol StatusCollectionViewCell: UICollectionViewCell, AttachmentViewDelegate {
// MARK: Subviews // MARK: Subviews
var avatarImageView: CachedImageView { get } var avatarImageView: CachedImageView { get }
var displayNameLabel: AccountDisplayNameLabel { get } var displayNameLabel: EmojiLabel { get }
var usernameLabel: UILabel { get } var usernameLabel: UILabel { get }
var contentWarningLabel: EmojiLabel { get } var contentWarningLabel: EmojiLabel { get }
var collapseButton: StatusCollapseButton { get } var collapseButton: StatusCollapseButton { get }

View File

@ -114,7 +114,7 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
$0.spacing = 4 $0.spacing = 4
} }
let displayNameLabel = AccountDisplayNameLabel().configure { let displayNameLabel = EmojiLabel().configure {
$0.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .body).addingAttributes([ $0.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .body).addingAttributes([
.traits: [ .traits: [
UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold.rawValue, UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold.rawValue,
@ -619,6 +619,10 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
metaIndicatorsView.updateUI(status: status) metaIndicatorsView.updateUI(status: status)
timelineReasonIcon.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * Self.timelineReasonIconSize timelineReasonIcon.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * Self.timelineReasonIconSize
if let rebloggerID,
let reblogger = mastodonController.persistentContainer.account(for: rebloggerID) {
updateRebloggerLabel(reblogger: reblogger)
}
} }
func updateStatusState(status: StatusMO) { func updateStatusState(status: StatusMO) {
@ -699,11 +703,6 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
updateUIForPreferences(status: status) updateUIForPreferences(status: status)
if let rebloggerID,
let reblogger = mastodonController.persistentContainer.account(for: rebloggerID) {
updateRebloggerLabel(reblogger: reblogger)
}
if isGrayscale != Preferences.shared.grayscaleImages { if isGrayscale != Preferences.shared.grayscaleImages {
updateGrayscaleableUI(status: status) updateGrayscaleableUI(status: status)
} }