133 lines
4.5 KiB
Swift
133 lines
4.5 KiB
Swift
// File created from TemplateAdvancedRoomsExample
|
|
// $ createSwiftUITwoScreen.sh Spaces/SpaceCreation SpaceCreation SpaceCreationMenu SpaceCreationSettings
|
|
//
|
|
// Copyright 2021-2024 New Vector Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
// Please see LICENSE in the repository root for full details.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct SpaceCreationMenu: View {
|
|
// MARK: - Properties
|
|
|
|
@ObservedObject var viewModel: SpaceCreationMenuViewModelType.Context
|
|
let showBackButton: Bool
|
|
|
|
// MARK: Private
|
|
|
|
@Environment(\.theme) private var theme: ThemeSwiftUI
|
|
|
|
// MARK: Public
|
|
|
|
var body: some View {
|
|
mainScreen
|
|
.navigationBarHidden(true)
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
@ViewBuilder
|
|
private var mainScreen: some View {
|
|
VStack {
|
|
ThemableNavigationBar(title: nil, showBackButton: showBackButton) {
|
|
viewModel.send(viewAction: .back)
|
|
} closeAction: {
|
|
viewModel.send(viewAction: .cancel)
|
|
}
|
|
GeometryReader { reader in
|
|
ScrollView {
|
|
VStack {
|
|
headerView
|
|
Spacer()
|
|
optionsView
|
|
}
|
|
.frame(minHeight: reader.size.height - 2)
|
|
}
|
|
}
|
|
.padding(EdgeInsets(top: 0, leading: 16, bottom: 24, trailing: 16))
|
|
}
|
|
.background(theme.colors.background.ignoresSafeArea())
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var headerView: some View {
|
|
VStack {
|
|
Text(viewModel.viewState.title)
|
|
.multilineTextAlignment(.center)
|
|
.font(theme.fonts.title3SB)
|
|
.foregroundColor(theme.colors.primaryContent)
|
|
.accessibility(identifier: "titleText")
|
|
.padding(.bottom, 20)
|
|
Text(viewModel.viewState.detail)
|
|
.multilineTextAlignment(.center)
|
|
.font(theme.fonts.body)
|
|
.foregroundColor(theme.colors.secondaryContent)
|
|
.accessibility(identifier: "detailText")
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var optionsView: some View {
|
|
VStack(spacing: 24) {
|
|
VStack(spacing: 16) {
|
|
ForEach(viewModel.viewState.options) { option in
|
|
OptionButton(icon: option.icon, title: option.title, detailMessage: option.detail) {
|
|
viewModel.send(viewAction: .didSelectOption(option.id))
|
|
}
|
|
.accessibility(identifier: "optionButton")
|
|
}
|
|
}
|
|
Text(VectorL10n.spacesCreationFooter)
|
|
.multilineTextAlignment(.center)
|
|
.font(theme.fonts.footnote)
|
|
.foregroundColor(theme.colors.secondaryContent)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Previews
|
|
|
|
struct SpaceCreationMenu_Previews: PreviewProvider {
|
|
static let stateRenderer = MockSpaceCreationMenuScreenState.stateRenderer
|
|
|
|
static var previews: some View {
|
|
Group {
|
|
stateRenderer.screenGroup()
|
|
.theme(.light).preferredColorScheme(.light)
|
|
stateRenderer.screenGroup()
|
|
.theme(.dark).preferredColorScheme(.dark)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Using an enum for the screen allows you define the different state cases with
|
|
/// the relevant associated data for each case.
|
|
enum MockSpaceCreationMenuScreenState: MockScreenState, CaseIterable {
|
|
// A case for each state you want to represent
|
|
// with specific, minimal associated data that will allow you
|
|
// mock that screen.
|
|
case options
|
|
|
|
/// The associated screen
|
|
var screenType: Any.Type {
|
|
SpaceCreationMenu.self
|
|
}
|
|
|
|
/// Generate the view struct for the screen state.
|
|
var screenView: ([Any], AnyView) {
|
|
let viewModel = SpaceCreationMenuViewModel(navTitle: VectorL10n.spacesCreateSpaceTitle, creationParams: SpaceCreationParameters(), title: "Some title", detail: "Some detail text", options: [
|
|
SpaceCreationMenuRoomOption(id: .publicSpace, icon: Asset.Images.spaceTypeIcon.image, title: "Title of option 1", detail: "Detail of option 1"),
|
|
SpaceCreationMenuRoomOption(id: .publicSpace, icon: Asset.Images.spaceTypeIcon.image, title: "Title of option 2", detail: "Detail of option 2")
|
|
])
|
|
|
|
// can simulate service and viewModel actions here if needs be.
|
|
|
|
return (
|
|
[viewModel],
|
|
AnyView(SpaceCreationMenu(viewModel: viewModel.context, showBackButton: true))
|
|
)
|
|
}
|
|
}
|