// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import UIKit import SessionUIKit import SessionUtilitiesKit import SessionMessagingKit import SignalUtilitiesKit extension MediaInfoVC { final class MediaInfoView: UIView { private static let cornerRadius: CGFloat = 12 private var attachment: Attachment? private let width: CGFloat = MediaInfoVC.mediaSize - 2 * MediaInfoVC.arrowSize.width // MARK: - UI private lazy var fileIdLabel: UILabel = { let result: UILabel = UILabel() result.font = .systemFont(ofSize: Values.mediumFontSize) result.themeTextColor = .textPrimary return result }() private lazy var fileTypeLabel: UILabel = { let result: UILabel = UILabel() result.font = .systemFont(ofSize: Values.mediumFontSize) result.themeTextColor = .textPrimary return result }() private lazy var fileSizeLabel: UILabel = { let result: UILabel = UILabel() result.font = .systemFont(ofSize: Values.mediumFontSize) result.themeTextColor = .textPrimary return result }() private lazy var resolutionLabel: UILabel = { let result: UILabel = UILabel() result.font = .systemFont(ofSize: Values.mediumFontSize) result.themeTextColor = .textPrimary return result }() private lazy var durationLabel: UILabel = { let result: UILabel = UILabel() result.font = .systemFont(ofSize: Values.mediumFontSize) result.themeTextColor = .textPrimary return result }() // MARK: - Lifecycle init(attachment: Attachment?) { self.attachment = attachment super.init(frame: CGRect.zero) self.accessibilityLabel = "Media info" setUpViewHierarchy() update(attachment: attachment) } override init(frame: CGRect) { preconditionFailure("Use init(attachment:) instead.") } required init?(coder: NSCoder) { preconditionFailure("Use init(attachment:) instead.") } private func setUpViewHierarchy() { let backgroundView: UIView = UIView() backgroundView.clipsToBounds = true backgroundView.themeBackgroundColor = .contextMenu_background backgroundView.layer.cornerRadius = Self.cornerRadius addSubview(backgroundView) backgroundView.pin(to: self) let container: UIView = UIView() container.set(.width, to: self.width) // File ID let fileIdTitleLabel: UILabel = { let result = UILabel() result.font = .boldSystemFont(ofSize: Values.mediumFontSize) result.text = "ATTACHMENT_INFO_FILE_ID".localized() + ":" result.themeTextColor = .textPrimary return result }() let fileIdContainerStackView: UIStackView = UIStackView(arrangedSubviews: [ fileIdTitleLabel, fileIdLabel ]) fileIdContainerStackView.axis = .vertical fileIdContainerStackView.spacing = 6 container.addSubview(fileIdContainerStackView) fileIdContainerStackView.pin([ UIView.HorizontalEdge.leading, UIView.HorizontalEdge.trailing, UIView.VerticalEdge.top ], to: container) // File Type let fileTypeTitleLabel: UILabel = { let result = UILabel() result.font = .boldSystemFont(ofSize: Values.mediumFontSize) result.text = "ATTACHMENT_INFO_FILE_TYPE".localized() + ":" result.themeTextColor = .textPrimary return result }() let fileTypeContainerStackView: UIStackView = UIStackView(arrangedSubviews: [ fileTypeTitleLabel, fileTypeLabel ]) fileTypeContainerStackView.axis = .vertical fileTypeContainerStackView.spacing = 6 container.addSubview(fileTypeContainerStackView) fileTypeContainerStackView.pin(.leading, to: .leading, of: container) fileTypeContainerStackView.pin(.top, to: .bottom, of: fileIdContainerStackView, withInset: Values.largeSpacing) // File Size let fileSizeTitleLabel: UILabel = { let result = UILabel() result.font = .boldSystemFont(ofSize: Values.mediumFontSize) result.text = "ATTACHMENT_INFO_FILE_SIZE".localized() + ":" result.themeTextColor = .textPrimary return result }() let fileSizeContainerStackView: UIStackView = UIStackView(arrangedSubviews: [ fileSizeTitleLabel, fileSizeLabel ]) fileSizeContainerStackView.axis = .vertical fileSizeContainerStackView.spacing = 6 container.addSubview(fileSizeContainerStackView) fileSizeContainerStackView.pin(.trailing, to: .trailing, of: container) fileSizeContainerStackView.pin(.top, to: .bottom, of: fileIdContainerStackView, withInset: Values.largeSpacing) fileSizeContainerStackView.set(.width, to: 90) // Resolution let resolutionTitleLabel: UILabel = { let result = UILabel() result.font = .boldSystemFont(ofSize: Values.mediumFontSize) result.text = "ATTACHMENT_INFO_RESOLUTION".localized() + ":" result.themeTextColor = .textPrimary return result }() let resolutionContainerStackView: UIStackView = UIStackView(arrangedSubviews: [ resolutionTitleLabel, resolutionLabel ]) resolutionContainerStackView.axis = .vertical resolutionContainerStackView.spacing = 6 container.addSubview(resolutionContainerStackView) resolutionContainerStackView.pin(.leading, to: .leading, of: container) resolutionContainerStackView.pin(.top, to: .bottom, of: fileTypeContainerStackView, withInset: Values.largeSpacing) // Duration let durationTitleLabel: UILabel = { let result = UILabel() result.font = .boldSystemFont(ofSize: Values.mediumFontSize) result.text = "ATTACHMENT_INFO_DURATION".localized() + ":" result.themeTextColor = .textPrimary return result }() let durationContainerStackView: UIStackView = UIStackView(arrangedSubviews: [ durationTitleLabel, durationLabel ]) durationContainerStackView.axis = .vertical durationContainerStackView.spacing = 6 container.addSubview(durationContainerStackView) durationContainerStackView.pin(.trailing, to: .trailing, of: container) durationContainerStackView.pin(.top, to: .bottom, of: fileSizeContainerStackView, withInset: Values.largeSpacing) durationContainerStackView.set(.width, to: 90) container.pin(.bottom, to: .bottom, of: durationContainerStackView) backgroundView.addSubview(container) container.pin(to: backgroundView, withInset: Values.largeSpacing) } // MARK: - Interaction public func update(attachment: Attachment?) { guard let attachment: Attachment = attachment else { return } self.attachment = attachment fileIdLabel.text = attachment.serverId fileTypeLabel.text = attachment.contentType fileSizeLabel.text = Format.fileSize(attachment.byteCount) resolutionLabel.text = { guard let width = attachment.width, let height = attachment.height else { return "N/A" } return "\(width)×\(height)" }() durationLabel.text = { guard let duration = attachment.duration else { return "N/A" } return floor(duration).formatted(format: .videoDuration) }() } } }