Add standalone wiring diagram PNG export
Fetch the wiring diagram from the VoltPlan API and share it as a standalone PNG from the Overview share menu on both platforms, with a localized error when the diagram cannot be generated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,7 @@ struct LoadsView: View {
|
||||
@State private var showingSystemEditor = false
|
||||
@State private var hasPresentedSystemEditorOnAppear = false
|
||||
@State private var hasOpenedLoadOnAppear = false
|
||||
@State private var showingComponentLibrary = false
|
||||
@State private var activeLibrary: ComponentLibraryType?
|
||||
@State private var showingSystemBOM = false
|
||||
@State private var selectedComponentTab: ComponentTab
|
||||
@State private var batteryDraft: BatteryConfiguration?
|
||||
@@ -86,23 +86,7 @@ struct LoadsView: View {
|
||||
.accessibilityIdentifier("components-tab")
|
||||
}
|
||||
|
||||
Group {
|
||||
if savedBatteries.isEmpty {
|
||||
OnboardingInfoView(
|
||||
configuration: .battery(),
|
||||
onPrimaryAction: { startBatteryConfiguration() }
|
||||
)
|
||||
} else {
|
||||
BatteriesView(
|
||||
system: system,
|
||||
batteries: savedBatteries,
|
||||
editMode: $editMode,
|
||||
onEdit: { editBattery($0) },
|
||||
onDelete: deleteBatteries
|
||||
)
|
||||
.environment(\.editMode, $editMode)
|
||||
}
|
||||
}
|
||||
batteriesTab
|
||||
.tag(ComponentTab.batteries)
|
||||
.tabItem {
|
||||
Label(
|
||||
@@ -117,14 +101,7 @@ struct LoadsView: View {
|
||||
}
|
||||
.environment(\.editMode, $editMode)
|
||||
|
||||
ChargersView(
|
||||
system: system,
|
||||
chargers: savedChargers,
|
||||
editMode: $editMode,
|
||||
onAdd: { startChargerConfiguration() },
|
||||
onEdit: { editCharger($0) },
|
||||
onDelete: deleteChargers
|
||||
)
|
||||
chargersTab
|
||||
.tag(ComponentTab.chargers)
|
||||
.tabItem {
|
||||
Label(
|
||||
@@ -272,9 +249,9 @@ struct LoadsView: View {
|
||||
exportDiagramImage()
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingComponentLibrary) {
|
||||
ComponentLibraryView { item in
|
||||
addComponent(item)
|
||||
.sheet(item: $activeLibrary) { type in
|
||||
ComponentLibraryView(libraryType: type) { item in
|
||||
handleLibrarySelection(item, for: type)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingSystemBOM) {
|
||||
@@ -439,9 +416,9 @@ struct LoadsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var libraryButton: some View {
|
||||
private func libraryButton(type: ComponentLibraryType) -> some View {
|
||||
Button {
|
||||
openComponentLibrary(source: "library-button")
|
||||
openComponentLibrary(source: "library-button", type: type)
|
||||
} label: {
|
||||
Group {
|
||||
if #available(iOS 26.0, *) {
|
||||
@@ -490,6 +467,53 @@ struct LoadsView: View {
|
||||
.background(Color(.systemGroupedBackground))
|
||||
}
|
||||
|
||||
private var batteriesTab: some View {
|
||||
Group {
|
||||
if savedBatteries.isEmpty {
|
||||
OnboardingInfoView(
|
||||
configuration: .battery(),
|
||||
onPrimaryAction: { startBatteryConfiguration() },
|
||||
onSecondaryAction: { openComponentLibrary(source: "batteries-onboarding", type: .battery) }
|
||||
)
|
||||
} else {
|
||||
BatteriesView(
|
||||
system: system,
|
||||
batteries: savedBatteries,
|
||||
editMode: $editMode,
|
||||
onEdit: { editBattery($0) },
|
||||
onDelete: deleteBatteries
|
||||
)
|
||||
.environment(\.editMode, $editMode)
|
||||
}
|
||||
}
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
if !savedBatteries.isEmpty {
|
||||
libraryButton(type: .battery)
|
||||
.padding(.trailing, 24)
|
||||
.padding(.bottom, 24)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var chargersTab: some View {
|
||||
ChargersView(
|
||||
system: system,
|
||||
chargers: savedChargers,
|
||||
editMode: $editMode,
|
||||
onAdd: { startChargerConfiguration() },
|
||||
onEdit: { editCharger($0) },
|
||||
onDelete: deleteChargers,
|
||||
onBrowseLibrary: { openComponentLibrary(source: "chargers-onboarding", type: .charger) }
|
||||
)
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
if !savedChargers.isEmpty {
|
||||
libraryButton(type: .charger)
|
||||
.padding(.trailing, 24)
|
||||
.padding(.bottom, 24)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var loadsListWithHeader: some View {
|
||||
Group {
|
||||
@@ -507,7 +531,7 @@ struct LoadsView: View {
|
||||
}
|
||||
}
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
libraryButton
|
||||
libraryButton(type: .load)
|
||||
.padding(.trailing, 24)
|
||||
.padding(.bottom, 24)
|
||||
}
|
||||
@@ -802,15 +826,63 @@ struct LoadsView: View {
|
||||
showingSystemEditor = true
|
||||
}
|
||||
|
||||
private func openComponentLibrary(source: String) {
|
||||
private func openComponentLibrary(source: String, type: ComponentLibraryType = .load) {
|
||||
AnalyticsTracker.log(
|
||||
"Component Library Opened",
|
||||
properties: [
|
||||
"source": source,
|
||||
"type": type.rawValue,
|
||||
"system": system.name
|
||||
]
|
||||
)
|
||||
showingComponentLibrary = true
|
||||
activeLibrary = type
|
||||
}
|
||||
|
||||
private func handleLibrarySelection(_ item: ComponentLibraryItem, for type: ComponentLibraryType) {
|
||||
switch type {
|
||||
case .load:
|
||||
addComponent(item)
|
||||
case .battery:
|
||||
addBatteryFromLibrary(item)
|
||||
case .charger:
|
||||
addChargerFromLibrary(item)
|
||||
}
|
||||
}
|
||||
|
||||
private func addBatteryFromLibrary(_ item: ComponentLibraryItem) {
|
||||
AnalyticsTracker.log(
|
||||
"Library Battery Added",
|
||||
properties: [
|
||||
"id": item.id,
|
||||
"name": item.localizedName,
|
||||
"system": system.name
|
||||
]
|
||||
)
|
||||
batteryDraft = SystemComponentsPersistence.makeBatteryDraft(
|
||||
from: item,
|
||||
for: system,
|
||||
existingLoads: savedLoads,
|
||||
existingBatteries: savedBatteries,
|
||||
existingChargers: savedChargers
|
||||
)
|
||||
}
|
||||
|
||||
private func addChargerFromLibrary(_ item: ComponentLibraryItem) {
|
||||
AnalyticsTracker.log(
|
||||
"Library Charger Added",
|
||||
properties: [
|
||||
"id": item.id,
|
||||
"name": item.localizedName,
|
||||
"system": system.name
|
||||
]
|
||||
)
|
||||
chargerDraft = SystemComponentsPersistence.makeChargerDraft(
|
||||
from: item,
|
||||
for: system,
|
||||
existingLoads: savedLoads,
|
||||
existingBatteries: savedBatteries,
|
||||
existingChargers: savedChargers
|
||||
)
|
||||
}
|
||||
|
||||
private func openBillOfMaterials() {
|
||||
|
||||
Reference in New Issue
Block a user