@@ -61,7 +61,6 @@ import SwiftUI
61
61
/// To see the `UtilityNetworkTrace` in action, check out the [Examples](https://github.com/Esri/arcgis-maps-sdk-swift-toolkit/tree/main/Examples/Examples)
62
62
/// and refer to [UtilityNetworkTraceExampleView.swift](https://github.com/Esri/arcgis-maps-sdk-swift-toolkit/blob/main/Examples/Examples/UtilityNetworkTraceExampleView.swift)
63
63
/// in the project. To learn more about using the `UtilityNetworkTrace` see the <doc:UtilityNetworkTraceTutorial>.
64
- @available ( visionOS, unavailable)
65
64
public struct UtilityNetworkTrace : View {
66
65
/// The proxy to provide access to map view operations.
67
66
private var mapViewProxy : MapViewProxy ?
@@ -180,38 +179,38 @@ public struct UtilityNetworkTrace: View {
180
179
currentActivity = . viewingTraces( . viewingFeatureResults)
181
180
}
182
181
makeDetailSectionHeader ( title: assetGroupName)
183
- List {
184
- ForEach (
185
- assetTypeGroups. sorted ( using: KeyPathComparator ( \. key) ) ,
186
- id: \. key
187
- ) { ( name, elements) in
188
- Section ( name) {
189
- DisclosureGroup {
190
- ForEach ( elements, id: \. globalID) { element in
191
- Button {
192
- Task {
193
- if let feature = await viewModel. feature ( for: element) ,
194
- let geometry = feature. geometry {
195
- updateViewpoint ( to: geometry. extent)
196
- }
197
- }
198
- } label: {
199
- Label {
200
- Text (
201
- " Object ID: \( element. objectID, format: . number. grouping ( . never) ) " ,
202
- bundle: . toolkitModule,
203
- comment: " A string identifying a utility network object. "
204
- )
205
- } icon: {
206
- Image ( systemName: " scope " )
182
+ List (
183
+ assetTypeGroups. sorted ( using: KeyPathComparator ( \. key) ) ,
184
+ id: \. key
185
+ ) { ( name, elements) in
186
+ Section ( name) {
187
+ DisclosureGroup {
188
+ ForEach ( elements, id: \. globalID) { element in
189
+ Button {
190
+ Task {
191
+ if let feature = await viewModel. feature ( for: element) ,
192
+ let geometry = feature. geometry {
193
+ updateViewpoint ( to: geometry. extent)
207
194
}
208
195
}
196
+ } label: {
197
+ Label (
198
+ String (
199
+ localized: " Object ID: \( element. objectID, format: . number. grouping ( . never) ) " ,
200
+ bundle: . toolkitModule,
201
+ comment: " A string identifying a utility network object. "
202
+ ) ,
203
+ systemImage: " scope "
204
+ )
209
205
}
210
- } label: {
211
- Text ( elements. count, format: . number)
212
- . catalystPadding ( 4 )
213
206
}
207
+ } label: {
208
+ Text ( elements. count, format: . number)
209
+ . catalystPadding ( 4 )
214
210
}
211
+ #if os(visionOS)
212
+ . listItemTint( . monochrome)
213
+ #endif
215
214
}
216
215
}
217
216
}
@@ -223,11 +222,9 @@ public struct UtilityNetworkTrace: View {
223
222
Text ( String . noConfigurationsAvailable)
224
223
} else {
225
224
ForEach ( viewModel. configurations. sorted { $0. name < $1. name } , id: \. name) { configuration in
226
- Button {
225
+ Button ( configuration . name ) {
227
226
viewModel. setPendingTrace ( configuration: configuration)
228
227
currentActivity = . creatingTrace( nil )
229
- } label: {
230
- Text ( configuration. name)
231
228
}
232
229
. listRowBackground ( configuration. name == viewModel. pendingTrace. configuration? . name ? Color . secondary. opacity ( 0.5 ) : nil )
233
230
}
@@ -237,13 +234,14 @@ public struct UtilityNetworkTrace: View {
237
234
/// Displays the list of available networks.
238
235
@ViewBuilder private var networksList : some View {
239
236
ForEach ( viewModel. networks, id: \. name) { network in
240
- Text ( network. name)
241
- . lineLimit ( 1 )
242
- . listRowBackground ( network. name == viewModel. network? . name ? Color . secondary. opacity ( 0.5 ) : nil )
243
- . onTapGesture {
244
- viewModel. setNetwork ( network)
245
- currentActivity = . creatingTrace( nil )
246
- }
237
+ Button {
238
+ viewModel. setNetwork ( network)
239
+ currentActivity = . creatingTrace( nil )
240
+ } label: {
241
+ Text ( network. name)
242
+ . lineLimit ( 1 )
243
+ }
244
+ . listRowBackground ( network. name == viewModel. network? . name ? Color . secondary. opacity ( 0.5 ) : nil )
247
245
}
248
246
}
249
247
@@ -311,20 +309,21 @@ public struct UtilityNetworkTrace: View {
311
309
Button ( String . deleteAllStartingPoints, systemImage: " trash " ) {
312
310
deleteAllStartingPointsConfirmationIsPresented = true
313
311
}
312
+ #if !os(visionOS)
314
313
. buttonStyle( . plain)
314
+ #endif
315
315
. labelStyle( . iconOnly)
316
316
. confirmationDialog (
317
- String . deleteAllStartingPoints,
318
- isPresented: $deleteAllStartingPointsConfirmationIsPresented
317
+ String . deleteAllStartingPointsQuestion,
318
+ isPresented: $deleteAllStartingPointsConfirmationIsPresented,
319
+ titleVisibility: . visible
319
320
) {
320
- Button ( String . deleteAllStartingPoints , role: . destructive) {
321
- viewModel. pendingTrace. startingPoints. forEach { startingPoint in
321
+ Button ( String . deleteButtonLabel , role: . destructive) {
322
+ for startingPoint in viewModel. pendingTrace. startingPoints {
322
323
viewModel. deleteStartingPoint ( startingPoint)
323
324
externalStartingPoints. removeAll ( )
324
325
}
325
326
}
326
- } message: {
327
- Text ( String . deleteAllStartingPointsMessage)
328
327
}
329
328
// Override default uppercase capitalization for list
330
329
// section headers on iOS and iPadOS.
@@ -348,7 +347,12 @@ public struct UtilityNetworkTrace: View {
348
347
viewModel. pendingTrace. userDidSpecifyName = true
349
348
}
350
349
. multilineTextAlignment ( . trailing)
350
+ #if os(visionOS)
351
+ . contentShape( . hoverEffect, . rect( cornerRadius: 12 ) )
352
+ . hoverEffect ( )
353
+ #else
351
354
. foregroundStyle( . blue)
355
+ #endif
352
356
}
353
357
ColorPicker ( String . colorLabel, selection: $viewModel. pendingTrace. color)
354
358
Toggle ( String . zoomToResult, isOn: $shouldZoomOnTraceCompletion)
@@ -436,15 +440,18 @@ public struct UtilityNetworkTrace: View {
436
440
) {
437
441
if let selectedTrace = viewModel. selectedTrace {
438
442
ForEach ( selectedTrace. assetGroupNames. sorted ( ) , id: \. self) { assetGroupName in
439
- HStack {
440
- Text ( assetGroupName)
441
- Spacer ( )
442
- Text ( selectedTrace. elements ( inAssetGroupNamed: assetGroupName) . count, format: . number)
443
- }
444
- . foregroundStyle ( . blue)
445
- . contentShape ( . rect)
446
- . onTapGesture {
443
+ Button {
447
444
currentActivity = . viewingTraces( . viewingElementGroup( named: assetGroupName) )
445
+ } label: {
446
+ HStack {
447
+ Text ( assetGroupName)
448
+ Spacer ( )
449
+ Text ( selectedTrace. elements ( inAssetGroupNamed: assetGroupName) . count, format: . number)
450
+ }
451
+ #if !os(visionOS)
452
+ . foregroundStyle( . blue)
453
+ . contentShape ( . rect)
454
+ #endif
448
455
}
449
456
}
450
457
}
@@ -584,18 +591,23 @@ public struct UtilityNetworkTrace: View {
584
591
viewModel. setTerminalConfigurationFor ( startingPoint: selectedStartingPoint!, to: newValue)
585
592
}
586
593
) {
587
- ForEach ( viewModel. pendingTrace. startingPoints. first {
588
- $0 == selectedStartingPoint
589
- } ? . utilityElement? . assetType. terminalConfiguration? . terminals ?? [ ] , id: \. self) {
594
+ ForEach (
595
+ viewModel. pendingTrace. startingPoints
596
+ . first ( where: { $0 == selectedStartingPoint } ) ?
597
+ . utilityElement? . assetType. terminalConfiguration? . terminals ?? [ ] ,
598
+ id: \. self
599
+ ) {
590
600
Text ( $0. name)
591
601
}
592
602
}
603
+ #if !os(visionOS)
593
604
. foregroundStyle( . blue)
605
+ #endif
594
606
}
595
607
}
596
608
Section ( String . attributesSectionTitle) {
597
609
ForEach ( Array ( selectedStartingPoint!. geoElement. attributes. sorted ( by: { $0. key < $1. key} ) ) , id: \. key) { item in
598
- HStack {
610
+ HStack {
599
611
Text ( item. key)
600
612
Spacer ( )
601
613
Text ( item. value as? String ?? " " )
@@ -802,16 +814,10 @@ public struct UtilityNetworkTrace: View {
802
814
/// - Parameter title: The button's title.
803
815
/// - Parameter action: The action to be performed.
804
816
/// - Returns: The configured button.
805
- private func makeBackButton( title: String , _ action: @escaping ( ) -> Void ) -> some View {
806
- Button { action ( ) } label: {
807
- Label {
808
- Text ( title)
809
- } icon: {
810
- Image ( systemName: " chevron.backward " )
811
- }
812
- }
813
- . padding ( )
814
- . frame ( maxWidth: . infinity, alignment: . leading)
817
+ private func makeBackButton( title: String , action: @escaping ( ) -> Void ) -> some View {
818
+ Button ( title, systemImage: " chevron.backward " , action: action)
819
+ . padding ( )
820
+ . frame ( maxWidth: . infinity, alignment: . leading)
815
821
}
816
822
817
823
/// Returns a section header.
@@ -890,11 +896,11 @@ private extension String {
890
896
)
891
897
}
892
898
893
- static var deleteAllStartingPointsMessage : Self {
899
+ static var deleteAllStartingPointsQuestion : Self {
894
900
. init(
895
- localized: " All starting points will be deleted. " ,
901
+ localized: " Delete all starting points? " ,
896
902
bundle: . toolkitModule,
897
- comment: " A message describing the outcome of clearing all starting points."
903
+ comment: " The title of the dialogue confirming deletion of all points."
898
904
)
899
905
}
900
906
@@ -1064,8 +1070,6 @@ private extension String {
1064
1070
}
1065
1071
}
1066
1072
1067
-
1068
- @available ( visionOS, unavailable)
1069
1073
public extension UtilityNetworkTrace /* Deprecated */ {
1070
1074
/// A graphical interface to run pre-configured traces on a map's utility networks.
1071
1075
/// - Parameters:
0 commit comments