Use Compound List in more screens. (#2099)

* Use Compound List in room member details, secure backup, notification settings.

* Use ListRow in CreateRoomScreen.

* Fix ListRow layout when isWaiting && !isSelected.
This commit is contained in:
Doug 2023-11-17 17:07:27 +00:00 committed by GitHub
parent f717c7dba4
commit f2b4525d91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 188 additions and 218 deletions

View File

@ -6664,7 +6664,7 @@
repositoryURL = "https://github.com/vector-im/compound-ios";
requirement = {
kind = revision;
revision = 7ae8b7ef4033861d0439427d5404538243afeffd;
revision = 59166acc95a775ba3b7e7d39e5605611cf0e657f;
};
};
9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {

View File

@ -14,7 +14,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/vector-im/compound-ios",
"state" : {
"revision" : "7ae8b7ef4033861d0439427d5404538243afeffd"
"revision" : "59166acc95a775ba3b7e7d39e5605611cf0e657f"
}
},
{

View File

@ -26,7 +26,7 @@ struct RoomProxyMockConfiguration {
var isDirect = Bool.random()
var isSpace = Bool.random()
var isPublic = Bool.random()
var isEncrypted = Bool.random()
var isEncrypted = true
var isTombstoned = Bool.random()
var hasOngoingCall = false
var canonicalAlias: String?

View File

@ -92,7 +92,7 @@ struct BugReportScreen: View {
PhotosPicker(selection: $selectedScreenshot,
matching: .screenshots,
photoLibrary: .shared()) {
ListLabel.plain(title: photosPickerTitle)
ListRowLabel.plain(title: photosPickerTitle)
}
})
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.attachScreenshot)

View File

@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct CreateRoomScreen: View {
@ -31,16 +32,12 @@ struct CreateRoomScreen: View {
topicSection
securitySection
}
.compoundForm()
.compoundList()
.track(screen: .createRoom)
.scrollDismissesKeyboard(.immediately)
.navigationTitle(L10n.screenCreateRoomTitle)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
createButton
}
}
.toolbar { toolbar }
.readFrame($frame)
.alert(item: $context.alertInfo)
}
@ -48,86 +45,82 @@ struct CreateRoomScreen: View {
private var roomSection: some View {
Section {
HStack(alignment: .center, spacing: 16) {
Button {
focus = nil
context.showAttachmentConfirmationDialog = true
} label: {
if let url = context.viewState.avatarURL {
AsyncImage(url: url) { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
} placeholder: {
ProgressView()
}
.scaledFrame(size: 70)
.clipShape(Circle())
} else {
cameraImage
}
}
.buttonStyle(.plain)
.confirmationDialog("", isPresented: $context.showAttachmentConfirmationDialog) {
Button(L10n.actionTakePhoto) {
context.send(viewAction: .displayCameraPicker)
}
Button(L10n.actionChoosePhoto) {
context.send(viewAction: .displayMediaPicker)
}
if context.viewState.avatarURL != nil {
Button(L10n.actionRemove, role: .destructive) {
context.send(viewAction: .removeImage)
}
}
}
roomAvatarButton
VStack(alignment: .leading, spacing: 8) {
Text(L10n.screenCreateRoomRoomNameLabel.uppercased())
.padding(.leading, FormRow.insets.leading)
.compoundFormSectionHeader()
.padding(.leading, ListRowPadding.horizontal)
.compoundListSectionHeader()
TextField(L10n.screenCreateRoomRoomNameLabel,
text: $context.roomName,
prompt: Text(L10n.commonRoomNamePlaceholder).foregroundColor(.compound.textPlaceholder),
axis: .horizontal)
.focused($focus, equals: .name)
.accessibilityIdentifier(A11yIdentifiers.createRoomScreen.roomName)
.padding(EdgeInsets(top: 10, leading: 16, bottom: 10, trailing: 16))
.background(Color.compound.bgCanvasDefaultLevel1)
.clipShape(RoundedRectangle(cornerRadius: 8))
.padding(.horizontal, ListRowPadding.horizontal)
.padding(.vertical, ListRowPadding.vertical)
.background(.compound.bgCanvasDefaultLevel1, in: RoundedRectangle(cornerRadius: 12))
}
}
.listRowInsets(.init())
.listRowBackground(Color.clear)
}
.compoundFormSection()
}
private var cameraImage: some View {
Image(systemName: "camera")
.font(.system(size: 28, weight: .semibold))
.foregroundColor(.compound.iconSecondary)
.scaledFrame(size: 70)
.background(Color.compound.bgSubtlePrimary)
.clipShape(Circle())
private var roomAvatarButton: some View {
Button {
focus = nil
context.showAttachmentConfirmationDialog = true
} label: {
if let url = context.viewState.avatarURL {
AsyncImage(url: url) { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
} placeholder: {
ProgressView()
}
.scaledFrame(size: 70)
.clipShape(Circle())
} else {
CompoundIcon(asset: Asset.Images.takePhoto, size: .custom(36), relativeTo: .title)
.foregroundColor(.compound.iconSecondary)
.scaledFrame(size: 70, relativeTo: .title)
.background(.compound.bgSubtlePrimary, in: Circle())
}
}
.buttonStyle(.plain)
.confirmationDialog("", isPresented: $context.showAttachmentConfirmationDialog) {
Button(L10n.actionTakePhoto) {
context.send(viewAction: .displayCameraPicker)
}
Button(L10n.actionChoosePhoto) {
context.send(viewAction: .displayMediaPicker)
}
if context.viewState.avatarURL != nil {
Button(L10n.actionRemove, role: .destructive) {
context.send(viewAction: .removeImage)
}
}
}
}
private var topicSection: some View {
Section {
TextField(L10n.screenCreateRoomTopicLabel,
text: $context.roomTopic,
prompt: Text(L10n.commonTopicPlaceholder).foregroundColor(.compound.textPlaceholder),
axis: .vertical)
ListRow(label: .plain(title: L10n.commonTopicPlaceholder),
kind: .textField(text: $context.roomTopic, axis: .vertical))
.lineLimit(3, reservesSpace: false)
.focused($focus, equals: .topic)
.accessibilityIdentifier(A11yIdentifiers.createRoomScreen.roomTopic)
.lineLimit(3, reservesSpace: false)
} header: {
Text(L10n.screenCreateRoomTopicLabel)
.compoundFormSectionHeader()
.compoundListSectionHeader()
} footer: {
if !context.viewState.selectedUsers.isEmpty {
selectedUsersSection
}
}
.compoundFormSection()
}
@State private var frame: CGRect = .zero
@ -143,61 +136,38 @@ struct CreateRoomScreen: View {
.frame(width: invitedUserCellWidth)
}
}
.padding(.init(top: 22, leading: 20, bottom: 0, trailing: 32))
.padding(.horizontal, ListRowPadding.horizontal)
.padding(.vertical, 22)
}
.frame(width: frame.width)
}
private var securitySection: some View {
Section {
Picker(L10n.commonSecurity, selection: $context.isRoomPrivate) {
Label {
VStack(alignment: .leading, spacing: 2) {
Text(L10n.screenCreateRoomPrivateOptionTitle)
.font(.compound.bodyLG)
Text(L10n.screenCreateRoomPrivateOptionDescription)
.font(.compound.bodyXS)
.foregroundColor(.compound.textSecondary)
}
} icon: {
Image(systemName: "lock.shield")
}
.tag(true)
.labelStyle(FormRowLabelStyle(alignment: .top))
Label {
VStack(alignment: .leading, spacing: 2) {
Text(L10n.screenCreateRoomPublicOptionTitle)
.font(.compound.bodyLG)
Text(L10n.screenCreateRoomPublicOptionDescription)
.font(.compound.bodyXS)
.foregroundColor(.compound.textSecondary)
}
} icon: {
Image(systemName: "exclamationmark.shield")
}
.tag(false)
.labelStyle(FormRowLabelStyle(alignment: .top))
}
.labelsHidden()
.pickerStyle(.inline)
ListRow(label: .default(title: L10n.screenCreateRoomPrivateOptionTitle,
description: L10n.screenCreateRoomPrivateOptionDescription,
icon: CompoundIcon(asset: Asset.Images.lock),
iconAlignment: .top),
kind: .selection(isSelected: context.isRoomPrivate) { context.isRoomPrivate = true })
ListRow(label: .default(title: L10n.screenCreateRoomPublicOptionTitle,
description: L10n.screenCreateRoomPublicOptionDescription,
icon: \.public,
iconAlignment: .top),
kind: .selection(isSelected: !context.isRoomPrivate) { context.isRoomPrivate = false })
} header: {
Text(L10n.commonSecurity.uppercased())
.compoundFormSectionHeader()
.padding(.top, 40)
.compoundListSectionHeader()
}
.listRowSeparatorTint(.compound.borderDisabled)
.listRowBackground(Color.compound.bgCanvasDefaultLevel1)
}
private var createButton: some View {
Button {
focus = nil
context.send(viewAction: .createRoom)
} label: {
Text(L10n.actionCreate)
private var toolbar: some ToolbarContent {
ToolbarItem(placement: .confirmationAction) {
Button(L10n.actionCreate) {
focus = nil
context.send(viewAction: .createRoom)
}
.disabled(!context.viewState.canCreateRoom)
}
.disabled(!context.viewState.canCreateRoom)
}
}

View File

@ -92,7 +92,7 @@ struct RoomDetailsEditScreen: View {
.focused($focus, equals: .name)
} else {
ListRow(kind: .custom {
ListLabel.plain(title: context.viewState.nameRowTitle)
ListRowLabel.plain(title: context.viewState.nameRowTitle)
.listRowBackground(Color.clear)
})
}
@ -111,7 +111,7 @@ struct RoomDetailsEditScreen: View {
.lineLimit(3...)
} else {
ListRow(kind: .custom {
ListLabel.plain(title: context.viewState.topicRowTitle)
ListRowLabel.plain(title: context.viewState.topicRowTitle)
.listRowBackground(Color.clear)
})
}

View File

@ -14,6 +14,7 @@
// limitations under the License.
//
import Compound
import SwiftUI
struct RoomMemberDetailsScreen: View {
@ -27,7 +28,7 @@ struct RoomMemberDetailsScreen: View {
blockUserSection
}
}
.compoundForm()
.compoundList()
.alert(item: $context.ignoreUserAlert, actions: blockUserAlertActions, message: blockUserAlertMessage)
.alert(item: $context.alertInfo)
.track(screen: .user)
@ -49,7 +50,7 @@ struct RoomMemberDetailsScreen: View {
if let permalink = context.viewState.details.permalink {
HStack(spacing: 32) {
ShareLink(item: permalink) {
Image(systemName: "square.and.arrow.up")
CompoundIcon(asset: Asset.Images.shareIos)
}
.buttonStyle(FormActionButtonStyle(title: L10n.actionShare))
}
@ -60,16 +61,16 @@ struct RoomMemberDetailsScreen: View {
private var blockUserSection: some View {
Section {
Button(role: context.viewState.details.isIgnored ? nil : .destructive) {
context.send(viewAction: blockUserButtonAction)
} label: {
Label(blockUserButtonTitle, systemImage: "slash.circle")
}
.accessibilityIdentifier(blockUserButtonAccessibilityIdentifier)
.buttonStyle(FormButtonStyle(accessory: context.viewState.isProcessingIgnoreRequest ? .progressView : nil))
.disabled(context.viewState.isProcessingIgnoreRequest)
ListRow(label: .default(title: blockUserButtonTitle,
icon: CompoundIcon(asset: Asset.Images.block),
role: context.viewState.details.isIgnored ? nil : .destructive),
details: .isWaiting(context.viewState.isProcessingIgnoreRequest),
kind: .button {
context.send(viewAction: blockUserButtonAction)
})
.accessibilityIdentifier(blockUserButtonAccessibilityIdentifier)
.disabled(context.viewState.isProcessingIgnoreRequest)
}
.compoundFormSection()
}
private var blockUserButtonAction: RoomMemberDetailsScreenViewAction {

View File

@ -63,13 +63,13 @@ struct RoomNotificationSettingsCustomSectionView_Previews: PreviewProvider, Test
Form {
RoomNotificationSettingsCustomSectionView(context: viewModel.context)
}
.compoundForm()
.compoundList()
.previewDisplayName("Encrypted")
Form {
RoomNotificationSettingsCustomSectionView(context: viewModelUnencrypted.context)
}
.compoundForm()
.compoundList()
.previewDisplayName("Unencrypted")
}
}

View File

@ -36,7 +36,7 @@ struct RoomNotificationSettingsUserDefinedScreen: View {
private var deleteButton: some View {
ListRow(label: .action(title: L10n.screenRoomNotificationSettingsEditRemoveSetting,
systemIcon: .trash,
icon: \.delete,
role: .destructive),
details: context.viewState.deletingCustomSetting ? .isWaiting(true) : nil,
kind: .button {

View File

@ -103,7 +103,7 @@ struct SecureBackupScreen: View {
}
} footer: {
recoveryKeySectionFooter
.compoundFormSectionFooter()
.compoundListSectionFooter()
}
}

View File

@ -63,7 +63,6 @@ struct NotificationSettingsEditScreen: View {
Text(L10n.screenNotificationSettingsEditCustomSettingsSectionTitle)
.compoundListSectionHeader()
}
.compoundFormSection()
}
}

View File

@ -50,7 +50,7 @@ struct NotificationSettingsEditScreenRoomCell: View {
}
@MainActor
var roomDetailsLabel: ListDetailsLabel<EmptyView>? {
var roomDetailsLabel: ListRowDetails<EmptyView>? {
guard let mode = room.notificationMode else { return nil }
return .label(title: context.viewState.strings.string(for: mode),
icon: EmptyView())

View File

@ -98,7 +98,7 @@ struct NotificationSettingsScreen: View {
// Group chats
ListRow(label: .plain(title: L10n.screenNotificationSettingsGroupChats),
details: context.viewState.settings.map {
ListDetailsLabel.title(context.viewState.strings.string(for: $0.groupChatsMode))
.title(context.viewState.strings.string(for: $0.groupChatsMode))
} ?? .isWaiting(true),
kind: .navigationLink {
context.send(viewAction: .groupChatsTapped)
@ -109,7 +109,7 @@ struct NotificationSettingsScreen: View {
// Direct chats
ListRow(label: .plain(title: L10n.screenNotificationSettingsDirectChats),
details: context.viewState.settings.map {
ListDetailsLabel.title(context.viewState.strings.string(for: $0.directChatsMode))
.title(context.viewState.strings.string(for: $0.directChatsMode))
} ?? .isWaiting(true),
kind: .navigationLink {
context.send(viewAction: .directChatsTapped)

View File

@ -71,9 +71,7 @@ struct SettingsScreen: View {
Spacer()
CompoundIcon(\.chevronRight)
.foregroundColor(.compound.iconTertiaryAlpha)
.flipsForRightToLeftLayoutDirection(true)
ListRowAccessory.navigationLink
}
.padding(.horizontal, ListRowPadding.horizontal)
.padding(.vertical, 8)

View File

@ -74,8 +74,8 @@ struct StartChatScreen: View {
Section {
ListRow(kind: .custom {
MatrixUserShareLink(userID: context.viewState.userID) {
ListLabel.default(title: L10n.actionInvitePeopleToApp(InfoPlistReader.main.bundleDisplayName),
icon: CompoundIcon(asset: Asset.Images.shareIos))
ListRowLabel.default(title: L10n.actionInvitePeopleToApp(InfoPlistReader.main.bundleDisplayName),
icon: CompoundIcon(asset: Asset.Images.shareIos))
}
})
.accessibilityIdentifier(A11yIdentifiers.startChatScreen.inviteFriends)

View File

@ -87,6 +87,7 @@ class AppLockUITests: XCTestCase {
try await app.assertScreenshot(.appLockFlow, step: Step.unlocked)
try client.send(.notification(name: UIApplication.didEnterBackgroundNotification))
try await Task.sleep(for: .milliseconds(500)) // Don't overwrite the previous signal immediately.
try client.send(.notification(name: UIApplication.didBecomeActiveNotification))
try await app.assertScreenshot(.appLockFlow, step: Step.lockScreen)

Binary file not shown.

View File

@ -0,0 +1 @@
Use Compound List in Start Chat and Room Member Details screens.

View File

@ -49,7 +49,7 @@ packages:
# path: ../matrix-rust-sdk
Compound:
url: https://github.com/vector-im/compound-ios
revision: 7ae8b7ef4033861d0439427d5404538243afeffd
revision: 59166acc95a775ba3b7e7d39e5605611cf0e657f
# path: ../compound-ios
AnalyticsEvents:
url: https://github.com/matrix-org/matrix-analytics-events