Run SwiftFormat.

This commit is contained in:
Doug
2026-05-27 14:38:50 +01:00
committed by Doug
parent 5138e05e47
commit fa67713726
573 changed files with 2426 additions and 2426 deletions
@@ -36,14 +36,14 @@ struct TimelineItemMenu: View {
if !actions.reactions.isEmpty {
reactionsSection
.padding(.bottom, 8.0)
Divider()
.background(Color.compound.bgSubtlePrimary)
}
if !actions.actions.isEmpty {
viewsForActions(actions.actions)
Divider()
.background(Color.compound.bgSubtlePrimary)
}
@@ -278,7 +278,7 @@ struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview {
static let (mediaItem, mediaItemActions) = makeActions(itemType: .outgoingMedia)
static let (mediaItemWithCaption, mediaItemWithCaptionActions) = makeActions(itemType: .outgoingMediaWithCaption)
static var previews: some View {
TimelineItemMenu(item: item, actions: actions)
.environmentObject(viewModel.context)
@@ -28,12 +28,12 @@ struct TimelineItemMenuActionProvider {
// Don't show a context menu for non-event based items.
return nil
}
if timelineItem is StateRoomTimelineItem {
// Don't show a context menu for state events.
return nil
}
if let encryptedItem = timelineItem as? EncryptedRoomTimelineItem {
return makeEncryptedItemActions(encryptedItem)
}
@@ -48,7 +48,7 @@ struct TimelineItemMenuActionProvider {
if canRedactItem(item), let poll = item.pollIfAvailable, !poll.hasEnded, let eventID = item.id.eventID {
actions.append(.endPoll(pollStartID: eventID))
}
if item.canBeRepliedTo, canCurrentUserSendMessage {
if let messageItem = item as? EventBasedMessageTimelineItemProtocol {
// If threads are enabled we will have the dedicated `replyInThread` action
@@ -88,7 +88,7 @@ struct TimelineItemMenuActionProvider {
if canCurrentUserPin, let eventID = item.id.eventID {
actions.append(pinnedEventIDs.contains(eventID) ? .unpin : .pin)
}
if item.isCopyable {
actions.append(.copy)
@@ -141,17 +141,17 @@ struct TimelineItemMenuActionProvider {
}
let isReactable = timelineKind == .live || timelineKind == .detached || timelineKind.isThread ? item.isReactable : false
return .init(isReactable: isReactable, actions: actions, secondaryActions: secondaryActions, emojiProvider: emojiProvider)
}
private func makeEncryptedItemActions(_ encryptedItem: EncryptedRoomTimelineItem) -> TimelineItemMenuActions? {
var actions: [TimelineItemMenuAction] = [.copyPermalink]
if isViewSourceEnabled {
actions.append(.viewSource)
}
return .init(isReactable: false,
actions: actions,
secondaryActions: [],
@@ -15,14 +15,14 @@ struct PollOptionView: View {
let pollOption: Poll.Option
let showVotes: Bool
let isFinalResult: Bool
var body: some View {
HStack(alignment: .firstTextBaseline, spacing: 12) {
Image(systemSymbol: pollOption.isSelected ? .checkmarkCircleFill : .circle)
.font(.compound.bodyLG)
.foregroundColor(pollOption.isSelected && isEnabled ? .compound.iconPrimary : .compound.iconTertiary)
.accessibilityAddTraits(pollOption.isSelected ? .isSelected : [])
VStack(spacing: 10) {
HStack(alignment: .lastTextBaseline, spacing: 8) {
Text(pollOption.text)
@@ -30,7 +30,7 @@ struct PollOptionView: View {
.multilineTextAlignment(.leading)
.foregroundColor(.compound.textPrimary)
.frame(maxWidth: .infinity, alignment: .leading)
if showVotes {
if isFinalWinningOption {
HStack(spacing: 4) {
@@ -49,14 +49,14 @@ struct PollOptionView: View {
}
}
}
PollProgressView(progress: progress)
}
}
}
// MARK: - Private
private var progress: Double {
switch (showVotes, pollOption.allVotes, pollOption.isSelected) {
case (true, let allVotes, _) where allVotes > 0:
@@ -67,7 +67,7 @@ struct PollOptionView: View {
return 0
}
}
private var isFinalWinningOption: Bool {
pollOption.isWinning && isFinalResult
}
@@ -75,13 +75,13 @@ struct PollOptionView: View {
private struct PollProgressView: View {
let progress: Double
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Capsule()
.foregroundColor(.compound._bgEmptyItemAlpha)
Capsule()
.frame(maxWidth: progress * geometry.size.width)
}
@@ -102,7 +102,7 @@ struct PollOptionView_Previews: PreviewProvider, TestablePreview {
isWinning: false),
showVotes: false,
isFinalResult: false)
PollOptionView(pollOption: .init(id: "2",
text: "Chinese 🇨🇳",
votes: 9,
@@ -111,7 +111,7 @@ struct PollOptionView_Previews: PreviewProvider, TestablePreview {
isWinning: true),
showVotes: true,
isFinalResult: false)
PollOptionView(pollOption: .init(id: "2",
text: "Chinese 🇨🇳",
votes: 9,
@@ -59,7 +59,7 @@ struct PollView: View {
.frame(maxWidth: 450)
}
}
// MARK: - Private
private var senderString: String {
@@ -76,14 +76,14 @@ struct PollView: View {
.accessibilityElement(children: .combine)
}
}
private var questionView: some View {
HStack(alignment: .top, spacing: 12) {
CompoundIcon(poll.hasEnded ? \.pollsEnd : \.polls,
size: .custom(22),
relativeTo: .compound.bodyLGSemibold)
.accessibilityLabel(poll.hasEnded ? L10n.a11yPollEnd : L10n.a11yPoll)
Text(poll.question)
.multilineTextAlignment(.leading)
.font(.compound.bodyLGSemibold)
@@ -91,7 +91,7 @@ struct PollView: View {
.accessibilityElement(children: .combine)
.accessibilityAddTraits(.isHeader)
}
private var optionsView: some View {
ForEach(poll.options, id: \.id) { option in
pollOption(option: option)
@@ -116,7 +116,7 @@ struct PollView: View {
}
.disabled(poll.hasEnded)
}
@ViewBuilder
private var summaryView: some View {
if let summaryText = poll.summaryText {
@@ -127,7 +127,7 @@ struct PollView: View {
.frame(maxWidth: .infinity, alignment: showVotes ? .trailing : .leading)
}
}
@ViewBuilder
private var toolbarView: some View {
if !poll.hasEnded, poll.createdByAccountOwner {
@@ -157,7 +157,7 @@ struct PollView: View {
actionHandler(.end)
}
}
private func progressBarColor(for option: Poll.Option) -> Color {
if poll.hasEnded {
return option.isWinning ? .compound.textActionAccent : .compound.textDisabled
@@ -165,7 +165,7 @@ struct PollView: View {
return .compound.textPrimary
}
}
private var showVotes: Bool {
poll.hasEnded || poll.kind == .disclosed
}
@@ -178,7 +178,7 @@ private extension Poll {
L10n.commonPollTotalVotes($0.allVotes)
}
}
switch kind {
case .disclosed:
return options.first.map {
@@ -195,19 +195,19 @@ struct PollView_Previews: PreviewProvider, TestablePreview {
PollView(poll: .disclosed(), state: .full(isEditable: false), sender: .test) { _ in }
.padding()
.previewDisplayName("Disclosed")
PollView(poll: .undisclosed(), state: .full(isEditable: false), sender: .test) { _ in }
.padding()
.previewDisplayName("Undisclosed")
PollView(poll: .endedDisclosed, state: .full(isEditable: false), sender: .test) { _ in }
.padding()
.previewDisplayName("Ended, Disclosed")
PollView(poll: .endedUndisclosed, state: .full(isEditable: false), sender: .test) { _ in }
.padding()
.previewDisplayName("Ended, Undisclosed")
PollView(poll: .disclosed(createdByAccountOwner: true), state: .full(isEditable: true), sender: .test) { _ in }
.padding()
.previewDisplayName("Creator, disclosed")
@@ -23,7 +23,7 @@ struct ReadReceiptCell: View {
}
return readReceipt.userID
}
var body: some View {
HStack(spacing: 12) {
LoadableAvatarImage(url: memberState?.avatarURL,
@@ -44,9 +44,9 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
.mockDan
]
let roomProxyMock = JoinedRoomProxyMock(.init(name: "Room", members: members))
let appSettings = AppSettings.volatile()
return TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockTimelineController(),
userSession: UserSessionMock(.init()),
@@ -144,7 +144,7 @@ private struct LongPressGestureRepresentable: UIGestureRecognizerRepresentable {
func handleUIGestureRecognizerAction(_ recognizer: UILongPressGestureRecognizer, context: Context) {
handle(recognizer)
}
class Coordinator: NSObject, UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
@@ -69,7 +69,7 @@ struct TimelineBubbleLayout: Layout {
// Calculate the natural size using the regular text and non-greedy quote bubbles.
let layoutSubviews = subviews.filter { $0[Size.self].shouldLayout }
let subviewSizes = layoutSubviews.map { size(for: $0, subviews: subviews, proposedSize: proposal, cache: &cache) }
let maxWidth = subviewSizes.map(\.width).reduce(0, max)
@@ -88,7 +88,7 @@ struct TimelineBubbleLayout: Layout {
// Place the regular text and greedy components using the calculated width.
let visibleSubviews = subviews.filter { $0[Size.self].shouldRender }
let subviewSizes = visibleSubviews.map { size(for: $0, subviews: subviews, proposedSize: ProposedViewSize(width: maxWidth, height: proposal.height), cache: &cache) }
var y = bounds.minY
@@ -17,15 +17,15 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
let timelineItem: EventBasedTimelineItemProtocol
let adjustedDeliveryStatus: TimelineItemDeliveryStatus?
@ViewBuilder let content: () -> Content
private var isDM: Bool {
context.viewState.isDM
}
private var isFocussed: Bool {
focussedEventID != nil && timelineItem.id.eventID == focussedEventID
}
private var isPinned: Bool {
guard context.viewState.timelineKind != .pinned,
let eventID = timelineItem.id.eventID else {
@@ -51,17 +51,17 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
header
.zIndex(1)
}
VStack(alignment: alignment, spacing: 0) {
HStack(spacing: 0) {
if timelineItem.isOutgoing {
Spacer()
}
messageBubbleWithReactions
}
.padding(timelineItem.isOutgoing ? .leading : .trailing, 48) // Additional padding to differentiate alignment.
HStack(spacing: 0) {
if !timelineItem.isOutgoing {
Spacer()
@@ -246,12 +246,12 @@ private extension EventBasedTimelineItemProtocol {
return defaultColor
}
}
/// 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)
switch self {
case is StickerRoomTimelineItem:
return .zero
@@ -286,7 +286,7 @@ private extension EdgeInsets {
init(around: CGFloat) {
self.init(top: around, leading: around, bottom: around, trailing: around)
}
static var zero: Self = .init(around: 0)
}
@@ -370,7 +370,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}()
static var previews: some View {
mockTimeline
.previewDisplayName("Mock Timeline")
@@ -465,7 +465,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
.environmentObject(viewModelWithPins.context)
.environment(\.timelineContext, viewModel.context)
}
static var pinned: some View {
ScrollView {
MockTimelineContent(isPinned: true)
@@ -646,7 +646,7 @@ private struct MockTimelineContent: View {
isThreaded: isThreaded,
threadSummary: threadSummary)),
groupStyle: .single))
AudioRoomTimelineView(timelineItem: .init(id: makeItemIdentifier(),
timestamp: .mock,
isOutgoing: true,
@@ -14,7 +14,7 @@ enum TimelineGroupStyle: Hashable {
case first
case middle
case last
var shouldShowSenderDetails: Bool {
switch self {
case .single, .first:
@@ -23,7 +23,7 @@ struct TimelineStyler<Content: View>: View {
self.content = content
_adjustedDeliveryStatus = State(initialValue: timelineItem.properties.deliveryStatus)
}
var body: some View {
mainContent
.onChange(of: timelineItem.properties.deliveryStatus) { _, newStatus in
@@ -56,7 +56,7 @@ struct TimelineStyler<Content: View>: View {
struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel.mock
static let base = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: true,
@@ -64,19 +64,19 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
canBeRepliedTo: true,
sender: .test,
content: .init(body: "Test"))
static let sentNonLast: TextRoomTimelineItem = {
var result = base
result.properties.deliveryStatus = .sent
return result
}()
static let sendingNonLast: TextRoomTimelineItem = {
var result = base
result.properties.deliveryStatus = .sending
return result
}()
static let sendingLast: TextRoomTimelineItem = {
let id = viewModel.state.timelineState.uniqueIDs.last ?? .init(UUID().uuidString)
var result = TextRoomTimelineItem(id: .event(uniqueID: id, eventOrTransactionID: .eventID(UUID().uuidString)),
@@ -89,13 +89,13 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
result.properties.deliveryStatus = .sending
return result
}()
static let failed: TextRoomTimelineItem = {
var result = base
result.properties.deliveryStatus = .sendingFailed(.unknown)
return result
}()
static let sentLast: TextRoomTimelineItem = {
let id = viewModel.state.timelineState.uniqueIDs.last ?? .init(UUID().uuidString)
return TextRoomTimelineItem(id: .event(uniqueID: id, eventOrTransactionID: .eventID(UUID().uuidString)),
@@ -106,21 +106,21 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
sender: .test,
content: .init(body: "Test"))
}()
static let ltrString = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: true,
isEditable: false,
canBeRepliedTo: true,
sender: .test, content: .init(body: "house!"))
static let rtlString = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: true,
isEditable: false,
canBeRepliedTo: true,
sender: .test, content: .init(body: "באמת!"))
static let ltrStringThatContainsRtl = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: true,
@@ -128,7 +128,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
canBeRepliedTo: true,
sender: .test,
content: .init(body: "house! -- באמת! -- house!"))
static let rtlStringThatContainsLtr = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: true,
@@ -136,7 +136,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
canBeRepliedTo: true,
sender: .test,
content: .init(body: "באמת! -- house! -- באמת!"))
static let ltrStringThatFinishesInRtl = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: true,
@@ -144,7 +144,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
canBeRepliedTo: true,
sender: .test,
content: .init(body: "house! -- באמת!"))
static let rtlStringThatFinishesInLtr = TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: true,
@@ -161,7 +161,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
shouldBoost: true,
sender: .test,
content: .init(body: "😮"))
static let endingWithBlockquote: TextRoomTimelineItem = {
let builder = AttributedStringBuilder(cacheKey: "preview", mentionBuilder: MentionBuilder())
let attributedString = builder.fromHTML("<p>Some text before</p><blockquote>A quoted line at the end</blockquote>")
@@ -173,7 +173,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
sender: .test,
content: .init(body: "", formattedBody: attributedString))
}()
static let endingWithCodeblock: TextRoomTimelineItem = {
let builder = AttributedStringBuilder(cacheKey: "preview", mentionBuilder: MentionBuilder())
let attributedString = builder.fromHTML("<p>Some text before</p><pre><code>let x = 42</code></pre>")
@@ -185,7 +185,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
sender: .test,
content: .init(body: "", formattedBody: attributedString))
}()
static var testView: some View {
VStack(spacing: 0) {
TextRoomTimelineView(timelineItem: base)
@@ -198,7 +198,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
TextRoomTimelineView(timelineItem: endingWithCodeblock)
}
}
static var languagesTestView: some View {
VStack(spacing: 0) {
TextRoomTimelineView(timelineItem: ltrString)
@@ -210,7 +210,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
TextRoomTimelineView(timelineItem: bigEmoji)
}
}
static var previews: some View {
testView
.environmentObject(viewModel.context)
@@ -219,7 +219,7 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
languagesTestView
.environmentObject(viewModel.context)
.previewDisplayName("Bubbles LTR with different layout languages")
languagesTestView
.environmentObject(viewModel.context)
.environment(\.layoutDirection, .rightToLeft)
@@ -14,9 +14,9 @@ struct TimelineDeliveryStatusView: View {
case sending
case sent
}
let deliveryStatus: Status
private var icon: CompoundIcon {
switch deliveryStatus {
case .sending:
@@ -13,15 +13,15 @@ struct TimelineItemStatusView: View {
let timelineItem: EventBasedTimelineItemProtocol
let adjustedDeliveryStatus: TimelineItemDeliveryStatus?
@EnvironmentObject private var context: TimelineViewModel.Context
private var isLastOutgoingMessage: Bool {
timelineItem.isOutgoing && context.viewState.timelineState.uniqueIDs.last == timelineItem.id.uniqueID
}
var body: some View {
mainContent
}
@ViewBuilder
private var mainContent: some View {
if context.viewState.timelineKind == .pinned {
@@ -33,7 +33,7 @@ struct TimelineItemStatusView: View {
deliveryStatusBadge
}
}
@ViewBuilder
var deliveryStatusBadge: some View {
switch adjustedDeliveryStatus {
@@ -49,7 +49,7 @@ struct TimelineItemStatusView: View {
EmptyView()
}
}
var readReceipts: some View {
TimelineReadReceiptsView(timelineItem: timelineItem)
.environmentObject(context)
@@ -13,7 +13,7 @@ import SwiftUI
struct TimelineReactionsView: View {
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
@Environment(\.layoutDirection) private var layoutDirection: LayoutDirection
let context: TimelineViewModel.Context
let itemID: TimelineItemIdentifier
let reactions: [AggregatedReaction]
@@ -20,7 +20,7 @@ struct TimelineReadReceiptsView: View {
contentID: receipt.userID)
}
}
var body: some View {
HStack(spacing: 2) {
StackedAvatarsView(overlap: 6,
@@ -78,10 +78,10 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
.mockDan,
.mockMe
]
static let viewModel = {
let appSettings = AppSettings.volatile()
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Test", members: members)),
timelineController: MockTimelineController(),
userSession: UserSessionMock(.init()),
@@ -94,7 +94,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}()
static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")]
static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),
ReadReceipt(userID: RoomMemberProxyMock.mockBob.userID, formattedTimestamp: "Before")]
@@ -105,7 +105,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
ReadReceipt(userID: RoomMemberProxyMock.mockBob.userID, formattedTimestamp: "Before"),
ReadReceipt(userID: RoomMemberProxyMock.mockCharlie.userID, formattedTimestamp: "Way before"),
ReadReceipt(userID: RoomMemberProxyMock.mockDan.userID, formattedTimestamp: "Way, way before")]
static func mockTimelineItem(with receipts: [ReadReceipt]) -> TextRoomTimelineItem {
TextRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
@@ -115,7 +115,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
sender: .init(id: UUID().uuidString), content: .init(body: "Test"),
properties: .init(orderedReadReceipts: receipts))
}
static var previews: some View {
VStack(spacing: 8) {
TimelineReadReceiptsView(timelineItem: mockTimelineItem(with: singleReceipt))
@@ -20,14 +20,14 @@ struct CallNotificationRoomTimelineView: View {
CompoundIcon(iconKeyPath, size: .medium, relativeTo: .compound.headingMDBold)
.foregroundStyle(.compound.iconSecondary)
.accessibilityHidden(true)
Text(tileTitle)
.font(.compound.bodyMD)
.foregroundColor(.compound.textSecondary)
.labelStyle(.custom(spacing: 4))
Spacer()
Text(timelineItem.timestamp.formattedTime())
.font(.compound.bodyXS)
.foregroundColor(.compound.textSecondary)
@@ -39,7 +39,7 @@ struct CallNotificationRoomTimelineView: View {
}
// MARK: - Private
private var tileTitle: String {
if timelineItem.isDM {
// As per design only have declined variants in DM
@@ -54,7 +54,7 @@ struct CallNotificationRoomTimelineView: View {
L10n.commonCallStarted
}
}
private var iconKeyPath: KeyPath<CompoundIcons, Image> {
if timelineItem.isDM, timelineItem.isDeclined || timelineItem.isDeclinedByMe {
// As per design only have declined variants in DM
@@ -82,9 +82,9 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
isDeclinedByMe: false,
isDeclined: false,
isVoiceCall: false))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
@@ -93,9 +93,9 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
isDeclinedByMe: false,
isDeclined: false,
isVoiceCall: true))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
@@ -104,9 +104,9 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
isDeclinedByMe: true,
isDeclined: true,
isVoiceCall: false))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
@@ -115,9 +115,9 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
isDeclinedByMe: false,
isDeclined: true,
isVoiceCall: true))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
@@ -126,9 +126,9 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
isDeclinedByMe: true,
isDeclined: true,
isVoiceCall: true))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
@@ -137,9 +137,9 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
isDeclinedByMe: false,
isDeclined: true,
isVoiceCall: false))
Divider()
CallNotificationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isEditable: false,
@@ -148,7 +148,7 @@ struct CallNotificationRoomTimelineView_Previews: PreviewProvider, TestablePrevi
isDeclinedByMe: true,
isDeclined: true,
isVoiceCall: false))
Divider()
}
.padding()
@@ -73,7 +73,7 @@ struct FormattedBodyText: View {
type: .plainText))
}
let lastPlainTextIndex = components.lastIndex { $0.type == .plainText }
return TimelineBubbleLayout(spacing: 8) {
// The `ForEach` needs to iterate over the id of the element to allow
// SwiftUI animations to work properly ater any edit.
@@ -98,7 +98,7 @@ struct FormattedBodyText: View {
.timelineBubbleLayoutSize(.natural)
}
}
// Make a second iteration through the components adding naturally sized versions of the
// block quotes and code blocks which are used for layout calculations but won't be rendered.
ForEach(components) { component in
@@ -91,7 +91,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
static let composerViewModel = ComposerToolbarViewModel.mock()
static let timelineViewModel = {
let appSettings = AppSettings.volatile()
return TimelineViewModel(roomProxy: roomProxyMock,
focussedEventID: focussedEventID,
timelineController: MockTimelineController(),
@@ -105,7 +105,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}()
static var previews: some View {
ElementNavigationStack {
RoomScreen(context: roomViewModel.context,
@@ -65,7 +65,7 @@ struct ImageRoomTimelineView: View {
.timelineMediaFrame(imageInfo: timelineItem.content.thumbnailInfo ?? timelineItem.content.imageInfo)
}
}
private var placeholder: some View {
Rectangle()
.foregroundColor(timelineItem.isOutgoing ? .compound._bgBubbleOutgoing : .compound._bgBubbleIncoming)
@@ -23,7 +23,7 @@ struct LocationRoomTimelineView: View {
}
}
}
@ViewBuilder
private var mainContent: some View {
if let geoURI = timelineItem.content.geoURI {
@@ -41,16 +41,16 @@ struct LocationRoomTimelineView: View {
trailingReservedSize: timelineItem.trailingReservedSize)
}
}
// MARK: - Private
private let mapAspectRatio: Double = 3 / 2
private let mapMaxHeight: Double = 300
}
struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel.mock
static var previews: some View {
PreviewScrollView {
VStack(spacing: 8) {
@@ -62,7 +62,7 @@ struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview {
.previewLayout(.sizeThatFits)
.previewDisplayName("Bubbles")
}
@ViewBuilder
static var states: some View {
LocationRoomTimelineView(timelineItem: .init(id: .randomEvent,
@@ -72,7 +72,7 @@ struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview {
canBeRepliedTo: true,
sender: .init(id: "Bob"),
content: .init(body: "Fallback geo uri description")))
LocationRoomTimelineView(timelineItem: .init(id: .randomEvent,
timestamp: .mock,
isOutgoing: false,
@@ -54,24 +54,24 @@ struct PollRoomTimelineView: View {
struct PollRoomTimelineView_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel.mock
static let pinnedEventsTimelineViewModel = TimelineViewModel.mock(timelineKind: .pinned)
static var previews: some View {
PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(), isOutgoing: false))
.environmentObject(viewModel.context)
.previewDisplayName("Disclosed, Bubble")
PollRoomTimelineView(timelineItem: .mock(poll: .undisclosed(), isOutgoing: false))
.environmentObject(viewModel.context)
.previewDisplayName("Undisclosed, Bubble")
PollRoomTimelineView(timelineItem: .mock(poll: .endedDisclosed))
.environmentObject(viewModel.context)
.previewDisplayName("Ended, Disclosed, Bubble")
PollRoomTimelineView(timelineItem: .mock(poll: .endedUndisclosed))
.environmentObject(viewModel.context)
.previewDisplayName("Ended, Undisclosed, Bubble")
PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(createdByAccountOwner: true)))
.environmentObject(viewModel.context)
.previewDisplayName("Creator, disclosed, Bubble")
@@ -29,9 +29,9 @@ struct ReadMarkerRoomTimelineView: View {
struct ReadMarkerRoomTimelineView_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel.mock
static let item = ReadMarkerRoomTimelineItem(id: .randomVirtual)
static var previews: some View {
VStack(alignment: .leading, spacing: 0) {
RoomTimelineItemView(viewState: .init(type: .separator(.init(id: .virtual(uniqueID: .init("Separator")), timestamp: .mock)), groupStyle: .single))
@@ -42,9 +42,9 @@ struct ReadMarkerRoomTimelineView_Previews: PreviewProvider, TestablePreview {
canBeRepliedTo: true,
sender: .init(id: "1", displayName: "Bob"),
content: .init(body: "This is another message"))), groupStyle: .single))
ReadMarkerRoomTimelineView(timelineItem: item)
RoomTimelineItemView(viewState: .init(type: .separator(.init(id: .virtual(uniqueID: .init("Separator")), timestamp: .mock)), groupStyle: .single))
RoomTimelineItemView(viewState: .init(type: .text(.init(id: .randomEvent,
timestamp: .mock,
@@ -9,6 +9,6 @@
// periphery: ignore - markdown protocol
protocol TextBasedRoomTimelineViewProtocol {
associatedtype TimelineItemType: TextBasedRoomTimelineItem
var timelineItem: TimelineItemType { get }
}
@@ -37,11 +37,11 @@ struct VoiceMessageRoomTimelineContent: View {
onPlaybackSpeedChange: onPlaybackSpeedChange)
.fixedSize(horizontal: false, vertical: true)
}
private func onPlaybackPlayPause() {
context?.send(viewAction: .handleAudioPlayerAction(.playPause(itemID: timelineItem.id)))
}
private func onPlaybackSpeedChange() {
context?.send(viewAction: .handleAudioPlayerAction(.changePlaybackSpeed(itemID: timelineItem.id)))
}
@@ -11,9 +11,9 @@ import SwiftUI
struct TimelineSenderAvatarView: View {
@Environment(\.timelineContext) private var context
let timelineItem: EventBasedTimelineItemProtocol
var body: some View {
LoadableAvatarImage(url: timelineItem.sender.avatarURL,
name: timelineItem.sender.displayName,
@@ -79,7 +79,7 @@ struct TimelineView: View {
/// A table view wrapper that displays the timeline of a room.
struct TimelineViewRepresentable: UIViewControllerRepresentable {
@EnvironmentObject private var viewModelContext: TimelineViewModel.Context
func makeUIViewController(context: Context) -> TimelineTableViewController {
TimelineTableViewController(coordinator: context.coordinator,
isScrolledToBottom: $viewModelContext.isScrolledToBottom,
@@ -133,7 +133,7 @@ struct TimelineViewRepresentable: UIViewControllerRepresentable {
if tableViewController.readMarkerUniqueID != context.viewState.timelineState.readMarkerUniqueID {
tableViewController.readMarkerUniqueID = context.viewState.timelineState.readMarkerUniqueID
}
if tableViewController.typingMembers.members != context.viewState.typingMembers {
tableViewController.setTypingMembers(context.viewState.typingMembers)
}
@@ -154,7 +154,7 @@ struct TimelineView_Previews: PreviewProvider { // Not testable as this preview
static let composerViewModel = ComposerToolbarViewModel.mock()
static let timelineViewModel = {
let appSettings = AppSettings.volatile()
return TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockTimelineController(),
userSession: UserSessionMock(.init()),
@@ -167,7 +167,7 @@ struct TimelineView_Previews: PreviewProvider { // Not testable as this preview
linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}()
static var previews: some View {
ElementNavigationStack {
RoomScreen(context: roomViewModel.context,
@@ -15,12 +15,12 @@ struct VoiceMessageRoomPlaybackView: View {
@ScaledMetric private var waveformLineWidth = 2.0
@ScaledMetric private var waveformLinePadding = 2.0
@GestureState var isDragging = false
let onPlayPause: () -> Void
let onSeek: (Double) -> Void
let onScrubbing: (Bool) -> Void
let onPlaybackSpeedChange: () -> Void
var body: some View {
HStack(spacing: 8) {
VoiceMessageButton(state: .init(playerState.playerButtonPlaybackState),
@@ -36,7 +36,7 @@ struct VoiceMessageRoomPlaybackView: View {
.monospacedDigit()
.fixedSize(horizontal: true, vertical: true)
}
waveformView
.waveformInteraction(isDragging: $isDragging,
progress: playerState.progress,
@@ -62,7 +62,7 @@ struct VoiceMessageRoomPlaybackView: View {
DateFormatter.elapsedTimeFormatter.string(from: duration)
}
}
private var timeLabelContent: String {
// Display the duration if progress is 0.0
let percent = playerState.progress > 0.0 ? playerState.progress : 1.0
@@ -82,7 +82,7 @@ struct VoiceMessageRoomPlaybackView: View {
L10n.a11yVoiceMessage(durationString)
}
}
@ViewBuilder
private var waveformView: some View {
if let url = playerState.fileURL {
@@ -96,7 +96,7 @@ struct VoiceMessageRoomPlaybackView: View {
estimatedWaveformView
}
}
private var estimatedWaveformView: some View {
EstimatedWaveformView(lineWidth: waveformLineWidth,
linePadding: waveformLinePadding,
@@ -111,7 +111,7 @@ private extension DateFormatter {
dateFormatter.dateFormat = "m:ss"
return dateFormatter
}()
static let longElapsedTimeFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "mm:ss"