From 39b244384be207f6d73006a3c23cefd90e0183fd Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 25 Oct 2020 16:05:28 -0400 Subject: [PATCH] Show link cards on statuses --- Pachyderm/Model/Card.swift | 35 ++- Tusker.xcodeproj/project.pbxproj | 4 + Tusker/CoreData/StatusMO.swift | 5 + .../Tusker.xcdatamodel/contents | 5 +- .../Status/BaseStatusTableViewCell.swift | 6 + .../ConversationMainStatusTableViewCell.xib | 9 + Tusker/Views/Status/StatusCardView.swift | 223 ++++++++++++++++++ .../Status/TimelineStatusTableViewCell.xib | 8 + 8 files changed, 282 insertions(+), 13 deletions(-) create mode 100644 Tusker/Views/Status/StatusCardView.swift diff --git a/Pachyderm/Model/Card.swift b/Pachyderm/Model/Card.swift index cd5b7ac0..bdcce268 100644 --- a/Pachyderm/Model/Card.swift +++ b/Pachyderm/Model/Card.swift @@ -8,7 +8,7 @@ import Foundation -public class Card: Decodable { +public class Card: Codable { public let url: URL public let title: String public let description: String @@ -21,6 +21,7 @@ public class Card: Decodable { public let html: String? public let width: Int? public let height: Int? + public let blurhash: String? public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) @@ -29,14 +30,26 @@ public class Card: Decodable { self.title = try container.decode(String.self, forKey: .title) self.description = try container.decode(String.self, forKey: .description) self.kind = try container.decode(Kind.self, forKey: .kind) - self.image = try? container.decode(URL.self, forKey: .image) - self.authorName = try? container.decode(String.self, forKey: .authorName) - self.authorURL = try? container.decode(URL.self, forKey: .authorURL) - self.providerName = try? container.decode(String.self, forKey: .providerName) - self.providerURL = try? container.decode(URL.self, forKey: .providerURL) - self.html = try? container.decode(String.self, forKey: .html) - self.width = try? container.decode(Int.self, forKey: .width) - self.height = try? container.decode(Int.self, forKey: .height) + self.image = try? container.decodeIfPresent(URL.self, forKey: .image) + self.authorName = try? container.decodeIfPresent(String.self, forKey: .authorName) + self.authorURL = try? container.decodeIfPresent(URL.self, forKey: .authorURL) + self.providerName = try? container.decodeIfPresent(String.self, forKey: .providerName) + self.providerURL = try? container.decodeIfPresent(URL.self, forKey: .providerURL) + self.html = try? container.decodeIfPresent(String.self, forKey: .html) + self.width = try? container.decodeIfPresent(Int.self, forKey: .width) + self.height = try? container.decodeIfPresent(Int.self, forKey: .height) + self.blurhash = try? container.decodeIfPresent(String.self, forKey: .blurhash) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(url, forKey: .url) + try container.encode(title, forKey: .title) + try container.encode(description, forKey: .description) + try container.encode(kind, forKey: .kind) + try container.encode(image, forKey: .image) + try container.encode(blurhash, forKey: .blurhash) } private enum CodingKeys: String, CodingKey { @@ -52,14 +65,14 @@ public class Card: Decodable { case html case width case height + case blurhash } } extension Card { - public enum Kind: String, Decodable { + public enum Kind: String, Codable { case link case photo case video - case rich } } diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index d54765aa..9fb44a5c 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -244,6 +244,7 @@ D6C143DA253510F4007DC240 /* ComposeContentWarningTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C143D9253510F4007DC240 /* ComposeContentWarningTextField.swift */; }; D6C143E025354E34007DC240 /* EmojiPickerCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C143DF25354E34007DC240 /* EmojiPickerCollectionViewController.swift */; }; D6C143FD25354FD0007DC240 /* EmojiCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C143FB25354FD0007DC240 /* EmojiCollectionViewCell.swift */; }; + D6C1B2082545D1EC00DAAA66 /* StatusCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */; }; D6C693EF216192C2007D6A6D /* TuskerNavigationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */; }; D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */; }; D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */; }; @@ -579,6 +580,7 @@ D6C143D9253510F4007DC240 /* ComposeContentWarningTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeContentWarningTextField.swift; sourceTree = ""; }; D6C143DF25354E34007DC240 /* EmojiPickerCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPickerCollectionViewController.swift; sourceTree = ""; }; D6C143FB25354FD0007DC240 /* EmojiCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiCollectionViewCell.swift; sourceTree = ""; }; + D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCardView.swift; sourceTree = ""; }; D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerNavigationDelegate.swift; sourceTree = ""; }; D6C693FB2162FE6F007D6A6D /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = ""; }; D6C693FD2162FEEA007D6A6D /* UIViewController+Children.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Children.swift"; sourceTree = ""; }; @@ -1061,6 +1063,7 @@ D6BED173212667E900F02DA0 /* TimelineStatusTableViewCell.swift */, D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */, D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */, + D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */, ); path = Status; sourceTree = ""; @@ -1945,6 +1948,7 @@ D67895BC24671E6D00D4CD9E /* PKDrawing+Render.swift in Sources */, 04D14BB022B34A2800642648 /* GalleryViewController.swift in Sources */, D641C773213CAA25004B4513 /* NotificationsTableViewController.swift in Sources */, + D6C1B2082545D1EC00DAAA66 /* StatusCardView.swift in Sources */, D6412B0524B0227D00F5412E /* ProfileViewController.swift in Sources */, D64BC18A23C16487000D0238 /* UnpinStatusActivity.swift in Sources */, D64D8CA92463B494006B0BAA /* MultiThreadDictionary.swift in Sources */, diff --git a/Tusker/CoreData/StatusMO.swift b/Tusker/CoreData/StatusMO.swift index 88297a9f..f1c8b7c4 100644 --- a/Tusker/CoreData/StatusMO.swift +++ b/Tusker/CoreData/StatusMO.swift @@ -21,6 +21,7 @@ public final class StatusMO: NSManagedObject, StatusProtocol { @NSManaged public var applicationName: String? @NSManaged private var attachmentsData: Data? @NSManaged private var bookmarkedInternal: Bool + @NSManaged public var cardData: Data? @NSManaged public var content: String @NSManaged public var createdAt: Date @NSManaged private var emojisData: Data? @@ -56,6 +57,9 @@ public final class StatusMO: NSManagedObject, StatusProtocol { @LazilyDecoding(arrayFrom: \StatusMO.mentionsData) public var mentions: [Mention] + @LazilyDecoding(from: \StatusMO.cardData, fallback: nil) + public var card: Card? + public var pinned: Bool? { pinnedInternal } public var bookmarked: Bool? { bookmarkedInternal } @@ -105,6 +109,7 @@ extension StatusMO { self.applicationName = status.application?.name self.attachments = status.attachments self.bookmarkedInternal = status.bookmarked ?? false + self.card = status.card self.content = status.content self.createdAt = status.createdAt self.emojis = status.emojis diff --git a/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents index 00a21a5c..6a75df8f 100644 --- a/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents +++ b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -44,6 +44,7 @@ + @@ -74,7 +75,7 @@ - + \ No newline at end of file diff --git a/Tusker/Views/Status/BaseStatusTableViewCell.swift b/Tusker/Views/Status/BaseStatusTableViewCell.swift index d3cfd2af..a607028b 100644 --- a/Tusker/Views/Status/BaseStatusTableViewCell.swift +++ b/Tusker/Views/Status/BaseStatusTableViewCell.swift @@ -32,6 +32,7 @@ class BaseStatusTableViewCell: UITableViewCell { @IBOutlet weak var contentWarningLabel: EmojiLabel! @IBOutlet weak var collapseButton: UIButton! @IBOutlet weak var contentTextView: StatusContentTextView! + @IBOutlet weak var cardView: StatusCardView! @IBOutlet weak var attachmentsView: AttachmentsContainerView! @IBOutlet weak var replyButton: UIButton! @IBOutlet weak var favoriteButton: UIButton! @@ -143,6 +144,10 @@ class BaseStatusTableViewCell: UITableViewCell { updateUI(account: account) updateUIForPreferences(account: account, status: status) + cardView.card = status.card + cardView.isHidden = status.card == nil + cardView.navigationDelegate = navigationDelegate + attachmentsView.updateUI(status: status) attachmentsView.isAccessibilityElement = status.attachments.count > 0 attachmentsView.accessibilityLabel = String(format: NSLocalizedString("%d attachments", comment: "status attachments count accessibility label"), status.attachments.count) @@ -265,6 +270,7 @@ class BaseStatusTableViewCell: UITableViewCell { self.collapsed = collapsed contentTextView.isHidden = collapsed + cardView.isHidden = cardView.card == nil || collapsed attachmentsView.isHidden = attachmentsView.attachments.count == 0 || collapsed let buttonImage = UIImage(systemName: collapsed ? "chevron.down" : "chevron.up")! diff --git a/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib b/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib index 25784c1a..aa9db08b 100644 --- a/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib +++ b/Tusker/Views/Status/ConversationMainStatusTableViewCell.xib @@ -96,6 +96,13 @@ +