Basic implementation of the UI, navigation wil be implemented in the next PR

This commit is contained in:
Mauro Romito
2025-10-29 18:59:45 +01:00
committed by Mauro
parent dfd757f2b6
commit b4f3e0c860
36 changed files with 250 additions and 135 deletions
@@ -13,59 +13,112 @@ struct SpaceSettingsScreen: View {
var body: some View {
Form {
Section {
ListRow(label: .plain(title: context.viewState.placeholder),
kind: .textField(text: $context.composerText))
ListRow(label: .centeredAction(title: L10n.actionDone,
icon: \.leave),
kind: .button { context.send(viewAction: .done) })
}
Section {
ListRow(label: .default(title: "Counter", icon: \.chart),
details: .counter(context.viewState.counter),
kind: .label)
ListRow(label: .default(title: "Increment", icon: \.plus),
kind: .button { context.send(viewAction: .incrementCounter) })
ListRow(label: .default(title: "Decrement", icon: \.minus),
kind: .button { context.send(viewAction: .decrementCounter) })
editSection
if context.viewState.canEditRolesOrPermissions {
securitySection
}
peopleSection
leaveSpaceSection
}
.compoundList()
.navigationTitle(context.viewState.title)
.onChange(of: context.composerText) {
context.send(viewAction: .textChanged)
.navigationTitle(L10n.commonSettings)
}
private var editSection: some View {
Section {
ListRow(kind: .custom {
Button {
context.send(viewAction: .processTapEdit)
} label: {
editSectionContent
}
})
}
}
private var editSectionContent: some View {
HStack(spacing: 12) {
RoomAvatarImage(avatar: context.viewState.details.avatar,
avatarSize: .room(on: .spaceSettings),
mediaProvider: context.mediaProvider)
.accessibilityHidden(true)
VStack(alignment: .leading, spacing: 2) {
Text(context.viewState.details.name ?? context.viewState.details.id)
.lineLimit(1)
.font(.compound.headingMD)
.foregroundStyle(.compound.textPrimary)
if let alias = context.viewState.details.canonicalAlias {
Text(alias)
.lineLimit(1)
.font(.compound.bodySM)
.foregroundStyle(.compound.textSecondary)
}
}
Spacer()
ListRowAccessory.navigationLink
}
.padding(.horizontal, ListRowPadding.horizontal)
.padding(.vertical, 16)
}
private var securitySection: some View {
Section {
ListRow(label: .default(title: L10n.screenSpaceSettingsSecurityAndPrivacy, icon: \.lock),
kind: .navigationLink {
context.send(viewAction: .processTapSecurity)
})
}
}
private var peopleSection: some View {
Section {
if context.viewState.hasMemberIdentityVerificationStateViolations {
ListRow(label: .default(title: L10n.commonPeople, icon: \.user),
details: .icon(CompoundIcon(\.infoSolid).foregroundStyle(.compound.iconCriticalPrimary)),
kind: .navigationLink {
context.send(viewAction: .processTapPeople)
})
} else {
ListRow(label: .default(title: L10n.commonPeople, icon: \.user),
details: .title(String(context.viewState.joinedMembersCount)),
kind: .navigationLink {
context.send(viewAction: .processTapPeople)
})
}
if context.viewState.canEditRolesOrPermissions {
ListRow(label: .default(title: L10n.screenSpaceSettingsRolesAndPermissions, icon: \.admin),
kind: .navigationLink {
context.send(viewAction: .processTapRolesAndPermissions)
})
}
}
}
private var leaveSpaceSection: some View {
ListRow(label: .action(title: L10n.screenSpaceSettingsLeaveSpace,
icon: \.leave,
role: .destructive),
kind: .button { context.send(viewAction: .processTapLeave) })
}
}
// MARK: - Previews
struct SpaceSettingsScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = makeViewModel()
static let incrementedViewModel = makeViewModel(counterValue: 1)
static let viewModel = SpaceSettingsScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Space",
avatarURL: .mockMXCAvatar,
isSpace: true,
canonicalAlias: "#space:matrix.org",
members: .allMembersAsCreator)),
userSession: UserSessionMock(.init()))
static var previews: some View {
NavigationStack {
SpaceSettingsScreen(context: viewModel.context)
}
.previewDisplayName("Initial")
NavigationStack {
SpaceSettingsScreen(context: incrementedViewModel.context)
}
.previewDisplayName("Incremented")
.snapshotPreferences(expect: incrementedViewModel.context.observe(\.viewState.counter).map { $0 == 1 }.eraseToStream())
}
static func makeViewModel(counterValue: Int = 0) -> SpaceSettingsScreenViewModel {
let viewModel = SpaceSettingsScreenViewModel()
for _ in 0..<counterValue {
viewModel.context.send(viewAction: .incrementCounter)
}
return viewModel
}
}