Fixes #271 - Allow bubbles to horizontally fill the available space (#290)

* Fixes #271 - Allow bubbles to horizontally fill the available space
* Set the existing timelineItems on the timeline when appearing. This fixes UI tests in which items exists without the need for backpagination. It also presumably will fix the timeline when having cached data.
This commit is contained in:
Stefan Ceriu
2022-11-04 17:16:39 +02:00
committed by GitHub
parent 162830086f
commit fcd94fca31
8 changed files with 2 additions and 43 deletions
@@ -24,10 +24,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
@ViewBuilder let content: () -> Content @ViewBuilder let content: () -> Content
@Environment(\.colorScheme) private var colorScheme @Environment(\.colorScheme) private var colorScheme
@Environment(\.timelineWidth) private var timelineWidth
@ScaledMetric private var senderNameVerticalPadding = 3 @ScaledMetric private var senderNameVerticalPadding = 3
private let bubbleWidthPercentIncoming = 0.72 // 281/390
private let bubbleWidthPercentOutgoing = 0.68 // 267/390
var body: some View { var body: some View {
VStack(alignment: alignment, spacing: -12) { VStack(alignment: alignment, spacing: -12) {
@@ -84,7 +81,6 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
alignment: .leading) { key in alignment: .leading) { key in
context.send(viewAction: .sendReaction(key: key, eventID: timelineItem.id)) context.send(viewAction: .sendReaction(key: key, eventID: timelineItem.id))
} }
.frame(width: bubbleWidth - 24)
.padding(.horizontal, 12) .padding(.horizontal, 12)
} }
} }
@@ -105,13 +101,11 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
if shouldAvoidBubbling { if shouldAvoidBubbling {
content() content()
.frame(width: bubbleWidth)
.cornerRadius(12, inGroupState: timelineItem.inGroupState) .cornerRadius(12, inGroupState: timelineItem.inGroupState)
.padding(.top, topPadding) .padding(.top, topPadding)
} else { } else {
VStack(alignment: .trailing, spacing: 4) { VStack(alignment: .trailing, spacing: 4) {
content() content()
.frame(width: bubbleWidth - 24, alignment: .leading)
if timelineItem.properties.isEdited { if timelineItem.properties.isEdited {
Text(ElementL10n.editedSuffix) Text(ElementL10n.editedSuffix)
@@ -130,12 +124,10 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
var styledContentIncoming: some View { var styledContentIncoming: some View {
if shouldAvoidBubbling { if shouldAvoidBubbling {
content() content()
.frame(width: bubbleWidth)
.cornerRadius(12, inGroupState: timelineItem.inGroupState) .cornerRadius(12, inGroupState: timelineItem.inGroupState)
} else { } else {
VStack(alignment: .trailing, spacing: 4) { VStack(alignment: .trailing, spacing: 4) {
content() content()
.frame(width: bubbleWidth - 24, alignment: .leading)
if timelineItem.properties.isEdited { if timelineItem.properties.isEdited {
Text(ElementL10n.editedSuffix) Text(ElementL10n.editedSuffix)
@@ -145,11 +137,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
} }
.padding(EdgeInsets(top: 6, leading: 12, bottom: 6, trailing: 12)) .padding(EdgeInsets(top: 6, leading: 12, bottom: 6, trailing: 12))
.background(Color.element.systemGray6) // Demo time! .background(Color.element.systemGray6) // Demo time!
.cornerRadius(12, inGroupState: timelineItem.inGroupState) // Demo time! .cornerRadius(12, inGroupState: timelineItem.inGroupState)
// .overlay(
// RoundedCornerShape(radius: 18, inGroupState: timelineItem.inGroupState)
// .stroke(Color.element.systemGray5)
// )
} }
} }
@@ -160,10 +148,6 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
private var alignment: HorizontalAlignment { private var alignment: HorizontalAlignment {
timelineItem.isOutgoing ? .trailing : .leading timelineItem.isOutgoing ? .trailing : .leading
} }
private var bubbleWidth: CGFloat {
timelineWidth * (timelineItem.isOutgoing ? bubbleWidthPercentOutgoing : bubbleWidthPercentIncoming)
}
} }
struct TimelineItemBubbledStylerView_Previews: PreviewProvider { struct TimelineItemBubbledStylerView_Previews: PreviewProvider {
@@ -181,7 +165,6 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider {
} }
} }
.timelineStyle(.bubbles) .timelineStyle(.bubbles)
.timelineWidth(390)
.padding(.horizontal, 8) .padding(.horizontal, 8)
.previewLayout(.sizeThatFits) .previewLayout(.sizeThatFits)
} }
@@ -50,22 +50,3 @@ extension View {
environment(\.timelineStyle, style) environment(\.timelineStyle, style)
} }
} }
// MARK: - Timeline Width
private struct TimelineWidthKey: EnvironmentKey {
static let defaultValue: CGFloat = 0
}
extension EnvironmentValues {
var timelineWidth: CGFloat {
get { self[TimelineWidthKey.self] }
set { self[TimelineWidthKey.self] = newValue }
}
}
extension View {
func timelineWidth(_ width: CGFloat) -> some View {
environment(\.timelineWidth, width)
}
}
@@ -56,7 +56,6 @@ struct EmoteRoomTimelineView_Previews: PreviewProvider {
timestamp: "Later", timestamp: "Later",
senderId: "Anne")) senderId: "Anne"))
} }
.environment(\.timelineWidth, 400)
} }
private static func itemWith(text: String, timestamp: String, senderId: String) -> EmoteRoomTimelineItem { private static func itemWith(text: String, timestamp: String, senderId: String) -> EmoteRoomTimelineItem {
@@ -92,6 +92,5 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
aspectRatio: 0.7, aspectRatio: 0.7,
blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW")) blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW"))
} }
.environment(\.timelineWidth, 400)
} }
} }
@@ -56,7 +56,6 @@ struct NoticeRoomTimelineView_Previews: PreviewProvider {
timestamp: "Later", timestamp: "Later",
senderId: "Anne")) senderId: "Anne"))
} }
.environment(\.timelineWidth, 400)
} }
private static func itemWith(text: String, timestamp: String, senderId: String) -> NoticeRoomTimelineItem { private static func itemWith(text: String, timestamp: String, senderId: String) -> NoticeRoomTimelineItem {
@@ -44,7 +44,6 @@ struct RedactedRoomTimelineView_Previews: PreviewProvider {
timestamp: "Later", timestamp: "Later",
senderId: "Anne")) senderId: "Anne"))
} }
.environment(\.timelineWidth, 400)
} }
private static func itemWith(text: String, timestamp: String, senderId: String) -> RedactedRoomTimelineItem { private static func itemWith(text: String, timestamp: String, senderId: String) -> RedactedRoomTimelineItem {
@@ -65,7 +65,6 @@ struct TextRoomTimelineView_Previews: PreviewProvider {
isOutgoing: true, isOutgoing: true,
senderId: "Anne")) senderId: "Anne"))
} }
.environment(\.timelineWidth, 400)
} }
private static func itemWith(text: String, timestamp: String, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem { private static func itemWith(text: String, timestamp: String, isOutgoing: Bool, senderId: String) -> TextRoomTimelineItem {
@@ -97,9 +97,9 @@ struct TimelineItemList: View {
} }
.scrollDismissesKeyboard(.immediately) .scrollDismissesKeyboard(.immediately)
.background(ViewFrameReader(frame: $viewFrame)) .background(ViewFrameReader(frame: $viewFrame))
.environment(\.timelineWidth, viewFrame.width)
.timelineStyle(settings.timelineStyle) .timelineStyle(settings.timelineStyle)
.onAppear { .onAppear {
timelineItems = context.viewState.items
requestBackPagination() requestBackPagination()
} }
// Allow SwiftUI to layout the views properly before checking if the top is visible // Allow SwiftUI to layout the views properly before checking if the top is visible