Files
evgeniyChepelevandClaude Opus 4.5 f5b1de0cc7 Redesign app (#60)
* 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>
2026-03-02 15:23:51 +01:00

104 lines
3.5 KiB
Swift

//
// AboutView.swift
// NetBirdiOS
//
// Created by Pascal Fischer on 01.08.23.
//
import SwiftUI
struct AboutView: View {
@EnvironmentObject var viewModel: ViewModel
var body: some View {
List {
Section {
HStack {
Spacer()
VStack(spacing: 12) {
Image("netbird-logo-menu")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 120)
Text("Version \(appVersion)")
.font(.subheadline)
.foregroundColor(Color("TextSecondary"))
}
Spacer()
}
.listRowBackground(Color.clear)
}
Section {
if let termsURL = URL(string: "https://netbird.io/terms") {
Link(destination: termsURL) {
HStack {
Text("License agreement")
.foregroundColor(Color("TextPrimary"))
Spacer()
Image(systemName: "arrow.up.right.square")
.foregroundColor(Color("TextSecondary"))
.font(.system(size: 14))
}
}
}
if let privacyURL = URL(string: "https://netbird.io/privacy") {
Link(destination: privacyURL) {
HStack {
Text("Privacy policy")
.foregroundColor(Color("TextPrimary"))
Spacer()
Image(systemName: "arrow.up.right.square")
.foregroundColor(Color("TextSecondary"))
.font(.system(size: 14))
}
}
}
}
Section {
Button("Join Beta Program") {
viewModel.showBetaProgramAlert = true
}
}
Section {
HStack {
Spacer()
Text("\u{00A9} \(String(Calendar.current.component(.year, from: Date()))) NetBird all rights reserved")
.font(.footnote)
.foregroundColor(Color("TextSecondary"))
Spacer()
}
.listRowBackground(Color.clear)
}
}
.listStyle(InsetGroupedListStyle())
.navigationTitle("About")
.navigationBarTitleDisplayMode(.inline)
.alert(isPresented: $viewModel.showBetaProgramAlert) {
Alert(
title: Text("Join TestFlight Beta"),
message: Text("By signing up for TestFlight you will receive new updates early and can give us valuable feedback before the official release."),
primaryButton: .default(Text("Sign Up")) {
if let url = URL(string: "https://testflight.apple.com/join/jISzXOP8") {
UIApplication.shared.open(url)
}
},
secondaryButton: .cancel()
)
}
}
private var appVersion: String {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "unknown"
}
}
struct AboutView_Previews: PreviewProvider {
static var previews: some View {
AboutView()
}
}