diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index f5944b262..302687811 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -117,6 +117,7 @@ 7B5233C6290636D700F8F375 /* _011_DisappearingMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5233C5290636D700F8F375 /* _011_DisappearingMessage.swift */; }; 7B7037432834B81F000DCF35 /* ReactionContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7037422834B81F000DCF35 /* ReactionContainerView.swift */; }; 7B7037452834BCC0000DCF35 /* ReactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7037442834BCC0000DCF35 /* ReactionView.swift */; }; + 7B71A98F2925E2A600E54854 /* SessionFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B71A98E2925E2A600E54854 /* SessionFooterView.swift */; }; 7B7CB18E270D066F0079FF93 /* IncomingCallBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */; }; 7B7CB190270FB2150079FF93 /* MiniCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18F270FB2150079FF93 /* MiniCallView.swift */; }; 7B7CB192271508AD0079FF93 /* CallRingTonePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */; }; @@ -1188,6 +1189,7 @@ 7B5233C5290636D700F8F375 /* _011_DisappearingMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _011_DisappearingMessage.swift; sourceTree = ""; }; 7B7037422834B81F000DCF35 /* ReactionContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionContainerView.swift; sourceTree = ""; }; 7B7037442834BCC0000DCF35 /* ReactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionView.swift; sourceTree = ""; }; + 7B71A98E2925E2A600E54854 /* SessionFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionFooterView.swift; sourceTree = ""; }; 7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallBanner.swift; sourceTree = ""; }; 7B7CB18F270FB2150079FF93 /* MiniCallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniCallView.swift; sourceTree = ""; }; 7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallRingTonePlayer.swift; sourceTree = ""; }; @@ -3864,6 +3866,7 @@ FD37EA0A28AB12E2003AE748 /* SessionCell.swift */, FD71164728E2CE8700B47552 /* SessionCell+AccessoryView.swift */, FD71164528E2CC1300B47552 /* SessionHighlightingBackgroundLabel.swift */, + 7B71A98E2925E2A600E54854 /* SessionFooterView.swift */, ); path = Views; sourceTree = ""; @@ -5672,6 +5675,7 @@ FD71163F28E2C82C00B47552 /* SessionHeaderView.swift in Sources */, B877E24226CA12910007970A /* CallVC.swift in Sources */, 7BA6890D27325CCC00EFC32F /* SessionCallManager+CXCallController.swift in Sources */, + 7B71A98F2925E2A600E54854 /* SessionFooterView.swift in Sources */, C374EEEB25DA3CA70073A857 /* ConversationTitleView.swift in Sources */, FD716E7128505E5200C96BF4 /* MessageRequestsCell.swift in Sources */, B88FA7F2260C3EB10049422F /* OpenGroupSuggestionGrid.swift in Sources */, diff --git a/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift b/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift index 5efd6b58b..9012bebee 100644 --- a/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift +++ b/Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift @@ -29,6 +29,14 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel UIView? { + let section: SectionModel = viewModel.settingsData[section] + + if let footerString = section.model.footer { + let result: SessionFooterView = tableView.dequeueHeaderFooterView(type: SessionFooterView.self) + result.update(title: footerString) + + return result + } + + return UIView() + } + // MARK: - UITableViewDelegate func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { @@ -458,6 +472,12 @@ class SessionTableViewController CGFloat { + let section: SectionModel = viewModel.settingsData[section] + + return section.model.footer == nil ? 0 : UITableView.automaticDimension + } + func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension } diff --git a/Session/Shared/Types/SessionTableSection.swift b/Session/Shared/Types/SessionTableSection.swift index b0f117269..2b4802912 100644 --- a/Session/Shared/Types/SessionTableSection.swift +++ b/Session/Shared/Types/SessionTableSection.swift @@ -6,11 +6,13 @@ import DifferenceKit protocol SessionTableSection: Differentiable { var title: String? { get } var style: SessionTableSectionStyle { get } + var footer: String? { get } } extension SessionTableSection { var title: String? { nil } var style: SessionTableSectionStyle { .none } + var footer: String? { nil } } public enum SessionTableSectionStyle: Differentiable { diff --git a/Session/Shared/Views/SessionFooterView.swift b/Session/Shared/Views/SessionFooterView.swift new file mode 100644 index 000000000..3508a724b --- /dev/null +++ b/Session/Shared/Views/SessionFooterView.swift @@ -0,0 +1,89 @@ +// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. + +import UIKit +import SessionUIKit + +class SessionFooterView: UITableViewHeaderFooterView { + private lazy var emptyHeightConstraint: NSLayoutConstraint = self.heightAnchor + .constraint(equalToConstant: (Values.verySmallSpacing * 2)) + private lazy var filledHeightConstraint: NSLayoutConstraint = self.heightAnchor + .constraint(greaterThanOrEqualToConstant: Values.mediumSpacing) + + // MARK: - UI + + private let stackView: UIStackView = { + let result: UIStackView = UIStackView() + result.translatesAutoresizingMaskIntoConstraints = false + result.axis = .vertical + result.distribution = .fill + result.alignment = .fill + result.isLayoutMarginsRelativeArrangement = true + + return result + }() + + private let titleLabel: UILabel = { + let result: UILabel = UILabel() + result.translatesAutoresizingMaskIntoConstraints = false + result.font = .systemFont(ofSize: Values.verySmallFontSize) + result.textAlignment = .center + result.numberOfLines = 0 + result.themeTextColor = .textSecondary + + return result + }() + + // MARK: - Initialization + + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + + self.backgroundView = UIView() + self.backgroundView?.themeBackgroundColor = .backgroundPrimary + + addSubview(stackView) + + stackView.addArrangedSubview(titleLabel) + + setupLayout() + } + + required init?(coder: NSCoder) { + fatalError("use init(reuseIdentifier:) instead") + } + + private func setupLayout() { + stackView.pin(to: self) + } + + // MARK: - Content + + public func update( + style: SessionCell.Style = .rounded, + title: String? + ) { + let titleIsEmpty: Bool = (title ?? "").isEmpty + let edgePadding: CGFloat = { + switch style { + case .rounded: + // Align to the start of the text in the cell + return (Values.largeSpacing + Values.mediumSpacing) + + case .edgeToEdge, .roundedEdgeToEdge: return Values.largeSpacing + } + }() + + titleLabel.text = title + titleLabel.isHidden = titleIsEmpty + stackView.layoutMargins = UIEdgeInsets( + top: (titleIsEmpty ? Values.verySmallSpacing : Values.mediumSpacing), + left: edgePadding, + bottom: (titleIsEmpty ? Values.verySmallSpacing : Values.mediumSpacing), + right: edgePadding + ) + emptyHeightConstraint.isActive = titleIsEmpty + filledHeightConstraint.isActive = !titleIsEmpty + + self.layoutIfNeeded() + } +}