Skip to content

Commit aa95890

Browse files
authored
Merge pull request #248 from surfstudio/SPT-1477-Add-static-height-by-components
SPT-1477 Добавление SizableItem компонентам
2 parents 6b6cb50 + 2582cf9 commit aa95890

File tree

11 files changed

+343
-24
lines changed

11 files changed

+343
-24
lines changed

Components/Sources/Collection/CollectionWrappedCell.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,23 @@ public final class CollectionWrappedCell<View: ConfigurableItem>: UICollectionVi
2222
public var cachedAlignment: Alignment?
2323

2424
}
25+
26+
// MARK: - CalculatableHeightItem
27+
28+
extension CollectionWrappedCell: CalculatableHeightItem where View: CalculatableHeightItem {
29+
30+
public static func getHeight(forWidth width: CGFloat, with model: Model) -> CGFloat {
31+
return View.getHeight(forWidth: width, with: model)
32+
}
33+
34+
}
35+
36+
// MARK: - CalculatableWidthItem
37+
38+
extension CollectionWrappedCell: CalculatableWidthItem where View: CalculatableWidthItem {
39+
40+
public static func getWidth(forHeight height: CGFloat, with model: View.Model) -> CGFloat {
41+
return View.getWidth(forHeight: height, with: model)
42+
}
43+
44+
}

Components/Sources/Common/Extensions/CollectionWrappedCell+RDDM.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,37 @@ public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem
1717
}
1818

1919
}
20+
21+
// MARK: - CalculatableHeightItem
22+
23+
public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableHeightItem {
24+
25+
func tableCalculatableHightGenerator(
26+
with model: Base.Model,
27+
width: CGFloat,
28+
and registerType: CellRegisterType = .nib
29+
) -> CalculatableHeightCollectionCellGenerator<CollectionWrappedCell<Base>> {
30+
31+
CalculatableHeightCollectionCellGenerator<CollectionWrappedCell<Base>>(with: model,
32+
width: width,
33+
registerType: registerType)
34+
}
35+
36+
}
37+
38+
// MARK: - CalculatableWidthItem
39+
40+
public extension StaticDataDisplayWrapper where Base: UIView & ConfigurableItem & CalculatableWidthItem {
41+
42+
func tableCalculatableWidthGenerator(
43+
with model: Base.Model,
44+
height: CGFloat,
45+
and registerType: CellRegisterType = .nib
46+
) -> CalculatableWidthCollectionCellGenerator<CollectionWrappedCell<Base>> {
47+
48+
CalculatableWidthCollectionCellGenerator<CollectionWrappedCell<Base>>(with: model,
49+
height: height,
50+
registerType: registerType)
51+
}
52+
53+
}

Components/Sources/Common/Models/ViewSize.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,51 @@ import Foundation
1111
public enum ViewSize: Equatable {
1212
case height(CGFloat)
1313
case width(CGFloat)
14+
case size(CGSize)
15+
16+
// MARK: - Properties
17+
18+
var height: CGFloat {
19+
switch self {
20+
case .size(let size):
21+
return size.height
22+
case .height(let height):
23+
return height
24+
case .width:
25+
return 0
26+
}
27+
}
28+
29+
var width: CGFloat {
30+
switch self {
31+
case .size(let size):
32+
return size.width
33+
case .height:
34+
return 0
35+
case .width(let width):
36+
return width
37+
}
38+
}
39+
40+
// MARK: - Methods
41+
42+
func applyTo(heightConstraint: NSLayoutConstraint?, widthConstraint: NSLayoutConstraint?) {
43+
switch self {
44+
case .height(let height):
45+
heightConstraint?.constant = height
46+
heightConstraint?.isActive = true
47+
widthConstraint?.isActive = false
48+
49+
case .width(let width):
50+
widthConstraint?.constant = width
51+
widthConstraint?.isActive = true
52+
heightConstraint?.isActive = false
53+
54+
case .size(let size):
55+
heightConstraint?.constant = size.height
56+
heightConstraint?.isActive = true
57+
widthConstraint?.constant = size.width
58+
widthConstraint?.isActive = true
59+
}
60+
}
1461
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// FrameProvider.swift
3+
// ReactiveDataDisplayManager
4+
//
5+
// Created by Konstantin Porokhov on 18.07.2023.
6+
//
7+
8+
import Foundation
9+
10+
protocol FrameProvider {
11+
12+
static func getFrame(constraintRect: CGSize, model: some TextProvider) -> CGRect
13+
14+
}
15+
16+
extension FrameProvider {
17+
18+
static func getFrame(constraintRect: CGSize, model: some TextProvider) -> CGRect {
19+
switch model.text {
20+
case .string(let text):
21+
return text.boundingRect(with: constraintRect,
22+
options: .usesLineFragmentOrigin,
23+
attributes: model.getAttributes(),
24+
context: nil)
25+
case .attributedString(let attributedText):
26+
return attributedText.boundingRect(with: constraintRect,
27+
options: .usesLineFragmentOrigin,
28+
context: nil)
29+
}
30+
}
31+
32+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// TextProvider.swift
3+
// ReactiveDataDisplayManager
4+
//
5+
// Created by Konstantin Porokhov on 18.07.2023.
6+
//
7+
8+
import Foundation
9+
10+
public protocol TextProvider {
11+
12+
var text: TextValue { get }
13+
14+
func getAttributes() -> [NSAttributedString.Key: Any]
15+
16+
}

Components/Sources/Common/Views/LabelView.swift

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ extension LabelView: ConfigurableItem {
2323

2424
// MARK: - Model
2525

26-
public struct Model: AlignmentProvider {
26+
public struct Model: AlignmentProvider, TextProvider {
2727

2828
// MARK: - Editor
2929

@@ -142,6 +142,34 @@ extension LabelView: ConfigurableItem {
142142

143143
}
144144

145+
// MARK: - CalculatableHeightItem
146+
147+
extension LabelView: CalculatableHeightItem {
148+
149+
public static func getHeight(forWidth width: CGFloat, with model: Model) -> CGFloat {
150+
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
151+
let boundingBox = getFrame(constraintRect: constraintRect, model: model)
152+
let height = ceil(boundingBox.height)
153+
154+
return height
155+
}
156+
157+
}
158+
159+
// MARK: - CalculatableHeightItem
160+
161+
extension LabelView: CalculatableWidthItem, FrameProvider {
162+
163+
public static func getWidth(forHeight height: CGFloat, with model: Model) -> CGFloat {
164+
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
165+
let boundingBox = getFrame(constraintRect: constraintRect, model: model)
166+
let width = ceil(boundingBox.width)
167+
168+
return width
169+
}
170+
171+
}
172+
145173
// MARK: - Private
146174

147175
private extension LabelView {
@@ -160,3 +188,37 @@ private extension LabelView {
160188
}
161189

162190
}
191+
192+
extension LabelView.Model {
193+
194+
public func getAttributes() -> [NSAttributedString.Key: Any] {
195+
switch text {
196+
case .string:
197+
let edgeInsets: UIEdgeInsets
198+
switch alignment {
199+
case .leading(let insets):
200+
edgeInsets = insets
201+
case .trailing(let insets):
202+
edgeInsets = insets
203+
case .all(let insets):
204+
edgeInsets = insets
205+
}
206+
let paragraphStyle = NSMutableParagraphStyle()
207+
paragraphStyle.lineBreakMode = layout.lineBreakMode
208+
paragraphStyle.firstLineHeadIndent = edgeInsets.left
209+
paragraphStyle.headIndent = edgeInsets.right
210+
paragraphStyle.paragraphSpacingBefore = edgeInsets.top
211+
paragraphStyle.paragraphSpacing = edgeInsets.bottom
212+
paragraphStyle.alignment = textAlignment
213+
214+
var attributes: [NSAttributedString.Key: Any] = [:]
215+
attributes[.font] = style.font
216+
attributes[.foregroundColor] = style.color
217+
attributes[.paragraphStyle] = paragraphStyle
218+
return attributes
219+
case .attributedString(let attributedText):
220+
return attributedText.attributes(at: 0, effectiveRange: nil)
221+
}
222+
}
223+
224+
}

Components/Sources/Common/Views/MessageView.swift

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extension MessageView: ConfigurableItem {
2424

2525
// MARK: - Model
2626

27-
public struct Model: Equatable, AlignmentProvider {
27+
public struct Model: Equatable, AlignmentProvider, TextProvider {
2828

2929
// MARK: - Editor
3030

@@ -211,6 +211,34 @@ extension MessageView: ConfigurableItem {
211211

212212
}
213213

214+
// MARK: - CalculatableHeightItem
215+
216+
extension MessageView: CalculatableHeightItem, FrameProvider {
217+
218+
public static func getHeight(forWidth width: CGFloat, with model: Model) -> CGFloat {
219+
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
220+
let boundingBox = getFrame(constraintRect: constraintRect, model: model)
221+
let height = ceil(boundingBox.height)
222+
223+
return height
224+
}
225+
226+
}
227+
228+
// MARK: - CalculatableWidthItem
229+
230+
extension MessageView: CalculatableWidthItem {
231+
232+
public static func getWidth(forHeight height: CGFloat, with model: Model) -> CGFloat {
233+
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
234+
let boundingBox = getFrame(constraintRect: constraintRect, model: model)
235+
let width = ceil(boundingBox.width)
236+
237+
return width
238+
}
239+
240+
}
241+
214242
// MARK: - Private methods
215243

216244
private extension MessageView {
@@ -269,5 +297,39 @@ extension MessageView: UITextViewDelegate {
269297
return false
270298
}
271299

300+
}
301+
302+
extension MessageView.Model {
303+
304+
public func getAttributes() -> [NSAttributedString.Key: Any] {
305+
switch text {
306+
case .string:
307+
let edgeInsets: UIEdgeInsets
308+
switch alignment {
309+
case .leading(let insets):
310+
edgeInsets = insets
311+
case .trailing(let insets):
312+
edgeInsets = insets
313+
case .all(let insets):
314+
edgeInsets = insets
315+
}
316+
let paragraphStyle = NSMutableParagraphStyle()
317+
paragraphStyle.lineBreakMode = textLayout.lineBreakMode
318+
paragraphStyle.firstLineHeadIndent = edgeInsets.left
319+
paragraphStyle.headIndent = edgeInsets.right
320+
paragraphStyle.paragraphSpacingBefore = edgeInsets.top
321+
paragraphStyle.paragraphSpacing = edgeInsets.bottom
322+
paragraphStyle.alignment = textAlignment
323+
324+
var attributes: [NSAttributedString.Key: Any] = [:]
325+
attributes[.font] = textStyle.font
326+
attributes[.foregroundColor] = textStyle.color
327+
attributes[.paragraphStyle] = paragraphStyle
328+
return attributes
329+
case .attributedString(let attributedText):
330+
return attributedText.attributes(at: 0, effectiveRange: nil)
331+
}
332+
}
333+
272334
}
273335
#endif

Components/Sources/Common/Views/SeparatorView.swift

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,33 @@ extension SeparatorView: ConfigurableItem {
4949

5050
public func configure(with model: Model) {
5151
backgroundColor = model.color
52-
switch model.size {
53-
case .height(let height):
54-
heightConstraint?.constant = height
55-
heightConstraint?.isActive = true
56-
widthConstraint?.isActive = false
57-
58-
case .width(let width):
59-
widthConstraint?.constant = width
60-
widthConstraint?.isActive = true
61-
heightConstraint?.isActive = false
62-
}
52+
model.size.applyTo(heightConstraint: heightConstraint, widthConstraint: widthConstraint)
6353

6454
layoutIfNeeded()
6555
}
6656

6757
}
6858

59+
// MARK: - CalculatableHeightItem
60+
61+
extension SeparatorView: CalculatableHeightItem {
62+
63+
public static func getHeight(forWidth width: CGFloat, with model: Model) -> CGFloat {
64+
return model.size.height
65+
}
66+
67+
}
68+
69+
// MARK: - CalculatableWidthItem
70+
71+
extension SeparatorView: CalculatableWidthItem {
72+
73+
public static func getWidth(forHeight height: CGFloat, with model: Model) -> CGFloat {
74+
return model.size.width
75+
}
76+
77+
}
78+
6979
// MARK: - Private
7080

7181
private extension SeparatorView {

0 commit comments

Comments
 (0)