mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Fix reaction height issue (#1482)
- Fix reaction height issue - Add regression test - Fix reaction summary button color for text based reactions
This commit is contained in:
@@ -141,13 +141,21 @@ struct CollapsibleReactionLayout: Layout {
|
|||||||
/// - rows: The list of rows
|
/// - rows: The list of rows
|
||||||
/// - Returns: The size render the rows
|
/// - Returns: The size render the rows
|
||||||
private func sizeThatFits(proposal: ProposedViewSize, rows: [[FlowLayoutSubview]]) -> CGSize {
|
private func sizeThatFits(proposal: ProposedViewSize, rows: [[FlowLayoutSubview]]) -> CGSize {
|
||||||
rows.enumerated().reduce(CGSize.zero) { partialResult, rowItem in
|
let sizes = rows.map { row in
|
||||||
|
row.map { subview in
|
||||||
|
subview.sizeThatFits(.unspecified)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let maxHeight = sizes.joined().reduce(0) { partialResult, size in
|
||||||
|
max(partialResult, size.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sizes.enumerated().reduce(CGSize.zero) { partialResult, rowItem in
|
||||||
let (rowIndex, row) = rowItem
|
let (rowIndex, row) = rowItem
|
||||||
let rowSize = row.enumerated().reduce(CGSize.zero) { partialResult, subviewItem in
|
let rowSize = row.enumerated().reduce(CGSize.zero) { partialResult, subviewItem in
|
||||||
let (subviewIndex, subview) = subviewItem
|
let (subviewIndex, size) = subviewItem
|
||||||
let size = subview.sizeThatFits(.unspecified)
|
|
||||||
let horizontalSpacing = subviewIndex == 0 ? 0 : itemSpacing
|
let horizontalSpacing = subviewIndex == 0 ? 0 : itemSpacing
|
||||||
return CGSize(width: partialResult.width + size.width + horizontalSpacing, height: max(partialResult.height, size.height))
|
return CGSize(width: partialResult.width + size.width + horizontalSpacing, height: maxHeight)
|
||||||
}
|
}
|
||||||
let verticalSpacing = rowIndex == 0 ? 0 : rowSpacing
|
let verticalSpacing = rowIndex == 0 ? 0 : rowSpacing
|
||||||
return CGSize(width: max(partialResult.width, rowSize.width), height: partialResult.height + rowSize.height + verticalSpacing)
|
return CGSize(width: max(partialResult.width, rowSize.width), height: partialResult.height + rowSize.height + verticalSpacing)
|
||||||
|
|||||||
@@ -95,10 +95,11 @@ private struct ReactionSummaryButton: View {
|
|||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Text(reaction.displayKey)
|
Text(reaction.displayKey)
|
||||||
.font(.compound.headingSM)
|
.font(.compound.headingSM)
|
||||||
|
.foregroundColor(textColor)
|
||||||
if reaction.count > 1 {
|
if reaction.count > 1 {
|
||||||
Text(String(reaction.count))
|
Text(String(reaction.count))
|
||||||
.font(.compound.headingSM)
|
.font(.compound.headingSM)
|
||||||
.foregroundColor(highlighted ? Color.compound.textOnSolidPrimary : Color.compound.textSecondary)
|
.foregroundColor(textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
@@ -106,6 +107,10 @@ private struct ReactionSummaryButton: View {
|
|||||||
.background(highlighted ? Color.compound.bgActionPrimaryRest : .clear, in: Capsule())
|
.background(highlighted ? Color.compound.bgActionPrimaryRest : .clear, in: Capsule())
|
||||||
.accessibilityElement(children: .combine)
|
.accessibilityElement(children: .combine)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var textColor: Color {
|
||||||
|
highlighted ? Color.compound.textOnSolidPrimary : Color.compound.textSecondary
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct ReactionSummarySenderView: View {
|
private struct ReactionSummarySenderView: View {
|
||||||
|
|||||||
@@ -101,6 +101,37 @@ final class CollapsibleFlowLayoutTests: XCTestCase {
|
|||||||
XCTAssertEqual(placedViews, targetPlacements)
|
XCTAssertEqual(placedViews, targetPlacements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testHeightIsCorrectGivenASmallerAddButton() {
|
||||||
|
let containerSize = CGSize(width: 250, height: 400)
|
||||||
|
let flowLayout = CollapsibleReactionLayout(itemSpacing: 5, rowSpacing: 5, rowsBeforeCollapsible: 2)
|
||||||
|
|
||||||
|
var placedViews: [CGRect] = []
|
||||||
|
let placedViewsCallback = { rect in
|
||||||
|
placedViews.append(rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add more button with smaller initial height
|
||||||
|
let subviews = createReactionLayoutSubviews(with: Array(repeating: CGSize(width: 100, height: 50), count: 2),
|
||||||
|
addMoreSize: CGSize(width: 100, height: 20),
|
||||||
|
placedPositionCallback: placedViewsCallback)
|
||||||
|
let subviewsMock = LayoutSubviewsMock(subviews: subviews)
|
||||||
|
var a: () = ()
|
||||||
|
let size = flowLayout.sizeThatFits(proposal: ProposedViewSize(containerSize), subviews: subviewsMock, cache: &a)
|
||||||
|
|
||||||
|
XCTAssertEqual(size, CGSize(width: 205, height: 105))
|
||||||
|
flowLayout.placeSubviews(in: CGRect(origin: .zero, size: size), proposal: ProposedViewSize(containerSize), subviews: subviewsMock, cache: &a)
|
||||||
|
|
||||||
|
let targetPlacements: [CGRect] = [
|
||||||
|
CGRect(x: 0, y: 25, width: 100, height: 50),
|
||||||
|
CGRect(x: 105, y: 25, width: 100, height: 50),
|
||||||
|
// Add more button with matching height
|
||||||
|
CGRect(x: 0, y: 80, width: 100, height: 50),
|
||||||
|
// Expand/Collapse button is hidden
|
||||||
|
CGRect(x: -10000, y: -10000, width: 0, height: 0)
|
||||||
|
]
|
||||||
|
XCTAssertEqual(placedViews, targetPlacements)
|
||||||
|
}
|
||||||
|
|
||||||
func testFlowLayoutEmptyState() {
|
func testFlowLayoutEmptyState() {
|
||||||
let containerSize = CGSize(width: 250, height: 400)
|
let containerSize = CGSize(width: 250, height: 400)
|
||||||
let flowLayout = CollapsibleReactionLayout(itemSpacing: 5, rowSpacing: 5, rowsBeforeCollapsible: 2)
|
let flowLayout = CollapsibleReactionLayout(itemSpacing: 5, rowSpacing: 5, rowsBeforeCollapsible: 2)
|
||||||
@@ -125,16 +156,19 @@ final class CollapsibleFlowLayoutTests: XCTestCase {
|
|||||||
XCTAssertEqual(placedViews, targetPlacements)
|
XCTAssertEqual(placedViews, targetPlacements)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createReactionLayoutSubviews(with sizes: [CGSize], placedPositionCallback: @escaping (CGRect) -> Void) -> [LayoutSubviewMock] {
|
func createReactionLayoutSubviews(with sizes: [CGSize],
|
||||||
|
expandCollapseSize: CGSize = CGSize(width: 100, height: 50),
|
||||||
|
addMoreSize: CGSize = CGSize(width: 100, height: 50),
|
||||||
|
placedPositionCallback: @escaping (CGRect) -> Void) -> [LayoutSubviewMock] {
|
||||||
sizes.map { size in
|
sizes.map { size in
|
||||||
LayoutSubviewMock(size: size,
|
LayoutSubviewMock(size: size,
|
||||||
layoutValues: [String(describing: ReactionLayoutItemType.self): ReactionLayoutItem.reaction],
|
layoutValues: [String(describing: ReactionLayoutItemType.self): ReactionLayoutItem.reaction],
|
||||||
placedPositionCallback: placedPositionCallback)
|
placedPositionCallback: placedPositionCallback)
|
||||||
} + [
|
} + [
|
||||||
LayoutSubviewMock(size: CGSize(width: 100, height: 50),
|
LayoutSubviewMock(size: expandCollapseSize,
|
||||||
layoutValues: [String(describing: ReactionLayoutItemType.self): ReactionLayoutItem.expandCollapse],
|
layoutValues: [String(describing: ReactionLayoutItemType.self): ReactionLayoutItem.expandCollapse],
|
||||||
placedPositionCallback: placedPositionCallback),
|
placedPositionCallback: placedPositionCallback),
|
||||||
LayoutSubviewMock(size: CGSize(width: 100, height: 50),
|
LayoutSubviewMock(size: addMoreSize,
|
||||||
layoutValues: [String(describing: ReactionLayoutItemType.self): ReactionLayoutItem.addMore],
|
layoutValues: [String(describing: ReactionLayoutItemType.self): ReactionLayoutItem.addMore],
|
||||||
placedPositionCallback: placedPositionCallback)
|
placedPositionCallback: placedPositionCallback)
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user