diff --git a/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogDetailView.swift b/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogDetailView.swift index 1871bef32ad..cd600f57a47 100644 --- a/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogDetailView.swift +++ b/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogDetailView.swift @@ -18,7 +18,9 @@ struct POSSettingsLocalCatalogDetailView: View { ScrollView { VStack(spacing: POSSpacing.medium) { catalogStatus - managingDataUsage + if viewModel.deviceHasCellularCapability { + managingDataUsage + } manualCatalogUpdate } .padding(.horizontal, POSPadding.medium) diff --git a/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogViewModel.swift b/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogViewModel.swift index e4ced8b21b1..8e6e8a2f196 100644 --- a/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogViewModel.swift +++ b/Modules/Sources/PointOfSale/Presentation/Settings/POSSettingsLocalCatalogViewModel.swift @@ -2,6 +2,7 @@ import CocoaLumberjackSwift import Yosemite import Foundation import Storage +import WooFoundation @Observable final class POSSettingsLocalCatalogViewModel { @@ -11,6 +12,7 @@ final class POSSettingsLocalCatalogViewModel { private(set) var isLoading: Bool = false private(set) var isRefreshingCatalog: Bool = false + let deviceHasCellularCapability: Bool = CellularCapabilityChecker.deviceHasCellularCapability() var catalogRefreshError: POSIdentifiableErrorState? = nil diff --git a/Modules/Sources/WooFoundation/Utilities/Connectivity/CellularCapabilityChecker.swift b/Modules/Sources/WooFoundation/Utilities/Connectivity/CellularCapabilityChecker.swift new file mode 100644 index 00000000000..cebed1982cf --- /dev/null +++ b/Modules/Sources/WooFoundation/Utilities/Connectivity/CellularCapabilityChecker.swift @@ -0,0 +1,26 @@ +import Darwin + +public struct CellularCapabilityChecker { + public static func deviceHasCellularCapability() -> Bool { + var addrs: UnsafeMutablePointer? + guard getifaddrs(&addrs) == 0 else { return false } + defer { freeifaddrs(addrs) } + + var cursor = addrs + while let addr = cursor { + guard let namePtr = addr.pointee.ifa_name else { + cursor = addr.pointee.ifa_next + continue + } + + let name = String(cString: namePtr) + // This isn't a great check, but the alternatives are deprecated, and apparently it's commonly used. + // pdp_ip0 is the first cellular interface – it's not present if there's no cellular hardware. + if name == "pdp_ip0" { + return true + } + cursor = addr.pointee.ifa_next + } + return false + } +}