import SwiftUI struct NetworkCarouselView: View { var networks: [NetworkCardModel] var selectedNetworkID: Int32? var onSelect: ((NetworkCardModel) -> Void)? init( networks: [NetworkCardModel], selectedNetworkID: Int32? = nil, onSelect: ((NetworkCardModel) -> Void)? = nil ) { self.networks = networks self.selectedNetworkID = selectedNetworkID self.onSelect = onSelect } var body: some View { Group { if networks.isEmpty { #if os(iOS) VStack(alignment: .leading, spacing: 6) { Text("No stored networks yet") .font(.headline) Text("WireGuard and Tailnet networks show up here as soon as you add one.") .font(.footnote) .foregroundStyle(.secondary) } .frame(maxWidth: .infinity, alignment: .leading) .padding() .background( RoundedRectangle(cornerRadius: 18) .fill(.thinMaterial) ) #else ContentUnavailableView( "No Networks Yet", systemImage: "network.slash", description: Text("Add a WireGuard network, or save a Tailnet account so Burrow can store a managed network when the daemon is reachable.") ) .frame(maxWidth: .infinity, minHeight: 175) #endif } else { #if os(macOS) LazyVStack(alignment: .leading, spacing: 12) { ForEach(networks) { network in networkCard(network) .frame(maxWidth: 560) } } .frame(maxWidth: .infinity, alignment: .leading) #else ScrollView(.horizontal) { LazyHStack { ForEach(networks) { network in networkCard(network) .containerRelativeFrame(.horizontal, count: 10, span: 7, spacing: 0, alignment: .center) .scrollTransition(.interactive, axis: .horizontal) { content, phase in content .scaleEffect(1.0 - abs(phase.value) * 0.1) } } } } .scrollTargetLayout() .scrollClipDisabled() .scrollIndicators(.hidden) .defaultScrollAnchor(.center) .scrollTargetBehavior(.viewAligned) .containerRelativeFrame(.horizontal) #endif } } } @ViewBuilder private func networkCard(_ network: NetworkCardModel) -> some View { if let onSelect { Button { onSelect(network) } label: { NetworkView(network: network) .overlay(selectionOverlay(for: network)) } .buttonStyle(.plain) } else { NetworkView(network: network) } } private func selectionOverlay(for network: NetworkCardModel) -> some View { RoundedRectangle(cornerRadius: 10) .stroke( selectedNetworkID == network.id ? Color.accentColor : Color.clear, lineWidth: 3 ) } } #if DEBUG struct NetworkCarouselView_Previews: PreviewProvider { static var previews: some View { NetworkCarouselView(networks: [WireGuardCard(id: 1, detail: "10.13.13.2/24 ยท wg.burrow.rs:51820").card]) } } #endif