import UIKit
// MARK: - DetailsHeaderView.Configuration
extension DetailsHeaderView {
struct Configuration {
/// Show debug background colors
let debug = false
let defaultSpacing: CGFloat = 35
let smallerSpacing: CGFloat = 24
let topMargin: CGFloat = 0
// defaultSpacing - spacing on top of first cell (i.e. 35 - 17)
let bottomMargin: CGFloat = 18
}
}
/// Header view for a details screen
///
/// - Note: This views margins don't include safe areas automatically. Either set them yourself or set constraints to
/// `safeAreaLayoutGuide`s.
final class DetailsHeaderView: UIStackView {
/// Set to update shown profile
var profileContentConfiguration: DetailsHeaderProfileView.ContentConfiguration {
didSet {
detailsHeaderProfileView.contentConfiguration = profileContentConfiguration
}
}
// MARK: - Private properties
private let profilePictureTapped: () -> Void
private let quickActions: [QuickAction]
private let mediaAndPollsQuickActions: [QuickAction]
private let configuration: Configuration
// MARK: - Subviews
private lazy var detailsHeaderProfileView = DetailsHeaderProfileView(
with: profileContentConfiguration,
profilePictureTapped: profilePictureTapped
)
private lazy var quickActionsView = QuickActionsView(quickActions: quickActions)
private lazy var mediaAndPollsQuickActionsView = QuickActionsView(
quickActions: mediaAndPollsQuickActions,
shadow: false
)
// MARK: - Initialization
init(
with contentConfiguration: DetailsHeaderProfileView.ContentConfiguration,
profilePictureTapped: @escaping () -> Void,
quickActions: [QuickAction] = [],
mediaAndPollsQuickActions: [QuickAction] = [],
configuration: Configuration = Configuration()
) {
self.profileContentConfiguration = contentConfiguration
self.profilePictureTapped = profilePictureTapped
self.quickActions = quickActions
self.mediaAndPollsQuickActions = mediaAndPollsQuickActions
self.configuration = configuration
super.init(frame: .zero)
configureView()
}
@available(*, unavailable, message: "Use init(for:delegate:with:)")
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Configuration
private func configureView() {
axis = .vertical
spacing = configuration.defaultSpacing
directionalLayoutMargins = NSDirectionalEdgeInsets(
top: configuration.topMargin,
leading: 0,
bottom: configuration.bottomMargin,
trailing: 0
)
isLayoutMarginsRelativeArrangement = true
if configuration.debug {
backgroundColor = .systemGreen
}
addArrangedSubview(detailsHeaderProfileView)
setCustomSpacing(configuration.smallerSpacing, after: detailsHeaderProfileView)
if !quickActions.isEmpty {
addArrangedSubview(quickActionsView)
}
if !mediaAndPollsQuickActions.isEmpty {
addArrangedSubview(mediaAndPollsQuickActionsView)
}
bringSubviewToFront(detailsHeaderProfileView)
}
// MARK: - Update
func reloadQuickActions() {
quickActionsView.reload()
}
// MARK: - Action
func showThreemaTypeTips() {
// Checking both tips at once is not an issue, they can never be shown togheter
detailsHeaderProfileView.showThreemaTypeTip()
detailsHeaderProfileView.showThreemaWorkAvailabilityStatusTip()
}
}
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland