From 6e8db9586fcd85454d0c3e68acdaafd823e98ba4 Mon Sep 17 00:00:00 2001 From: Justin Mazzocchi <2831158+jzzocc@users.noreply.github.com> Date: Fri, 28 Aug 2020 12:56:28 -0700 Subject: [PATCH] Basic attachments --- Metatext.xcodeproj/project.pbxproj | 52 ++++++++++--- View Models/AttachmentViewModel.swift | 28 +++++++ View Models/StatusViewModel.swift | 3 + Views/Attachments/AttachmentView.swift | 49 ++++++++++++ Views/Attachments/AttachmentsView.swift | 74 +++++++++++++++++++ .../StatusTableViewCell.swift | 5 ++ .../{ => Status Cell}/StatusTableViewCell.xib | 9 ++- .../TouchFallthroughTextView.swift | 0 8 files changed, 207 insertions(+), 13 deletions(-) create mode 100644 View Models/AttachmentViewModel.swift create mode 100644 Views/Attachments/AttachmentView.swift create mode 100644 Views/Attachments/AttachmentsView.swift rename Views/{ => Status Cell}/StatusTableViewCell.swift (98%) rename Views/{ => Status Cell}/StatusTableViewCell.xib (98%) rename Views/{ => Status Cell}/TouchFallthroughTextView.swift (100%) diff --git a/Metatext.xcodeproj/project.pbxproj b/Metatext.xcodeproj/project.pbxproj index e64105a..77fa3a9 100644 --- a/Metatext.xcodeproj/project.pbxproj +++ b/Metatext.xcodeproj/project.pbxproj @@ -7,6 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + D01F41D724F880C400D55A2D /* StatusTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D01F41D424F880C400D55A2D /* StatusTableViewCell.xib */; }; + D01F41D824F880C400D55A2D /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41D524F880C400D55A2D /* StatusTableViewCell.swift */; }; + D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */; }; + D01F41DF24F8868800D55A2D /* AttachmentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41DE24F8868800D55A2D /* AttachmentViewModel.swift */; }; + D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41E224F8889700D55A2D /* AttachmentsView.swift */; }; D03658D124EDD80900AC17EC /* ContextEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03658D024EDD80900AC17EC /* ContextEndpoint+Stubbing.swift */; }; D04FD73924D4A7B4007D572D /* AccountEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73824D4A7B4007D572D /* AccountEndpoint+Stubbing.swift */; }; D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73B24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift */; }; @@ -21,7 +26,7 @@ D074577724D29006004758DB /* MockWebAuthSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* MockWebAuthSession.swift */; }; D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; }; D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift */; }; - D0C7D49624F7616A001EBDBB /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42124F76169001EBDBB /* StatusTableViewCell.swift */; }; + D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; }; D0C7D49724F7616A001EBDBB /* IdentitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42224F76169001EBDBB /* IdentitiesView.swift */; }; D0C7D49824F7616A001EBDBB /* CustomEmojiText.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42324F76169001EBDBB /* CustomEmojiText.swift */; }; D0C7D49924F7616A001EBDBB /* AddIdentityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42424F76169001EBDBB /* AddIdentityView.swift */; }; @@ -30,8 +35,6 @@ D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42724F76169001EBDBB /* RootView.swift */; }; D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42824F76169001EBDBB /* PostingReadingPreferencesView.swift */; }; D0C7D49E24F7616A001EBDBB /* SecondaryNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42924F76169001EBDBB /* SecondaryNavigationView.swift */; }; - D0C7D4A024F7616A001EBDBB /* TouchFallthroughTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42B24F76169001EBDBB /* TouchFallthroughTextView.swift */; }; - D0C7D4A124F7616A001EBDBB /* StatusTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D0C7D42C24F76169001EBDBB /* StatusTableViewCell.xib */; }; D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */; }; D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */; }; D0C7D4A524F7616A001EBDBB /* StatusListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D43124F76169001EBDBB /* StatusListViewController.swift */; }; @@ -171,6 +174,11 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + D01F41D424F880C400D55A2D /* StatusTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatusTableViewCell.xib; sourceTree = ""; }; + D01F41D524F880C400D55A2D /* StatusTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = ""; }; + D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchFallthroughTextView.swift; sourceTree = ""; }; + D01F41DE24F8868800D55A2D /* AttachmentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentViewModel.swift; sourceTree = ""; }; + D01F41E224F8889700D55A2D /* AttachmentsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsView.swift; sourceTree = ""; }; D03658D024EDD80900AC17EC /* ContextEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContextEndpoint+Stubbing.swift"; sourceTree = ""; }; D047FA8C24C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; }; D04FD73824D4A7B4007D572D /* AccountEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountEndpoint+Stubbing.swift"; sourceTree = ""; }; @@ -185,9 +193,9 @@ D074577624D29006004758DB /* MockWebAuthSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockWebAuthSession.swift; sourceTree = ""; }; D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSessionConfiguration+Extensions.swift"; sourceTree = ""; }; D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PreferencesEndpoint+Stubbing.swift"; sourceTree = ""; }; + D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = ""; }; D0C7D41E24F76169001EBDBB /* Metatext.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Metatext.entitlements; sourceTree = ""; }; D0C7D41F24F76169001EBDBB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D0C7D42124F76169001EBDBB /* StatusTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = ""; }; D0C7D42224F76169001EBDBB /* IdentitiesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentitiesView.swift; sourceTree = ""; }; D0C7D42324F76169001EBDBB /* CustomEmojiText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomEmojiText.swift; sourceTree = ""; }; D0C7D42424F76169001EBDBB /* AddIdentityView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddIdentityView.swift; sourceTree = ""; }; @@ -196,8 +204,6 @@ D0C7D42724F76169001EBDBB /* RootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = ""; }; D0C7D42824F76169001EBDBB /* PostingReadingPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostingReadingPreferencesView.swift; sourceTree = ""; }; D0C7D42924F76169001EBDBB /* SecondaryNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationView.swift; sourceTree = ""; }; - D0C7D42B24F76169001EBDBB /* TouchFallthroughTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchFallthroughTextView.swift; sourceTree = ""; }; - D0C7D42C24F76169001EBDBB /* StatusTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatusTableViewCell.xib; sourceTree = ""; }; D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationTypesPreferencesView.swift; sourceTree = ""; }; D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabNavigationView.swift; sourceTree = ""; }; D0C7D43124F76169001EBDBB /* StatusListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusListViewController.swift; sourceTree = ""; }; @@ -328,6 +334,25 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + D01F41D324F8807E00D55A2D /* Status Cell */ = { + isa = PBXGroup; + children = ( + D01F41D524F880C400D55A2D /* StatusTableViewCell.swift */, + D01F41D424F880C400D55A2D /* StatusTableViewCell.xib */, + D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */, + ); + path = "Status Cell"; + sourceTree = ""; + }; + D01F41E024F8885900D55A2D /* Attachments */ = { + isa = PBXGroup; + children = ( + D01F41E224F8889700D55A2D /* AttachmentsView.swift */, + D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */, + ); + path = Attachments; + sourceTree = ""; + }; D047FA7F24C3E21000AF17C5 = { isa = PBXGroup; children = ( @@ -391,6 +416,7 @@ D0C7D42024F76169001EBDBB /* Views */ = { isa = PBXGroup; children = ( + D01F41E024F8885900D55A2D /* Attachments */, D0C7D42424F76169001EBDBB /* AddIdentityView.swift */, D0C7D42324F76169001EBDBB /* CustomEmojiText.swift */, D0C7D42224F76169001EBDBB /* IdentitiesView.swift */, @@ -399,11 +425,9 @@ D0C7D42624F76169001EBDBB /* PreferencesView.swift */, D0C7D42724F76169001EBDBB /* RootView.swift */, D0C7D42924F76169001EBDBB /* SecondaryNavigationView.swift */, + D01F41D324F8807E00D55A2D /* Status Cell */, D0C7D42524F76169001EBDBB /* StatusListView.swift */, - D0C7D42124F76169001EBDBB /* StatusTableViewCell.swift */, - D0C7D42C24F76169001EBDBB /* StatusTableViewCell.xib */, D0C7D42E24F76169001EBDBB /* TabNavigationView.swift */, - D0C7D42B24F76169001EBDBB /* TouchFallthroughTextView.swift */, ); path = Views; sourceTree = ""; @@ -478,6 +502,7 @@ isa = PBXGroup; children = ( D0C7D46024F76169001EBDBB /* AddIdentityViewModel.swift */, + D01F41DE24F8868800D55A2D /* AttachmentViewModel.swift */, D0C7D45F24F76169001EBDBB /* IdentitiesViewModel.swift */, D0C7D45D24F76169001EBDBB /* NotificationTypesPreferencesViewModel.swift */, D0C7D45A24F76169001EBDBB /* PostingReadingPreferencesViewModel.swift */, @@ -767,8 +792,8 @@ buildActionMask = 2147483647; files = ( D0C7D4C524F7616A001EBDBB /* Localizable.strings in Resources */, + D01F41D724F880C400D55A2D /* StatusTableViewCell.xib in Resources */, D054950124EA4FFE008B00A5 /* DevelopmentAssets.xcassets in Resources */, - D0C7D4A124F7616A001EBDBB /* StatusTableViewCell.xib in Resources */, D0C7D4C224F7616A001EBDBB /* Assets.xcassets in Resources */, D0C7D4C624F7616A001EBDBB /* Localizable.stringsdict in Resources */, ); @@ -818,13 +843,13 @@ D0C7D4CA24F7616A001EBDBB /* NotificationTypesPreferencesViewModel.swift in Sources */, D0C7D4EE24F7616A001EBDBB /* MastodonEncoder.swift in Sources */, D0C7D4E624F7616A001EBDBB /* TimelinesEndpoint.swift in Sources */, - D0C7D49624F7616A001EBDBB /* StatusTableViewCell.swift in Sources */, D0C7D4B924F7616A001EBDBB /* Status.swift in Sources */, D0C7D4F424F7616A001EBDBB /* StatusListService.swift in Sources */, D0C7D4B824F7616A001EBDBB /* Application.swift in Sources */, D0C7D4E724F7616A001EBDBB /* AppAuthorizationEndpoint.swift in Sources */, D0C7D4EA24F7616A001EBDBB /* DeletionEndpoint.swift in Sources */, D0C7D4B724F7616A001EBDBB /* TransientStatusCollection.swift in Sources */, + D01F41DF24F8868800D55A2D /* AttachmentViewModel.swift in Sources */, D0C7D4E824F7616A001EBDBB /* AccountEndpoint.swift in Sources */, D0C7D4A324F7616A001EBDBB /* TabNavigationView.swift in Sources */, D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */, @@ -834,9 +859,10 @@ D0C7D4FA24F7616A001EBDBB /* AllIdentitiesService.swift in Sources */, D0C7D4CD24F7616A001EBDBB /* AddIdentityViewModel.swift in Sources */, D03658D124EDD80900AC17EC /* ContextEndpoint+Stubbing.swift in Sources */, - D0C7D4A024F7616A001EBDBB /* TouchFallthroughTextView.swift in Sources */, + D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */, D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */, D0C7D49A24F7616A001EBDBB /* StatusListView.swift in Sources */, + D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */, D0C7D4A524F7616A001EBDBB /* StatusListViewController.swift in Sources */, D0C7D4CC24F7616A001EBDBB /* IdentitiesViewModel.swift in Sources */, D0C7D4E024F7616A001EBDBB /* WebAuthSession.swift in Sources */, @@ -901,6 +927,7 @@ D074577724D29006004758DB /* MockWebAuthSession.swift in Sources */, D0C7D4F924F7616A001EBDBB /* UserNotificationService.swift in Sources */, D0C7D49824F7616A001EBDBB /* CustomEmojiText.swift in Sources */, + D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */, D0C7D4AA24F7616A001EBDBB /* Attachment.swift in Sources */, D0C7D4AF24F7616A001EBDBB /* PushNotification.swift in Sources */, D0C7D4C924F7616A001EBDBB /* TabNavigationViewModel.swift in Sources */, @@ -916,6 +943,7 @@ D0C7D4F324F7616A001EBDBB /* ContextService.swift in Sources */, D0C7D4DD24F7616A001EBDBB /* CodingUserInfoKey+Extensions.swift in Sources */, D0C7D4D824F7616A001EBDBB /* Publisher+Extensions.swift in Sources */, + D01F41D824F880C400D55A2D /* StatusTableViewCell.swift in Sources */, D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */, D0C7D4BE24F7616A001EBDBB /* Unknowable.swift in Sources */, D0C7D4AE24F7616A001EBDBB /* Timeline.swift in Sources */, diff --git a/View Models/AttachmentViewModel.swift b/View Models/AttachmentViewModel.swift new file mode 100644 index 0000000..8c5f958 --- /dev/null +++ b/View Models/AttachmentViewModel.swift @@ -0,0 +1,28 @@ +// Copyright © 2020 Metabolist. All rights reserved. + +import Foundation + +struct AttachmentViewModel { + let attachment: Attachment + + init(attachment: Attachment) { + self.attachment = attachment + } +} + +extension AttachmentViewModel { + var aspectRatio: Double? { + if + let info = attachment.meta?.original, + let width = info.width, + let height = info.height, + width != 0, + height != 0 { + let aspectRatio = Double(width) / Double(height) + + return aspectRatio.isNaN ? nil : aspectRatio + } + + return nil + } +} diff --git a/View Models/StatusViewModel.swift b/View Models/StatusViewModel.swift index 42dbfb6..ffc1b90 100644 --- a/View Models/StatusViewModel.swift +++ b/View Models/StatusViewModel.swift @@ -12,6 +12,7 @@ struct StatusViewModel { let isReblog: Bool let rebloggedByDisplayName: String let rebloggedByDisplayNameEmoji: [Emoji] + let attachmentViewModels: [AttachmentViewModel] let pollOptionTitles: [String] let pollEmoji: [Emoji] var isPinned = false @@ -38,6 +39,8 @@ struct StatusViewModel { ? statusService.status.account.username : statusService.status.account.displayName rebloggedByDisplayNameEmoji = statusService.status.account.emojis + attachmentViewModels = statusService.status.displayStatus.mediaAttachments + .map(AttachmentViewModel.init(attachment:)) pollOptionTitles = statusService.status.displayStatus.poll?.options.map { $0.title } ?? [] pollEmoji = statusService.status.displayStatus.poll?.emojis ?? [] events = eventsInput.eraseToAnyPublisher() diff --git a/Views/Attachments/AttachmentView.swift b/Views/Attachments/AttachmentView.swift new file mode 100644 index 0000000..5fc23c4 --- /dev/null +++ b/Views/Attachments/AttachmentView.swift @@ -0,0 +1,49 @@ +// Copyright © 2020 Metabolist. All rights reserved. + +import UIKit +import Kingfisher + +class AttachmentView: UIView { + let imageView = AnimatedImageView() + let button = UIButton() + let viewModel: AttachmentViewModel + + init(viewModel: AttachmentViewModel) { + self.viewModel = viewModel + + super.init(frame: .zero) + + layoutMargins = .zero + addSubview(imageView) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + imageView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor).isActive = true + imageView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + imageView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor).isActive = true + imageView.contentMode = .scaleAspectFill + imageView.clipsToBounds = true + + addSubview(button) + button.translatesAutoresizingMaskIntoConstraints = false + button.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + button.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor).isActive = true + button.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + button.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor).isActive = true + + let highlightedButtonBackgroundImage = UIColor(white: 0, alpha: 0.5).image() + + button.setBackgroundImage(highlightedButtonBackgroundImage, for: .highlighted) + + switch viewModel.attachment.type { + case .image: + imageView.kf.setImage(with: viewModel.attachment.previewUrl) + default: + break + } + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Views/Attachments/AttachmentsView.swift b/Views/Attachments/AttachmentsView.swift new file mode 100644 index 0000000..c72fbaf --- /dev/null +++ b/Views/Attachments/AttachmentsView.swift @@ -0,0 +1,74 @@ +// Copyright © 2020 Metabolist. All rights reserved. + +import UIKit + +class AttachmentsView: UIView { + private let containerStackView = UIStackView() + private let leftStackView = UIStackView() + private let rightStackView = UIStackView() + + var attachmentViewModels = [AttachmentViewModel]() { + didSet { + for stackView in [leftStackView, rightStackView] { + for view in stackView.arrangedSubviews { + stackView.removeArrangedSubview(view) + view.removeFromSuperview() + } + } + + let attachmentCount = attachmentViewModels.count + + rightStackView.isHidden = attachmentCount == 1 + + for (index, viewModel) in attachmentViewModels.enumerated() { + if attachmentCount == 2 && index == 1 + || attachmentCount == 3 && index != 0 + || attachmentCount > 3 && index % 2 != 0 { + rightStackView.addArrangedSubview(AttachmentView(viewModel: viewModel)) + } else { + leftStackView.addArrangedSubview(AttachmentView(viewModel: viewModel)) + } + } + } + } + + override init(frame: CGRect) { + super.init(frame: frame) + + initializationActions() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + + initializationActions() + } +} + +private extension AttachmentsView { + static let spacing: CGFloat = 4 + static let cornerRadius: CGFloat = 8 + + func initializationActions() { + backgroundColor = .clear + layoutMargins = .zero + clipsToBounds = true + layer.cornerRadius = Self.cornerRadius + addSubview(containerStackView) + containerStackView.translatesAutoresizingMaskIntoConstraints = false + containerStackView.distribution = .fillEqually + containerStackView.spacing = Self.spacing + containerStackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + containerStackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor).isActive = true + containerStackView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + containerStackView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor).isActive = true + leftStackView.distribution = .fillEqually + leftStackView.spacing = Self.spacing + leftStackView.axis = .vertical + rightStackView.distribution = .fillEqually + rightStackView.spacing = Self.spacing + rightStackView.axis = .vertical + containerStackView.addArrangedSubview(leftStackView) + containerStackView.addArrangedSubview(rightStackView) + } +} diff --git a/Views/StatusTableViewCell.swift b/Views/Status Cell/StatusTableViewCell.swift similarity index 98% rename from Views/StatusTableViewCell.swift rename to Views/Status Cell/StatusTableViewCell.swift index fcf53c1..f0b7896 100644 --- a/Views/StatusTableViewCell.swift +++ b/Views/Status Cell/StatusTableViewCell.swift @@ -23,6 +23,7 @@ class StatusTableViewCell: UITableViewCell { @IBOutlet weak var reblogButton: UIButton! @IBOutlet weak var favoriteButton: UIButton! @IBOutlet weak var shareButton: UIButton! + @IBOutlet weak var attachmentsView: AttachmentsView! @IBOutlet weak var cardView: UIView! @IBOutlet weak var cardImageView: UIImageView! @IBOutlet weak var cardTitleLabel: UILabel! @@ -172,6 +173,10 @@ class StatusTableViewCell: UITableViewCell { metaIcon.isHidden = true } + attachmentsView.isHidden = viewModel.attachmentViewModels.count == 0 + attachmentsView.attachmentViewModels = viewModel.attachmentViewModels + setNeedsLayout() + if let cardURL = viewModel.cardURL { cardTitleLabel.text = viewModel.cardTitle cardDescriptionLabel.text = viewModel.cardDescription diff --git a/Views/StatusTableViewCell.xib b/Views/Status Cell/StatusTableViewCell.xib similarity index 98% rename from Views/StatusTableViewCell.xib rename to Views/Status Cell/StatusTableViewCell.xib index 277e102..7867c9b 100644 --- a/Views/StatusTableViewCell.xib +++ b/Views/Status Cell/StatusTableViewCell.xib @@ -200,10 +200,16 @@ - + + + + + + + @@ -481,6 +487,7 @@ + diff --git a/Views/TouchFallthroughTextView.swift b/Views/Status Cell/TouchFallthroughTextView.swift similarity index 100% rename from Views/TouchFallthroughTextView.swift rename to Views/Status Cell/TouchFallthroughTextView.swift