Skip to content

Commit 630016b

Browse files
committed
Merge branch 'trunk' into issue/5616-setup-path
2 parents 9687d45 + 5524af8 commit 630016b

21 files changed

+797
-236
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,18 +189,20 @@ private extension DashboardViewController {
189189
}
190190

191191
private func configureNavigationItem() {
192-
let rightBarButton = UIBarButtonItem(image: .gearBarButtonItemImage,
193-
style: .plain,
194-
target: self,
195-
action: #selector(settingsTapped))
196-
rightBarButton.accessibilityLabel = NSLocalizedString("Settings", comment: "Accessibility label for the Settings button.")
197-
rightBarButton.accessibilityTraits = .button
198-
rightBarButton.accessibilityHint = NSLocalizedString(
199-
"Navigates to Settings.",
200-
comment: "VoiceOver accessibility hint, informing the user the button can be used to navigate to the Settings screen."
201-
)
202-
rightBarButton.accessibilityIdentifier = "dashboard-settings-button"
203-
navigationItem.setRightBarButton(rightBarButton, animated: false)
192+
if !ServiceLocator.featureFlagService.isFeatureFlagEnabled(.hubMenu) {
193+
let rightBarButton = UIBarButtonItem(image: .gearBarButtonItemImage,
194+
style: .plain,
195+
target: self,
196+
action: #selector(settingsTapped))
197+
rightBarButton.accessibilityLabel = NSLocalizedString("Settings", comment: "Accessibility label for the Settings button.")
198+
rightBarButton.accessibilityTraits = .button
199+
rightBarButton.accessibilityHint = NSLocalizedString(
200+
"Navigates to Settings.",
201+
comment: "VoiceOver accessibility hint, informing the user the button can be used to navigate to the Settings screen."
202+
)
203+
rightBarButton.accessibilityIdentifier = "dashboard-settings-button"
204+
navigationItem.setRightBarButton(rightBarButton, animated: false)
205+
}
204206
}
205207

206208
func configureDashboardUIContainer() {

WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,17 @@ private extension SettingsViewModel {
169169

170170
func configureSections() {
171171
// Selected Store
172-
let selectedStoreSection: Section = {
173-
let storeRows: [Row] = sites.count > 1 ?
172+
let selectedStoreSection: Section? = {
173+
if featureFlagService.isFeatureFlagEnabled(.hubMenu) {
174+
return nil
175+
}
176+
else {
177+
let storeRows: [Row] = sites.count > 1 ?
174178
[.selectedStore, .switchStore] : [.selectedStore]
175-
return Section(title: Localization.selectedStoreTitle,
176-
rows: storeRows,
177-
footerHeight: UITableView.automaticDimension)
179+
return Section(title: Localization.selectedStoreTitle,
180+
rows: storeRows,
181+
footerHeight: UITableView.automaticDimension)
182+
}
178183
}()
179184

180185
// Plugins

WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/OrderCustomerSection.swift

Lines changed: 77 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,101 +3,110 @@ import SwiftUI
33
/// Represents the Customer section
44
///
55
struct OrderCustomerSection: View {
6-
let geometry: GeometryProxy
76

8-
/// View model to drive the view content
9-
let viewModel: NewOrderViewModel.CustomerDataViewModel
7+
/// Parent view model to access all data
8+
@ObservedObject var viewModel: NewOrderViewModel
109

11-
/// View model for Address Form
12-
let addressFormViewModel: CreateOrderAddressFormViewModel
10+
/// View model to drive the view content
11+
private var customerDataViewModel: NewOrderViewModel.CustomerDataViewModel {
12+
viewModel.customerDataViewModel
13+
}
1314

1415
@State private var showAddressForm: Bool = false
1516

1617
var body: some View {
17-
Group {
18-
Divider()
18+
OrderCustomerSectionContent(viewModel: viewModel.customerDataViewModel, showAddressForm: $showAddressForm)
19+
.sheet(isPresented: $showAddressForm) {
20+
NavigationView {
21+
EditOrderAddressForm(dismiss: {
22+
showAddressForm.toggle()
23+
}, viewModel: viewModel.createOrderAddressFormViewModel())
24+
}
25+
}
26+
}
27+
}
1928

20-
VStack(alignment: .leading) {
21-
HStack(alignment: .top) {
22-
Text(Localization.customer)
23-
.headlineStyle()
24-
25-
Spacer()
26-
27-
if viewModel.isDataAvailable {
28-
Button(Localization.editButton) {
29-
showAddressForm.toggle()
30-
}
31-
.buttonStyle(LinkButtonStyle())
32-
.fixedSize(horizontal: true, vertical: true)
33-
.padding(.top, -Layout.linkButtonTopPadding) // remove padding to align button title to the top
34-
.padding(.trailing, -Layout.linkButtonTrailingPadding) // remove padding to align button title to the side
35-
}
36-
}
29+
private struct OrderCustomerSectionContent: View {
30+
31+
/// View model to drive the view content
32+
var viewModel: NewOrderViewModel.CustomerDataViewModel
33+
34+
@Binding var showAddressForm: Bool
35+
36+
@Environment(\.safeAreaInsets) var safeAreaInsets: EdgeInsets
37+
38+
var body: some View {
39+
Divider()
3740

38-
if !viewModel.isDataAvailable {
39-
createCustomerView
40-
} else {
41-
customerDataView
41+
VStack(alignment: .leading, spacing: .zero) {
42+
HStack(alignment: .top) {
43+
Text(Localization.customer)
44+
.headlineStyle()
45+
46+
Spacer()
47+
48+
if viewModel.isDataAvailable {
49+
Button(Localization.editButton) {
50+
showAddressForm.toggle()
51+
}
52+
.buttonStyle(LinkButtonStyle())
53+
.fixedSize(horizontal: true, vertical: true)
54+
.padding(.top, -Layout.linkButtonTopPadding) // remove padding to align button title to the top
55+
.padding(.trailing, -Layout.linkButtonTrailingPadding) // remove padding to align button title to the side
4256
}
4357
}
44-
.padding(.horizontal, insets: geometry.safeAreaInsets)
45-
.padding()
46-
.background(Color(.listForeground))
58+
.padding([.leading, .top, .trailing])
4759

48-
Divider()
49-
}
50-
.sheet(isPresented: $showAddressForm) {
51-
NavigationView {
52-
EditOrderAddressForm(dismiss: {
53-
showAddressForm.toggle()
54-
}, viewModel: addressFormViewModel)
60+
if !viewModel.isDataAvailable {
61+
Spacer(minLength: Layout.verticalHeadlineSpacing)
62+
createCustomerView
63+
} else {
64+
customerDataView
5565
}
5666
}
67+
.padding(.horizontal, insets: safeAreaInsets)
68+
.background(Color(.listForeground))
69+
70+
Divider()
5771
}
5872

5973
private var createCustomerView: some View {
6074
Button(Localization.addCustomer) {
6175
showAddressForm.toggle()
6276
}
6377
.buttonStyle(PlusButtonStyle())
78+
.padding([.leading, .bottom, .trailing])
6479
}
6580

6681
private var customerDataView: some View {
6782
Group {
68-
VStack(alignment: .leading, spacing: Layout.verticalEmailSpacing) {
69-
if let fullName = viewModel.fullName {
70-
Text(fullName)
71-
.bodyStyle()
72-
}
73-
if let email = viewModel.email {
74-
Text(email)
75-
.footnoteStyle()
76-
}
77-
}
78-
if let billingAddressFormatted = viewModel.billingAddressFormatted {
79-
addressDetails(title: Localization.billingTitle, formattedAddress: billingAddressFormatted)
80-
}
81-
if let shippingAddressFormatted = viewModel.shippingAddressFormatted {
82-
addressDetails(title: Localization.shippingTitle, formattedAddress: shippingAddressFormatted)
83-
}
83+
addressDetails(title: Localization.shippingTitle, formattedAddress: viewModel.shippingAddressFormatted)
84+
Divider()
85+
.padding(.leading)
86+
addressDetails(title: Localization.billingTitle, formattedAddress: viewModel.billingAddressFormatted)
8487
}
8588
}
8689

87-
@ViewBuilder private func addressDetails(title: String, formattedAddress: String) -> some View {
88-
Divider()
90+
@ViewBuilder private func addressDetails(title: String, formattedAddress: String?) -> some View {
8991
VStack(alignment: .leading, spacing: Layout.verticalAddressSpacing) {
9092
Text(title)
9193
.headlineStyle()
92-
Text(formattedAddress)
93-
.bodyStyle()
94+
if let formattedAddress = formattedAddress, formattedAddress.isNotEmpty {
95+
Text(formattedAddress)
96+
.bodyStyle()
97+
} else {
98+
Text(Localization.noAddress)
99+
.bodyStyle()
100+
}
94101
}
102+
.padding()
95103
}
96104
}
97105

98106
// MARK: Constants
99-
private extension OrderCustomerSection {
107+
private extension OrderCustomerSectionContent {
100108
enum Layout {
109+
static let verticalHeadlineSpacing: CGFloat = 22.0
101110
static let verticalEmailSpacing: CGFloat = 4.0
102111
static let verticalAddressSpacing: CGFloat = 6.0
103112
static let linkButtonTopPadding: CGFloat = 12.0
@@ -111,28 +120,28 @@ private extension OrderCustomerSection {
111120

112121
static let billingTitle = NSLocalizedString("Billing Address", comment: "Title for the Billing Address section in order customer data")
113122
static let shippingTitle = NSLocalizedString("Shipping Address", comment: "Title for the Edit Shipping Address section in order customer data")
123+
124+
static let noAddress = NSLocalizedString("No address specified.", comment: "Placeholder for empty address in order customer data")
114125
}
115126
}
116127

128+
@available(iOS 15.0, *)
117129
struct OrderCustomerSection_Previews: PreviewProvider {
118130
static var previews: some View {
119-
let orderAdressFormViewModel = NewOrderViewModel(siteID: 123).createOrderAddressFormViewModel()
120131
let emptyViewModel = NewOrderViewModel.CustomerDataViewModel(billingAddress: nil, shippingAddress: nil)
121132
let addressViewModel = NewOrderViewModel.CustomerDataViewModel(fullName: "Johnny Appleseed",
122133
123-
billingAddressFormatted: """
134+
billingAddressFormatted: nil,
135+
shippingAddressFormatted: """
124136
Johnny Appleseed
125137
234 70th Street
126138
Niagara Falls NY 14304
127139
US
128-
""",
129-
shippingAddressFormatted: nil)
140+
""")
130141

131-
GeometryReader { geometry in
132-
ScrollView {
133-
OrderCustomerSection(geometry: geometry, viewModel: emptyViewModel, addressFormViewModel: orderAdressFormViewModel)
134-
OrderCustomerSection(geometry: geometry, viewModel: addressViewModel, addressFormViewModel: orderAdressFormViewModel)
135-
}
142+
ScrollView {
143+
OrderCustomerSectionContent(viewModel: emptyViewModel, showAddressForm: .constant(false))
144+
OrderCustomerSectionContent(viewModel: addressViewModel, showAddressForm: .constant(false))
136145
}
137146
}
138147
}

WooCommerce/Classes/ViewRelated/Orders/Order Creation/NewOrder.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct NewOrder: View {
5252
ScrollViewReader { scroll in
5353
ScrollView {
5454
VStack(spacing: Layout.noSpacing) {
55-
OrderStatusSection(geometry: geometry, viewModel: viewModel)
55+
OrderStatusSection(viewModel: viewModel)
5656

5757
Spacer(minLength: Layout.sectionSpacing)
5858

@@ -66,9 +66,7 @@ struct NewOrder: View {
6666
Spacer(minLength: Layout.sectionSpacing)
6767
}
6868

69-
OrderCustomerSection(geometry: geometry,
70-
viewModel: viewModel.customerDataViewModel,
71-
addressFormViewModel: viewModel.createOrderAddressFormViewModel())
69+
OrderCustomerSection(viewModel: viewModel)
7270
}
7371
}
7472
.background(Color(.listBackground).ignoresSafeArea())

WooCommerce/Classes/ViewRelated/Orders/Order Creation/NewOrderViewModel.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,6 @@ final class NewOrderViewModel: ObservableObject {
4646
///
4747
@Published var shouldShowOrderStatusList: Bool = false
4848

49-
/// Representation of customer data display properties.
50-
///
51-
@Published private(set) var customerDataViewModel: CustomerDataViewModel = .init(billingAddress: nil, shippingAddress: nil)
52-
53-
/// Assign this closure to be notified when a new order is created
54-
///
55-
var onOrderCreated: (Order) -> Void = { _ in }
56-
5749
/// Status Results Controller.
5850
///
5951
private lazy var statusResultsController: ResultsController<StorageOrderStatus> = {
@@ -139,6 +131,12 @@ final class NewOrderViewModel: ObservableObject {
139131
configureProductRowViewModels()
140132
}
141133

134+
// MARK: Customer data properties
135+
136+
/// Representation of customer data display properties.
137+
///
138+
@Published private(set) var customerDataViewModel: CustomerDataViewModel = .init(billingAddress: nil, shippingAddress: nil)
139+
142140
/// Creates a view model to be used in Address Form for customer address.
143141
///
144142
func createOrderAddressFormViewModel() -> CreateOrderAddressFormViewModel {
@@ -170,6 +168,10 @@ final class NewOrderViewModel: ObservableObject {
170168
}
171169
stores.dispatch(action)
172170
}
171+
172+
/// Assign this closure to be notified when a new order is created
173+
///
174+
var onOrderCreated: (Order) -> Void = { _ in }
173175
}
174176

175177
// MARK: - Types

WooCommerce/Classes/ViewRelated/Orders/Order Creation/ProductsSection/AddProductToOrder.swift

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import SwiftUI
22

3-
/// View showing a list of products to add to an order.
3+
/// View showing a list of products or product variations to add to an order.
44
///
5-
struct AddProductToOrder: View {
5+
struct AddProductToOrder<ViewModel: AddProductToOrderViewModelProtocol>: View {
66
/// Defines whether the view is presented.
77
///
88
@Binding var isPresented: Bool
99

1010
/// View model to drive the view.
1111
///
12-
@ObservedObject var viewModel: AddProductToOrderViewModel
12+
@ObservedObject var viewModel: ViewModel
1313

1414
var body: some View {
1515
NavigationView {
@@ -20,7 +20,7 @@ struct AddProductToOrder: View {
2020
ForEach(viewModel.productRows) { rowViewModel in
2121
ProductRow(viewModel: rowViewModel)
2222
.onTapGesture {
23-
viewModel.selectProduct(rowViewModel.productID)
23+
viewModel.selectProductOrVariation(rowViewModel.productOrVariationID)
2424
isPresented.toggle()
2525
}
2626
}
@@ -88,13 +88,11 @@ private struct InfiniteScrollIndicator: View {
8888
}
8989
}
9090

91-
private extension AddProductToOrder {
92-
enum Localization {
93-
static let title = NSLocalizedString("Add Product", comment: "Title for the screen to add a product to an order")
94-
static let close = NSLocalizedString("Close", comment: "Text for the close button in the Add Product screen")
95-
static let emptyStateMessage = NSLocalizedString("No products found",
96-
comment: "Message displayed if there are no products to display in the Add Product screen")
97-
}
91+
private enum Localization {
92+
static let title = NSLocalizedString("Add Product", comment: "Title for the screen to add a product to an order")
93+
static let close = NSLocalizedString("Close", comment: "Text for the close button in the Add Product screen")
94+
static let emptyStateMessage = NSLocalizedString("No products found",
95+
comment: "Message displayed if there are no products to display in the Add Product screen")
9896
}
9997

10098
struct AddProduct_Previews: PreviewProvider {

0 commit comments

Comments
 (0)