mirror of
https://github.com/netbirdio/ios-client.git
synced 2026-09-23 09:28:33 -07:00
* fix ui state for airplaine mode * fix slide bar * Keep VPN tunnel alive during network unavailability - Add isNetworkUnavailable flag to NetBirdAdapter to track network state - Modify ConnectionListener to stay in 'connecting' state when network is unavailable instead of transitioning to 'disconnected' - Update PacketTunnelProvider to set network unavailable flag and trigger automatic reconnect when network returns - Fix CustomLottieView to show grey 'Disconnected' state immediately when network is lost, without closing the VPN tunnel - Ensure UI shows correct state after app foreground/background cycle This allows the VPN tunnel to survive temporary network outages (e.g. airplane mode) and automatically reconnect when network returns. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix UI state after app foreground/background cycle Show correct connected/disconnected state immediately when app returns from background, without replaying animations. Use extensionStatus (iOS VPN state) as the source of truth for UI state. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * netbird credential * Update MainView.swift * Separate button by state * Add gogoleServiceInfo plist reference * Remove dead code in animation state machine and fix copy-to-clipboard UX - Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return) - Guard against copying empty fqdn/ip strings when disconnected - Use consistent .smooth animation for both fqdn and ip copy feedback - Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return) - Guard against copying empty fqdn/ip strings when disconnected - Use consistent .smooth animation for both fqdn and ip copy feedback * Tab bar * Update peer view * Add offline state handling and network warning banner - Show "Offline" instead of "Connected" when VPN tunnel is active but device has no internet - Add NetworkWarningBanner with "Network Issues" warning when connected without internet - Remove InternetStatusView (online/offline indicator) from connection screen - Add FirstLaunchView onboarding screen - Remove unused components (CustomBackButton, Extensions, JustifiedText, SolidButton, TransparentGradientButton) - Update AboutView, AdvancedView, ServerView, PeerTabView, RouteTabView, iOSNetworksView styling - Add EmptyTabPlaceholder component * Add AppButton component with liquid glass support for iOS 26+ * Update FirstLaunchView.swift * old version * Update project.pbxproj * Code refactoring * Update project.pbxproj * Update MainViewModel.swift --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
96 lines
3.2 KiB
Swift
96 lines
3.2 KiB
Swift
//
|
|
// PeerDetailSheet.swift
|
|
// NetBird
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct PeerDetailSheet: View {
|
|
@ObservedObject var peer: PeerInfo
|
|
@Environment(\.presentationMode) var presentationMode
|
|
|
|
@State private var relativeDateText: String = ""
|
|
|
|
private let dateFormatter: DateFormatter = {
|
|
let formatter = DateFormatter()
|
|
formatter.locale = Locale(identifier: "en_US_POSIX")
|
|
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
|
formatter.timeZone = TimeZone(secondsFromGMT: 0)
|
|
return formatter
|
|
}()
|
|
|
|
private let relativeFormatter: RelativeDateTimeFormatter = {
|
|
let formatter = RelativeDateTimeFormatter()
|
|
formatter.unitsStyle = .full
|
|
return formatter
|
|
}()
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
List {
|
|
Section {
|
|
detailRow("Status", peer.connStatus)
|
|
detailRow("Last status update", relativeDateText)
|
|
detailRow("Connection type", peer.relayed ? "Relayed" : "P2P")
|
|
detailRow("Direct", peer.direct.description)
|
|
detailRow("Latency", peer.latency)
|
|
detailRow("Quantum resistance", peer.rosenpassEnabled.description)
|
|
}
|
|
|
|
Section(header: Text("ICE")) {
|
|
detailRow("Candidate (Local/Remote)", "\(peer.localIceCandidateType)/\(peer.remoteIceCandidateType)")
|
|
detailRow("Local endpoint", peer.localIceCandidateEndpoint)
|
|
detailRow("Remote endpoint", peer.remoteIceCandidateEndpoint)
|
|
}
|
|
|
|
if !peer.routes.isEmpty {
|
|
Section(header: Text("Routes")) {
|
|
ForEach(peer.routes, id: \.self) { route in
|
|
Text(route)
|
|
.font(.system(.body, design: .monospaced))
|
|
}
|
|
}
|
|
}
|
|
|
|
Section {
|
|
detailRow("Public key", peer.pubKey)
|
|
}
|
|
}
|
|
.listStyle(.insetGrouped)
|
|
.navigationTitle(peer.fqdn)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigationBarTrailing) {
|
|
Button("Done") { presentationMode.wrappedValue.dismiss() }
|
|
}
|
|
}
|
|
}
|
|
.onAppear { updateRelativeDate() }
|
|
}
|
|
|
|
@ViewBuilder
|
|
private func detailRow(_ label: String, _ value: String) -> some View {
|
|
HStack {
|
|
Text(label)
|
|
.foregroundColor(Color("TextPrimary"))
|
|
Spacer()
|
|
Text(value)
|
|
.foregroundColor(.gray)
|
|
.multilineTextAlignment(.trailing)
|
|
}
|
|
.font(.subheadline)
|
|
}
|
|
|
|
private func updateRelativeDate() {
|
|
if peer.connStatusUpdate == "0001-01-01 00:00:00" {
|
|
relativeDateText = "never"
|
|
return
|
|
}
|
|
if let date = dateFormatter.date(from: peer.connStatusUpdate) {
|
|
relativeDateText = relativeFormatter.localizedString(for: date, relativeTo: Date())
|
|
} else {
|
|
relativeDateText = peer.connStatusUpdate
|
|
}
|
|
}
|
|
}
|