Compare commits

...

6 Commits

10 changed files with 127 additions and 28 deletions

View File

@ -1,5 +1,13 @@
# Changelog # Changelog
## 2023.5 (97)
Features/Improvements:
- Change favorite/reblog button order to match Mastodon
- Use QuickLook as a fallback for uknown attachment types
Bugfixes:
- Fix crash when adding drawing attachment
## 2023.5 (96) ## 2023.5 (96)
Features/Improvements: Features/Improvements:
- Resolve Mastodon's remote status links - Resolve Mastodon's remote status links

View File

@ -96,14 +96,17 @@ class AttachmentsListController: ViewController {
} }
private func addImage() { private func addImage() {
parent.deleteDraftOnDisappear = false
parent.config.presentAssetPicker?({ results in parent.config.presentAssetPicker?({ results in
self.insertAttachments(at: self.draft.attachments.count, itemProviders: results.map(\.itemProvider)) self.insertAttachments(at: self.draft.attachments.count, itemProviders: results.map(\.itemProvider))
}) })
} }
private func addDrawing() { private func addDrawing() {
parent.deleteDraftOnDisappear = false
parent.config.presentDrawing?(PKDrawing()) { drawing in parent.config.presentDrawing?(PKDrawing()) { drawing in
let attachment = DraftAttachment(context: DraftsPersistentContainer.shared.viewContext) let attachment = DraftAttachment(context: DraftsPersistentContainer.shared.viewContext)
attachment.id = UUID()
attachment.drawing = drawing attachment.drawing = drawing
attachment.draft = self.draft attachment.draft = self.draft
self.draft.attachments.add(attachment) self.draft.attachments.add(attachment)

View File

@ -208,6 +208,7 @@ public final class ComposeController: ViewController {
do { do {
try await poster.post() try await poster.post()
deleteDraftOnDisappear = true
didPostSuccessfully = true didPostSuccessfully = true
// wait .25 seconds so the user can see the progress bar has completed // wait .25 seconds so the user can see the progress bar has completed

View File

@ -304,6 +304,7 @@
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 */; }; D6D79F572A1160B800AB2315 /* AccountDisplayNameLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F562A1160B800AB2315 /* AccountDisplayNameLabel.swift */; };
D6D79F592A13293200AB2315 /* BackgroundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F582A13293200AB2315 /* BackgroundManager.swift */; }; D6D79F592A13293200AB2315 /* BackgroundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F582A13293200AB2315 /* BackgroundManager.swift */; };
D6D79F5B2A13D22B00AB2315 /* GalleryFallbackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F5A2A13D22B00AB2315 /* GalleryFallbackViewController.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 */; };
@ -706,6 +707,7 @@
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>"; }; D6D79F562A1160B800AB2315 /* AccountDisplayNameLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDisplayNameLabel.swift; sourceTree = "<group>"; };
D6D79F582A13293200AB2315 /* BackgroundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundManager.swift; sourceTree = "<group>"; }; D6D79F582A13293200AB2315 /* BackgroundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundManager.swift; sourceTree = "<group>"; };
D6D79F5A2A13D22B00AB2315 /* GalleryFallbackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryFallbackViewController.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>"; };
@ -1092,6 +1094,7 @@
D6C94D862139E62700CB5196 /* LargeImageViewController.swift */, D6C94D862139E62700CB5196 /* LargeImageViewController.swift */,
D681A299249AD62D0085E54E /* LargeImageContentView.swift */, D681A299249AD62D0085E54E /* LargeImageContentView.swift */,
041160FE22B442870030A9B7 /* LoadingLargeImageViewController.swift */, 041160FE22B442870030A9B7 /* LoadingLargeImageViewController.swift */,
D6D79F5A2A13D22B00AB2315 /* GalleryFallbackViewController.swift */,
); );
path = "Large Image"; path = "Large Image";
sourceTree = "<group>"; sourceTree = "<group>";
@ -2148,6 +2151,7 @@
D6E77D0B286D426E00D8B732 /* TrendingLinkCardCollectionViewCell.swift in Sources */, D6E77D0B286D426E00D8B732 /* TrendingLinkCardCollectionViewCell.swift in Sources */,
D6114E1127F899B30080E273 /* TrendingLinksViewController.swift in Sources */, D6114E1127F899B30080E273 /* TrendingLinksViewController.swift in Sources */,
D65B4B58297203A700DABDFB /* ReportSelectRulesView.swift in Sources */, D65B4B58297203A700DABDFB /* ReportSelectRulesView.swift in Sources */,
D6D79F5B2A13D22B00AB2315 /* GalleryFallbackViewController.swift in Sources */,
D6C3F4FB299035650009FCFF /* TrendsViewController.swift in Sources */, D6C3F4FB299035650009FCFF /* TrendsViewController.swift in Sources */,
D6B81F442560390300F6E31D /* MenuController.swift in Sources */, D6B81F442560390300F6E31D /* MenuController.swift in Sources */,
D691771129A2B76A0054D7EF /* MainActor+Unsafe.swift in Sources */, D691771129A2B76A0054D7EF /* MainActor+Unsafe.swift in Sources */,
@ -2382,7 +2386,7 @@
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements; CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
INFOPLIST_FILE = Tusker/Info.plist; INFOPLIST_FILE = Tusker/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@ -2448,7 +2452,7 @@
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements; CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
INFOPLIST_FILE = OpenInTusker/Info.plist; INFOPLIST_FILE = OpenInTusker/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1; IPHONEOS_DEPLOYMENT_TARGET = 14.1;
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3; "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
@ -2474,7 +2478,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShareExtension/Info.plist; INFOPLIST_FILE = ShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension; INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
@ -2503,7 +2507,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShareExtension/Info.plist; INFOPLIST_FILE = ShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension; INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
@ -2532,7 +2536,7 @@
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShareExtension/Info.plist; INFOPLIST_FILE = ShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension; INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
@ -2687,7 +2691,7 @@
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements; CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
INFOPLIST_FILE = Tusker/Info.plist; INFOPLIST_FILE = Tusker/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@ -2718,7 +2722,7 @@
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements; CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
INFOPLIST_FILE = Tusker/Info.plist; INFOPLIST_FILE = Tusker/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@ -2824,7 +2828,7 @@
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements; CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
INFOPLIST_FILE = OpenInTusker/Info.plist; INFOPLIST_FILE = OpenInTusker/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1; IPHONEOS_DEPLOYMENT_TARGET = 14.1;
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3; "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
@ -2850,7 +2854,7 @@
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements; CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 96; CURRENT_PROJECT_VERSION = 97;
INFOPLIST_FILE = OpenInTusker/Info.plist; INFOPLIST_FILE = OpenInTusker/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1; IPHONEOS_DEPLOYMENT_TARGET = 14.1;
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3; "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;

View File

@ -109,7 +109,7 @@ class GalleryViewController: UIPageViewController, UIPageViewControllerDataSourc
vc.shrinkGestureEnabled = false vc.shrinkGestureEnabled = false
return vc return vc
default: default:
fatalError() return UINavigationController(rootViewController: GalleryFallbackViewController(attachment: attachment))
} }
} }

View File

@ -0,0 +1,71 @@
//
// GalleryFallbackViewController.swift
// Tusker
//
// Created by Shadowfacts on 5/16/23.
// Copyright © 2023 Shadowfacts. All rights reserved.
//
import UIKit
import QuickLook
import Pachyderm
class GalleryFallbackViewController: QLPreviewController {
private let attachment: Attachment
private let previewItem: GalleryPreviewItem
private var loadAttachmentTask: Task<Void, Never>?
deinit {
loadAttachmentTask?.cancel()
}
init(attachment: Attachment) {
self.attachment = attachment
self.previewItem = GalleryPreviewItem()
super.init(nibName: nil, bundle: nil)
dataSource = self
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if previewItem.previewItemURL == nil,
loadAttachmentTask == nil {
loadAttachmentTask = Task {
do {
let (data, _) = try await URLSession.shared.data(from: attachment.url)
let url = FileManager.default.temporaryDirectory.appendingPathComponent(attachment.url.lastPathComponent)
try data.write(to: url)
try Task.checkCancellation()
previewItem.previewItemURL = url
refreshCurrentPreviewItem()
} catch {
return
}
}
}
}
}
extension GalleryFallbackViewController: QLPreviewControllerDataSource {
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
return 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return previewItem
}
}
private class GalleryPreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL? = nil
}

View File

@ -107,10 +107,6 @@ class AttachmentView: GIFImageView {
} }
func loadAttachment() { func loadAttachment() {
guard AttachmentsContainerView.supportedAttachmentTypes.contains(attachment.kind) else {
fatalError("invalid attachment type")
}
if let hash = attachment.blurHash { if let hash = attachment.blurHash {
AttachmentView.queue.async { [weak self] in AttachmentView.queue.async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
@ -142,8 +138,8 @@ class AttachmentView: GIFImageView {
loadAudio() loadAudio()
case .gifv: case .gifv:
loadGifv() loadGifv()
default: case .unknown:
fatalError("invalid attachment type") createUnknownLabel()
} }
} }
@ -301,6 +297,25 @@ class AttachmentView: GIFImageView {
]) ])
} }
func createUnknownLabel() {
backgroundColor = .appSecondaryBackground
let label = UILabel()
label.text = "Unknown Attachment Type"
label.numberOfLines = 0
label.textAlignment = .center
label.textColor = .secondaryLabel
label.font = .preferredFont(forTextStyle: .body)
label.adjustsFontForContentSizeCategory = true
label.translatesAutoresizingMaskIntoConstraints = false
addSubview(label)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: leadingAnchor),
label.trailingAnchor.constraint(equalTo: trailingAnchor),
label.topAnchor.constraint(equalTo: topAnchor),
label.bottomAnchor.constraint(equalTo: bottomAnchor),
])
}
@MainActor @MainActor
private func displayImage() { private func displayImage() {
isGrayscale = Preferences.shared.grayscaleImages isGrayscale = Preferences.shared.grayscaleImages

View File

@ -10,8 +10,6 @@ import UIKit
import Pachyderm import Pachyderm
class AttachmentsContainerView: UIView { class AttachmentsContainerView: UIView {
static let supportedAttachmentTypes = [Attachment.Kind.image, .video, .audio, .gifv]
weak var delegate: AttachmentViewDelegate? weak var delegate: AttachmentViewDelegate?
@ -70,7 +68,6 @@ class AttachmentsContainerView: UIView {
// MARK: - User Interaface // MARK: - User Interaface
func updateUI(attachments: [Attachment]) { func updateUI(attachments: [Attachment]) {
let attachments = attachments.filter { AttachmentsContainerView.supportedAttachmentTypes.contains($0.kind) }
let newTokens = attachments.map { AttachmentToken(attachment: $0) } let newTokens = attachments.map { AttachmentToken(attachment: $0) }
guard self.attachmentTokens != newTokens else { guard self.attachmentTokens != newTokens else {

View File

@ -141,8 +141,8 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
} }
private lazy var actionsCountHStack = UIStackView(arrangedSubviews: [ private lazy var actionsCountHStack = UIStackView(arrangedSubviews: [
favoritesCountButton,
reblogsCountButton, reblogsCountButton,
favoritesCountButton,
]).configure { ]).configure {
$0.axis = .horizontal $0.axis = .horizontal
$0.spacing = 8 $0.spacing = 8
@ -210,13 +210,13 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
} }
private var actionButtons: [UIButton] { private var actionButtons: [UIButton] {
[replyButton, favoriteButton, reblogButton, moreButton] [replyButton, reblogButton, favoriteButton, moreButton]
} }
private lazy var actionsHStack = UIStackView(arrangedSubviews: [ private lazy var actionsHStack = UIStackView(arrangedSubviews: [
replyButton, replyButton,
favoriteButton,
reblogButton, reblogButton,
favoriteButton,
moreButton, moreButton,
]).configure { ]).configure {
$0.axis = .horizontal $0.axis = .horizontal

View File

@ -217,15 +217,15 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
replyButton.topAnchor.constraint(equalTo: $0.topAnchor), replyButton.topAnchor.constraint(equalTo: $0.topAnchor),
replyButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor), replyButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor),
favoriteButton.leadingAnchor.constraint(equalTo: replyButton.trailingAnchor), reblogButton.leadingAnchor.constraint(equalTo: replyButton.trailingAnchor),
favoriteButton.topAnchor.constraint(equalTo: $0.topAnchor),
favoriteButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor),
reblogButton.leadingAnchor.constraint(equalTo: favoriteButton.trailingAnchor),
reblogButton.topAnchor.constraint(equalTo: $0.topAnchor), reblogButton.topAnchor.constraint(equalTo: $0.topAnchor),
reblogButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor), reblogButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor),
moreButton.leadingAnchor.constraint(equalTo: reblogButton.trailingAnchor), favoriteButton.leadingAnchor.constraint(equalTo: reblogButton.trailingAnchor),
favoriteButton.topAnchor.constraint(equalTo: $0.topAnchor),
favoriteButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor),
moreButton.leadingAnchor.constraint(equalTo: favoriteButton.trailingAnchor),
moreButton.trailingAnchor.constraint(equalTo: $0.trailingAnchor), moreButton.trailingAnchor.constraint(equalTo: $0.trailingAnchor),
moreButton.topAnchor.constraint(equalTo: $0.topAnchor), moreButton.topAnchor.constraint(equalTo: $0.topAnchor),
moreButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor), moreButton.bottomAnchor.constraint(equalTo: $0.bottomAnchor),