mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Tweak the design of various Forms to match Figma (#573)
Add formBackground and formRowBackground colours and adopt them. * Include topic in UI tests.
This commit is contained in:
@@ -21,7 +21,7 @@ struct FormSectionHeaderStyle: ViewModifier {
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.font(.element.footnoteBold)
|
||||
.font(.element.caption1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ struct SettingsActionButtonStyle: ButtonStyle {
|
||||
.frame(width: menuIconSize, height: menuIconSize)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(Color.element.background.opacity(configuration.isPressed ? 0.5 : 1))
|
||||
.fill(Color.element.formRowBackground.opacity(configuration.isPressed ? 0.5 : 1))
|
||||
}
|
||||
|
||||
Text(title)
|
||||
@@ -32,7 +32,7 @@ struct BugReportScreen: View {
|
||||
.padding(.horizontal, horizontalPadding)
|
||||
}
|
||||
.scrollDismissesKeyboard(.immediately)
|
||||
.background(Color.element.system)
|
||||
.background(Color.element.formBackground.ignoresSafeArea())
|
||||
.navigationTitle(ElementL10n.bugReportScreenTitle)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbar }
|
||||
@@ -52,18 +52,15 @@ struct BugReportScreen: View {
|
||||
private var descriptionTextEditor: some View {
|
||||
ZStack(alignment: .topLeading) {
|
||||
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||
.fill(Color.element.background)
|
||||
.fill(Color.element.formRowBackground)
|
||||
|
||||
TextEditor(text: $context.reportText)
|
||||
.tint(.element.brand)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 4)
|
||||
.background(Color.clear)
|
||||
.cornerRadius(14)
|
||||
.accessibilityIdentifier("reportTextView")
|
||||
.introspectTextView { textView in
|
||||
textView.backgroundColor = .clear
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
|
||||
if context.reportText.isEmpty {
|
||||
Text(ElementL10n.bugReportScreenDescription)
|
||||
@@ -90,7 +87,7 @@ struct BugReportScreen: View {
|
||||
.accessibilityIdentifier("sendLogsToggle")
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 11)
|
||||
.background(RoundedRectangle(cornerRadius: 14).fill(Color.element.background))
|
||||
.background(RoundedRectangle(cornerRadius: 14).fill(Color.element.formRowBackground))
|
||||
|
||||
Text(ElementL10n.bugReportScreenLogsDescription)
|
||||
.font(.element.caption1)
|
||||
@@ -142,9 +139,11 @@ struct BugReportScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct BugReport_Previews: PreviewProvider {
|
||||
static let viewModel = BugReportViewModel(bugReportService: MockBugReportService(),
|
||||
screenshot: Asset.Images.appLogo.image,
|
||||
isModallyPresented: false)
|
||||
|
||||
static var previews: some View {
|
||||
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(), screenshot: Asset.Images.appLogo.image, isModallyPresented: false)
|
||||
BugReportScreen(context: viewModel.context)
|
||||
.previewInterfaceOrientation(.portrait)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,14 +28,19 @@ struct RoomDetailsScreen: View {
|
||||
|
||||
if let topic = context.viewState.topic {
|
||||
topicSection(with: topic)
|
||||
.listRowBackground(Color.element.formRowBackground)
|
||||
}
|
||||
|
||||
aboutSection
|
||||
.listRowBackground(Color.element.formRowBackground)
|
||||
|
||||
if context.viewState.isEncrypted {
|
||||
securitySection
|
||||
.listRowBackground(Color.element.formRowBackground)
|
||||
}
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.background(Color.element.formBackground.ignoresSafeArea())
|
||||
.alert(item: $context.alertInfo) { $0.alert }
|
||||
}
|
||||
|
||||
@@ -82,103 +87,111 @@ struct RoomDetailsScreen: View {
|
||||
}
|
||||
|
||||
private func topicSection(with topic: String) -> some View {
|
||||
Section(header: Text(ElementL10n.roomSettingsTopic)
|
||||
.formSectionHeader()) {
|
||||
Text(topic)
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.font(.element.footnote)
|
||||
}
|
||||
Section {
|
||||
Text(topic)
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.font(.element.footnote)
|
||||
} header: {
|
||||
Text(ElementL10n.roomSettingsTopic)
|
||||
.formSectionHeader()
|
||||
}
|
||||
}
|
||||
|
||||
private var aboutSection: some View {
|
||||
Section(header: Text(ElementL10n.roomDetailsAboutSectionTitle)
|
||||
.formSectionHeader()) {
|
||||
Button {
|
||||
context.send(viewAction: .processTapPeople)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "person")
|
||||
Section {
|
||||
Button {
|
||||
context.send(viewAction: .processTapPeople)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "person")
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.padding(4)
|
||||
.background(Color.element.formBackground)
|
||||
.cornerRadius(8)
|
||||
.frame(width: menuIconSize, height: menuIconSize)
|
||||
|
||||
Text(ElementL10n.bottomActionPeople)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.font(.body)
|
||||
|
||||
Spacer()
|
||||
|
||||
if context.viewState.isLoadingMembers {
|
||||
ProgressView()
|
||||
} else {
|
||||
Text(String(context.viewState.members.count))
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.padding(4)
|
||||
.background(Color.element.system)
|
||||
.clipShape(RoundedCornerShape(radius: 8, corners: .allCorners))
|
||||
.frame(width: menuIconSize, height: menuIconSize)
|
||||
|
||||
Text(ElementL10n.bottomActionPeople)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.font(.body)
|
||||
|
||||
Spacer()
|
||||
|
||||
if context.viewState.isLoadingMembers {
|
||||
ProgressView()
|
||||
} else {
|
||||
Text(String(context.viewState.members.count))
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.font(.element.body)
|
||||
Image(systemName: "chevron.forward")
|
||||
.foregroundColor(.element.quaternaryContent)
|
||||
}
|
||||
.font(.element.body)
|
||||
Image(systemName: "chevron.forward")
|
||||
.foregroundColor(.element.quaternaryContent)
|
||||
}
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("peopleButton")
|
||||
.disabled(context.viewState.isLoadingMembers)
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("peopleButton")
|
||||
.disabled(context.viewState.isLoadingMembers)
|
||||
} header: {
|
||||
Text(ElementL10n.roomDetailsAboutSectionTitle)
|
||||
.formSectionHeader()
|
||||
}
|
||||
}
|
||||
|
||||
private var securitySection: some View {
|
||||
Section(header: Text(ElementL10n.roomProfileSectionSecurity)
|
||||
.formSectionHeader()) {
|
||||
HStack(alignment: .top) {
|
||||
Image(systemName: "lock.shield")
|
||||
Section {
|
||||
HStack(alignment: .top) {
|
||||
Image(systemName: "lock.shield")
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.padding(4)
|
||||
.background(Color.element.formBackground)
|
||||
.cornerRadius(8)
|
||||
.frame(width: menuIconSize, height: menuIconSize)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(ElementL10n.encryptionEnabled)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.font(.element.body)
|
||||
|
||||
Text(ElementL10n.encryptionEnabledTileDescription)
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.padding(4)
|
||||
.background(Color.element.system)
|
||||
.clipShape(RoundedCornerShape(radius: 8, corners: .allCorners))
|
||||
.frame(width: menuIconSize, height: menuIconSize)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(ElementL10n.encryptionEnabled)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.font(.element.body)
|
||||
|
||||
Text(ElementL10n.encryptionEnabledTileDescription)
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.font(.element.footnote)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.element.quaternaryContent)
|
||||
.font(.element.footnote)
|
||||
}
|
||||
.padding(.horizontal, -3)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.element.quaternaryContent)
|
||||
}
|
||||
.padding(.horizontal, -3)
|
||||
} header: {
|
||||
Text(ElementL10n.roomProfileSectionSecurity)
|
||||
.formSectionHeader()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct RoomDetails_Previews: PreviewProvider {
|
||||
static let viewModel = {
|
||||
let members: [RoomMemberProxy] = [
|
||||
.mockAlice,
|
||||
.mockBob,
|
||||
.mockCharlie
|
||||
]
|
||||
let roomProxy = MockRoomProxy(displayName: "Room A",
|
||||
topic: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
isDirect: false,
|
||||
isEncrypted: true,
|
||||
canonicalAlias: "#alias:domain.com",
|
||||
members: members)
|
||||
|
||||
return RoomDetailsViewModel(roomProxy: roomProxy,
|
||||
mediaProvider: MockMediaProvider())
|
||||
}()
|
||||
|
||||
static var previews: some View {
|
||||
Group {
|
||||
let members: [RoomMemberProxy] = [
|
||||
.mockAlice,
|
||||
.mockBob,
|
||||
.mockCharlie
|
||||
]
|
||||
let roomProxy = MockRoomProxy(displayName: "Room A",
|
||||
topic: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
isDirect: false,
|
||||
isEncrypted: true,
|
||||
canonicalAlias: "#alias:domain.com",
|
||||
members: members)
|
||||
let viewModel = RoomDetailsViewModel(roomProxy: roomProxy,
|
||||
mediaProvider: MockMediaProvider())
|
||||
RoomDetailsScreen(context: viewModel.context)
|
||||
}
|
||||
.tint(.element.accent)
|
||||
RoomDetailsScreen(context: viewModel.context)
|
||||
.tint(.element.accent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ struct SettingsScreen: View {
|
||||
|
||||
@ScaledMetric private var avatarSize = AvatarSize.user(on: .settings).value
|
||||
@ScaledMetric private var menuIconSize = 30.0
|
||||
|
||||
private let listRowInsets = EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16)
|
||||
|
||||
@ObservedObject var context: SettingsScreenViewModel.Context
|
||||
@@ -29,25 +30,23 @@ struct SettingsScreen: View {
|
||||
var body: some View {
|
||||
Form {
|
||||
userSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
.listRowBackground(Color.element.formRowBackground)
|
||||
|
||||
if context.viewState.showSessionVerificationSection {
|
||||
sessionVerificationSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
.listRowBackground(Color.element.formRowBackground)
|
||||
}
|
||||
|
||||
simplifiedSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
.listRowBackground(Color.element.formRowBackground)
|
||||
|
||||
signOutSection
|
||||
.listRowBackground(rowBackgroundColor)
|
||||
}
|
||||
.introspectTableView { tableView in
|
||||
tableView.backgroundColor = .clear
|
||||
.listRowBackground(Color.element.formRowBackground)
|
||||
}
|
||||
.scrollContentBackground(.hidden)
|
||||
.background(Color.element.formBackground.ignoresSafeArea())
|
||||
.navigationTitle(ElementL10n.settings)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.background(backgroundColor.ignoresSafeArea())
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
doneButton
|
||||
@@ -59,14 +58,6 @@ struct SettingsScreen: View {
|
||||
Text(ElementL10n.settingsVersion + ": " + InfoPlistReader.main.bundleShortVersionString + " (" + InfoPlistReader.main.bundleVersion + ")")
|
||||
}
|
||||
|
||||
private var backgroundColor: Color {
|
||||
.element.system
|
||||
}
|
||||
|
||||
private var rowBackgroundColor: Color {
|
||||
colorScheme == .light ? .element.background : .element.system
|
||||
}
|
||||
|
||||
private var userSection: some View {
|
||||
Section {
|
||||
HStack(spacing: 13) {
|
||||
@@ -189,7 +180,7 @@ struct SettingsScreen_Previews: PreviewProvider {
|
||||
|
||||
NavigationView {
|
||||
SettingsScreen(context: viewModel.context)
|
||||
.previewInterfaceOrientation(.portrait)
|
||||
.tint(.element.accent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,8 +287,10 @@ class MockScreen: Identifiable {
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
let roomProxy = MockRoomProxy(id: "MockRoomIdentifier",
|
||||
displayName: "Room",
|
||||
topic: "Bacon ipsum dolor amet commodo incididunt ribeye dolore cupidatat short ribs.",
|
||||
avatarURL: URL.picturesDirectory,
|
||||
isEncrypted: true,
|
||||
canonicalAlias: "#mock:room.org",
|
||||
members: [.mockAlice, .mockBob, .mockCharlie])
|
||||
let coordinator = RoomDetailsCoordinator(parameters: .init(navigationStackCoordinator: navigationStackCoordinator,
|
||||
roomProxy: roomProxy,
|
||||
|
||||
Reference in New Issue
Block a user