Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor TimelineItemSendInfo out of the styler. #3100

Merged
merged 4 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@
5710AAB27D5D866292C1FE06 /* SessionVerificationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF848B41DAF1066F3054D4A1 /* SessionVerificationScreenModels.swift */; };
5732395A4F71F51F9C754C5A /* ElementCallService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33AE897D86784CCA5E4E9227 /* ElementCallService.swift */; };
5780E444F405AA1304E1C23E /* DeveloperOptionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E521D6C2BF8DF0DFB35146 /* DeveloperOptionsScreen.swift */; };
57B9562E6FE788FC172D4AAF /* TimelineItemSendInfoLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15447A39D91D2EF536C74DD /* TimelineItemSendInfoLabel.swift */; };
57E115A8C33E599DE564F8C3 /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDEB27575FEBCF414D4DEE31 /* TimelineView.swift */; };
588411C8FD72B2A2DFE5F7DE /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; };
5894C2514400A4FBC9327632 /* ServerConfirmationScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03277E40D0E0DE0712021A71 /* ServerConfirmationScreenCoordinator.swift */; };
Expand Down Expand Up @@ -2014,6 +2015,7 @@
D09A267106B9585D3D0CFC0D /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
D0C2D52E36AD614B3C003EF6 /* RoomTimelineItemViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemViewState.swift; sourceTree = "<group>"; };
D15447A39D91D2EF536C74DD /* TimelineItemSendInfoLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemSendInfoLabel.swift; sourceTree = "<group>"; };
D162B2280A15ACAF35360554 /* HighlightedTimelineItemModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightedTimelineItemModifier.swift; sourceTree = "<group>"; };
D1896F6288D80E1F3EFB3DF8 /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ka; path = ka.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
D196116D2DD3F2757D45FCB7 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/SAS.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4368,6 +4370,7 @@
E2DCA495ED42D2463DDAA94D /* TimelineBubbleLayout.swift */,
74C6F3DAD167F972702C8893 /* TimelineItemAccessibilityModifier.swift */,
98A2932515EA11D3DD8A3506 /* TimelineItemBubbledStylerView.swift */,
D15447A39D91D2EF536C74DD /* TimelineItemSendInfoLabel.swift */,
8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */,
892E29C98C4E8182C9037F84 /* TimelineStyler.swift */,
);
Expand Down Expand Up @@ -6640,6 +6643,7 @@
1C815DD79B401DEBA2914773 /* TimelineItemMock.swift in Sources */,
440123E29E2F9B001A775BBE /* TimelineItemProxy.swift in Sources */,
9586E90A447C4896C0CA3A8E /* TimelineItemReplyDetails.swift in Sources */,
57B9562E6FE788FC172D4AAF /* TimelineItemSendInfoLabel.swift in Sources */,
1B88BB631F7FC45A213BB554 /* TimelineItemSender.swift in Sources */,
A680F54935A6ADEA4ED6C38F /* TimelineItemStatusView.swift in Sources */,
562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
/* Used for testing */
"untranslated" = "Untranslated";

// MARK: - Shields

"send_info_not_encrypted" = "Not encrypted";

// MARK: - Soft logout

"soft_logout_signin_title" = "Sign in";
Expand Down
2 changes: 2 additions & 0 deletions ElementX/Sources/Generated/Strings+Untranslated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import Foundation
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
internal enum UntranslatedL10n {
/// Not encrypted
internal static var sendInfoNotEncrypted: String { return UntranslatedL10n.tr("Untranslated", "send_info_not_encrypted") }
/// Clear all data currently stored on this device?
/// Sign in again to access your account data and messages.
internal static var softLogoutClearDataDialogContent: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_clear_data_dialog_content") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@
// limitations under the License.
//

import Foundation
import SwiftUI

import Compound
import SwiftUI

struct TimelineItemBubbledStylerView<Content: View>: View {
@EnvironmentObject private var context: RoomScreenViewModel.Context
Expand All @@ -34,9 +32,9 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
/// The base padding applied to bubbles on either side.
///
/// **Note:** This is on top of the insets applied to the cells by the table view.
let bubbleHorizontalPadding: CGFloat = 8
private let bubbleHorizontalPadding: CGFloat = 8
/// Additional padding applied to outgoing bubbles when the avatar is shown
var bubbleAvatarPadding: CGFloat {
private var bubbleAvatarPadding: CGFloat {
guard !timelineItem.isOutgoing, !isEncryptedOneToOneRoom else { return 0 }
return 8
}
Expand Down Expand Up @@ -108,7 +106,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
private var messageBubbleWithReactions: some View {
// Figma overlaps reactions by 3
VStack(alignment: alignment, spacing: -3) {
messageBubble
messageBubbleWithActions
.timelineItemAccessibility(timelineItem) {
context.send(viewAction: .displayTimelineItemMenu(itemID: timelineItem.id))
}
Expand All @@ -124,8 +122,8 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
}
}

var messageBubble: some View {
styledContent
var messageBubbleWithActions: some View {
messageBubble
.onTapGesture {
context.send(viewAction: .itemTapped(itemID: timelineItem.id))
}
Expand Down Expand Up @@ -156,59 +154,14 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
}
.padding(.top, messageBubbleTopPadding)
}

@ViewBuilder
var styledContent: some View {
contentWithTimestamp
var messageBubble: some View {
contentWithReply
.timelineItemSendInfo(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus)
.bubbleStyle(insets: timelineItem.bubbleInsets,
color: timelineItem.bubbleBackgroundColor,
corners: roundedCorners)
}

@ViewBuilder
var contentWithTimestamp: some View {
timelineItem.bubbleSendInfoLayoutType
.layout {
contentWithReply
layoutedLocalizedSendInfo
}
}

@ViewBuilder
var layoutedLocalizedSendInfo: some View {
switch timelineItem.bubbleSendInfoLayoutType {
case .overlay(capsuleStyle: true):
localizedSendInfo
.padding(.horizontal, 4)
.padding(.vertical, 2)
.background(Color.compound.bgSubtleSecondary)
.cornerRadius(10)
.padding(.trailing, 4)
.padding(.bottom, 4)
case .horizontal, .overlay(capsuleStyle: false):
localizedSendInfo
.padding(.bottom, -4)
case .vertical:
GridRow {
localizedSendInfo
.gridColumnAlignment(.trailing)
}
}
}

@ViewBuilder
var localizedSendInfo: some View {
HStack(spacing: 4) {
Text(timelineItem.localizedSendInfo)

if adjustedDeliveryStatus == .sendingFailed {
CompoundIcon(\.error, size: .xSmall, relativeTo: .compound.bodyXS)
.accessibilityLabel(L10n.commonSendingFailed)
}
}
.font(.compound.bodyXS)
.foregroundColor(adjustedDeliveryStatus == .sendingFailed ? .compound.textCriticalPrimary : .compound.textSecondary)
}

@ViewBuilder
var contentWithReply: some View {
Expand Down Expand Up @@ -293,28 +246,6 @@ private extension View {
}
}

// Describes how the content and the send info should be arranged inside a bubble
private enum BubbleSendInfoLayoutType {
case horizontal(spacing: CGFloat = 4)
case vertical(spacing: CGFloat = 4)
case overlay(capsuleStyle: Bool)

var layout: AnyLayout {
let layout: any Layout

switch self {
case .horizontal(let spacing):
layout = HStackLayout(alignment: .bottom, spacing: spacing)
case .vertical(let spacing):
layout = GridLayout(alignment: .leading, verticalSpacing: spacing)
case .overlay:
layout = ZStackLayout(alignment: .bottomTrailing)
}

return AnyLayout(layout)
}
}

private extension EventBasedTimelineItemProtocol {
var bubbleBackgroundColor: Color? {
let defaultColor: Color = isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming
Expand All @@ -335,8 +266,8 @@ private extension EventBasedTimelineItemProtocol {
}
}

// The insets for the full bubble content.
// Padding affecting just the "send info" should be added inside `layoutedLocalizedSendInfo`
/// The insets for the full bubble content.
/// Padding affecting just the "send info" should be added inside `TimelineItemSendInfoView`
var bubbleInsets: EdgeInsets {
let defaultInsets: EdgeInsets = .init(around: 8)

Expand All @@ -363,25 +294,6 @@ private extension EventBasedTimelineItemProtocol {
return defaultInsets
}
}

var bubbleSendInfoLayoutType: BubbleSendInfoLayoutType {
let defaultTimestampLayout: BubbleSendInfoLayoutType = .horizontal()

switch self {
case is TextBasedRoomTimelineItem:
return .overlay(capsuleStyle: false)
case is ImageRoomTimelineItem,
is VideoRoomTimelineItem,
is StickerRoomTimelineItem:
return .overlay(capsuleStyle: true)
case let locationTimelineItem as LocationRoomTimelineItem:
return .overlay(capsuleStyle: locationTimelineItem.content.geoURI != nil)
case is PollRoomTimelineItem:
return .vertical(spacing: 16)
default:
return defaultTimestampLayout
}
}

var contentCornerRadius: CGFloat {
guard let message = self as? EventBasedMessageTimelineItemProtocol else { return .zero }
Expand All @@ -395,6 +307,16 @@ private extension EventBasedTimelineItemProtocol {
}
}

private extension EdgeInsets {
init(around: CGFloat) {
self.init(top: around, leading: around, bottom: around, trailing: around)
}

static var zero: Self = .init(around: 0)
}

// MARK: - Previews

struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
static let viewModel = RoomScreenViewModel.mock

Expand Down Expand Up @@ -556,11 +478,3 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
.environmentObject(viewModel.context)
}
}

private extension EdgeInsets {
init(around: CGFloat) {
self.init(top: around, leading: around, bottom: around, trailing: around)
}

static var zero: Self = .init(around: 0)
}
Loading
Loading