chore: update status timeline margin

This commit is contained in:
CMK 2022-02-18 17:49:20 +08:00
parent b52f969c05
commit a1b9ac8394
14 changed files with 210 additions and 205 deletions

View File

@ -482,7 +482,6 @@
DBB45B5627B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5527B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift */; };
DBB45B5927B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5827B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift */; };
DBB45B5B27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5A27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift */; };
DBB45B5E27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5D27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift */; };
DBB45B6027B50A4F002DC5A7 /* RecommendAccountItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5F27B50A4F002DC5A7 /* RecommendAccountItem.swift */; };
DBB45B6227B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */; };
DBB525082611EAC0002F1F29 /* Tabman in Frameworks */ = {isa = PBXBuildFile; productRef = DBB525072611EAC0002F1F29 /* Tabman */; };
@ -1230,7 +1229,6 @@
DBB45B5527B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewVideoViewController.swift; sourceTree = "<group>"; };
DBB45B5827B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewVideoViewModel.swift; sourceTree = "<group>"; };
DBB45B5A27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewTransitionViewController.swift; sourceTree = "<group>"; };
DBB45B5D27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveMarginStatusTableViewCell.swift; sourceTree = "<group>"; };
DBB45B5F27B50A4F002DC5A7 /* RecommendAccountItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendAccountItem.swift; sourceTree = "<group>"; };
DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SuggestionAccountViewModel+Diffable.swift"; sourceTree = "<group>"; };
DBB5250D2611EBAF002F1F29 /* ProfileSegmentedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileSegmentedViewController.swift; sourceTree = "<group>"; };
@ -1745,7 +1743,6 @@
DBE3CDBA261C427900430CC6 /* TimelineHeaderTableViewCell.swift */,
DB6B750327300B4000C70B6E /* TimelineFooterTableViewCell.swift */,
DB02CDAA26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift */,
DBB45B5D27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift */,
);
path = TableviewCell;
sourceTree = "<group>";
@ -3841,7 +3838,6 @@
DBA465952696E387002B41DB /* AppPreference.swift in Sources */,
2D8434F525FF465D00EECE90 /* HomeTimelineNavigationBarTitleViewModel.swift in Sources */,
DB938F0F2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift in Sources */,
DBB45B5E27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift in Sources */,
DB6180F226391CF40018D199 /* MediaPreviewImageViewModel.swift in Sources */,
DBA5E7A3263AD0A3004598BB /* PhotoLibraryService.swift in Sources */,
DBD5B1F627BCD3D200BD6B38 /* SuggestionAccountTableViewCell+ViewModel.swift in Sources */,

View File

@ -7,7 +7,7 @@
<key>AppShared.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>29</integer>
<integer>19</integer>
</dict>
<key>CoreDataStack.xcscheme_^#shared#^_</key>
<dict>
@ -97,7 +97,7 @@
<key>MastodonIntent.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>28</integer>
<integer>20</integer>
</dict>
<key>MastodonIntents.xcscheme_^#shared#^_</key>
<dict>
@ -117,7 +117,7 @@
<key>ShareActionExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>30</integer>
<integer>18</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>

View File

@ -36,7 +36,7 @@ extension NotificationTableViewCell {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): did layout for new cell")
notificationView.statusView.frame.size.width = tableView.frame.width - containerViewHorizontalMargin
notificationView.quoteStatusView.frame.size.width = tableView.frame.width - StatusView.containerLayoutMargin.left - StatusView.containerLayoutMargin.right - containerViewHorizontalMargin
notificationView.quoteStatusView.frame.size.width = tableView.frame.width - 2 * StatusView.containerLayoutMargin - containerViewHorizontalMargin
}
switch viewModel.value {

View File

@ -26,9 +26,6 @@ final class UserTimelineViewController: UIViewController, NeedsDependency, Media
lazy var tableView: UITableView = {
let tableView = UITableView()
tableView.register(StatusTableViewCell.self, forCellReuseIdentifier: String(describing: StatusTableViewCell.self))
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
tableView.register(TimelineHeaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineHeaderTableViewCell.self))
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 100
tableView.separatorStyle = .none

View File

@ -1,45 +0,0 @@
//
// AdaptiveMarginStatusTableViewCell.swift
// Mastodon
//
// Created by MainasuK on 2022-2-10.
//
import UIKit
import MastodonUI
protocol AdaptiveContainerMarginTableViewCell: UITableViewCell {
associatedtype ContainerView: UIView
static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { get }
var containerView: ContainerView { get }
var containerViewLeadingLayoutConstraint: NSLayoutConstraint! { get set }
var containerViewTrailingLayoutConstraint: NSLayoutConstraint! { get set }
}
extension AdaptiveContainerMarginTableViewCell {
static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { 64 }
func setupContainerViewMarginConstraints() {
containerViewLeadingLayoutConstraint = containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
containerViewTrailingLayoutConstraint = contentView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
}
func updateContainerViewMarginConstraints() {
guard traitCollection.userInterfaceIdiom != .phone,
traitCollection.horizontalSizeClass == .regular
else {
containerViewLeadingLayoutConstraint.constant = 0
containerViewTrailingLayoutConstraint.constant = 0
return
}
containerViewLeadingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass
containerViewTrailingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass
}
var containerViewHorizontalMargin: CGFloat {
containerViewLeadingLayoutConstraint.constant + containerViewTrailingLayoutConstraint.constant
}
}

View File

@ -28,20 +28,6 @@ final class StatusTableViewCell: UITableViewCell {
var containerViewLeadingLayoutConstraint: NSLayoutConstraint!
var containerViewTrailingLayoutConstraint: NSLayoutConstraint!
// var isFiltered: Bool = false {
// didSet {
// configure(isFiltered: isFiltered)
// }
// }
//
// let filteredLabel: UILabel = {
// let label = UILabel()
// label.textColor = Asset.Colors.Label.secondary.color
// label.text = L10n.Common.Controls.Timeline.filtered
// label.font = .preferredFont(forTextStyle: .body)
// return label
// }()
//
override func prepareForReuse() {
super.prepareForReuse()
@ -71,7 +57,6 @@ extension StatusTableViewCell {
statusView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(statusView)
setupContainerViewMarginConstraints()
updateContainerViewMarginConstraints()
NSLayoutConstraint.activate([
statusView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16),
containerViewLeadingLayoutConstraint,
@ -79,6 +64,7 @@ extension StatusTableViewCell {
statusView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
statusView.setup(style: .inline)
updateContainerViewMarginConstraints()
separatorLine.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(separatorLine)

View File

@ -58,7 +58,6 @@ extension StatusThreadRootTableViewCell {
statusView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(statusView)
setupContainerViewMarginConstraints()
updateContainerViewMarginConstraints()
NSLayoutConstraint.activate([
statusView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16),
containerViewLeadingLayoutConstraint,
@ -66,6 +65,7 @@ extension StatusThreadRootTableViewCell {
statusView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
statusView.setup(style: .plain)
updateContainerViewMarginConstraints()
separatorLine.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(separatorLine)
@ -108,7 +108,6 @@ extension StatusThreadRootTableViewCell {
statusView.mediaGridContainerView,
statusView.pollTableView,
statusView.pollStatusStackView,
statusView.statusVisibilityView,
statusView.actionToolbarContainer,
statusView.statusMetricView
]
@ -123,10 +122,6 @@ extension StatusThreadRootTableViewCell {
elements.removeAll(where: { $0 === statusView.contentMetaText.textView })
}
if statusView.statusVisibilityView.isHidden {
elements.removeAll(where: { $0 === statusView.statusVisibilityView })
}
if statusView.viewModel.pollItems.isEmpty {
elements.removeAll(where: { $0 === statusView.pollTableView })
elements.removeAll(where: { $0 === statusView.pollStatusStackView })

View File

@ -0,0 +1,56 @@
//
// AdaptiveMarginStatusTableViewCell.swift
//
//
// Created by MainasuK on 2022-2-18.
//
import UIKit
public protocol AdaptiveContainerView: UIView {
func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool)
}
public protocol AdaptiveContainerMarginTableViewCell: UITableViewCell {
associatedtype ContainerView: AdaptiveContainerView
static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { get }
var containerView: ContainerView { get }
var containerViewLeadingLayoutConstraint: NSLayoutConstraint! { get set }
var containerViewTrailingLayoutConstraint: NSLayoutConstraint! { get set }
}
extension AdaptiveContainerMarginTableViewCell {
public static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { 64 }
public func setupContainerViewMarginConstraints() {
containerViewLeadingLayoutConstraint = containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor)
containerViewTrailingLayoutConstraint = contentView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
}
public func updateContainerViewMarginConstraints() {
func setupContainerForPhone() {
containerView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: true) // add inner margin for phone
containerViewLeadingLayoutConstraint.constant = 0 // remove outer margin for phone
containerViewTrailingLayoutConstraint.constant = 0
}
switch traitCollection.userInterfaceIdiom {
case .phone:
setupContainerForPhone()
default:
guard traitCollection.horizontalSizeClass == .regular else {
setupContainerForPhone()
return
}
containerView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: false) // remove margin for iPad
containerViewLeadingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass // add outer margin for iPad
containerViewTrailingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass
}
}
public var containerViewHorizontalMargin: CGFloat {
containerViewLeadingLayoutConstraint.constant + containerViewTrailingLayoutConstraint.constant
}
}

View File

@ -0,0 +1,55 @@
//
// AdaptiveMarginContainerView.swift
//
//
// Created by MainasuK on 2022-2-18.
//
import UIKit
public final class AdaptiveMarginContainerView: UIView {
public var margin: CGFloat = 0 {
didSet { updateConstraints() }
}
public var contentView: UIView? {
didSet {
guard let contentView = contentView else { return }
guard contentView.superview == nil else { return }
contentView.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentView)
let _leadingLayoutConstraint = contentView.leadingAnchor.constraint(equalTo: leadingAnchor)
let _trailingLayoutConstraint = trailingAnchor.constraint(equalTo: contentView.trailingAnchor)
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: topAnchor),
_leadingLayoutConstraint,
_trailingLayoutConstraint,
contentView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
leadingLayoutConstraint = _leadingLayoutConstraint
trailingLayoutConstraint = _trailingLayoutConstraint
updateConstraints()
}
}
var leadingLayoutConstraint: NSLayoutConstraint?
var trailingLayoutConstraint: NSLayoutConstraint?
}
extension AdaptiveMarginContainerView {
public override func updateConstraints() {
super.updateConstraints()
leadingLayoutConstraint?.constant = margin
trailingLayoutConstraint?.constant = margin
}
}

View File

@ -22,6 +22,7 @@ public final class MediaView: UIView {
formatter.allowedUnits = [.minute, .second]
return formatter
}()
public static let placeholderImage = UIImage.placeholder(color: .systemGray6)
public let container = TouchBlockingView()
@ -154,7 +155,10 @@ extension MediaView {
.receive(on: DispatchQueue.main)
.sink { [weak self] isReveal, previewImage, blurhashImage in
guard let self = self else { return }
let image = isReveal ? (previewImage ?? blurhashImage) : blurhashImage
let image = isReveal ?
(previewImage ?? blurhashImage ?? MediaView.placeholderImage) :
(blurhashImage ?? MediaView.placeholderImage)
self.imageView.image = image
}
.store(in: &configuration.disposeBag)
@ -204,30 +208,6 @@ extension MediaView {
assetURL: info.previewURL
)
bindImage(configuration: configuration, info: imageInfo)
// indicatorBlurEffectView.translatesAutoresizingMaskIntoConstraints = false
// imageView.addSubview(indicatorBlurEffectView)
// NSLayoutConstraint.activate([
// imageView.trailingAnchor.constraint(equalTo: indicatorBlurEffectView.trailingAnchor, constant: 11),
// imageView.bottomAnchor.constraint(equalTo: indicatorBlurEffectView.bottomAnchor, constant: 8),
// ])
// setupIndicatorViewHierarchy()
// playerIndicatorLabel.attributedText = {
// let imageAttachment = NSTextAttachment(image: UIImage(systemName: "play.fill")!)
// let imageAttributedString = AttributedString(NSAttributedString(attachment: imageAttachment))
// let duration: String = {
// guard let durationMS = info.durationMS else { return "" }
// let timeInterval = TimeInterval(durationMS / 1000)
// guard timeInterval > 0 else { return "" }
// guard let text = MediaView.durationFormatter.string(from: timeInterval) else { return "" }
// return " \(text)"
// }()
// let textAttributedString = AttributedString("\(duration)")
// var attributedString = imageAttributedString + textAttributedString
// attributedString.foregroundColor = .secondaryLabel
// return NSAttributedString(attributedString)
// }()
}
private func layoutBlurhash() {

View File

@ -136,7 +136,7 @@ public final class NotificationView: UIView {
extension NotificationView {
private func _init() {
// container: V - [ author container | (authorContainerViewBottomPaddingView) | statusView | quoteStatusView ]
containerStackView.layoutMargins = StatusView.containerLayoutMargin
// containerStackView.layoutMargins = StatusView.containerLayoutMargin
containerStackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(containerStackView)
@ -228,9 +228,9 @@ extension NotificationView {
containerStackView.addArrangedSubview(quoteStatusViewContainerView)
quoteStatusViewContainerView.layoutMargins = UIEdgeInsets(
top: 0,
left: StatusView.containerLayoutMargin.left,
left: StatusView.containerLayoutMargin,
bottom: 16,
right: StatusView.containerLayoutMargin.right
right: StatusView.containerLayoutMargin
)
quoteBackgroundView.layoutMargins = UIEdgeInsets(top: 16, left: 0, bottom: 0, right: 0)
@ -297,6 +297,13 @@ extension NotificationView {
}
// MARK: - AdaptiveContainerView
extension NotificationView: AdaptiveContainerView {
public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) {
statusView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: isEnabled)
}
}
extension NotificationView {
public typealias AuthorMenuContext = StatusView.AuthorMenuContext

View File

@ -71,8 +71,8 @@ extension StatusMetricView {
addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: topAnchor, constant: 8),
containerStackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor),
bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 12),
])

View File

@ -24,19 +24,15 @@ public protocol StatusViewDelegate: AnyObject {
func statusView(_ statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action)
func statusView(_ statusView: StatusView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action)
func statusView(_ statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView)
// func statusView(_ statusView: StatusView, spoilerBannerViewDidPressed bannerView: SpoilerBannerView)
func statusView(_ statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaSensitiveButtonDidPressed button: UIButton)
// a11y
func statusView(_ statusView: StatusView, accessibilityActivate: Void)
// func statusView(_ statusView: StatusView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
// func statusView(_ statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
}
public final class StatusView: UIView {
public static let containerLayoutMargin = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
public static let containerLayoutMargin: CGFloat = 16
let logger = Logger(subsystem: "StatusView", category: "View")
@ -61,6 +57,7 @@ public final class StatusView: UIView {
}()
// header
let headerAdaptiveMarginContainerView = AdaptiveMarginContainerView()
public let headerContainerView = UIView()
// header icon
@ -75,6 +72,7 @@ public final class StatusView: UIView {
let headerInfoLabel = MetaLabel(style: .statusHeader)
// author
let authorAdaptiveMarginContainerView = AdaptiveMarginContainerView()
let authorContainerView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .horizontal
@ -122,6 +120,7 @@ public final class StatusView: UIView {
}()
// content
let contentAdaptiveMarginContainerView = AdaptiveMarginContainerView()
let contentContainer = UIStackView()
public let contentMetaText: MetaText = {
let metaText = MetaText()
@ -160,7 +159,8 @@ public final class StatusView: UIView {
public let mediaGridContainerView = MediaGridContainerView()
// poll
public let pollContainerView = UIStackView()
let pollAdaptiveMarginContainerView = AdaptiveMarginContainerView()
let pollContainerView = UIStackView()
public let pollTableView: UITableView = {
let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
tableView.register(PollOptionTableViewCell.self, forCellReuseIdentifier: String(describing: PollOptionTableViewCell.self))
@ -213,17 +213,13 @@ public final class StatusView: UIView {
indicatorView.stopAnimating()
return indicatorView
}()
// visibility
public let statusVisibilityView = StatusVisibilityView()
// spoiler banner
// public let spoilerBannerView = SpoilerBannerView()
// toolbar
let actionToolbarAdaptiveMarginContainerView = AdaptiveMarginContainerView()
public let actionToolbarContainer = ActionToolbarContainer()
// metric
let statusMetricViewAdaptiveMarginContainerView = AdaptiveMarginContainerView()
public let statusMetricView = StatusMetricView()
// filter hint
@ -252,13 +248,12 @@ public final class StatusView: UIView {
}
}
headerContainerView.isHidden = true
contentSensitiveeToggleButton.isHidden = true
setHeaderDisplay(isDisplay: false)
setContentSensitiveeToggleButtonDisplay(isDisplay: false)
setSpoilerOverlayViewHidden(isHidden: true)
mediaContainerView.isHidden = true
pollContainerView.isHidden = true
statusVisibilityView.isHidden = true
filterHintLabel.isHidden = true
setMediaDisplay(isDisplay: false)
setPollDisplay(isDisplay: false)
setFilterHintLabelDisplay(isDisplay: false)
}
public override init(frame: CGRect) {
@ -323,12 +318,6 @@ extension StatusView {
])
pollTableView.delegate = self
pollVoteButton.addTarget(self, action: #selector(StatusView.pollVoteButtonDidPressed(_:)), for: .touchUpInside)
// statusSpoilerBannerView
// let spoilerBannerViewTapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer
// spoilerBannerView.addGestureRecognizer(spoilerBannerViewTapGestureRecognizer)
// spoilerBannerViewTapGestureRecognizer.addTarget(self, action: #selector(StatusView.spoilerBannerViewTapGestureRecognizerHandler(_:)))
// toolbar
actionToolbarContainer.delegate = self
}
@ -362,11 +351,6 @@ extension StatusView {
delegate?.statusView(self, spoilerOverlayViewDidPressed: spoilerOverlayView)
}
// @objc private func spoilerBannerViewTapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) {
// logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
// delegate?.statusView(self, spoilerBannerViewDidPressed: spoilerBannerView)
// }
}
extension StatusView {
@ -408,22 +392,23 @@ extension StatusView.Style {
private func base(statusView: StatusView) {
// container: V - [ header container | author container | content container | media container | pollTableView | actionToolbarContainer ]
statusView.containerStackView.layoutMargins = StatusView.containerLayoutMargin
// header container: H - [ icon | label ]
statusView.headerContainerView.preservesSuperviewLayoutMargins = true
statusView.containerStackView.addArrangedSubview(statusView.headerContainerView)
statusView.headerAdaptiveMarginContainerView.contentView = statusView.headerContainerView
statusView.headerAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
statusView.containerStackView.addArrangedSubview(statusView.headerAdaptiveMarginContainerView)
statusView.headerIconImageView.translatesAutoresizingMaskIntoConstraints = false
statusView.headerInfoLabel.translatesAutoresizingMaskIntoConstraints = false
statusView.headerContainerView.addSubview(statusView.headerIconImageView)
statusView.headerContainerView.addSubview(statusView.headerInfoLabel)
NSLayoutConstraint.activate([
statusView.headerIconImageView.leadingAnchor.constraint(equalTo: statusView.headerContainerView.layoutMarginsGuide.leadingAnchor),
statusView.headerIconImageView.leadingAnchor.constraint(equalTo: statusView.headerContainerView.leadingAnchor),
statusView.headerIconImageView.heightAnchor.constraint(equalTo: statusView.headerInfoLabel.heightAnchor, multiplier: 1.0).priority(.required - 1),
statusView.headerIconImageView.widthAnchor.constraint(equalTo: statusView.headerIconImageView.heightAnchor, multiplier: 1.0).priority(.required - 1),
statusView.headerInfoLabel.topAnchor.constraint(equalTo: statusView.headerContainerView.topAnchor),
statusView.headerInfoLabel.leadingAnchor.constraint(equalTo: statusView.headerIconImageView.trailingAnchor, constant: 6),
statusView.headerInfoLabel.trailingAnchor.constraint(equalTo: statusView.headerContainerView.layoutMarginsGuide.trailingAnchor),
statusView.headerInfoLabel.trailingAnchor.constraint(equalTo: statusView.headerContainerView.trailingAnchor),
statusView.headerInfoLabel.bottomAnchor.constraint(equalTo: statusView.headerContainerView.bottomAnchor),
statusView.headerInfoLabel.centerYAnchor.constraint(equalTo: statusView.headerIconImageView.centerYAnchor),
])
@ -434,9 +419,10 @@ extension StatusView.Style {
statusView.headerIconImageView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
// author container: H - [ avatarButton | author meta container | contentWarningToggleButton ]
statusView.authorContainerView.preservesSuperviewLayoutMargins = true
statusView.authorContainerView.isLayoutMarginsRelativeArrangement = true
statusView.containerStackView.addArrangedSubview(statusView.authorContainerView)
statusView.authorAdaptiveMarginContainerView.contentView = statusView.authorContainerView
statusView.authorAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
statusView.containerStackView.addArrangedSubview(statusView.authorAdaptiveMarginContainerView)
UIContentSizeCategory.publisher
.sink { category in
statusView.authorContainerView.axis = category > .accessibilityLarge ? .vertical : .horizontal
@ -514,9 +500,9 @@ extension StatusView.Style {
statusView.contentContainer.distribution = .fill
statusView.contentContainer.alignment = .top
statusView.contentContainer.preservesSuperviewLayoutMargins = true
statusView.contentContainer.isLayoutMarginsRelativeArrangement = true
statusView.containerStackView.addArrangedSubview(statusView.contentContainer)
statusView.contentAdaptiveMarginContainerView.contentView = statusView.contentContainer
statusView.contentAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
statusView.containerStackView.addArrangedSubview(statusView.contentAdaptiveMarginContainerView)
statusView.contentContainer.setContentHuggingPriority(.required - 1, for: .vertical)
statusView.contentContainer.setContentCompressionResistancePriority(.required - 1, for: .vertical)
@ -533,7 +519,12 @@ extension StatusView.Style {
])
// media container: V - [ mediaGridContainerView ]
statusView.mediaContainerView.translatesAutoresizingMaskIntoConstraints = false
statusView.containerStackView.addArrangedSubview(statusView.mediaContainerView)
NSLayoutConstraint.activate([
statusView.mediaContainerView.leadingAnchor.constraint(equalTo: statusView.containerStackView.leadingAnchor),
statusView.mediaContainerView.trailingAnchor.constraint(equalTo: statusView.containerStackView.trailingAnchor),
])
statusView.mediaGridContainerView.translatesAutoresizingMaskIntoConstraints = false
statusView.mediaContainerView.addSubview(statusView.mediaGridContainerView)
@ -545,10 +536,10 @@ extension StatusView.Style {
])
// pollContainerView: V - [ pollTableView | pollStatusStackView ]
statusView.pollAdaptiveMarginContainerView.contentView = statusView.pollContainerView
statusView.pollAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
statusView.pollContainerView.axis = .vertical
statusView.pollContainerView.preservesSuperviewLayoutMargins = true
statusView.pollContainerView.isLayoutMarginsRelativeArrangement = true
statusView.containerStackView.addArrangedSubview(statusView.pollContainerView)
statusView.containerStackView.addArrangedSubview(statusView.pollAdaptiveMarginContainerView)
// pollTableView
statusView.pollContainerView.addArrangedSubview(statusView.pollTableView)
@ -567,18 +558,11 @@ extension StatusView.Style {
statusView.pollCountdownLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
statusView.pollVoteButton.setContentHuggingPriority(.defaultHigh + 3, for: .horizontal)
// statusVisibilityView
statusView.statusVisibilityView.preservesSuperviewLayoutMargins = true
statusView.containerStackView.addArrangedSubview(statusView.statusVisibilityView)
// spoilerBannerView
// statusView.spoilerBannerView.preservesSuperviewLayoutMargins = true
// statusView.containerStackView.addArrangedSubview(statusView.spoilerBannerView)
// action toolbar
statusView.actionToolbarAdaptiveMarginContainerView.contentView = statusView.actionToolbarContainer
statusView.actionToolbarAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
statusView.actionToolbarContainer.configure(for: .inline)
statusView.actionToolbarContainer.preservesSuperviewLayoutMargins = true
statusView.containerStackView.addArrangedSubview(statusView.actionToolbarContainer)
statusView.containerStackView.addArrangedSubview(statusView.actionToolbarAdaptiveMarginContainerView)
// filterHintLabel
statusView.filterHintLabel.translatesAutoresizingMaskIntoConstraints = false
@ -591,8 +575,6 @@ extension StatusView.Style {
func inline(statusView: StatusView) {
base(statusView: statusView)
statusView.statusVisibilityView.removeFromSuperview()
}
func plain(statusView: StatusView) {
@ -600,8 +582,10 @@ extension StatusView.Style {
base(statusView: statusView) // override the base style
// statusMetricView
statusView.statusMetricView.layoutMargins = StatusView.containerLayoutMargin
statusView.containerStackView.addArrangedSubview(statusView.statusMetricView)
statusView.statusMetricViewAdaptiveMarginContainerView.contentView = statusView.statusMetricView
statusView.statusMetricViewAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin
statusView.containerStackView.addArrangedSubview(statusView.statusMetricViewAdaptiveMarginContainerView)
UIContentSizeCategory.publisher
.sink { category in
statusView.statusMetricView.containerStackView.axis = category > .accessibilityLarge ? .vertical : .horizontal
@ -614,16 +598,14 @@ extension StatusView.Style {
base(statusView: statusView) // override the base style
statusView.menuButton.removeFromSuperview()
statusView.statusVisibilityView.removeFromSuperview()
statusView.actionToolbarContainer.removeFromSuperview()
statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview()
}
func notification(statusView: StatusView) {
base(statusView: statusView) // override the base style
statusView.headerContainerView.removeFromSuperview()
statusView.authorContainerView.removeFromSuperview()
statusView.statusVisibilityView.removeFromSuperview()
statusView.headerAdaptiveMarginContainerView.removeFromSuperview()
statusView.authorAdaptiveMarginContainerView.removeFromSuperview()
}
func notificationQuote(statusView: StatusView) {
@ -632,8 +614,7 @@ extension StatusView.Style {
statusView.contentContainer.layoutMargins.bottom = 16 // fix contentText align to edge issue
statusView.contentSensitiveeToggleButton.removeFromSuperview()
statusView.menuButton.removeFromSuperview()
statusView.statusVisibilityView.removeFromSuperview()
statusView.actionToolbarContainer.removeFromSuperview()
statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview()
}
func composeStatusReplica(statusView: StatusView) {
@ -641,9 +622,7 @@ extension StatusView.Style {
statusView.avatarButton.isUserInteractionEnabled = false
statusView.menuButton.removeFromSuperview()
statusView.statusVisibilityView.removeFromSuperview()
// statusView.spoilerBannerView.removeFromSuperview()
statusView.actionToolbarContainer.removeFromSuperview()
statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview()
}
func composeStatusAuthor(statusView: StatusView) {
@ -653,24 +632,22 @@ extension StatusView.Style {
statusView.menuButton.removeFromSuperview()
statusView.usernameTrialingDotLabel.removeFromSuperview()
statusView.dateLabel.removeFromSuperview()
statusView.contentContainer.removeFromSuperview()
statusView.contentAdaptiveMarginContainerView.removeFromSuperview()
statusView.spoilerOverlayView.removeFromSuperview()
statusView.mediaContainerView.removeFromSuperview()
statusView.pollContainerView.removeFromSuperview()
statusView.statusVisibilityView.removeFromSuperview()
// statusView.spoilerBannerView.removeFromSuperview()
statusView.actionToolbarContainer.removeFromSuperview()
statusView.pollAdaptiveMarginContainerView.removeFromSuperview()
statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview()
}
}
extension StatusView {
func setHeaderDisplay() {
headerContainerView.isHidden = false
func setHeaderDisplay(isDisplay: Bool = true) {
headerAdaptiveMarginContainerView.isHidden = !isDisplay
}
func setContentSensitiveeToggleButtonDisplay() {
contentSensitiveeToggleButton.isHidden = false
func setContentSensitiveeToggleButtonDisplay(isDisplay: Bool = true) {
contentSensitiveeToggleButton.isHidden = !isDisplay
}
func setSpoilerOverlayViewHidden(isHidden: Bool) {
@ -678,31 +655,35 @@ extension StatusView {
spoilerOverlayView.setComponentHidden(isHidden)
}
func setMediaDisplay() {
mediaContainerView.isHidden = false
func setMediaDisplay(isDisplay: Bool = true) {
mediaContainerView.isHidden = !isDisplay
}
func setPollDisplay() {
pollContainerView.isHidden = false
func setPollDisplay(isDisplay: Bool = true) {
pollAdaptiveMarginContainerView.isHidden = !isDisplay
}
func setVisibilityDisplay() {
statusVisibilityView.isHidden = false
func setFilterHintLabelDisplay(isDisplay: Bool = true) {
filterHintLabel.isHidden = !isDisplay
}
func setFilterHintLabelDisplay() {
filterHintLabel.isHidden = false
}
// content text Width
// container width
public var contentMaxLayoutWidth: CGFloat {
let inset = contentLayoutInset
return frame.width - inset.left - inset.right
return frame.width
}
public var contentLayoutInset: UIEdgeInsets {
// TODO: adaptive iPad regular horizontal size class
return .zero
}
// MARK: - AdaptiveContainerView
extension StatusView: AdaptiveContainerView {
public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) {
let margin = isEnabled ? StatusView.containerLayoutMargin : .zero
headerAdaptiveMarginContainerView.margin = margin
authorAdaptiveMarginContainerView.margin = margin
contentAdaptiveMarginContainerView.margin = margin
pollAdaptiveMarginContainerView.margin = margin
actionToolbarAdaptiveMarginContainerView.margin = margin
statusMetricViewAdaptiveMarginContainerView.margin = margin
}
}

View File

@ -48,10 +48,7 @@ public final class ActionToolbarContainer: UIView {
extension ActionToolbarContainer {
private func _init() {
container.preservesSuperviewLayoutMargins = true
container.isLayoutMarginsRelativeArrangement = true
private func _init() {
container.translatesAutoresizingMaskIntoConstraints = false
addSubview(container)
NSLayoutConstraint.activate([