mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Remove plain style layout (#2980)
This commit is contained in:
@@ -1,307 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct TimelineItemPlainStylerView<Content: View>: View {
|
||||
@EnvironmentObject private var context: RoomScreenViewModel.Context
|
||||
@Environment(\.timelineGroupStyle) private var timelineGroupStyle
|
||||
@Environment(\.focussedEventID) private var focussedEventID
|
||||
|
||||
let timelineItem: EventBasedTimelineItemProtocol
|
||||
let adjustedDeliveryStatus: TimelineItemDeliveryStatus?
|
||||
@ViewBuilder let content: () -> Content
|
||||
|
||||
private var isFocussed: Bool { focussedEventID != nil && timelineItem.id.eventID == focussedEventID }
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .trailing, spacing: 0) {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
header
|
||||
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
contentWithReply
|
||||
supplementaryViews
|
||||
}
|
||||
}
|
||||
TimelineItemStatusView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus)
|
||||
.environmentObject(context)
|
||||
}
|
||||
.padding(TimelineStyle.plain.rowInsets)
|
||||
.highlightedTimelineItem(isFocussed)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var contentWithReply: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
if let messageTimelineItem = timelineItem as? EventBasedMessageTimelineItemProtocol {
|
||||
if messageTimelineItem.isThreaded {
|
||||
ThreadDecorator()
|
||||
}
|
||||
if let replyDetails = messageTimelineItem.replyDetails {
|
||||
HStack(spacing: 4.0) {
|
||||
Rectangle()
|
||||
.foregroundColor(.compound.iconTertiary)
|
||||
.frame(width: 4.0)
|
||||
|
||||
TimelineReplyView(placement: .timeline, timelineItemReplyDetails: replyDetails)
|
||||
.onTapGesture {
|
||||
context.send(viewAction: .focusOnEventID(replyDetails.eventID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
content()
|
||||
.layoutPriority(1)
|
||||
.timelineItemAccessibility(timelineItem) {
|
||||
context.send(viewAction: .displayTimelineItemMenu(itemID: timelineItem.id))
|
||||
}
|
||||
}
|
||||
.onTapGesture(count: 2) {
|
||||
context.send(viewAction: .displayEmojiPicker(itemID: timelineItem.id))
|
||||
}
|
||||
.onTapGesture {
|
||||
context.send(viewAction: .itemTapped(itemID: timelineItem.id))
|
||||
}
|
||||
// We need a tap gesture before this long one so that it doesn't
|
||||
// steal away the gestures from the scroll view
|
||||
.longPressWithFeedback {
|
||||
context.send(viewAction: .displayTimelineItemMenu(itemID: timelineItem.id))
|
||||
}
|
||||
.swipeRightAction {
|
||||
SwipeToReplyView(timelineItem: timelineItem)
|
||||
} shouldStartAction: {
|
||||
context.viewState.timelineItemMenuActionProvider?(timelineItem.id)?.canReply ?? false
|
||||
} action: {
|
||||
let isThread = (timelineItem as? EventBasedMessageTimelineItemProtocol)?.isThreaded ?? false
|
||||
context.send(viewAction: .handleTimelineItemMenuAction(itemID: timelineItem.id, action: .reply(isThread: isThread)))
|
||||
}
|
||||
.contextMenu {
|
||||
TimelineItemMacContextMenu(item: timelineItem,
|
||||
actionProvider: context.viewState.timelineItemMenuActionProvider) { action in
|
||||
context.send(viewAction: .handleTimelineItemMenuAction(itemID: timelineItem.id, action: action))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var header: some View {
|
||||
if shouldShowSenderDetails {
|
||||
HStack(spacing: 8) {
|
||||
HStack(spacing: 8) {
|
||||
TimelineSenderAvatarView(timelineItem: timelineItem)
|
||||
Text(timelineItem.sender.displayName ?? timelineItem.sender.id)
|
||||
.font(.compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.decorativeColor(for: timelineItem.sender.id).text)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.onTapGesture {
|
||||
context.send(viewAction: .displayRoomMemberDetails(userID: timelineItem.sender.id))
|
||||
}
|
||||
Spacer()
|
||||
Text(timelineItem.timestamp)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.font(.compound.bodyXS)
|
||||
}
|
||||
.padding(.top, 16)
|
||||
// sender info are read inside the `TimelineAccessibilityModifier`
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var supplementaryViews: some View {
|
||||
VStack(spacing: 4) {
|
||||
if timelineItem.properties.isEdited {
|
||||
Text(L10n.commonEditedSuffix)
|
||||
.font(.compound.bodySM)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
}
|
||||
|
||||
if !timelineItem.properties.reactions.isEmpty {
|
||||
TimelineReactionsView(context: context,
|
||||
itemID: timelineItem.id,
|
||||
reactions: timelineItem.properties.reactions)
|
||||
// Workaround to stop the message long press stealing the touch from the reaction buttons
|
||||
.onTapGesture { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var shouldShowSenderDetails: Bool {
|
||||
timelineGroupStyle.shouldShowSenderDetails
|
||||
}
|
||||
}
|
||||
|
||||
struct TimelineItemPlainStylerView_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = RoomScreenViewModel.mock
|
||||
|
||||
static var previews: some View {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
ForEach(1..<MockRoomTimelineController().timelineItems.count, id: \.self) { index in
|
||||
let item = MockRoomTimelineController().timelineItems[index]
|
||||
RoomTimelineItemView(viewState: .init(item: item, groupStyle: .single))
|
||||
}
|
||||
}
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewLayout(.sizeThatFits)
|
||||
|
||||
threads
|
||||
.padding()
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.previewDisplayName("Threads")
|
||||
|
||||
replies
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.previewDisplayName("Replies")
|
||||
}
|
||||
|
||||
// These akwats include a reply
|
||||
static var threads: some View {
|
||||
ScrollView {
|
||||
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""),
|
||||
timestamp: "10:42",
|
||||
isOutgoing: true,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: true,
|
||||
sender: .init(id: "whoever"),
|
||||
content: .init(body: "A long message that should be on multiple lines."),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))),
|
||||
groupStyle: .single))
|
||||
|
||||
AudioRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""),
|
||||
timestamp: "10:42",
|
||||
isOutgoing: true,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: true,
|
||||
sender: .init(id: ""),
|
||||
content: .init(body: "audio.ogg",
|
||||
duration: 100,
|
||||
waveform: nil,
|
||||
source: nil,
|
||||
contentType: nil),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))))
|
||||
FileRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""),
|
||||
timestamp: "10:42",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: true,
|
||||
sender: .init(id: ""),
|
||||
content: .init(body: "File",
|
||||
source: nil,
|
||||
thumbnailSource: nil,
|
||||
contentType: nil),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))))
|
||||
ImageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""),
|
||||
timestamp: "10:42",
|
||||
isOutgoing: true,
|
||||
isEditable: true,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: true,
|
||||
sender: .init(id: ""),
|
||||
content: .init(body: "Some image", source: MediaSourceProxy(url: .picturesDirectory, mimeType: "image/png"), thumbnailSource: nil),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))))
|
||||
LocationRoomTimelineView(timelineItem: .init(id: .random,
|
||||
timestamp: "Now",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: true,
|
||||
sender: .init(id: "Bob"),
|
||||
content: .init(body: "Fallback geo uri description",
|
||||
geoURI: .init(latitude: 41.902782,
|
||||
longitude: 12.496366),
|
||||
description: "Location description description description description description description description description"),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))))
|
||||
LocationRoomTimelineView(timelineItem: .init(id: .random,
|
||||
timestamp: "Now",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: true,
|
||||
sender: .init(id: "Bob"),
|
||||
content: .init(body: "Fallback geo uri description",
|
||||
geoURI: .init(latitude: 41.902782, longitude: 12.496366), description: nil),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))))
|
||||
VoiceMessageRoomTimelineView(timelineItem: .init(id: .init(timelineID: ""),
|
||||
timestamp: "10:42",
|
||||
isOutgoing: true,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: true,
|
||||
sender: .init(id: ""),
|
||||
content: .init(body: "audio.ogg",
|
||||
duration: 100,
|
||||
waveform: EstimatedWaveform.mockWaveform,
|
||||
source: nil,
|
||||
contentType: nil),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))),
|
||||
playerState: AudioPlayerState(id: .timelineItemIdentifier(.init(timelineID: "")), duration: 10, waveform: EstimatedWaveform.mockWaveform))
|
||||
}
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var replies: some View {
|
||||
ScrollView {
|
||||
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""),
|
||||
timestamp: "10:42",
|
||||
isOutgoing: true,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: false,
|
||||
sender: .init(id: "whoever"),
|
||||
content: .init(body: "A long message that should be on multiple lines."),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "Short"))))),
|
||||
groupStyle: .single))
|
||||
|
||||
RoomTimelineItemView(viewState: .init(item: TextRoomTimelineItem(id: .init(timelineID: ""),
|
||||
timestamp: "10:42",
|
||||
isOutgoing: true,
|
||||
isEditable: false,
|
||||
canBeRepliedTo: true,
|
||||
isThreaded: false,
|
||||
sender: .init(id: "whoever"),
|
||||
content: .init(body: "Short message"),
|
||||
replyDetails: .loaded(sender: .init(id: "", displayName: "Alice"),
|
||||
eventID: "123",
|
||||
eventContent: .message(.text(.init(body: "A long message that should be on more than 2 lines and so will be clipped by the layout."))))),
|
||||
groupStyle: .single))
|
||||
}
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,11 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
enum TimelineStyle: String, CaseIterable, Codable {
|
||||
case plain
|
||||
case bubbles
|
||||
|
||||
/// List row insets for a timeline
|
||||
var rowInsets: EdgeInsets {
|
||||
switch self {
|
||||
case .plain:
|
||||
return EdgeInsets(top: 4, leading: 20, bottom: 4, trailing: 20)
|
||||
case .bubbles:
|
||||
return EdgeInsets(top: 1, leading: 8, bottom: 1, trailing: 8)
|
||||
}
|
||||
@@ -34,8 +31,6 @@ enum TimelineStyle: String, CaseIterable, Codable {
|
||||
/// Short hand for `self == .bubbles`
|
||||
var isBubbles: Bool {
|
||||
switch self {
|
||||
case .plain:
|
||||
return false
|
||||
case .bubbles:
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ struct TimelineStyler<Content: View>: View {
|
||||
@ViewBuilder
|
||||
var mainContent: some View {
|
||||
switch style {
|
||||
case .plain:
|
||||
TimelineItemPlainStylerView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, content: content)
|
||||
case .bubbles:
|
||||
TimelineItemBubbledStylerView(timelineItem: timelineItem, adjustedDeliveryStatus: adjustedDeliveryStatus, content: content)
|
||||
}
|
||||
@@ -204,11 +202,6 @@ struct TimelineItemStyler_Previews: PreviewProvider, TestablePreview {
|
||||
.environmentObject(viewModel.context)
|
||||
.environment(\.timelineStyle, .bubbles)
|
||||
.previewDisplayName("Bubbles")
|
||||
|
||||
testView
|
||||
.environmentObject(viewModel.context)
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.previewDisplayName("Plain")
|
||||
|
||||
languagesTestView
|
||||
.environmentObject(viewModel.context)
|
||||
|
||||
@@ -51,13 +51,8 @@ struct TimelineItemStatusView: View {
|
||||
TimelineDeliveryStatusView(deliveryStatus: .sent)
|
||||
}
|
||||
case .sendingFailed:
|
||||
// Bubbles handle the failure internally, but plain items don't.
|
||||
if style == .plain {
|
||||
CompoundIcon(\.error, size: .xSmall, relativeTo: .compound.bodyMD)
|
||||
.foregroundColor(.compound.iconCriticalPrimary)
|
||||
.accessibilityLabel(L10n.commonSendingFailed)
|
||||
.accessibilityHint(L10n.actionTapForOptions)
|
||||
}
|
||||
// Bubbles handle the case internally
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,6 @@ struct AudioRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -37,9 +37,6 @@ struct EmoteRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -62,9 +62,6 @@ struct EncryptedRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -40,9 +40,6 @@ struct FileRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -173,8 +173,6 @@ struct FormattedBodyText: View {
|
||||
struct FormattedBodyText_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
body
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
||||
@@ -61,9 +61,6 @@ struct ImageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
body
|
||||
.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -93,15 +93,6 @@ struct LocationRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Bubbles")
|
||||
|
||||
ScrollView {
|
||||
VStack(spacing: 0) {
|
||||
states
|
||||
}
|
||||
}
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Plain")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
||||
@@ -49,9 +49,6 @@ struct NoticeRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -77,40 +77,10 @@ struct PollRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
.environment(\.timelineStyle, .bubbles)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Creator, disclosed, Bubble")
|
||||
|
||||
PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(), isOutgoing: false))
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Disclosed, Plain")
|
||||
|
||||
PollRoomTimelineView(timelineItem: .mock(poll: .undisclosed(), isOutgoing: false))
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Undisclosed, Plain")
|
||||
|
||||
PollRoomTimelineView(timelineItem: .mock(poll: .endedDisclosed))
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Ended, Disclosed, Plain")
|
||||
|
||||
PollRoomTimelineView(timelineItem: .mock(poll: .endedUndisclosed))
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Ended, Undisclosed, Plain")
|
||||
|
||||
PollRoomTimelineView(timelineItem: .mock(poll: .disclosed(createdByAccountOwner: true)))
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Creator, disclosed, Plain")
|
||||
|
||||
PollRoomTimelineView(timelineItem: .mock(poll: .emptyDisclosed, isEditable: true))
|
||||
.environment(\.timelineStyle, .bubbles)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Creator, no votes, Bubble")
|
||||
|
||||
PollRoomTimelineView(timelineItem: .mock(poll: .emptyDisclosed, isEditable: true))
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Creator, no votes, Plain")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,6 @@ struct StateRoomTimelineView: View {
|
||||
struct StateRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
body
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -52,9 +52,6 @@ struct StickerRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -42,19 +42,10 @@ struct TextRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Bubble")
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Plain")
|
||||
body
|
||||
.environmentObject(viewModel.context)
|
||||
.environment(\.layoutDirection, .rightToLeft)
|
||||
.previewDisplayName("Bubble RTL")
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.environment(\.layoutDirection, .rightToLeft)
|
||||
.previewDisplayName("Plain RTL")
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -44,9 +44,6 @@ struct UnsupportedRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
@@ -72,9 +72,6 @@ struct VideoRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
-11
@@ -41,17 +41,6 @@ struct AdvancedSettingsScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
private extension TimelineStyle {
|
||||
var name: String {
|
||||
switch self {
|
||||
case .plain:
|
||||
return L10n.commonModern
|
||||
case .bubbles:
|
||||
return L10n.commonBubbles
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension AppAppearance {
|
||||
var name: String {
|
||||
switch self {
|
||||
|
||||
-4
@@ -86,10 +86,6 @@ struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
body.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Bubble")
|
||||
body
|
||||
.environment(\.timelineStyle, .plain)
|
||||
.environmentObject(viewModel.context)
|
||||
.previewDisplayName("Plain")
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
|
||||
Reference in New Issue
Block a user