Skip to content

Commit

Permalink
Refactor TimelineItemSendInfo out of the styler. (#3100)
Browse files Browse the repository at this point in the history
* Reorder some properties.

No code changes.

* Refactor TimelineItemSendInfo out of the styler.

* Add (unused) examples of encryption shields.

* Rename file.
  • Loading branch information
pixlwave authored Jul 30, 2024
1 parent 0fab3a8 commit a2ea9c4
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 114 deletions.
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

0 comments on commit a2ea9c4

Please sign in to comment.